From 0f87cd842dd46205d5252c35da6d2c869f3d2e98 Mon Sep 17 00:00:00 2001 From: croachrose Date: Wed, 20 Sep 2006 15:47:42 +0000 Subject: [PATCH] Initial checkin of skia source in google codebase. * reviewed by me! git-svn-id: http://skia.googlecode.com/svn/trunk@2 2bbb7eff-a529-9590-31e7-b0007b416f81 --- include/corecg/Sk64.h | 219 ++ include/corecg/SkBuffer.h | 135 + include/corecg/SkChunkAlloc.h | 30 + include/corecg/SkEndian.h | 82 + include/corecg/SkFDot6.h | 51 + include/corecg/SkFixed.h | 159 + include/corecg/SkFloatingPoint.h | 44 + include/corecg/SkMath.h | 132 + include/corecg/SkMatrix.h | 298 ++ include/corecg/SkPoint.h | 244 ++ include/corecg/SkPostConfig.h | 169 + include/corecg/SkPreConfig.h | 101 + include/corecg/SkRandom.h | 85 + include/corecg/SkRect.h | 266 ++ include/corecg/SkRegion.h | 249 ++ include/corecg/SkScalar.h | 235 ++ include/corecg/SkTemplates.h | 161 + include/corecg/SkThread.h | 40 + include/corecg/SkThread_platform.h | 37 + include/corecg/SkTypes.h | 299 ++ include/corecg/SkUserConfig.h | 59 + include/graphics/DoxygenMain.dox | 3 + include/graphics/Sk1DPathEffect.h | 65 + include/graphics/Sk2DPathEffect.h | 53 + include/graphics/SkAnimator.h | 492 +++ include/graphics/SkAnimatorView.h | 31 + include/graphics/SkApplication.h | 10 + include/graphics/SkAvoidXfermode.h | 34 + include/graphics/SkBGViewArtist.h | 25 + include/graphics/SkBML_WXMLParser.h | 38 + include/graphics/SkBML_XMLParser.h | 23 + include/graphics/SkBitmap.h | 374 +++ include/graphics/SkBitmapRef.h | 58 + include/graphics/SkBlurMaskFilter.h | 37 + include/graphics/SkBorderView.h | 31 + include/graphics/SkBounder.h | 45 + include/graphics/SkCamera.h | 80 + include/graphics/SkCanvas.h | 470 +++ include/graphics/SkColor.h | 126 + include/graphics/SkColorFilter.h | 56 + include/graphics/SkColorPriv.h | 218 ++ include/graphics/SkCornerPathEffect.h | 45 + include/graphics/SkCullPoints.h | 58 + include/graphics/SkDOM.h | 83 + include/graphics/SkDashPathEffect.h | 49 + include/graphics/SkDeque.h | 191 ++ include/graphics/SkDescriptor.h | 158 + include/graphics/SkDiscretePathEffect.h | 40 + include/graphics/SkDrawExtraPathEffect.h | 6 + include/graphics/SkEmbossMaskFilter.h | 47 + include/graphics/SkEvent.h | 228 ++ include/graphics/SkEventSink.h | 87 + include/graphics/SkFlattenable.h | 23 + include/graphics/SkFontCodec.h | 20 + include/graphics/SkFontHost.h | 43 + include/graphics/SkGlobals.h | 51 + include/graphics/SkGradientShader.h | 57 + include/graphics/SkGraphics.h | 30 + include/graphics/SkImageDecoder.h | 130 + include/graphics/SkImageView.h | 59 + include/graphics/SkInterpolator.h | 98 + include/graphics/SkJS.h | 31 + include/graphics/SkKey.h | 47 + include/graphics/SkLayerRasterizer.h | 41 + include/graphics/SkMask.h | 65 + include/graphics/SkMaskFilter.h | 83 + include/graphics/SkMetaData.h | 138 + include/graphics/SkNinePatch.h | 21 + include/graphics/SkOSFile.h | 70 + include/graphics/SkOSMenu.h | 39 + include/graphics/SkOSSound.h | 20 + include/graphics/SkOSWindow_Mac.h | 32 + include/graphics/SkOSWindow_Unix.h | 44 + include/graphics/SkOSWindow_Win.h | 43 + include/graphics/SkOSWindow_wxwidgets.h | 37 + include/graphics/SkPaint.h | 630 ++++ include/graphics/SkParse.h | 29 + include/graphics/SkParsePaint.h | 18 + include/graphics/SkPath.h | 373 +++ include/graphics/SkPathEffect.h | 143 + include/graphics/SkPathMeasure.h | 95 + include/graphics/SkPorterDuff.h | 47 + include/graphics/SkPrefix_Debug_Fixed.h | 14 + include/graphics/SkPrefix_Release_Fixed.h | 26 + include/graphics/SkProgressBarView.h | 41 + include/graphics/SkRasterizer.h | 33 + include/graphics/SkRefCnt.h | 87 + include/graphics/SkSVGAttribute.h | 33 + include/graphics/SkSVGBase.h | 16 + include/graphics/SkSVGPaintState.h | 80 + include/graphics/SkSVGParser.h | 65 + include/graphics/SkSVGTypes.h | 30 + include/graphics/SkScalerContext.h | 87 + include/graphics/SkScrollBarView.h | 35 + include/graphics/SkShader.h | 146 + include/graphics/SkShaderExtras.h | 36 + include/graphics/SkStackViewLayout.h | 80 + include/graphics/SkStdLib_Redirect.h | 17 + include/graphics/SkStream.h | 199 ++ include/graphics/SkStream_Win.h | 37 + include/graphics/SkString.h | 150 + include/graphics/SkStroke.h | 58 + include/graphics/SkSystemEventTypes.h | 16 + include/graphics/SkTDArray.h | 288 ++ include/graphics/SkTDStack.h | 104 + include/graphics/SkTDict.h | 154 + include/graphics/SkTSearch.h | 56 + include/graphics/SkTextBox.h | 61 + include/graphics/SkTextLayout.h | 44 + include/graphics/SkTime.h | 32 + include/graphics/SkTransparentShader.h | 23 + include/graphics/SkTypeface.h | 67 + include/graphics/SkUnitMapper.h | 35 + include/graphics/SkUtils.h | 85 + include/graphics/SkView.h | 328 ++ include/graphics/SkViewInflate.h | 63 + include/graphics/SkWidget.h | 460 +++ include/graphics/SkWidgetViews.h | 294 ++ include/graphics/SkWindow.h | 84 + include/graphics/SkXMLParser.h | 79 + include/graphics/SkXMLWriter.h | 77 + include/graphics/SkXfermode.h | 62 + libs/corecg/Makefile | 30 + libs/corecg/Sk64.cpp | 553 ++++ libs/corecg/SkBuffer.cpp | 106 + libs/corecg/SkChunkAlloc.cpp | 45 + libs/corecg/SkCordic.cpp | 284 ++ libs/corecg/SkCordic.h | 20 + libs/corecg/SkDebug.cpp | 42 + libs/corecg/SkDebug_stdio.cpp | 21 + libs/corecg/SkFP.h | 68 + libs/corecg/SkFloat.cpp | 387 +++ libs/corecg/SkFloat.h | 91 + libs/corecg/SkMath.cpp | 703 +++++ libs/corecg/SkMatrix.cpp | 1220 ++++++++ libs/corecg/SkMemory_stdlib.cpp | 79 + libs/corecg/SkPoint.cpp | 238 ++ libs/corecg/SkRect.cpp | 103 + libs/corecg/SkRegion.cpp | 1168 +++++++ libs/corecg/SkRegionPriv.h | 70 + libs/corecg/SkSinTable.h | 268 ++ libs/corecg/SkTSort.h | 48 + libs/graphics/Makefile | 137 + libs/graphics/animator/SkAnimate.h | 26 + libs/graphics/animator/SkAnimate3DSchema.xsd | 39 + libs/graphics/animator/SkAnimate3DSchema.xsx | 3 + libs/graphics/animator/SkAnimateActive.cpp | 492 +++ libs/graphics/animator/SkAnimateActive.h | 70 + libs/graphics/animator/SkAnimateBase.cpp | 230 ++ libs/graphics/animator/SkAnimateBase.h | 74 + libs/graphics/animator/SkAnimateField.cpp | 113 + libs/graphics/animator/SkAnimateMaker.cpp | 356 +++ libs/graphics/animator/SkAnimateMaker.h | 153 + libs/graphics/animator/SkAnimateProperties.h | 12 + libs/graphics/animator/SkAnimateSchema.xsd | 2787 +++++++++++++++++ libs/graphics/animator/SkAnimateSchema.xsx | 3 + libs/graphics/animator/SkAnimateSet.cpp | 81 + libs/graphics/animator/SkAnimateSet.h | 19 + libs/graphics/animator/SkAnimator.cpp | 705 +++++ libs/graphics/animator/SkAnimatorScript.cpp | 590 ++++ libs/graphics/animator/SkAnimatorScript.h | 67 + libs/graphics/animator/SkAnimatorScript2.cpp | 618 ++++ libs/graphics/animator/SkAnimatorScript2.h | 43 + libs/graphics/animator/SkBase64.cpp | 171 + libs/graphics/animator/SkBase64.h | 30 + libs/graphics/animator/SkBoundable.cpp | 47 + libs/graphics/animator/SkBoundable.h | 33 + .../animator/SkBuildCondensedInfo.cpp | 275 ++ libs/graphics/animator/SkCondensedDebug.cpp | 1380 ++++++++ libs/graphics/animator/SkCondensedRelease.cpp | 1357 ++++++++ libs/graphics/animator/SkDisplayAdd.cpp | 237 ++ libs/graphics/animator/SkDisplayAdd.h | 64 + libs/graphics/animator/SkDisplayApply.cpp | 797 +++++ libs/graphics/animator/SkDisplayApply.h | 99 + libs/graphics/animator/SkDisplayBounds.cpp | 37 + libs/graphics/animator/SkDisplayBounds.h | 16 + libs/graphics/animator/SkDisplayEvent.cpp | 248 ++ libs/graphics/animator/SkDisplayEvent.h | 58 + libs/graphics/animator/SkDisplayEvents.cpp | 104 + libs/graphics/animator/SkDisplayEvents.h | 34 + libs/graphics/animator/SkDisplayInclude.cpp | 50 + libs/graphics/animator/SkDisplayInclude.h | 17 + libs/graphics/animator/SkDisplayInput.cpp | 46 + libs/graphics/animator/SkDisplayInput.h | 25 + libs/graphics/animator/SkDisplayList.cpp | 151 + libs/graphics/animator/SkDisplayList.h | 62 + libs/graphics/animator/SkDisplayMath.cpp | 231 ++ libs/graphics/animator/SkDisplayMath.h | 23 + libs/graphics/animator/SkDisplayMovie.cpp | 121 + libs/graphics/animator/SkDisplayMovie.h | 43 + libs/graphics/animator/SkDisplayNumber.cpp | 50 + libs/graphics/animator/SkDisplayNumber.h | 13 + libs/graphics/animator/SkDisplayPost.cpp | 298 ++ libs/graphics/animator/SkDisplayPost.h | 50 + libs/graphics/animator/SkDisplayRandom.cpp | 63 + libs/graphics/animator/SkDisplayRandom.h | 32 + .../graphics/animator/SkDisplayScreenplay.cpp | 13 + libs/graphics/animator/SkDisplayScreenplay.h | 12 + libs/graphics/animator/SkDisplayType.cpp | 757 +++++ libs/graphics/animator/SkDisplayType.h | 198 ++ libs/graphics/animator/SkDisplayTypes.cpp | 212 ++ libs/graphics/animator/SkDisplayTypes.h | 98 + libs/graphics/animator/SkDisplayXMLParser.cpp | 301 ++ libs/graphics/animator/SkDisplayXMLParser.h | 84 + libs/graphics/animator/SkDisplayable.cpp | 549 ++++ libs/graphics/animator/SkDisplayable.h | 103 + libs/graphics/animator/SkDraw3D.cpp | 100 + libs/graphics/animator/SkDraw3D.h | 42 + libs/graphics/animator/SkDrawBitmap.cpp | 186 ++ libs/graphics/animator/SkDrawBitmap.h | 65 + libs/graphics/animator/SkDrawBlur.cpp | 23 + libs/graphics/animator/SkDrawBlur.h | 17 + libs/graphics/animator/SkDrawClip.cpp | 31 + libs/graphics/animator/SkDrawClip.h | 20 + libs/graphics/animator/SkDrawColor.cpp | 261 ++ libs/graphics/animator/SkDrawColor.h | 33 + libs/graphics/animator/SkDrawDash.cpp | 27 + libs/graphics/animator/SkDrawDash.h | 18 + libs/graphics/animator/SkDrawDiscrete.cpp | 26 + libs/graphics/animator/SkDrawDiscrete.h | 15 + libs/graphics/animator/SkDrawEmboss.cpp | 25 + libs/graphics/animator/SkDrawEmboss.h | 16 + .../animator/SkDrawExtraPathEffect.cpp | 499 +++ libs/graphics/animator/SkDrawFull.cpp | 10 + libs/graphics/animator/SkDrawFull.h | 13 + libs/graphics/animator/SkDrawGradient.cpp | 214 ++ libs/graphics/animator/SkDrawGradient.h | 59 + libs/graphics/animator/SkDrawGroup.cpp | 314 ++ libs/graphics/animator/SkDrawGroup.h | 63 + libs/graphics/animator/SkDrawLine.cpp | 28 + libs/graphics/animator/SkDrawLine.h | 20 + libs/graphics/animator/SkDrawMatrix.cpp | 273 ++ libs/graphics/animator/SkDrawMatrix.h | 65 + libs/graphics/animator/SkDrawOval.cpp | 20 + libs/graphics/animator/SkDrawOval.h | 14 + libs/graphics/animator/SkDrawPaint.cpp | 260 ++ libs/graphics/animator/SkDrawPaint.h | 71 + libs/graphics/animator/SkDrawPath.cpp | 212 ++ libs/graphics/animator/SkDrawPath.h | 60 + libs/graphics/animator/SkDrawPoint.cpp | 37 + libs/graphics/animator/SkDrawPoint.h | 24 + libs/graphics/animator/SkDrawRectangle.cpp | 136 + libs/graphics/animator/SkDrawRectangle.h | 47 + libs/graphics/animator/SkDrawSaveLayer.cpp | 67 + libs/graphics/animator/SkDrawSaveLayer.h | 27 + libs/graphics/animator/SkDrawShader.cpp | 74 + libs/graphics/animator/SkDrawShader.h | 21 + libs/graphics/animator/SkDrawText.cpp | 47 + libs/graphics/animator/SkDrawText.h | 27 + libs/graphics/animator/SkDrawTextBox.cpp | 73 + libs/graphics/animator/SkDrawTextBox.h | 30 + libs/graphics/animator/SkDrawTo.cpp | 47 + libs/graphics/animator/SkDrawTo.h | 25 + .../animator/SkDrawTransparentShader.cpp | 7 + .../animator/SkDrawTransparentShader.h | 12 + libs/graphics/animator/SkDrawable.cpp | 16 + libs/graphics/animator/SkDrawable.h | 19 + libs/graphics/animator/SkDump.cpp | 141 + libs/graphics/animator/SkDump.h | 34 + libs/graphics/animator/SkExtraPathEffects.xsd | 33 + libs/graphics/animator/SkExtras.h | 25 + libs/graphics/animator/SkGetCondensedInfo.cpp | 113 + libs/graphics/animator/SkHitClear.cpp | 24 + libs/graphics/animator/SkHitClear.h | 16 + libs/graphics/animator/SkHitTest.cpp | 66 + libs/graphics/animator/SkHitTest.h | 21 + libs/graphics/animator/SkIntArray.h | 49 + libs/graphics/animator/SkInterpolator.cpp | 252 ++ libs/graphics/animator/SkMatrixParts.cpp | 284 ++ libs/graphics/animator/SkMatrixParts.h | 110 + libs/graphics/animator/SkMemberInfo.cpp | 551 ++++ libs/graphics/animator/SkMemberInfo.h | 266 ++ libs/graphics/animator/SkOpArray.cpp | 16 + libs/graphics/animator/SkOpArray.h | 22 + libs/graphics/animator/SkOperand.h | 37 + libs/graphics/animator/SkOperand2.h | 47 + .../graphics/animator/SkOperandInterpolator.h | 39 + .../animator/SkOperandIterpolator.cpp | 139 + libs/graphics/animator/SkPaintParts.cpp | 94 + libs/graphics/animator/SkPaintParts.h | 66 + libs/graphics/animator/SkPathParts.cpp | 311 ++ libs/graphics/animator/SkPathParts.h | 156 + libs/graphics/animator/SkPostParts.cpp | 48 + libs/graphics/animator/SkPostParts.h | 22 + libs/graphics/animator/SkSVGPath.cpp | 226 ++ libs/graphics/animator/SkScript.cpp | 1901 +++++++++++ libs/graphics/animator/SkScript.h | 257 ++ libs/graphics/animator/SkScript2.h | 285 ++ libs/graphics/animator/SkScriptCallBack.h | 58 + libs/graphics/animator/SkScriptDecompile.cpp | 204 ++ libs/graphics/animator/SkScriptRuntime.cpp | 342 ++ libs/graphics/animator/SkScriptRuntime.h | 43 + libs/graphics/animator/SkScriptTokenizer.cpp | 1513 +++++++++ libs/graphics/animator/SkSnapshot.cpp | 54 + libs/graphics/animator/SkSnapshot.h | 25 + .../animator/SkTDArray_Experimental.h | 133 + libs/graphics/animator/SkTextOnPath.cpp | 30 + libs/graphics/animator/SkTextOnPath.h | 21 + libs/graphics/animator/SkTextToPath.cpp | 39 + libs/graphics/animator/SkTextToPath.h | 23 + libs/graphics/animator/SkTime.cpp | 72 + libs/graphics/animator/SkTypedArray.cpp | 170 + libs/graphics/animator/SkTypedArray.h | 22 + .../graphics/animator/SkXMLAnimatorWriter.cpp | 74 + libs/graphics/animator/SkXMLAnimatorWriter.h | 25 + libs/graphics/animator/thingstodo.txt | 21 + libs/graphics/effects/Sk1DPathEffect.cpp | 162 + libs/graphics/effects/Sk2DPathEffect.cpp | 89 + libs/graphics/effects/SkAvoidXfermode.cpp | 131 + libs/graphics/effects/SkBlurMask.cpp | 308 ++ libs/graphics/effects/SkBlurMask.h | 23 + libs/graphics/effects/SkBlurMaskFilter.cpp | 96 + libs/graphics/effects/SkCamera.cpp | 251 ++ libs/graphics/effects/SkColorFilters.cpp | 264 ++ libs/graphics/effects/SkCornerPathEffect.cpp | 117 + libs/graphics/effects/SkCullPoints.cpp | 141 + libs/graphics/effects/SkDashPathEffect.cpp | 163 + .../graphics/effects/SkDiscretePathEffect.cpp | 89 + libs/graphics/effects/SkEmbossMask.cpp | 165 + libs/graphics/effects/SkEmbossMask.h | 12 + libs/graphics/effects/SkEmbossMaskFilter.cpp | 116 + libs/graphics/effects/SkEmbossMask_Table.h | 1029 ++++++ libs/graphics/effects/SkGradientShader.cpp | 1025 ++++++ libs/graphics/effects/SkLayerRasterizer.cpp | 251 ++ libs/graphics/effects/SkNinePatch.cpp | 177 ++ .../graphics/effects/SkRadialGradient_Table.h | 130 + libs/graphics/effects/SkShaderExtras.cpp | 51 + libs/graphics/effects/SkTransparentShader.cpp | 104 + libs/graphics/images/SkBitmapRef.cpp | 121 + libs/graphics/images/SkBitmapRefPriv.h | 31 + libs/graphics/images/SkImageDecoder.cpp | 175 ++ .../graphics/images/SkImageDecoder_libgif.cpp | 123 + .../images/SkImageDecoder_libjpeg.cpp | 427 +++ .../graphics/images/SkImageDecoder_libpng.cpp | 605 ++++ libs/graphics/images/SkStream.cpp | 585 ++++ libs/graphics/ports/SkFontHost.cpp | 272 ++ libs/graphics/ports/SkFontHost_FONTPATH.cpp | 85 + libs/graphics/ports/SkFontHost_FreeType.cpp | 633 ++++ libs/graphics/ports/SkFontHost_none.cpp | 33 + libs/graphics/ports/SkGlobals_global.cpp | 11 + .../graphics/ports/SkImageDecoder_Factory.cpp | 28 + libs/graphics/ports/SkOSEvent_android.cpp | 138 + libs/graphics/ports/SkOSEvent_dummy.cpp | 11 + libs/graphics/ports/SkOSFile_stdio.cpp | 83 + libs/graphics/ports/SkThread_none.cpp | 32 + libs/graphics/ports/SkTime_Unix.cpp | 33 + libs/graphics/ports/SkXMLParser_empty.cpp | 19 + libs/graphics/ports/SkXMLParser_expat.cpp | 132 + libs/graphics/ports/SkXMLParser_tinyxml.cpp | 79 + libs/graphics/sgl/SkAlphaRuns.cpp | 168 + libs/graphics/sgl/SkAntiRun.h | 168 + libs/graphics/sgl/SkBitmap.cpp | 412 +++ libs/graphics/sgl/SkBitmapSampler.cpp | 281 ++ libs/graphics/sgl/SkBitmapSampler.h | 150 + libs/graphics/sgl/SkBitmapSamplerTemplate.h | 99 + libs/graphics/sgl/SkBitmapShader.cpp | 476 +++ libs/graphics/sgl/SkBitmapShader.h | 51 + .../sgl/SkBitmapShader16BilerpTemplate.h | 126 + libs/graphics/sgl/SkBitmapShaderTemplate.h | 231 ++ libs/graphics/sgl/SkBlitBWMaskTemplate.h | 120 + libs/graphics/sgl/SkBlitter.cpp | 795 +++++ libs/graphics/sgl/SkBlitter.h | 102 + libs/graphics/sgl/SkBlitter_A1.cpp | 46 + libs/graphics/sgl/SkBlitter_A8.cpp | 365 +++ libs/graphics/sgl/SkBlitter_ARGB32.cpp | 465 +++ libs/graphics/sgl/SkBlitter_RGB16.cpp | 674 ++++ libs/graphics/sgl/SkBlitter_Sprite.cpp | 73 + libs/graphics/sgl/SkCanvas.cpp | 623 ++++ libs/graphics/sgl/SkColor.cpp | 118 + libs/graphics/sgl/SkColorFilter.cpp | 36 + libs/graphics/sgl/SkColorTable.cpp | 99 + libs/graphics/sgl/SkCoreBlitters.h | 177 ++ libs/graphics/sgl/SkDeque.cpp | 389 +++ libs/graphics/sgl/SkDraw.cpp | 1139 +++++++ libs/graphics/sgl/SkDraw.h | 89 + libs/graphics/sgl/SkEdge.cpp | 429 +++ libs/graphics/sgl/SkEdge.h | 77 + libs/graphics/sgl/SkFP.h | 70 + libs/graphics/sgl/SkFilterProc.cpp | 38 + libs/graphics/sgl/SkFilterProc.h | 22 + libs/graphics/sgl/SkGeometry.cpp | 1013 ++++++ libs/graphics/sgl/SkGeometry.h | 146 + libs/graphics/sgl/SkGlobals.cpp | 75 + libs/graphics/sgl/SkGlyphCache.cpp | 234 ++ libs/graphics/sgl/SkGlyphCache.h | 89 + libs/graphics/sgl/SkGraphics.cpp | 143 + libs/graphics/sgl/SkMaskFilter.cpp | 69 + libs/graphics/sgl/SkPaint.cpp | 868 +++++ libs/graphics/sgl/SkPath.cpp | 1139 +++++++ libs/graphics/sgl/SkPathEffect.cpp | 181 ++ libs/graphics/sgl/SkPathMeasure.cpp | 623 ++++ libs/graphics/sgl/SkProcSpriteBlitter.cpp | 38 + libs/graphics/sgl/SkRasterizer.cpp | 45 + libs/graphics/sgl/SkRefCnt.cpp | 36 + libs/graphics/sgl/SkRegion_path.cpp | 478 +++ libs/graphics/sgl/SkScalerContext.cpp | 498 +++ libs/graphics/sgl/SkScan.cpp | 32 + libs/graphics/sgl/SkScan.h | 30 + libs/graphics/sgl/SkScanPriv.h | 25 + libs/graphics/sgl/SkScan_AntiPath.cpp | 209 ++ libs/graphics/sgl/SkScan_Antihair.cpp | 397 +++ libs/graphics/sgl/SkScan_Hairline.cpp | 254 ++ libs/graphics/sgl/SkScan_Path.cpp | 430 +++ libs/graphics/sgl/SkShader.cpp | 370 +++ libs/graphics/sgl/SkSinTable.h | 268 ++ libs/graphics/sgl/SkSpriteBlitter.h | 41 + libs/graphics/sgl/SkSpriteBlitterTemplate.h | 60 + libs/graphics/sgl/SkSpriteBlitter_ARGB32.cpp | 81 + libs/graphics/sgl/SkSpriteBlitter_RGB16.cpp | 300 ++ libs/graphics/sgl/SkString.cpp | 602 ++++ libs/graphics/sgl/SkStroke.cpp | 586 ++++ libs/graphics/sgl/SkStrokerPriv.cpp | 216 ++ libs/graphics/sgl/SkStrokerPriv.h | 33 + libs/graphics/sgl/SkTSearch.cpp | 176 ++ libs/graphics/sgl/SkTSort.h | 48 + libs/graphics/sgl/SkTemplatesPriv.h | 67 + libs/graphics/sgl/SkTextLayout.cpp | 66 + libs/graphics/sgl/SkUtils.cpp | 496 +++ libs/graphics/sgl/SkXfermode.cpp | 535 ++++ libs/graphics/svg/SkSVG.cpp | 19 + libs/graphics/svg/SkSVGCircle.cpp | 36 + libs/graphics/svg/SkSVGCircle.h | 15 + libs/graphics/svg/SkSVGClipPath.cpp | 31 + libs/graphics/svg/SkSVGClipPath.h | 14 + libs/graphics/svg/SkSVGDefs.cpp | 15 + libs/graphics/svg/SkSVGDefs.h | 14 + libs/graphics/svg/SkSVGElements.cpp | 79 + libs/graphics/svg/SkSVGElements.h | 64 + libs/graphics/svg/SkSVGEllipse.cpp | 38 + libs/graphics/svg/SkSVGEllipse.h | 16 + libs/graphics/svg/SkSVGFeColorMatrix.cpp | 15 + libs/graphics/svg/SkSVGFeColorMatrix.h | 17 + libs/graphics/svg/SkSVGFilter.cpp | 16 + libs/graphics/svg/SkSVGFilter.h | 18 + libs/graphics/svg/SkSVGG.cpp | 7 + libs/graphics/svg/SkSVGG.h | 12 + libs/graphics/svg/SkSVGGradient.cpp | 106 + libs/graphics/svg/SkSVGGradient.h | 20 + libs/graphics/svg/SkSVGGroup.cpp | 36 + libs/graphics/svg/SkSVGGroup.h | 19 + libs/graphics/svg/SkSVGImage.cpp | 35 + libs/graphics/svg/SkSVGImage.h | 19 + libs/graphics/svg/SkSVGLine.cpp | 21 + libs/graphics/svg/SkSVGLine.h | 16 + libs/graphics/svg/SkSVGLinearGradient.cpp | 35 + libs/graphics/svg/SkSVGLinearGradient.h | 19 + libs/graphics/svg/SkSVGMask.cpp | 24 + libs/graphics/svg/SkSVGMask.h | 20 + libs/graphics/svg/SkSVGMetadata.cpp | 15 + libs/graphics/svg/SkSVGMetadata.h | 14 + libs/graphics/svg/SkSVGPaintState.cpp | 446 +++ libs/graphics/svg/SkSVGParser.cpp | 428 +++ libs/graphics/svg/SkSVGPath.cpp | 28 + libs/graphics/svg/SkSVGPath.h | 13 + libs/graphics/svg/SkSVGPolygon.cpp | 24 + libs/graphics/svg/SkSVGPolygon.h | 14 + libs/graphics/svg/SkSVGPolyline.cpp | 34 + libs/graphics/svg/SkSVGPolyline.h | 18 + libs/graphics/svg/SkSVGRadialGradient.cpp | 33 + libs/graphics/svg/SkSVGRadialGradient.h | 21 + libs/graphics/svg/SkSVGRect.cpp | 26 + libs/graphics/svg/SkSVGRect.h | 17 + libs/graphics/svg/SkSVGSVG.cpp | 65 + libs/graphics/svg/SkSVGSVG.h | 22 + libs/graphics/svg/SkSVGStop.cpp | 15 + libs/graphics/svg/SkSVGStop.h | 14 + libs/graphics/svg/SkSVGSymbol.cpp | 13 + libs/graphics/svg/SkSVGSymbol.h | 13 + libs/graphics/svg/SkSVGText.cpp | 30 + libs/graphics/svg/SkSVGText.h | 23 + libs/graphics/svg/SkSVGUse.cpp | 21 + libs/graphics/svg/SkSVGUse.h | 19 + libs/graphics/text/ATextEntry.h | 20 + libs/graphics/views/SkEvent.cpp | 548 ++++ libs/graphics/views/SkEventSink.cpp | 328 ++ libs/graphics/views/SkMetaData.cpp | 388 +++ libs/graphics/views/SkTagList.cpp | 54 + libs/graphics/views/SkTagList.h | 34 + libs/graphics/views/SkTextBox.cpp | 195 ++ libs/graphics/xml/SkBML_Verbs.h | 16 + libs/graphics/xml/SkBML_XMLParser.cpp | 175 ++ libs/graphics/xml/SkDOM.cpp | 495 +++ libs/graphics/xml/SkJS.cpp | 219 ++ libs/graphics/xml/SkJSDisplayable.cpp | 455 +++ libs/graphics/xml/SkParse.cpp | 319 ++ libs/graphics/xml/SkParseColor.cpp | 529 ++++ libs/graphics/xml/SkXMLParser.cpp | 78 + libs/graphics/xml/SkXMLWriter.cpp | 325 ++ 488 files changed, 79697 insertions(+) create mode 100644 include/corecg/Sk64.h create mode 100644 include/corecg/SkBuffer.h create mode 100644 include/corecg/SkChunkAlloc.h create mode 100644 include/corecg/SkEndian.h create mode 100644 include/corecg/SkFDot6.h create mode 100644 include/corecg/SkFixed.h create mode 100644 include/corecg/SkFloatingPoint.h create mode 100644 include/corecg/SkMath.h create mode 100644 include/corecg/SkMatrix.h create mode 100644 include/corecg/SkPoint.h create mode 100644 include/corecg/SkPostConfig.h create mode 100644 include/corecg/SkPreConfig.h create mode 100644 include/corecg/SkRandom.h create mode 100644 include/corecg/SkRect.h create mode 100644 include/corecg/SkRegion.h create mode 100644 include/corecg/SkScalar.h create mode 100644 include/corecg/SkTemplates.h create mode 100644 include/corecg/SkThread.h create mode 100644 include/corecg/SkThread_platform.h create mode 100644 include/corecg/SkTypes.h create mode 100644 include/corecg/SkUserConfig.h create mode 100644 include/graphics/DoxygenMain.dox create mode 100644 include/graphics/Sk1DPathEffect.h create mode 100644 include/graphics/Sk2DPathEffect.h create mode 100644 include/graphics/SkAnimator.h create mode 100644 include/graphics/SkAnimatorView.h create mode 100644 include/graphics/SkApplication.h create mode 100644 include/graphics/SkAvoidXfermode.h create mode 100644 include/graphics/SkBGViewArtist.h create mode 100644 include/graphics/SkBML_WXMLParser.h create mode 100644 include/graphics/SkBML_XMLParser.h create mode 100644 include/graphics/SkBitmap.h create mode 100644 include/graphics/SkBitmapRef.h create mode 100644 include/graphics/SkBlurMaskFilter.h create mode 100644 include/graphics/SkBorderView.h create mode 100644 include/graphics/SkBounder.h create mode 100644 include/graphics/SkCamera.h create mode 100644 include/graphics/SkCanvas.h create mode 100644 include/graphics/SkColor.h create mode 100644 include/graphics/SkColorFilter.h create mode 100644 include/graphics/SkColorPriv.h create mode 100644 include/graphics/SkCornerPathEffect.h create mode 100644 include/graphics/SkCullPoints.h create mode 100644 include/graphics/SkDOM.h create mode 100644 include/graphics/SkDashPathEffect.h create mode 100644 include/graphics/SkDeque.h create mode 100644 include/graphics/SkDescriptor.h create mode 100644 include/graphics/SkDiscretePathEffect.h create mode 100755 include/graphics/SkDrawExtraPathEffect.h create mode 100644 include/graphics/SkEmbossMaskFilter.h create mode 100644 include/graphics/SkEvent.h create mode 100644 include/graphics/SkEventSink.h create mode 100644 include/graphics/SkFlattenable.h create mode 100644 include/graphics/SkFontCodec.h create mode 100644 include/graphics/SkFontHost.h create mode 100644 include/graphics/SkGlobals.h create mode 100644 include/graphics/SkGradientShader.h create mode 100644 include/graphics/SkGraphics.h create mode 100644 include/graphics/SkImageDecoder.h create mode 100644 include/graphics/SkImageView.h create mode 100644 include/graphics/SkInterpolator.h create mode 100644 include/graphics/SkJS.h create mode 100644 include/graphics/SkKey.h create mode 100644 include/graphics/SkLayerRasterizer.h create mode 100644 include/graphics/SkMask.h create mode 100644 include/graphics/SkMaskFilter.h create mode 100644 include/graphics/SkMetaData.h create mode 100644 include/graphics/SkNinePatch.h create mode 100644 include/graphics/SkOSFile.h create mode 100644 include/graphics/SkOSMenu.h create mode 100644 include/graphics/SkOSSound.h create mode 100644 include/graphics/SkOSWindow_Mac.h create mode 100644 include/graphics/SkOSWindow_Unix.h create mode 100644 include/graphics/SkOSWindow_Win.h create mode 100644 include/graphics/SkOSWindow_wxwidgets.h create mode 100644 include/graphics/SkPaint.h create mode 100644 include/graphics/SkParse.h create mode 100644 include/graphics/SkParsePaint.h create mode 100644 include/graphics/SkPath.h create mode 100644 include/graphics/SkPathEffect.h create mode 100644 include/graphics/SkPathMeasure.h create mode 100644 include/graphics/SkPorterDuff.h create mode 100644 include/graphics/SkPrefix_Debug_Fixed.h create mode 100644 include/graphics/SkPrefix_Release_Fixed.h create mode 100644 include/graphics/SkProgressBarView.h create mode 100644 include/graphics/SkRasterizer.h create mode 100644 include/graphics/SkRefCnt.h create mode 100644 include/graphics/SkSVGAttribute.h create mode 100644 include/graphics/SkSVGBase.h create mode 100644 include/graphics/SkSVGPaintState.h create mode 100644 include/graphics/SkSVGParser.h create mode 100644 include/graphics/SkSVGTypes.h create mode 100644 include/graphics/SkScalerContext.h create mode 100644 include/graphics/SkScrollBarView.h create mode 100644 include/graphics/SkShader.h create mode 100644 include/graphics/SkShaderExtras.h create mode 100644 include/graphics/SkStackViewLayout.h create mode 100644 include/graphics/SkStdLib_Redirect.h create mode 100644 include/graphics/SkStream.h create mode 100644 include/graphics/SkStream_Win.h create mode 100644 include/graphics/SkString.h create mode 100644 include/graphics/SkStroke.h create mode 100644 include/graphics/SkSystemEventTypes.h create mode 100644 include/graphics/SkTDArray.h create mode 100644 include/graphics/SkTDStack.h create mode 100644 include/graphics/SkTDict.h create mode 100644 include/graphics/SkTSearch.h create mode 100644 include/graphics/SkTextBox.h create mode 100644 include/graphics/SkTextLayout.h create mode 100644 include/graphics/SkTime.h create mode 100644 include/graphics/SkTransparentShader.h create mode 100644 include/graphics/SkTypeface.h create mode 100644 include/graphics/SkUnitMapper.h create mode 100644 include/graphics/SkUtils.h create mode 100644 include/graphics/SkView.h create mode 100644 include/graphics/SkViewInflate.h create mode 100644 include/graphics/SkWidget.h create mode 100644 include/graphics/SkWidgetViews.h create mode 100644 include/graphics/SkWindow.h create mode 100644 include/graphics/SkXMLParser.h create mode 100644 include/graphics/SkXMLWriter.h create mode 100644 include/graphics/SkXfermode.h create mode 100644 libs/corecg/Makefile create mode 100644 libs/corecg/Sk64.cpp create mode 100644 libs/corecg/SkBuffer.cpp create mode 100644 libs/corecg/SkChunkAlloc.cpp create mode 100644 libs/corecg/SkCordic.cpp create mode 100644 libs/corecg/SkCordic.h create mode 100644 libs/corecg/SkDebug.cpp create mode 100644 libs/corecg/SkDebug_stdio.cpp create mode 100644 libs/corecg/SkFP.h create mode 100644 libs/corecg/SkFloat.cpp create mode 100644 libs/corecg/SkFloat.h create mode 100644 libs/corecg/SkMath.cpp create mode 100644 libs/corecg/SkMatrix.cpp create mode 100644 libs/corecg/SkMemory_stdlib.cpp create mode 100644 libs/corecg/SkPoint.cpp create mode 100644 libs/corecg/SkRect.cpp create mode 100644 libs/corecg/SkRegion.cpp create mode 100644 libs/corecg/SkRegionPriv.h create mode 100644 libs/corecg/SkSinTable.h create mode 100644 libs/corecg/SkTSort.h create mode 100644 libs/graphics/Makefile create mode 100644 libs/graphics/animator/SkAnimate.h create mode 100644 libs/graphics/animator/SkAnimate3DSchema.xsd create mode 100644 libs/graphics/animator/SkAnimate3DSchema.xsx create mode 100644 libs/graphics/animator/SkAnimateActive.cpp create mode 100644 libs/graphics/animator/SkAnimateActive.h create mode 100644 libs/graphics/animator/SkAnimateBase.cpp create mode 100644 libs/graphics/animator/SkAnimateBase.h create mode 100644 libs/graphics/animator/SkAnimateField.cpp create mode 100644 libs/graphics/animator/SkAnimateMaker.cpp create mode 100644 libs/graphics/animator/SkAnimateMaker.h create mode 100644 libs/graphics/animator/SkAnimateProperties.h create mode 100644 libs/graphics/animator/SkAnimateSchema.xsd create mode 100644 libs/graphics/animator/SkAnimateSchema.xsx create mode 100644 libs/graphics/animator/SkAnimateSet.cpp create mode 100644 libs/graphics/animator/SkAnimateSet.h create mode 100644 libs/graphics/animator/SkAnimator.cpp create mode 100644 libs/graphics/animator/SkAnimatorScript.cpp create mode 100644 libs/graphics/animator/SkAnimatorScript.h create mode 100755 libs/graphics/animator/SkAnimatorScript2.cpp create mode 100755 libs/graphics/animator/SkAnimatorScript2.h create mode 100644 libs/graphics/animator/SkBase64.cpp create mode 100644 libs/graphics/animator/SkBase64.h create mode 100644 libs/graphics/animator/SkBoundable.cpp create mode 100644 libs/graphics/animator/SkBoundable.h create mode 100644 libs/graphics/animator/SkBuildCondensedInfo.cpp create mode 100644 libs/graphics/animator/SkCondensedDebug.cpp create mode 100644 libs/graphics/animator/SkCondensedRelease.cpp create mode 100644 libs/graphics/animator/SkDisplayAdd.cpp create mode 100644 libs/graphics/animator/SkDisplayAdd.h create mode 100644 libs/graphics/animator/SkDisplayApply.cpp create mode 100644 libs/graphics/animator/SkDisplayApply.h create mode 100644 libs/graphics/animator/SkDisplayBounds.cpp create mode 100644 libs/graphics/animator/SkDisplayBounds.h create mode 100644 libs/graphics/animator/SkDisplayEvent.cpp create mode 100644 libs/graphics/animator/SkDisplayEvent.h create mode 100644 libs/graphics/animator/SkDisplayEvents.cpp create mode 100644 libs/graphics/animator/SkDisplayEvents.h create mode 100644 libs/graphics/animator/SkDisplayInclude.cpp create mode 100644 libs/graphics/animator/SkDisplayInclude.h create mode 100644 libs/graphics/animator/SkDisplayInput.cpp create mode 100644 libs/graphics/animator/SkDisplayInput.h create mode 100644 libs/graphics/animator/SkDisplayList.cpp create mode 100644 libs/graphics/animator/SkDisplayList.h create mode 100644 libs/graphics/animator/SkDisplayMath.cpp create mode 100644 libs/graphics/animator/SkDisplayMath.h create mode 100644 libs/graphics/animator/SkDisplayMovie.cpp create mode 100644 libs/graphics/animator/SkDisplayMovie.h create mode 100644 libs/graphics/animator/SkDisplayNumber.cpp create mode 100644 libs/graphics/animator/SkDisplayNumber.h create mode 100644 libs/graphics/animator/SkDisplayPost.cpp create mode 100644 libs/graphics/animator/SkDisplayPost.h create mode 100644 libs/graphics/animator/SkDisplayRandom.cpp create mode 100644 libs/graphics/animator/SkDisplayRandom.h create mode 100644 libs/graphics/animator/SkDisplayScreenplay.cpp create mode 100644 libs/graphics/animator/SkDisplayScreenplay.h create mode 100644 libs/graphics/animator/SkDisplayType.cpp create mode 100644 libs/graphics/animator/SkDisplayType.h create mode 100644 libs/graphics/animator/SkDisplayTypes.cpp create mode 100644 libs/graphics/animator/SkDisplayTypes.h create mode 100644 libs/graphics/animator/SkDisplayXMLParser.cpp create mode 100644 libs/graphics/animator/SkDisplayXMLParser.h create mode 100644 libs/graphics/animator/SkDisplayable.cpp create mode 100644 libs/graphics/animator/SkDisplayable.h create mode 100644 libs/graphics/animator/SkDraw3D.cpp create mode 100644 libs/graphics/animator/SkDraw3D.h create mode 100644 libs/graphics/animator/SkDrawBitmap.cpp create mode 100644 libs/graphics/animator/SkDrawBitmap.h create mode 100644 libs/graphics/animator/SkDrawBlur.cpp create mode 100644 libs/graphics/animator/SkDrawBlur.h create mode 100644 libs/graphics/animator/SkDrawClip.cpp create mode 100644 libs/graphics/animator/SkDrawClip.h create mode 100644 libs/graphics/animator/SkDrawColor.cpp create mode 100644 libs/graphics/animator/SkDrawColor.h create mode 100644 libs/graphics/animator/SkDrawDash.cpp create mode 100644 libs/graphics/animator/SkDrawDash.h create mode 100644 libs/graphics/animator/SkDrawDiscrete.cpp create mode 100644 libs/graphics/animator/SkDrawDiscrete.h create mode 100644 libs/graphics/animator/SkDrawEmboss.cpp create mode 100644 libs/graphics/animator/SkDrawEmboss.h create mode 100644 libs/graphics/animator/SkDrawExtraPathEffect.cpp create mode 100644 libs/graphics/animator/SkDrawFull.cpp create mode 100644 libs/graphics/animator/SkDrawFull.h create mode 100644 libs/graphics/animator/SkDrawGradient.cpp create mode 100644 libs/graphics/animator/SkDrawGradient.h create mode 100644 libs/graphics/animator/SkDrawGroup.cpp create mode 100644 libs/graphics/animator/SkDrawGroup.h create mode 100644 libs/graphics/animator/SkDrawLine.cpp create mode 100644 libs/graphics/animator/SkDrawLine.h create mode 100644 libs/graphics/animator/SkDrawMatrix.cpp create mode 100644 libs/graphics/animator/SkDrawMatrix.h create mode 100644 libs/graphics/animator/SkDrawOval.cpp create mode 100644 libs/graphics/animator/SkDrawOval.h create mode 100644 libs/graphics/animator/SkDrawPaint.cpp create mode 100644 libs/graphics/animator/SkDrawPaint.h create mode 100644 libs/graphics/animator/SkDrawPath.cpp create mode 100644 libs/graphics/animator/SkDrawPath.h create mode 100644 libs/graphics/animator/SkDrawPoint.cpp create mode 100644 libs/graphics/animator/SkDrawPoint.h create mode 100644 libs/graphics/animator/SkDrawRectangle.cpp create mode 100644 libs/graphics/animator/SkDrawRectangle.h create mode 100644 libs/graphics/animator/SkDrawSaveLayer.cpp create mode 100644 libs/graphics/animator/SkDrawSaveLayer.h create mode 100644 libs/graphics/animator/SkDrawShader.cpp create mode 100644 libs/graphics/animator/SkDrawShader.h create mode 100644 libs/graphics/animator/SkDrawText.cpp create mode 100644 libs/graphics/animator/SkDrawText.h create mode 100644 libs/graphics/animator/SkDrawTextBox.cpp create mode 100644 libs/graphics/animator/SkDrawTextBox.h create mode 100644 libs/graphics/animator/SkDrawTo.cpp create mode 100644 libs/graphics/animator/SkDrawTo.h create mode 100644 libs/graphics/animator/SkDrawTransparentShader.cpp create mode 100644 libs/graphics/animator/SkDrawTransparentShader.h create mode 100644 libs/graphics/animator/SkDrawable.cpp create mode 100644 libs/graphics/animator/SkDrawable.h create mode 100644 libs/graphics/animator/SkDump.cpp create mode 100644 libs/graphics/animator/SkDump.h create mode 100644 libs/graphics/animator/SkExtraPathEffects.xsd create mode 100644 libs/graphics/animator/SkExtras.h create mode 100644 libs/graphics/animator/SkGetCondensedInfo.cpp create mode 100644 libs/graphics/animator/SkHitClear.cpp create mode 100644 libs/graphics/animator/SkHitClear.h create mode 100644 libs/graphics/animator/SkHitTest.cpp create mode 100644 libs/graphics/animator/SkHitTest.h create mode 100644 libs/graphics/animator/SkIntArray.h create mode 100644 libs/graphics/animator/SkInterpolator.cpp create mode 100644 libs/graphics/animator/SkMatrixParts.cpp create mode 100644 libs/graphics/animator/SkMatrixParts.h create mode 100644 libs/graphics/animator/SkMemberInfo.cpp create mode 100644 libs/graphics/animator/SkMemberInfo.h create mode 100755 libs/graphics/animator/SkOpArray.cpp create mode 100755 libs/graphics/animator/SkOpArray.h create mode 100644 libs/graphics/animator/SkOperand.h create mode 100755 libs/graphics/animator/SkOperand2.h create mode 100644 libs/graphics/animator/SkOperandInterpolator.h create mode 100644 libs/graphics/animator/SkOperandIterpolator.cpp create mode 100644 libs/graphics/animator/SkPaintParts.cpp create mode 100644 libs/graphics/animator/SkPaintParts.h create mode 100644 libs/graphics/animator/SkPathParts.cpp create mode 100644 libs/graphics/animator/SkPathParts.h create mode 100644 libs/graphics/animator/SkPostParts.cpp create mode 100644 libs/graphics/animator/SkPostParts.h create mode 100644 libs/graphics/animator/SkSVGPath.cpp create mode 100644 libs/graphics/animator/SkScript.cpp create mode 100644 libs/graphics/animator/SkScript.h create mode 100755 libs/graphics/animator/SkScript2.h create mode 100755 libs/graphics/animator/SkScriptCallBack.h create mode 100644 libs/graphics/animator/SkScriptDecompile.cpp create mode 100755 libs/graphics/animator/SkScriptRuntime.cpp create mode 100755 libs/graphics/animator/SkScriptRuntime.h create mode 100755 libs/graphics/animator/SkScriptTokenizer.cpp create mode 100644 libs/graphics/animator/SkSnapshot.cpp create mode 100644 libs/graphics/animator/SkSnapshot.h create mode 100644 libs/graphics/animator/SkTDArray_Experimental.h create mode 100644 libs/graphics/animator/SkTextOnPath.cpp create mode 100644 libs/graphics/animator/SkTextOnPath.h create mode 100644 libs/graphics/animator/SkTextToPath.cpp create mode 100644 libs/graphics/animator/SkTextToPath.h create mode 100644 libs/graphics/animator/SkTime.cpp create mode 100644 libs/graphics/animator/SkTypedArray.cpp create mode 100644 libs/graphics/animator/SkTypedArray.h create mode 100644 libs/graphics/animator/SkXMLAnimatorWriter.cpp create mode 100644 libs/graphics/animator/SkXMLAnimatorWriter.h create mode 100644 libs/graphics/animator/thingstodo.txt create mode 100644 libs/graphics/effects/Sk1DPathEffect.cpp create mode 100644 libs/graphics/effects/Sk2DPathEffect.cpp create mode 100644 libs/graphics/effects/SkAvoidXfermode.cpp create mode 100644 libs/graphics/effects/SkBlurMask.cpp create mode 100644 libs/graphics/effects/SkBlurMask.h create mode 100644 libs/graphics/effects/SkBlurMaskFilter.cpp create mode 100644 libs/graphics/effects/SkCamera.cpp create mode 100644 libs/graphics/effects/SkColorFilters.cpp create mode 100644 libs/graphics/effects/SkCornerPathEffect.cpp create mode 100644 libs/graphics/effects/SkCullPoints.cpp create mode 100644 libs/graphics/effects/SkDashPathEffect.cpp create mode 100644 libs/graphics/effects/SkDiscretePathEffect.cpp create mode 100644 libs/graphics/effects/SkEmbossMask.cpp create mode 100644 libs/graphics/effects/SkEmbossMask.h create mode 100644 libs/graphics/effects/SkEmbossMaskFilter.cpp create mode 100644 libs/graphics/effects/SkEmbossMask_Table.h create mode 100644 libs/graphics/effects/SkGradientShader.cpp create mode 100644 libs/graphics/effects/SkLayerRasterizer.cpp create mode 100644 libs/graphics/effects/SkNinePatch.cpp create mode 100644 libs/graphics/effects/SkRadialGradient_Table.h create mode 100644 libs/graphics/effects/SkShaderExtras.cpp create mode 100644 libs/graphics/effects/SkTransparentShader.cpp create mode 100644 libs/graphics/images/SkBitmapRef.cpp create mode 100644 libs/graphics/images/SkBitmapRefPriv.h create mode 100644 libs/graphics/images/SkImageDecoder.cpp create mode 100644 libs/graphics/images/SkImageDecoder_libgif.cpp create mode 100644 libs/graphics/images/SkImageDecoder_libjpeg.cpp create mode 100644 libs/graphics/images/SkImageDecoder_libpng.cpp create mode 100644 libs/graphics/images/SkStream.cpp create mode 100644 libs/graphics/ports/SkFontHost.cpp create mode 100644 libs/graphics/ports/SkFontHost_FONTPATH.cpp create mode 100644 libs/graphics/ports/SkFontHost_FreeType.cpp create mode 100644 libs/graphics/ports/SkFontHost_none.cpp create mode 100644 libs/graphics/ports/SkGlobals_global.cpp create mode 100644 libs/graphics/ports/SkImageDecoder_Factory.cpp create mode 100644 libs/graphics/ports/SkOSEvent_android.cpp create mode 100644 libs/graphics/ports/SkOSEvent_dummy.cpp create mode 100644 libs/graphics/ports/SkOSFile_stdio.cpp create mode 100644 libs/graphics/ports/SkThread_none.cpp create mode 100644 libs/graphics/ports/SkTime_Unix.cpp create mode 100644 libs/graphics/ports/SkXMLParser_empty.cpp create mode 100644 libs/graphics/ports/SkXMLParser_expat.cpp create mode 100644 libs/graphics/ports/SkXMLParser_tinyxml.cpp create mode 100644 libs/graphics/sgl/SkAlphaRuns.cpp create mode 100644 libs/graphics/sgl/SkAntiRun.h create mode 100644 libs/graphics/sgl/SkBitmap.cpp create mode 100644 libs/graphics/sgl/SkBitmapSampler.cpp create mode 100644 libs/graphics/sgl/SkBitmapSampler.h create mode 100644 libs/graphics/sgl/SkBitmapSamplerTemplate.h create mode 100644 libs/graphics/sgl/SkBitmapShader.cpp create mode 100644 libs/graphics/sgl/SkBitmapShader.h create mode 100644 libs/graphics/sgl/SkBitmapShader16BilerpTemplate.h create mode 100644 libs/graphics/sgl/SkBitmapShaderTemplate.h create mode 100644 libs/graphics/sgl/SkBlitBWMaskTemplate.h create mode 100644 libs/graphics/sgl/SkBlitter.cpp create mode 100644 libs/graphics/sgl/SkBlitter.h create mode 100644 libs/graphics/sgl/SkBlitter_A1.cpp create mode 100644 libs/graphics/sgl/SkBlitter_A8.cpp create mode 100644 libs/graphics/sgl/SkBlitter_ARGB32.cpp create mode 100644 libs/graphics/sgl/SkBlitter_RGB16.cpp create mode 100644 libs/graphics/sgl/SkBlitter_Sprite.cpp create mode 100644 libs/graphics/sgl/SkCanvas.cpp create mode 100644 libs/graphics/sgl/SkColor.cpp create mode 100644 libs/graphics/sgl/SkColorFilter.cpp create mode 100644 libs/graphics/sgl/SkColorTable.cpp create mode 100644 libs/graphics/sgl/SkCoreBlitters.h create mode 100644 libs/graphics/sgl/SkDeque.cpp create mode 100644 libs/graphics/sgl/SkDraw.cpp create mode 100644 libs/graphics/sgl/SkDraw.h create mode 100644 libs/graphics/sgl/SkEdge.cpp create mode 100644 libs/graphics/sgl/SkEdge.h create mode 100644 libs/graphics/sgl/SkFP.h create mode 100644 libs/graphics/sgl/SkFilterProc.cpp create mode 100644 libs/graphics/sgl/SkFilterProc.h create mode 100644 libs/graphics/sgl/SkGeometry.cpp create mode 100644 libs/graphics/sgl/SkGeometry.h create mode 100644 libs/graphics/sgl/SkGlobals.cpp create mode 100644 libs/graphics/sgl/SkGlyphCache.cpp create mode 100644 libs/graphics/sgl/SkGlyphCache.h create mode 100644 libs/graphics/sgl/SkGraphics.cpp create mode 100644 libs/graphics/sgl/SkMaskFilter.cpp create mode 100644 libs/graphics/sgl/SkPaint.cpp create mode 100644 libs/graphics/sgl/SkPath.cpp create mode 100644 libs/graphics/sgl/SkPathEffect.cpp create mode 100644 libs/graphics/sgl/SkPathMeasure.cpp create mode 100644 libs/graphics/sgl/SkProcSpriteBlitter.cpp create mode 100644 libs/graphics/sgl/SkRasterizer.cpp create mode 100644 libs/graphics/sgl/SkRefCnt.cpp create mode 100644 libs/graphics/sgl/SkRegion_path.cpp create mode 100644 libs/graphics/sgl/SkScalerContext.cpp create mode 100644 libs/graphics/sgl/SkScan.cpp create mode 100644 libs/graphics/sgl/SkScan.h create mode 100644 libs/graphics/sgl/SkScanPriv.h create mode 100644 libs/graphics/sgl/SkScan_AntiPath.cpp create mode 100644 libs/graphics/sgl/SkScan_Antihair.cpp create mode 100644 libs/graphics/sgl/SkScan_Hairline.cpp create mode 100644 libs/graphics/sgl/SkScan_Path.cpp create mode 100644 libs/graphics/sgl/SkShader.cpp create mode 100644 libs/graphics/sgl/SkSinTable.h create mode 100644 libs/graphics/sgl/SkSpriteBlitter.h create mode 100644 libs/graphics/sgl/SkSpriteBlitterTemplate.h create mode 100644 libs/graphics/sgl/SkSpriteBlitter_ARGB32.cpp create mode 100644 libs/graphics/sgl/SkSpriteBlitter_RGB16.cpp create mode 100644 libs/graphics/sgl/SkString.cpp create mode 100644 libs/graphics/sgl/SkStroke.cpp create mode 100644 libs/graphics/sgl/SkStrokerPriv.cpp create mode 100644 libs/graphics/sgl/SkStrokerPriv.h create mode 100644 libs/graphics/sgl/SkTSearch.cpp create mode 100644 libs/graphics/sgl/SkTSort.h create mode 100644 libs/graphics/sgl/SkTemplatesPriv.h create mode 100644 libs/graphics/sgl/SkTextLayout.cpp create mode 100644 libs/graphics/sgl/SkUtils.cpp create mode 100644 libs/graphics/sgl/SkXfermode.cpp create mode 100644 libs/graphics/svg/SkSVG.cpp create mode 100644 libs/graphics/svg/SkSVGCircle.cpp create mode 100644 libs/graphics/svg/SkSVGCircle.h create mode 100644 libs/graphics/svg/SkSVGClipPath.cpp create mode 100644 libs/graphics/svg/SkSVGClipPath.h create mode 100644 libs/graphics/svg/SkSVGDefs.cpp create mode 100644 libs/graphics/svg/SkSVGDefs.h create mode 100644 libs/graphics/svg/SkSVGElements.cpp create mode 100644 libs/graphics/svg/SkSVGElements.h create mode 100644 libs/graphics/svg/SkSVGEllipse.cpp create mode 100644 libs/graphics/svg/SkSVGEllipse.h create mode 100644 libs/graphics/svg/SkSVGFeColorMatrix.cpp create mode 100644 libs/graphics/svg/SkSVGFeColorMatrix.h create mode 100644 libs/graphics/svg/SkSVGFilter.cpp create mode 100644 libs/graphics/svg/SkSVGFilter.h create mode 100644 libs/graphics/svg/SkSVGG.cpp create mode 100644 libs/graphics/svg/SkSVGG.h create mode 100644 libs/graphics/svg/SkSVGGradient.cpp create mode 100644 libs/graphics/svg/SkSVGGradient.h create mode 100644 libs/graphics/svg/SkSVGGroup.cpp create mode 100644 libs/graphics/svg/SkSVGGroup.h create mode 100644 libs/graphics/svg/SkSVGImage.cpp create mode 100644 libs/graphics/svg/SkSVGImage.h create mode 100644 libs/graphics/svg/SkSVGLine.cpp create mode 100644 libs/graphics/svg/SkSVGLine.h create mode 100644 libs/graphics/svg/SkSVGLinearGradient.cpp create mode 100644 libs/graphics/svg/SkSVGLinearGradient.h create mode 100644 libs/graphics/svg/SkSVGMask.cpp create mode 100644 libs/graphics/svg/SkSVGMask.h create mode 100644 libs/graphics/svg/SkSVGMetadata.cpp create mode 100644 libs/graphics/svg/SkSVGMetadata.h create mode 100644 libs/graphics/svg/SkSVGPaintState.cpp create mode 100644 libs/graphics/svg/SkSVGParser.cpp create mode 100644 libs/graphics/svg/SkSVGPath.cpp create mode 100644 libs/graphics/svg/SkSVGPath.h create mode 100644 libs/graphics/svg/SkSVGPolygon.cpp create mode 100644 libs/graphics/svg/SkSVGPolygon.h create mode 100644 libs/graphics/svg/SkSVGPolyline.cpp create mode 100644 libs/graphics/svg/SkSVGPolyline.h create mode 100644 libs/graphics/svg/SkSVGRadialGradient.cpp create mode 100644 libs/graphics/svg/SkSVGRadialGradient.h create mode 100644 libs/graphics/svg/SkSVGRect.cpp create mode 100644 libs/graphics/svg/SkSVGRect.h create mode 100644 libs/graphics/svg/SkSVGSVG.cpp create mode 100644 libs/graphics/svg/SkSVGSVG.h create mode 100644 libs/graphics/svg/SkSVGStop.cpp create mode 100644 libs/graphics/svg/SkSVGStop.h create mode 100644 libs/graphics/svg/SkSVGSymbol.cpp create mode 100644 libs/graphics/svg/SkSVGSymbol.h create mode 100644 libs/graphics/svg/SkSVGText.cpp create mode 100644 libs/graphics/svg/SkSVGText.h create mode 100644 libs/graphics/svg/SkSVGUse.cpp create mode 100644 libs/graphics/svg/SkSVGUse.h create mode 100644 libs/graphics/text/ATextEntry.h create mode 100644 libs/graphics/views/SkEvent.cpp create mode 100644 libs/graphics/views/SkEventSink.cpp create mode 100644 libs/graphics/views/SkMetaData.cpp create mode 100644 libs/graphics/views/SkTagList.cpp create mode 100644 libs/graphics/views/SkTagList.h create mode 100644 libs/graphics/views/SkTextBox.cpp create mode 100644 libs/graphics/xml/SkBML_Verbs.h create mode 100644 libs/graphics/xml/SkBML_XMLParser.cpp create mode 100644 libs/graphics/xml/SkDOM.cpp create mode 100644 libs/graphics/xml/SkJS.cpp create mode 100644 libs/graphics/xml/SkJSDisplayable.cpp create mode 100644 libs/graphics/xml/SkParse.cpp create mode 100644 libs/graphics/xml/SkParseColor.cpp create mode 100644 libs/graphics/xml/SkXMLParser.cpp create mode 100644 libs/graphics/xml/SkXMLWriter.cpp diff --git a/include/corecg/Sk64.h b/include/corecg/Sk64.h new file mode 100644 index 000000000..ed67b1f8f --- /dev/null +++ b/include/corecg/Sk64.h @@ -0,0 +1,219 @@ +#ifndef Sk64_DEFINED +#define Sk64_DEFINED + +#include "SkMath.h" + +/** \class Sk64 + + Sk64 is a 64-bit math package that does not require long long support from the compiler. +*/ +struct 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 sign() 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); + + SkFixed addGetFixed(const Sk64& other) const + { + return this->addGetFixed(other.fHi, other.fLo); + } + 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 + (1 << 15); + + hi = fHi + hi + (sum < fLo); + 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 SK_CAN_USE_LONGLONG + SkLONGLONG getLongLong() const; +#endif + +#ifdef SK_DEBUG + /** @cond UNIT_TEST */ + static void UnitTest(); + /** @endcond */ +#endif +}; + +#endif + + diff --git a/include/corecg/SkBuffer.h b/include/corecg/SkBuffer.h new file mode 100644 index 000000000..cd670fc67 --- /dev/null +++ b/include/corecg/SkBuffer.h @@ -0,0 +1,135 @@ +#ifndef SkBuffer_DEFINED +#define SkBuffer_DEFINED + +#include "SkScalar.h" + +/** \class SkRBuffer + + Light weight class for reading data from a memory block. + The RBuffer is given the buffer to read from, with either a specified size + or no size (in which case no range checking is performed). It is iillegal + to attempt to read a value from an empty RBuffer (data == null). +*/ +class SkRBuffer { +public: + SkRBuffer() : fData(0), fPos(0), fStop(0) {} + /** Initialize RBuffer with a data pointer, but no specified length. + This signals the RBuffer to not perform range checks during reading. + */ + SkRBuffer(const void* data) + { + fData = (const char*)data; + fPos = (const char*)data; + fStop = 0; // no bounds checking + } + /** Initialize RBuffer with a data point and length. + */ + SkRBuffer(const void* data, size_t size) + { + SkASSERT(data != 0 || size == 0); + fData = (const char*)data; + fPos = (const char*)data; + fStop = (const char*)data + size; + } + + /** Return the number of bytes that have been read from the beginning + of the data pointer. + */ + size_t pos() const { return fPos - fData; } + /** Return the total size of the data pointer. Only defined if the length was + specified in the constructor or in a call to reset(). + */ + size_t size() const { return fStop - fData; } + /** Return true if the buffer has read to the end of the data pointer. + Only defined if the length was specified in the constructor or in a call + to reset(). Always returns true if the length was not specified. + */ + bool eof() const { return fPos >= fStop; } + + /** Read the specified number of bytes from the data pointer. If buffer is not + null, copy those bytes into buffer. + */ + void read(void* buffer, size_t size) { if (size) this->readNoSizeCheck(buffer, size); } + size_t skipToAlign4(); + + void* readPtr() { void* ptr; read(&ptr, sizeof(ptr)); return ptr; } + SkScalar readScalar() { SkScalar x; read(&x, 4); return x; } + uint32_t readU32() { uint32_t x; read(&x, 4); return x; } + int32_t readS32() { int32_t x; read(&x, 4); return x; } + uint16_t readU16() { uint16_t x; read(&x, 2); return x; } + int16_t readS16() { int16_t x; read(&x, 2); return x; } + uint8_t readU8() { uint8_t x; read(&x, 1); return x; } + bool readBool() { return this->readU8() != 0; } + +private: + void readNoSizeCheck(void* buffer, size_t size); + + const char* fData; + const char* fPos; + const char* fStop; +}; + +/** \class SkWBuffer + + Light weight class for writing data to a memory block. + The WBuffer is given the buffer to write into, with either a specified size + or no size, in which case no range checking is performed. An empty WBuffer + is legal, in which case no data is ever written, but the relative pos() + is updated. +*/ +class SkWBuffer { +public: + SkWBuffer() : fData(0), fPos(0), fStop(0) {} + SkWBuffer(void* data) + { + fData = (char*)data; + fPos = (char*)data; + fStop = 0; // no bounds checking + } + SkWBuffer(void* data, size_t size) + { + SkASSERT(data != 0 || size == 0); + fData = (char*)data; + fPos = (char*)data; + fStop = (char*)data + size; + } + + void reset(void* data) + { + fData = (char*)data; + fPos = (char*)data; + fStop = 0; // no bounds checking + } + void reset(void* data, size_t size) + { + SkASSERT(data != 0 || size == 0); + fData = (char*)data; + fPos = (char*)data; + fStop = (char*)data + size; + } + + void* data() const { return fData; } + size_t pos() const { return fPos - fData; } + size_t size() const { return fStop - fData; } + bool eof() const { return fPos >= fStop; } + + void write(const void* buffer, size_t size) { if (size) this->writeNoSizeCheck(buffer, size); } + size_t padToAlign4(); + + void writePtr(const void* x) { this->writeNoSizeCheck(&x, sizeof(x)); } + void writeScalar(SkScalar x) { this->writeNoSizeCheck(&x, 4); } + void write32(int32_t x) { this->writeNoSizeCheck(&x, 4); } + void write16(int16_t x) { this->writeNoSizeCheck(&x, 2); } + void write8(int8_t x) { this->writeNoSizeCheck(&x, 1); } + void writeBool(bool x) { this->write8(x); } + +private: + void writeNoSizeCheck(const void* buffer, size_t size); + + char* fData; + char* fPos; + char* fStop; +}; + +#endif + diff --git a/include/corecg/SkChunkAlloc.h b/include/corecg/SkChunkAlloc.h new file mode 100644 index 000000000..3070af875 --- /dev/null +++ b/include/corecg/SkChunkAlloc.h @@ -0,0 +1,30 @@ +#ifndef SkChunkAlloc_DEFINED +#define SkChunkAlloc_DEFINED + +#include "SkTypes.h" + +class SkChunkAlloc { +public: + SkChunkAlloc(size_t minSize) : fBlock(nil), fMinSize(SkAlign4(minSize)) {} + ~SkChunkAlloc(); + + void reset(); + + enum AllocFailType { + kReturnNil_AllocFailType, + kThrow_AllocFailType + }; + void* alloc(size_t bytes, AllocFailType); + +private: + struct Block { + Block* fNext; + size_t fFreeSize; + char* fFreePtr; + // data[] follows + }; + Block* fBlock; + size_t fMinSize; +}; + +#endif diff --git a/include/corecg/SkEndian.h b/include/corecg/SkEndian.h new file mode 100644 index 000000000..845037c65 --- /dev/null +++ b/include/corecg/SkEndian.h @@ -0,0 +1,82 @@ +#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 +*/ +inline uint16_t SkEndianSwap16(U16CPU value) +{ + SkASSERT(value == (uint16_t)value); + return (uint16_t)((value >> 8) | (value << 8)); +} + +/** Vector version of SkEndianSwap16(), which swaps the + low two bytes of each value in the array. +*/ +inline void SkEndianSwap16s(uint16_t array[], int count) +{ + SkASSERT(count == 0 || array != nil); + + while (--count >= 0) + { + *array = SkEndianSwap16(*array); + array += 1; + } +} + +/** Reverse all 4 bytes in a 32bit value. + e.g. 0x12345678 -> 0x78563412 +*/ +inline uint32_t SkEndianSwap32(uint32_t value) +{ + return ((value & 0xFF) << 24) | + ((value & 0xFF00) << 8) | + ((value & 0xFF0000) >> 8) | + (value >> 24); +} + +/** Vector version of SkEndianSwap16(), which swaps the + bytes of each value in the array. +*/ +inline void SkEndianSwap32s(uint32_t array[], int count) +{ + SkASSERT(count == 0 || array != nil); + + while (--count >= 0) + { + *array = SkEndianSwap32(*array); + array += 1; + } +} + +#ifdef SK_CPU_LENDIAN + #define SkEndian_SwapBE16(n) SkEndianSwap16(n) + #define SkEndian_SwapBE32(n) SkEndianSwap32(n) + #define SkEndian_SwapLE16(n) (n) + #define SkEndian_SwapLE32(n) (n) +#else // SK_CPU_BENDIAN + #define SkEndian_SwapBE16(n) (n) + #define SkEndian_SwapBE32(n) (n) + #define SkEndian_SwapLE16(n) SkEndianSwap16(n) + #define SkEndian_SwapLE32(n) SkEndianSwap32(n) +#endif + + +#endif + diff --git a/include/corecg/SkFDot6.h b/include/corecg/SkFDot6.h new file mode 100644 index 000000000..838c3ba12 --- /dev/null +++ b/include/corecg/SkFDot6.h @@ -0,0 +1,51 @@ +#ifndef SkFDot6_DEFINED +#define SkFDot6_DEFINED + +#include "SkMath.h" + +typedef int32_t SkFDot6; + +#define SK_FDot61 (64) +#define SK_FDot6Half (32) + +#ifdef SK_DEBUG + inline SkFDot6 SkIntToFDot6(S16CPU x) + { + SkASSERT(SkToS16(x) == x); + return x << 6; + } +#else + #define SkIntToFDot6(x) ((x) << 6) +#endif + +#define SkFDot6Floor(x) ((x) >> 6) +#define SkFDot6Ceil(x) (((x) + 63) >> 6) +#define SkFDot6Round(x) (((x) + 32) >> 6) + +#define SkFixedToFDot6(x) ((x) >> 10) + +inline SkFixed SkFDot6ToFixed(SkFDot6 x) +{ + SkASSERT((x << 10 >> 10) == x); + + return x << 10; +} + +#ifdef SK_SCALAR_IS_FLOAT + #define SkScalarToFDot6(x) (SkFDot6)((x) * 64) +#else + #define SkScalarToFDot6(x) ((x) >> 10) +#endif + +inline SkFixed SkFDot6Div(SkFDot6 a, SkFDot6 b) +{ + SkASSERT(b != 0); + + if (a == (int16_t)a) + return (a << 16) / b; + else + return SkFixedDiv(a, b); +} + +#endif + diff --git a/include/corecg/SkFixed.h b/include/corecg/SkFixed.h new file mode 100644 index 000000000..ddb4a6f71 --- /dev/null +++ b/include/corecg/SkFixed.h @@ -0,0 +1,159 @@ +#ifndef SkFixed_DEFINED +#define SkFixed_DEFINED + +/** \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 (0x1) +#define SK_FixedNaN ((int) 0x80000000) +#define SK_FixedPI (0x3243F) +#define SK_FixedSqrt2 (92682) +#define SK_FixedTanPIOver8 (0x6A0A) +#define SK_FixedRoot2Over2 (0xB505) + +#ifdef SK_CAN_USE_FLOAT + #define SkFixedToFloat(x) ((x) * 1.5258789e-5f) + #define SkFloatToFixed(x) ((SkFixed)((x) * SK_Fixed1)) +#endif + +/** 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) + +#ifdef SK_CAN_USE_FLOAT + #define SkFractToFloat(x) ((float)(x) * 0.00000000093132257f) + #define SkFloatToFract(x) ((SkFract)((x) * SK_Fract1)) +#endif + +/** 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) +/** Round a SkFixed to an integer +*/ +#define SkFixedRound(x) (((x) + SK_FixedHalf) >> 16) +#define SkFixedCeil(x) (((x) + SK_Fixed1 - 1) >> 16) +#define SkFixedFloor(x) ((x) >> 16) +#define SkFixedAbs(x) SkAbs32(x) +#define SkFixedAve(a, b) (((a) + (b)) >> 1) + +#if defined(SK_BUILD_FOR_BREW) && !defined(AEE_SIMULATOR) + inline SkFixed SkFixedSquare(SkFixed a) + { + SkFixed answer; + asm volatile ( "SMULL r6, r7, %0, %0" : : "r"(a) : "r6", "r7" ); + asm volatile ( "MOV r6, r6, LSR #16" ); + asm volatile ( "ORR r6, r6, r7, LSL #16" ); + asm volatile ( "STR r6, %0" : "=m"(answer) ); + return answer; + } + inline SkFixed SkFixedMul(SkFixed a, SkFixed b) + { + SkFixed answer; + asm volatile ( "SMULL r6, r7, %0, %1" : : "r"(a), "r"(b) : "r6", "r7" ); + asm volatile ( "MOV r6, r6, LSR #16" ); + asm volatile ( "ORR r6, r6, r7, LSL #16" ); + asm volatile ( "STR r6, %0" : "=m"(answer) ); + return answer; + } + inline SkFract SkFractMul(SkFract a, SkFract b) + { + SkFract answer; + asm volatile ( "SMULL r6, r7, %0, %1" : : "r"(a), "r"(b) : "r6", "r7" ); + asm volatile ( "MOV r6, r6, LSR #30" ); + asm volatile ( "ORR r6, r6, r7, LSL #2" ); + asm volatile ( "STR r6, %0" : "=m"(answer) ); + return answer; + } +#else + inline SkFixed SkFixedSquare(SkFixed value) + { + uint32_t a = SkAbs32(value); + uint32_t ah = a >> 16; + uint32_t al = a & 0xFFFF; + return ah * a + al * ah + (al * al >> 16); + } + SkFixed SkFixedMul(SkFixed, SkFixed); + SkFract SkFractMul(SkFract, SkFract); +#endif +#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) +#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* cosValueOrNil); +#define SkFixedSin(radians) SkFixedSinCos(radians, nil) +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; +} + +#endif + diff --git a/include/corecg/SkFloatingPoint.h b/include/corecg/SkFloatingPoint.h new file mode 100644 index 000000000..984108620 --- /dev/null +++ b/include/corecg/SkFloatingPoint.h @@ -0,0 +1,44 @@ +#ifndef SkFloatingPoint_DEFINED +#define SkFloatingPoint_DEFINED + +#include "SkTypes.h" + +#ifdef SK_CAN_USE_FLOAT + +#include +#include + +#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) +#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) +#ifdef SK_BUILD_FOR_MAC + #define sk_float_acos(x) acos(x) + #define sk_float_asin(x) 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) + #define sk_float_isNaN(x) _isnan(x) +#endif + +#endif +#endif diff --git a/include/corecg/SkMath.h b/include/corecg/SkMath.h new file mode 100644 index 000000000..9657f7120 --- /dev/null +++ b/include/corecg/SkMath.h @@ -0,0 +1,132 @@ +#ifndef SkMath_DEFINED +#define SkMath_DEFINED + +#include "SkTypes.h" + +/** \file SkMath.h + + This file defines various math types and functions. It also introduces + SkScalar, the type used to describe fractional values and coordinates. + SkScalar is defined at compile time to be either an IEEE float, or a + 16.16 fixed point integer. Various macros and functions in SkMath.h + allow arithmetic operations to be performed on SkScalars without known + which representation is being used. e.g. SkScalarMul(a, b) multiplies + two SkScalar values, and returns a SkScalar, and this works with either + float or fixed implementations. +*/ + +//#if defined(SK_BUILD_FOR_BREW) && !defined(AEE_SIMULATOR) +#if 0 + inline int SkCLZ(uint32_t value) + { + int answer; + asm volatile ( "CLZ r6, %0" : : "r"(value) : "r6" ); + asm volatile ( "STR r6, %0" : "=m"(answer) ); + return answer; + } +#else + int SkCLZ(uint32_t); //> 31) + +/** If sign == -1, returns -n, else sign must be 0, and returns n. + Typically used in conjunction with SkExtractSign(). +*/ +inline int32_t SkApplySign(int32_t n, int32_t sign) +{ + SkASSERT(sign == 0 || sign == -1); + return (n ^ sign) - sign; +} + +/** Returns max(value, 0) +*/ +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. + Note: only works as long as max - value doesn't wrap around + @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 +*/ +inline int SkClampMax(int value, int max) +{ + // ensure that max is positive + SkASSERT(max >= 0); + // ensure that if value is negative, max - value doesn't wrap around + SkASSERT(value >= 0 || max - value > 0); + +#ifdef SK_CPU_HAS_CONDITIONAL_INSTR + if (value < 0) + value = 0; + if (value > max) + value = max; + return value; +#else + + int diff = max - value; + // clear diff if diff is positive + diff &= diff >> 31; + + // clear the result if value < 0 + return (value + diff) & ~(value >> 31); +#endif +} + +/** Given a positive value and a positive max, return the value + pinned against max. + Note: only works as long as max - value doesn't wrap around + @return max if value >= max, else value +*/ +inline unsigned SkClampUMax(unsigned value, unsigned max) +{ +#ifdef SK_CPU_HAS_CONDITIONAL_INSTR + if (value > max) + value = max; + return value; +#else + int diff = max - value; + // clear diff if diff is positive + diff &= diff >> 31; + + return value + diff; +#endif +} + +#include "SkFixed.h" +#include "SkScalar.h" + +#ifdef SK_DEBUG + class SkMath { + public: + static void UnitTest(); + }; +#endif + +#endif + diff --git a/include/corecg/SkMatrix.h b/include/corecg/SkMatrix.h new file mode 100644 index 000000000..26fdb294c --- /dev/null +++ b/include/corecg/SkMatrix.h @@ -0,0 +1,298 @@ +#ifndef SkMatrix_DEFINED +#define SkMatrix_DEFINED + +#include "SkRect.h" + +/** \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 SkMatrix { +public: + /** Bit fields used to identify the characteristics of the matrix. + See TypeMask for the corresponding mask values. + */ + enum TypeShift { + kTranslate_Shift, + kScale_Shift, + kAffine_Shift, + kPerspective_Shift, + + kShiftCount + }; + + /** Enum of bit fields for the mask return by getType(). + Use this to identify the complexity of the matrix. + */ + enum TypeMask { + kIdentity_Mask = 0, //!< type is 0 iff the matrix is the identiy + kTranslate_Mask = 1 << kTranslate_Shift, //!< set if the matrix has non-zero translation + kScale_Mask = 1 << kScale_Shift, //!< set if the matrix has X or Y scale different from 1.0 + kAffine_Mask = 1 << kAffine_Shift, //!< set if the matrix skews or rotates + kPerspective_Mask = 1 << kPerspective_Shift //!< set if the matrix is in perspective + }; + + /** Returns true if the mask represents a matrix that will only scale + or translate (i.e., will map a rectangle into another rectangle). + */ + static bool RectStaysRect(TypeMask mask) + { + return (mask & (kAffine_Mask | kPerspective_Mask)) == 0; + } + + /** Returns a mask bitfield describing the types of transformations + that the matrix will perform. This information is used by routines + like mapPoints, to optimize its inner loops to only perform as much + arithmetic as is necessary. + */ + TypeMask getType() const; + + /** Returns true if the matrix is identity. + This is faster than testing if (getType() == kIdentity_Mask) + */ + bool isIdentity() const; + + /** Returns true if the matrix that will only scale + or translate (i.e., will map a rectangle into another rectangle). + */ + bool rectStaysRect() const { return RectStaysRect(this->getType()); } + + SkScalar getScaleX() const { return fMat[0]; } + SkScalar getScaleY() const { return fMat[4]; } + SkScalar getSkewY() const { return fMat[3]; } + SkScalar getSkewX() const { return fMat[1]; } + SkScalar getTranslateX() const { return fMat[2]; } + SkScalar getTranslateY() const { return fMat[5]; } + SkScalar getPerspX() const { return fMat[6]; } + SkScalar getPerspY() const { return fMat[7]; } + + void setScaleX(SkScalar v) { fMat[0] = v; } + void setScaleY(SkScalar v) { fMat[4] = v; } + void setSkewY(SkScalar v) { fMat[3] = v; } + void setSkewX(SkScalar v) { fMat[1] = v; } + void setTranslateX(SkScalar v) { fMat[2] = v; } + void setTranslateY(SkScalar v) { fMat[5] = v; } +#ifdef SK_SCALAR_IS_FIXED + void setPerspX(SkFract v) { fMat[6] = v; } + void setPerspY(SkFract v) { fMat[7] = v; } +#else + void setPerspX(SkScalar v) { fMat[6] = v; } + void setPerspY(SkScalar v) { fMat[7] = v; } +#endif + /** Set the matrix to identity + */ + void reset(); + + void set(const SkMatrix& other) { *this = other; } + + /** Set the matrix to translate by (dx, dy). + */ + void setTranslate(SkScalar dx, SkScalar dy); + /** 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 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 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 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 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 rotation. + M' = M * R(degrees, px, py) + */ + bool preRotate(SkScalar degrees, SkScalar px, SkScalar py); + /** 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 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 rotation. + M' = R(degrees, px, py) * M + */ + bool postRotate(SkScalar degrees, SkScalar px, SkScalar py); + /** 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 matrix. + M' = other * M + */ + bool postConcat(const SkMatrix& other); + + enum ScaleToFit { + kFill_ScaleToFit, //!< scale in X and Y independently + kStart_ScaleToFit, //!< uniform scale in X/Y, align along left/top + kCenter_ScaleToFit, //!< uniform scale in X/Y, align along center + kEnd_ScaleToFit //!< uniform scale in X/Y, align along right/bottom + }; + /** 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 = kFill_ScaleToFit); + /** Set the matrix such that the specified src points would map to the + specified dst points. count must be withing [0..4]. + */ + bool setPolyToPoly(const SkPoint dst[], const SkPoint src[], int count); + + + /** If this matrix can be inverted, return true and if inverse is not nil, set inverse + to be the inverse of this matrix. If this matrix cannot be inverted, ignore inverse + and return false + */ + bool invert(SkMatrix* inverse) 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. + @param typeMask The mask bits returned by getType() for this matrix. + */ + bool mapPoints(SkPoint dst[], const SkPoint src[], int count, TypeMask typeMask) const; + /** Apply this matrix to the array of vectors specified by src, and write the transformed + vectors into the array of points 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. + @param typeMask The mask bits returned by getType() for this matrix. + */ + bool mapVectors(SkVector dst[], const SkVector src[], int count, TypeMask typeMask) const; + /** 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. + @param typeMask The mask bits returned by getType() for this matrix. + */ + bool mapRect(SkRect* dst, const SkRect& src, TypeMask typeMask) const; + + /** Helper method for mapPoints() where the TypeMask needs to be computed. + */ + bool mapPoints(SkPoint dst[], const SkPoint src[], int count) const + { + return this->mapPoints(dst, src, count, this->getType()); + } + /** Helper method for mapPoints() where the src and dst arrays are the + same, and the TypeMask needs to be computed. + */ + bool mapPoints(SkPoint pts[], int count) const + { + return this->mapPoints(pts, pts, count, this->getType()); + } + /** Helper method for mapVectors() where the TypeMask needs to be computed. + */ + bool mapVectors(SkVector dst[], const SkVector src[], int count) const + { + return this->mapVectors(dst, src, count, this->getType()); + } + /** Helper method for mapVectors() where the src and dst arrays are the + same, and the TypeMask needs to be computed. + */ + bool mapVectors(SkVector vecs[], int count) const + { + return this->mapVectors(vecs, vecs, count, this->getType()); + } + /** Helper method for mapRect() where the TypeMask needs to be computed. + */ + bool mapRect(SkRect* dst, const SkRect& src) const + { + return this->mapRect(dst, src, this->getType()); + } + /** Helper method for mapRect() where the TypeMask needs to be computed + and the src and dst rects are the same (i.e. map in place) + */ + bool mapRect(SkRect* rect) const + { + return this->mapRect(rect, *rect, this->getType()); + } + + /** 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 (*MapPtProc)(const SkMatrix& mat, SkScalar x, SkScalar y, SkPoint* result); + MapPtProc getMapPtProc() const; + + /** If the matrix can be stepped in X (not complex perspective) + then return true and if step[XY] is not nil, return the step[XY] value. + If it cannot, return false and ignore step. + */ + bool fixedStepInX(SkScalar y, SkFixed* stepX, SkFixed* stepY) const; + + friend bool operator==(const SkMatrix& a, const SkMatrix& b) + { + return memcmp(a.fMat, b.fMat, sizeof(a)) == 0; + } + +#ifdef SK_DEBUG + /** @cond UNIT_TEST */ + void dump() const; + + static void UnitTest(); + /** @endcond */ +#endif + +private: + SkScalar fMat[9]; + + static void Map2Pt(const SkPoint srcPt[], SkMatrix* dst, SkScalar scale); + static void Map3Pt(const SkPoint srcPt[], SkMatrix* dst, SkScalar scaleX, SkScalar scaleY); + static void Map4Pt(const SkPoint srcPt[], SkMatrix* dst, SkScalar scaleX, SkScalar scaleY); + + static void Perspective_ptProc(const SkMatrix&, SkScalar, SkScalar, SkPoint*); + static void Affine_ptProc(const SkMatrix&, SkScalar, SkScalar, SkPoint*); + static void Scale_ptProc(const SkMatrix&, SkScalar, SkScalar, SkPoint*); + static void Translate_ptProc(const SkMatrix&, SkScalar, SkScalar, SkPoint*); + static void Identity_ptProc(const SkMatrix&, SkScalar, SkScalar, SkPoint*); +}; + +#endif + diff --git a/include/corecg/SkPoint.h b/include/corecg/SkPoint.h new file mode 100644 index 000000000..5c9e16545 --- /dev/null +++ b/include/corecg/SkPoint.h @@ -0,0 +1,244 @@ +#ifndef SkPoint_DEFINED +#define SkPoint_DEFINED + +#include "SkMath.h" + +/** \struct SkPoint16 + + SkPoint16 holds two 16 bit integer coordinates +*/ +struct SkPoint16 { + int16_t fX, fY; + + void set(S16CPU x, S16CPU y) { fX = SkToS16(x); fY = SkToS16(y); } + + /** Rotate the point clockwise, writing the new point into dst + It is legal for dst == this + */ + void rotateCW(SkPoint16* 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(SkPoint16* 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 + */ + SkPoint16 operator-() const + { + SkPoint16 neg; + neg.fX = -fX; + neg.fY = -fY; + return neg; + } + /** Add v's coordinates to this point's + */ + void operator+=(const SkPoint16& v) + { + fX = SkToS16(fX + v.fX); + fY = SkToS16(fY + v.fY); + } + /** Subtract v's coordinates from this point's + */ + void operator-=(const SkPoint16& v) + { + fX = SkToS16(fX - v.fX); + fY = SkToS16(fY - v.fY); + } + /** Returns true if the point's coordinates equal (x,y) + */ + bool equals(S16CPU x, S16CPU y) const { return fX == x && fY == y; } + friend bool operator==(const SkPoint16& a, const SkPoint16& b) + { + return a.fX == b.fX && a.fY == b.fY; + } + friend bool operator!=(const SkPoint16& a, const SkPoint16& b) + { + return a.fX != b.fX || a.fY != b.fY; + } + /** Returns a new point whose coordinates are the difference between a and b (a - b) + */ + friend SkPoint16 operator-(const SkPoint16& a, const SkPoint16& b) + { + SkPoint16 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 SkPoint16 operator+(const SkPoint16& a, const SkPoint16& b) + { + SkPoint16 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 SkPoint16& a, const SkPoint16& 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 SkPoint16& a, const SkPoint16& b) + { + return a.fX * b.fY - a.fY * b.fX; + } +}; + +struct SkPoint32 { + int32_t fX, fY; + + void set(int x, int y) { fX = x; fY = y; } +}; + +struct SkPoint { + SkScalar fX, 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(S16CPU x, S16CPU 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 SkPoint16& p) { fX = SkIntToScalar(p.fX); fY = SkIntToScalar(p.fY); } + + /** Return the euclidian distance from (0,0) to the point + */ + SkScalar length() const { return SkPoint::Length(fX, fY); } + + /** Set the point (vector) to be unit-length in the same direction as it + currently is, and return its old length. If the old length is + degenerately small (nearly zero), do nothing and return 0. + */ + bool normalize(); + /** Set the point (vector) to be unit-length in the same direction as the + x,y params, and return their old length. If the old length is + degenerately small (nearly zero), do nothing and return 0. + */ + bool setUnit(SkScalar x, SkScalar y); + /** Scale the point to have the specified length, and return that + length. If the original length is + degenerately small (nearly zero), do nothing and return 0. + */ + bool setLength(SkScalar length); + /** Set the point to have the specified length in the same direction as (x,y), + and return the old length of (x,y). If that old length is + degenerately small (nearly zero), do nothing and return 0. + */ + 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 scale) { this->scale(scale, 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 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; + } + + /** 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); + /** 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); + } +}; + +typedef SkPoint SkVector; + +#endif + diff --git a/include/corecg/SkPostConfig.h b/include/corecg/SkPostConfig.h new file mode 100644 index 000000000..18f1517fd --- /dev/null +++ b/include/corecg/SkPostConfig.h @@ -0,0 +1,169 @@ +#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) + #ifdef SK_CAN_USE_FLOAT + #define SK_SCALAR_IS_FLOAT + #else + #define SK_SCALAR_IS_FIXED + #endif +#endif + +#if defined(SK_SCALAR_IS_FLOAT) && !defined(SK_CAN_USE_FLOAT) + #define SK_CAN_USE_FLOAT + // we do nothing in the else case: fixed-scalars can have floats or not +#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 + +#ifndef SkNEW + #define SkNEW(type_name) new type_name + #define SkNEW_ARGS(type_name, args) new type_name args + #define SkDELETE(obj) delete obj +#endif + +/////////////////////////////////////////////////////////////////////////////// + +#ifdef SK_BUILD_FOR_WIN + #define WIN32_LEAN_AND_MEAN + #include + #undef WIN32_LEAN_AND_MEAN + + #ifndef SK_DEBUGBREAK + #define SK_DEBUGBREAK(cond) do { if (!(cond)) DebugBreak(); } while (false) + #endif + + #ifdef SK_BUILD_FOR_WIN32 + #define strcasecmp(a, b) stricmp(a, b) + #define strncasecmp(a, b, c) strnicmp(a, b, c) + #elif defined(SK_BUILD_FOR_WINCE) + #define strcasecmp(a, b) _stricmp(a, b) + #define strncasecmp(a, b, c) _strnicmp(a, b, c) + #endif +#elif defined(SK_BUILD_FOR_MAC) + #include + #ifndef SK_DEBUGBREAK + #define SK_DEBUGBREAK(cond) do { if (!(cond)) sk_throw(); } while (false) + #endif +#else + #ifdef SK_DEBUG + #include + #ifndef SK_DEBUGBREAK + #define SK_DEBUGBREAK(cond) assert(cond) + #endif + #endif +#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 + +////////////////////////////////////////////////////////////////////////////////////////////// +#ifndef SK_BUILD_FOR_WINCE +#include +#include +#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 +#undef free + +#ifdef SK_DEBUG +#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 + diff --git a/include/corecg/SkPreConfig.h b/include/corecg/SkPreConfig.h new file mode 100644 index 000000000..7e142872d --- /dev/null +++ b/include/corecg/SkPreConfig.h @@ -0,0 +1,101 @@ +#ifndef SkPreConfig_DEFINED +#define SkPreConfig_DEFINED + +#ifdef ANDROID + #define SK_BUILD_FOR_UNIX + #define SK_SCALAR_IS_FIXED + #define SK_CAN_USE_FLOAT +#endif + +#if !defined(SK_CPU_BENDIAN) && !defined(SK_CPU_LENDIAN) + #if defined(__APPLE__) || defined(__MC68K__) + #define SK_CPU_BENDIAN + #else + #define SK_CPU_LENDIAN + #endif +#endif + +////////////////////////////////////////////////////////////////////// + +#if !defined(SK_BUILD_FOR_PALM) && !defined(SK_BUILD_FOR_WINCE) && !defined(SK_BUILD_FOR_WIN32) && !defined(SK_BUILD_FOR_SYMBIAN) && !defined(SK_BUILD_FOR_UNIX) && !defined(SK_BUILD_FOR_MAC) + + #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(linux) + #define SK_BUILD_FOR_UNIX + #else + #define SK_BUILD_FOR_MAC + #endif + +#endif + +////////////////////////////////////////////////////////////////////// + +#if !defined(SK_DEBUG) && !defined(SK_RELEASE) + #ifdef NDEBUG + #define SK_RELEASE + #else + #define SK_DEBUG + #endif +#endif + +////////////////////////////////////////////////////////////////////// + +#ifdef SK_BUILD_FOR_WIN32 + #define SK_SCALAR_IS_FLOAT +#endif + +#if defined(SK_BUILD_FOR_WIN32) || defined(SK_BUILD_FOR_MAC) + #define SK_CAN_USE_FLOAT + #define SK_SCALAR_IS_FIXED + #define SK_CAN_USE_LONGLONG +#endif + +////////////////////////////////////////////////////////////////////// + +#ifdef SK_CAN_USE_LONGLONG + #ifdef SK_BUILD_FOR_WIN32 + #define SkLONGLONG __int64 + #else + #define SkLONGLONG long long + #endif +#endif + +////////////////////////////////////////////////////////////////////// + +#if !defined(SK_CPU_BENDIAN) && !defined(SK_CPU_LENDIAN) + +#ifdef SK_BUILD_FOR_MAC + #define SK_CPU_BENDIAN +#else + #define SK_CPU_LENDIAN +#endif + +#endif + +#if defined(SK_BUILD_FOR_BREW) || defined(SK_BUILD_FOR_WINCE) || (defined(SK_BUILD_FOR_SYMBIAN) && !defined(__MARM_THUMB__)) + /* e.g. the ARM instructions have conditional execution, making tiny branches cheap */ + #define SK_CPU_HAS_CONDITIONAL_INSTR +#endif + +////////////////////////////////////////////////////////////////////// +// Conditional features based on build target + +#if defined(SK_BUILD_FOR_WIN32) || defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_UNIX) + #ifndef SK_BUILD_NO_IMAGE_ENCODE + #define SK_SUPPORT_IMAGE_ENCODE + #endif +#endif + +#ifdef SK_BUILD_FOR_SYMBIAN + #define SK_USE_RUNTIME_GLOBALS +#endif + +#endif + diff --git a/include/corecg/SkRandom.h b/include/corecg/SkRandom.h new file mode 100644 index 000000000..362117e2b --- /dev/null +++ b/include/corecg/SkRandom.h @@ -0,0 +1,85 @@ +#ifndef SkRandom_DEFINED +#define SkRandom_DEFINED + +#include "Sk64.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; } + + /** 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); + return min + this->nextU() % (max - min + 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 (-SK_Scalar1..SK_Scalar1). + */ + SkScalar nextSScalar1() { return SkFixedToScalar(this->nextSFixed1()); } + + /** Return the next pseudo random number as a signed 64bit value. + */ + void next64(Sk64* a) { SkASSERT(a); a->set(this->nextS(), this->nextU()); } + /** 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: + // "Numerical Recipes in C", 1992 page 284 + enum { + kMul = 1664525, + kAdd = 1013904223 + }; + uint32_t fSeed; +}; + +#endif + diff --git a/include/corecg/SkRect.h b/include/corecg/SkRect.h new file mode 100644 index 000000000..ec48e38af --- /dev/null +++ b/include/corecg/SkRect.h @@ -0,0 +1,266 @@ +#ifndef SkRect_DEFINED +#define SkRect_DEFINED + +#include "SkPoint.h" + +/** \struct SkRect16 + + SkRect16 holds four 16 bit integer coordinates for a rectangle +*/ +struct SkRect16 { + S16 fLeft, fTop, fRight, fBottom; + + /** Returns true if the rectangle is empty (e.g. left >= right or top >= bottom) + */ + bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; } + /** Returns the rectangle's width. This does not check for a valid rectangle (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 rectangle (i.e. top <= bottom) + so the result may be negative. + */ + int height() const { return fBottom - fTop; } + + friend int operator==(const SkRect16& a, const SkRect16& b) + { + return !memcmp(&a, &b, sizeof(a)); + } + friend int operator!=(const SkRect16& a, const SkRect16& b) + { + return memcmp(&a, &b, sizeof(a)); + } + + /** Set the rectangle to (0,0,0,0) + */ + void setEmpty() { memset(this, 0, sizeof(*this)); } + + void set(S16CPU left, S16CPU top, S16CPU right, S16CPU bottom) + { + fLeft = SkToS16(left); + fTop = SkToS16(top); + fRight = SkToS16(right); + fBottom = SkToS16(bottom); + } + /** Offset set the rectangle by adding dx to its left and right, + and adding dy to its top and bottom. + */ + void offset(S16CPU dx, S16CPU dy) + { + fLeft = SkToS16(fLeft + dx); + fTop = SkToS16(fTop + dy); + fRight = SkToS16(fRight + dx); + fBottom = SkToS16(fBottom + dy); + } + /** 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 hods true for dy and the top and bottom. + */ + void inset(S16CPU dx, S16CPU dy) + { + fLeft = SkToS16(fLeft + dx); + fTop = SkToS16(fTop + dy); + fRight = SkToS16(fRight - dx); + fBottom = SkToS16(fBottom - dy); + } + /** Returns true if (x,y) is inside the rectangle. 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(S16CPU x, S16CPU 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. + */ + bool contains(S16CPU left, S16CPU top, S16CPU right, S16CPU bottom) const + { + return 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 SkRect16& r) const + { + return fLeft <= r.fLeft && fTop <= r.fTop && + fRight >= r.fRight && fBottom >= 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. + */ + bool intersect(const SkRect16& r); + /** If rectangles a and b intersect, return true and set this rectangle to that + intersection, otherwise return false and do not change this rectangle. + */ + bool intersect(const SkRect16& a, const SkRect16& b); + /** 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. + */ + bool intersect(S16CPU left, S16CPU top, S16CPU right, S16CPU bottom); + /** Returns true if a and b intersect + */ + static bool Intersects(const SkRect16& a, const SkRect16& b) + { + return a.fLeft < b.fRight && b.fLeft < a.fRight && + a.fTop < b.fBottom && b.fTop < a.fBottom; + } + void join(const SkRect16& r) + { + fLeft = SkToS16(SkMin32(fLeft, r.fLeft)); + fTop = SkToS16(SkMin32(fTop, r.fTop)); + fRight = SkToS16(SkMax32(fRight, r.fRight)); + fBottom = SkToS16(SkMax32(fBottom, 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(); +}; + +/** \struct SkRect +*/ +struct SkRect { + SkScalar fLeft, fTop, fRight, fBottom; + + bool isEmpty() const { return fLeft >= fRight || fTop >= 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 int operator==(const SkRect& a, const SkRect& b) + { + return !memcmp(&a, &b, sizeof(a)); + } + friend int operator!=(const SkRect& a, const SkRect& b) + { + return memcmp(&a, &b, sizeof(a)); + } + + /** 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 SkRect16& 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; + } + /** 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); + + /** 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; + } + /** 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 hods true for dy and the top and bottom. + */ + void inset(SkScalar dx, SkScalar dy) + { + fLeft += dx; + fTop += dy; + fRight -= dx; + fBottom -= dy; + } + + /** If this rectangle intersects r, return true and set this rectangle to that + intersection, otherwise return false and do not change this rectangle. + */ + 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. + */ + bool intersect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom); + /** Return true if rectangles a and b intersect. + */ + static bool Intersects(const SkRect& a, const SkRect& b) + { + return a.fLeft < b.fRight && b.fLeft < a.fRight && + a.fTop < b.fBottom && b.fTop < a.fBottom; + } + + /** Returns true if (p.fX,p.fY) is inside the rectangle. The left and top coordinates of + the rectangle are considered to be inside, while the right and bottom coordinates + 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(const SkPoint& p) const + { + return fLeft <= p.fX && p.fX < fRight && + fTop <= p.fY && p.fY < fBottom; + } + /** Returns true if (x,y) is inside the rectangle. The left and top coordinates of + the rectangle are considered to be inside, while the right and bottom coordinates + 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(SkScalar x, SkScalar y) const + { + return fLeft <= x && x < fRight && + fTop <= y && y < fBottom; + } + /** Return true if this rectangle contains r + */ + bool contains(const SkRect& r) const + { + return fLeft <= r.fLeft && fTop <= r.fTop && + fRight >= r.fRight && fBottom >= r.fBottom; + } + /** Set the dst integer rectangle by rounding this rectangle's coordinates + to their nearest integer values. + */ + void round(SkRect16* dst) const + { + SkASSERT(dst); + dst->set(SkScalarRound(fLeft), SkScalarRound(fTop), SkScalarRound(fRight), SkScalarRound(fBottom)); + } + /** Set the dst integer rectangle by rounding "out" this rectangle, choosing the floor of top and left, + and the ceiling of right and bototm. + */ + void roundOut(SkRect16* dst) const + { + SkASSERT(dst); + dst->set(SkScalarFloor(fLeft), SkScalarFloor(fTop), SkScalarCeil(fRight), SkScalarCeil(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(); +}; + +#endif + diff --git a/include/corecg/SkRegion.h b/include/corecg/SkRegion.h new file mode 100644 index 000000000..73daa9ce6 --- /dev/null +++ b/include/corecg/SkRegion.h @@ -0,0 +1,249 @@ +#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 SkRegion { +public: + typedef int16_t RunType; + + SkRegion(); + explicit SkRegion(const SkRegion&); + explicit SkRegion(const SkRect16&); + ~SkRegion(); + + SkRegion& operator=(const SkRegion&); + + friend int operator==(const SkRegion& a, const SkRegion& b); + friend int operator!=(const SkRegion& a, const SkRegion& b) + { + return !(a == b); + } + + // provide explicitly, so we'll have a java equivalent + void set(const SkRegion& src) + { + SkASSERT(&src); + *this = src; + } + /** 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 SkRect16& getBounds() const { return fBounds; } + + /** Returns true if the region is non-empty, and if so, sets the specified path to the + boundary(s) of the region. + */ + bool getBoundaryPath(SkPath* path) const; + + /** Set the region to be empty, and return false */ + 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 SkRect16&); + /** 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(S16CPU left, S16CPU top, S16CPU right, S16CPU bottom); + /** 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, optionally clipped (if clip is + not nil). 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). + */ + bool setPath(const SkPath&, const SkRegion* clip = nil); + /** Return true if the specified x,y coordinate is inside the region. + */ + bool contains(S16CPU x, S16CPU y) 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 SkRect16& r) const + { + return this->isRect() && fBounds.contains(r); + } + /** 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(S16CPU left, S16CPU top, S16CPU right, S16CPU bottom) const + { + return this->isRect() && fBounds.contains(left, top, right, 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 SkRect16& rect) const + { + return this->isEmpty() || !SkRect16::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() || !SkRect16::Intersects(fBounds, rgn.fBounds); + } + + void translate(int dx, int dy) + { + this->translate(dx, dy, this); + } + void translate(int dx, int dy, SkRegion* dst) const; + + enum Op { + kDifference_Op, + kIntersect_Op, + kUnion_Op, + kXOR_Op, + + kOpCount + }; + /** Set this region to the result of applying the Opereation to this region and the specified + rectangle. Return true if the resulting region is non-empty. + */ + bool op(const SkRect16&, Op); + // helper for java, so it doesn't have to create a Rect object + bool op(S16CPU left, S16CPU top, S16CPU right, S16CPU bottom, Op op) + { + SkRect16 r; + r.set(left, top, right, bottom); + return this->op(r, op); + } + /** Set this region to the result of applying the Opereation to this region and the specified + region. 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 Opereation to the specified rectangle and region. + Return true if the resulting region is non-empty. + */ + bool op(const SkRect16&, const SkRegion&, Op); + /** Set this region to the result of applying the Opereation to the specified regions. + Return true if the resulting region is non-empty. + */ + bool op(const SkRegion&, const SkRegion&, Op); + + /** Helper class that returns the sequence of rectangles that make up this region. + */ + class Iterator { + public: + Iterator(); + Iterator(const SkRegion&); + void reset(const SkRegion&); + bool done() { return fDone; } + void next(); + const SkRect16& rect() const { return fRect; } + + private: + const RunType* fRuns; + SkRect16 fRect; + bool fDone; + }; + + /** Helper class that returns the sequence of rectangles that make up this region, + intersected with the clip rectangle. + */ + class Cliperator { + public: + Cliperator(const SkRegion&, const SkRect16& clip); + bool done() { return fDone; } + void next(); + const SkRect16& rect() const { return fRect; } + + private: + Iterator fIter; + SkRect16 fClip; + SkRect16 fRect; + bool fDone; + }; + + /** Helper class that returns the sequence of scanline runs that make up this region. + */ + 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; + }; + + /** Return the number of bytes need to write this region to a buffer. + */ + size_t computeBufferSize() const; + /** Write the region to the buffer, and return the number of bytes written. + */ + size_t writeToBuffer(void* buffer) const; + /** Initialized the region from the buffer, returning the number + of bytes actually read. + */ + size_t readFromBuffer(const void* buffer); + + SkDEBUGCODE(void dump() const;) + SkDEBUGCODE(void validate() const;) + SkDEBUGCODE(static void UnitTest();) + +private: + enum { + kRectRegionRuns = 6, // need to store a region of a rect [T B L R S S] + kRunTypeSentinel = 0x7FFF + }; + + friend class android::Region; // needed for marshalling efficiently + void allocateRuns(int count); // allocate space for count runs + + struct RunHead; + + SkRect16 fBounds; + RunHead* fRunHead; + + void freeRuns(); + const RunType* getRuns(RunType tmpStorage[], int* count) const; + bool setRuns(RunType runs[], int count); + + int count_runtype_values(int* itop, int* ibot) const; + + static void build_rect_runs(const SkRect16& bounds, RunType runs[kRectRegionRuns]); + static bool compute_run_bounds(const RunType runs[], int count, SkRect16* bounds); + + friend struct RunHead; + friend class Iterator; + friend class Spanerator; + friend class SkRgnBuilder; +}; + + +#endif + diff --git a/include/corecg/SkScalar.h b/include/corecg/SkScalar.h new file mode 100644 index 000000000..271f1d391 --- /dev/null +++ b/include/corecg/SkScalar.h @@ -0,0 +1,235 @@ +#ifndef SkScalar_DEFINED +#define SkScalar_DEFINED + +#include "SkTypes.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 + #include "SkFloatingPoint.h" + + /** 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; + extern const uint32_t gIEEENotANumber; + extern const uint32_t gIEEEInfinity; + + /** 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 (*(const float*)&gIEEEInfinity) + /** SK_ScalarMax is defined to be the largest value representable as an SkScalar + */ + #define SK_ScalarMax (3.4028235e+38f) + /** SK_ScalarMin is defined to be the smallest value representable as an SkScalar + */ + #define SK_ScalarMin (1.1754944e-38f) + /** SK_ScalarNaN is defined to be 'Not a Number' as an SkScalar + */ + #define SK_ScalarNaN (*(const float*)&gIEEENotANumber) + /** SkScalarIsNaN(n) returns true if argument is not a number + */ + static inline bool SkScalarIsNaN(float x) { return x != x; } + /** 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) + /** SkFixedToScalar(n) returns its SkScalar argument as an SkFixed + */ + #define SkScalarToFixed(x) (SkFixed)((x) * SK_Fixed1) + + #define SkScalarToFloat(n) (n) + #define SkFloatToScalar(n) (n) + + /** SkScalarFraction(x) returns the signed fractional part of the argument + */ + #define SkScalarFraction(x) sk_float_mod(x, 1.0f) + /** Rounds the SkScalar to the nearest integer value + */ + inline int SkScalarRound(SkScalar x) + { + if (x < 0) + x -= SK_ScalarHalf; + else + x += SK_ScalarHalf; + return (int)x; + } + /** Returns the smallest integer that is >= the specified SkScalar + */ + #define SkScalarCeil(x) (int)ceil(x) + /** Returns the largest integer that is <= the specified SkScalar + */ + #define SkScalarFloor(x) (int)floor(x) + /** Returns the absolute value of the specified SkScalar + */ + #define SkScalarAbs(x) sk_float_abs(x) + /** 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) ((a) * (b)) + /** Returns the product of a SkScalar and an int rounded to the nearest integer value + */ + #define SkScalarMulRound(a, b) SkScalarRound((a) * (b)) + /** Returns the product of a SkScalar and an int promoted to the next larger int + */ + #define SkScalarMulCeil(a, b) SkScalarCeil((a) * (b)) + /** Returns the product of a SkScalar and an int truncated to the next smaller int + */ + #define SkScalarMulFloor(a, b) SkScalarFloor((a) * (b)) + /** Returns the quotient of two SkScalars (a/b) + */ + #define SkScalarDiv(a, b) ((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) ((a) * (b) / (c)) + /** Returns the multiplicative inverse of the SkScalar (1/x) + */ + #define SkScalarInvert(x) (SK_Scalar1 / (x)) + /** Returns the square root of the SkScalar + */ + #define SkScalarSqrt(x) sk_float_sqrt(x) + /** 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((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; } + +#else + #include "SkFixed.h" + + typedef SkFixed SkScalar; + + #define SK_Scalar1 SK_Fixed1 + #define SK_ScalarHalf SK_FixedHalf + #define SK_ScalarInfinity SK_FixedMax + #define SK_ScalarMax SK_FixedMax + #define SK_ScalarMin SK_FixedMin + #define SK_ScalarNaN SK_FixedNaN + #define SkScalarIsNaN(x) ((x) == SK_FixedNaN) + #define SkIntToScalar(n) SkIntToFixed(n) + #define SkFixedToScalar(x) (x) + #define SkScalarToFixed(x) (x) + #ifdef SK_CAN_USE_FLOAT + #define SkScalarToFloat(n) SkFixedToFloat(n) + #define SkFloatToScalar(n) SkFloatToFixed(n) + #endif + #define SkScalarFraction(x) SkFixedFraction(x) + #define SkScalarRound(x) SkFixedRound(x) + #define SkScalarCeil(x) SkFixedCeil(x) + #define SkScalarFloor(x) SkFixedFloor(x) + #define SkScalarAbs(x) SkFixedAbs(x) + #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 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 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) +#endif + +#define SK_ScalarNearlyZero (SK_Scalar1 / (1 << 12)) + +/* <= is slower than < for floats, so we use < for our tolerance test +*/ + +inline bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance = SK_ScalarNearlyZero) +{ + SkASSERT(tolerance > 0); + return SkScalarAbs(x) < 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] +*/ +inline SkScalar SkScalarInterp(SkScalar A, SkScalar B, SkScalar t) +{ + SkASSERT(t >= 0 && t <= SK_Scalar1); + return A + SkScalarMul(B - A, t); +} + +#endif + diff --git a/include/corecg/SkTemplates.h b/include/corecg/SkTemplates.h new file mode 100644 index 000000000..448638d0a --- /dev/null +++ b/include/corecg/SkTemplates.h @@ -0,0 +1,161 @@ +#ifndef SkTemplates_DEFINED +#define SkTemplates_DEFINED + +#include "SkTypes.h" + +/** \file SkTemplates.h + + This file contains light-weight template classes for type-safe and exception-safe + resource management. +*/ + +/** \class SkAutoTCallProc + + Similar to SkAutoTDelete, this class is used to auto delete an object + when leaving the scope of the object. This is mostly useful when + errors occur and objects need to be cleaned up. The template uses two + parameters, the object, and a function that is to be called in the destructor. + If detach() is called then the function is not called when SkAutoTCallProc goes out + of scope. This also happens is the passed in object is nil. + +*/ +template class SkAutoTCallProc { +public: + SkAutoTCallProc(T* obj): fObj(obj) {} + ~SkAutoTCallProc() + { + if (fObj) + P(fObj); + } + T* detach() { T* obj = fObj; fObj = nil; return obj; } +private: + T* fObj; +}; + +template class SkAutoTDelete { +public: + SkAutoTDelete(T* obj) : fObj(obj) {} + ~SkAutoTDelete() { delete fObj; } + + void free() { delete fObj; fObj = nil; } + T* detach() { T* obj = fObj; fObj = nil; return obj; } + +private: + T* fObj; +}; + +template class SkAutoTDeleteArray { +public: + SkAutoTDeleteArray(T array[]) : fArray(array) {} + ~SkAutoTDeleteArray() { delete[] fArray; } + + void free() { delete[] fArray; fArray = nil; } + T* detach() { T* array = fArray; fArray = nil; return array; } + +private: + T* fArray; +}; + +template class SkAutoTArray { +public: + SkAutoTArray(size_t count) + { + fArray = nil; // init first in case we throw + if (count) + fArray = new T[count]; +#ifdef SK_DEBUG + fCount = count; +#endif + } + ~SkAutoTArray() + { + delete[] fArray; + } + + T* get() const { return fArray; } + T& operator[](int index) const { SkASSERT((unsigned)index < fCount); return fArray[index]; } + + void reset() + { + if (fArray) + { + delete[] fArray; + fArray = nil; + } + } + + void replace(T* array) + { + if (fArray != array) + { + delete[] fArray; + fArray = array; + } + } + + /** Call swap to exchange your pointer to an array of T with the SkAutoTArray object. + After this call, the SkAutoTArray object will be responsible for deleting your + array, and you will be responsible for deleting its. + */ + void swap(T*& other) + { + T* tmp = fArray; + fArray = other; + other = tmp; + } + +private: +#ifdef SK_DEBUG + size_t fCount; +#endif + T* fArray; +}; + +/** Allocate a temp array on the stack/heap. + Does NOT call any constructors/destructors on T (i.e. T must be POD) +*/ +template class SkAutoTMalloc { +public: + SkAutoTMalloc(size_t count) + { + fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP); + } + ~SkAutoTMalloc() + { + sk_free(fPtr); + } + T* get() const { return fPtr; } + +private: + T* fPtr; + // illegal + SkAutoTMalloc(const SkAutoTMalloc&); + SkAutoTMalloc& operator=(const SkAutoTMalloc&); +}; + +template class SkAutoSTMalloc { +public: + SkAutoSTMalloc(size_t count) + { + if (count <= N) + fPtr = (T*)fStorage; + else + fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP); + } + ~SkAutoSTMalloc() + { + if (fPtr != (T*)fStorage) + sk_free(fPtr); + } + T* get() const { return fPtr; } + +private: + T* fPtr; + uint32_t fStorage[(N*sizeof(T) + 3) >> 2]; + // illegal + SkAutoSTMalloc(const SkAutoSTMalloc&); + SkAutoSTMalloc& operator=(const SkAutoSTMalloc&); +}; + +#endif + diff --git a/include/corecg/SkThread.h b/include/corecg/SkThread.h new file mode 100644 index 000000000..ac548c476 --- /dev/null +++ b/include/corecg/SkThread.h @@ -0,0 +1,40 @@ +#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_dec(int32_t*); + +class SkMutex { +public: + SkMutex(); + ~SkMutex(); + + void acquire(); + void release(); +}; + +****************/ + +class SkAutoMutexAcquire { +public: + explicit SkAutoMutexAcquire(SkMutex& mutex) : fMutex(mutex) + { + mutex.acquire(); + } + ~SkAutoMutexAcquire() + { + fMutex.release(); + } +private: + SkMutex& fMutex; + + // illegal + SkAutoMutexAcquire& operator=(SkAutoMutexAcquire&); +}; + +#endif diff --git a/include/corecg/SkThread_platform.h b/include/corecg/SkThread_platform.h new file mode 100644 index 000000000..bfa3899c6 --- /dev/null +++ b/include/corecg/SkThread_platform.h @@ -0,0 +1,37 @@ +#ifndef SkThread_platform_DEFINED +#define SkThread_platform_DEFINED + +#ifdef ANDROID + +#include +#include + +#define sk_atomic_inc(addr) android_atomic_inc(addr) +#define sk_atomic_dec(addr) android_atomic_dec(addr) + +class SkMutex : android::Mutex { +public: + SkMutex() {} + ~SkMutex() {} + + void acquire() { this->lock(); } + void release() { this->unlock(); } +}; + +#else /* SkThread_empty.cpp */ + +int32_t sk_atomic_inc(int32_t* addr); +int32_t sk_atomic_dec(int32_t* addr); + +class SkMutex { +public: + SkMutex(); + ~SkMutex(); + + void acquire(); + void release(); +}; + +#endif + +#endif diff --git a/include/corecg/SkTypes.h b/include/corecg/SkTypes.h new file mode 100644 index 000000000..fe0cc38a6 --- /dev/null +++ b/include/corecg/SkTypes.h @@ -0,0 +1,299 @@ +#ifndef SkTypes_DEFINED +#define SkTypes_DEFINED + +#include "SkPreConfig.h" +#include "SkUserConfig.h" +#include "SkPostConfig.h" + +#include +#include + +/** \file SkTypes.h +*/ + +/* + memory wrappers +*/ + +extern void sk_out_of_memory(void); // platform specific, does not return +extern void sk_throw(void); // platform specific, does not return +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 nil (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(). +*/ +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 +*/ +extern void* sk_malloc_throw(size_t size); +/** Same as standard realloc(), but this one never returns nil on failure. It will throw + an exception if it fails. +*/ +extern void* sk_realloc_throw(void* buffer, size_t size); +/** Free memory returned by sk_malloc(). It is safe to pass nil. +*/ +extern void sk_free(void*); + +/////////////////////////////////////////////////////////////////////// + +#define SK_INIT_TO_AVOID_WARNING = 0 + +#ifdef SK_DEBUG + #define SkASSERT(cond) SK_DEBUGBREAK(cond) + #define SkDEBUGCODE(code) code + #define SkDECLAREPARAM(type, var) , type var + #define SkPARAM(var) , var +// #define SkDEBUGF(args ) SkDebugf##args + #define SkDEBUGF(args ) SkDebugf args + void SkDebugf(const char format[], ...); + + #define SkAssertResult(cond) SkASSERT(cond) +#else + #define SkASSERT(cond) + #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 + +/////////////////////////////////////////////////////////////////////// + +#ifndef nil + #define nil 0 +#endif + +// legacy defines. will be removed before shipping +typedef int8_t S8; +typedef uint8_t U8; +typedef int16_t S16; +typedef uint16_t U16; +typedef int32_t S32; +typedef uint32_t U32; + +/** 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 int S16CPU; +/** Fast type for signed 16 bits. Use for parameter passing and local variables, not for storage +*/ +typedef unsigned U8CPU; +/** 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 + int8_t SkToS8(long); + uint8_t SkToU8(size_t); + int16_t SkToS16(long); + uint16_t SkToU16(size_t); + int32_t SkToS32(long); + uint32_t SkToU32(size_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 0x80000001 +#define SK_MaxU32 0xFFFFFFFF +#define SK_MinU32 0 +#define SK_NaN32 0x80000000 + +#ifndef SK_OFFSETOF + #define SK_OFFSETOF(type, field) ((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])) + +/** Returns x rounded up to a multiple of 2 +*/ +#define SkAlign2(x) (((x) + 1) >> 1 << 1) +/** Returns x rounded up to a multiple of 4 +*/ +#define SkAlign4(x) (((x) + 3) >> 2 << 2) + +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 +*/ +inline int Sk32ToBool(uint32_t n) +{ + return (n | (0-n)) >> 31; +} + +template inline void SkTSwap(T& a, T& b) +{ + T c(a); + a = b; + b = c; +} + +inline int32_t SkAbs32(int32_t value) +{ +#ifdef SK_CPU_HAS_CONDITIONAL_INSTR + if (value < 0) + value = -value; + return value; +#else + int32_t mask = value >> 31; + return (value ^ mask) - mask; +#endif +} + +inline int32_t SkMax32(int32_t a, int32_t b) +{ + if (a < b) + a = b; + return a; +} + +inline int32_t SkMin32(int32_t a, int32_t b) +{ + if (a > b) + a = b; + return a; +} + +inline int32_t SkSign32(int32_t a) +{ + return (a >> 31) | ((unsigned) -a >> 31); +} + +inline int32_t SkFastMin32(int32_t value, int32_t max) +{ +#ifdef SK_CPU_HAS_CONDITIONAL_INSTR + if (value > max) + value = max; + return value; +#else + int diff = max - value; + // clear diff if it is negative (clear if value > max) + diff &= (diff >> 31); + return value + diff; +#endif +} + +/** Returns signed 32 bit value pinned between min and max, inclusively +*/ +inline int32_t SkPin32(int32_t value, int32_t min, int32_t max) +{ +#ifdef SK_CPU_HAS_CONDITIONAL_INSTR + if (value < min) + value = min; + if (value > max) + value = max; +#else + if (value < min) + value = min; + else if (value > max) + value = max; +#endif + return value; +} + +inline uint32_t SkSetClear32(uint32_t flags, bool cond, unsigned shift) +{ + return flags & ~(1 << shift) | ((int)cond << shift); +} + +class SkAutoMalloc { +public: + SkAutoMalloc(size_t size) + { + fPtr = sk_malloc_flags(size, SK_MALLOC_THROW | SK_MALLOC_TEMP); + } + ~SkAutoMalloc() + { + sk_free(fPtr); + } + void* get() const { return fPtr; } +private: + void* fPtr; + // illegal + SkAutoMalloc(const SkAutoMalloc&); + SkAutoMalloc& operator=(const SkAutoMalloc&); +}; + +template class SkAutoSMalloc { +public: + SkAutoSMalloc(size_t size) + { + if (size <= kSize) + fPtr = fStorage; + else + fPtr = sk_malloc_flags(size, SK_MALLOC_THROW | SK_MALLOC_TEMP); + } + ~SkAutoSMalloc() + { + if (fPtr != (void*)fStorage) + sk_free(fPtr); + } + void* get() const { return fPtr; } +private: + void* fPtr; + uint32_t fStorage[(kSize + 3) >> 2]; + // illegal + SkAutoSMalloc(const SkAutoSMalloc&); + SkAutoSMalloc& operator=(const SkAutoSMalloc&); +}; + +#endif /* C++ */ + +#endif + diff --git a/include/corecg/SkUserConfig.h b/include/corecg/SkUserConfig.h new file mode 100644 index 000000000..21f160484 --- /dev/null +++ b/include/corecg/SkUserConfig.h @@ -0,0 +1,59 @@ +#ifndef SkUserConfig_DEFINED +#define SkUserConfig_DEFINED + +/* This file is included before all other headers, except for SkPreConfig.h. + That file uses various heuristics to make a "best guess" at settings for + the following build defines. + + However, in this file you can override any of those decisions by either + defining new symbols, or #undef symbols that were already set. +*/ + +// experimental for now +#define SK_SUPPORT_MIPMAP + +// android specific defines and tests + +#ifdef SK_FORCE_SCALARFIXED + #define SK_SCALAR_IS_FIXED + #undef SK_SCALAR_IS_FLOAT + #undef SK_CAN_USE_FLOAT +#endif + +#ifdef SK_FORCE_SCALARFLOAT + #define SK_SCALAR_IS_FLOAT + #define SK_CAN_USE_FLOAT + #undef SK_SCALAR_IS_FIXED +#endif + +#ifdef ANDROID + #include + + #if __BYTE_ORDER == __BIG_ENDIAN + #define SK_CPU_BENDIAN + #undef SK_CPU_LENDIAN + #else + #define SK_CPU_LENDIAN + #undef SK_CPU_BENDIAN + #endif +#endif + +#ifdef SK_DEBUG + #define SK_SUPPORT_UNITTEST + /* Define SK_SIMULATE_FAILED_MALLOC to have + * sk_malloc throw an exception. Use this to + * detect unhandled memory leaks. */ + //#define SK_SIMULATE_FAILED_MALLOC + //#define SK_FIND_MEMORY_LEAKS +#endif + +#ifdef SK_BUILD_FOR_BREW + #include "SkBrewUserConfig.h" +#endif + +#ifdef SK_BUILD_FOR_MAC + #define SK_CAN_USE_FLOAT +#endif + +#endif + diff --git a/include/graphics/DoxygenMain.dox b/include/graphics/DoxygenMain.dox new file mode 100644 index 000000000..975186200 --- /dev/null +++ b/include/graphics/DoxygenMain.dox @@ -0,0 +1,3 @@ +/** \mainpage notitle +* \htmlinclude "SGL Spec. rev 9.htm" +*/ \ No newline at end of file diff --git a/include/graphics/Sk1DPathEffect.h b/include/graphics/Sk1DPathEffect.h new file mode 100644 index 000000000..3fd28859e --- /dev/null +++ b/include/graphics/Sk1DPathEffect.h @@ -0,0 +1,65 @@ +#ifndef Sk1DPathEffect_DEFINED +#define Sk1DPathEffect_DEFINED + +#include "SkPathEffect.h" +#include "SkPath.h" + +class SkPathMeasure; + +// This class is not exported to java. +class Sk1DPathEffect : public SkPathEffect { +public: + Sk1DPathEffect() {} + + virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width); + +protected: + /** Called at the start of each contour, returns the initial offset + into that contour. + */ + virtual SkScalar begin(SkScalar contourLength); + /** 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 distance, SkPathMeasure&); + + Sk1DPathEffect(SkRBuffer& buffer) : SkPathEffect(buffer) {} + +private: + // illegal + Sk1DPathEffect(const Sk1DPathEffect&); + Sk1DPathEffect& operator=(const Sk1DPathEffect&); + + typedef SkPathEffect INHERITED; +}; + +class 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 + }; + SkPath1DPathEffect(const SkPath& path, SkScalar advance, SkScalar phase, Style); + + // This method is not exported to java. + virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width); + +protected: + virtual SkScalar begin(SkScalar contourLength); + virtual SkScalar next(SkPath* dst, SkScalar distance, SkPathMeasure&); + +private: + SkPath fPath; + SkScalar fAdvance, fPhase; + Style fStyle; + + typedef Sk1DPathEffect INHERITED; +}; + + +#endif diff --git a/include/graphics/Sk2DPathEffect.h b/include/graphics/Sk2DPathEffect.h new file mode 100644 index 000000000..502d4a3b0 --- /dev/null +++ b/include/graphics/Sk2DPathEffect.h @@ -0,0 +1,53 @@ +#ifndef Sk2DPathEffect_DEFINED +#define Sk2DPathEffect_DEFINED + +#include "SkPathEffect.h" +#include "SkMatrix.h" + +// This class is not exported to java. +class Sk2DPathEffect : public SkPathEffect { +public: + Sk2DPathEffect(const SkMatrix& mat); + + // overrides + virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width); + + // overrides from SkFlattenable + virtual void flatten(SkWBuffer&); + virtual Factory getFactory(); + +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 SkRect16& uvBounds, SkPath* dst); + virtual void next(const SkPoint& loc, int u, int v, SkPath* dst); + virtual void end(SkPath* dst); + + /** 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 SkMatrix& getMatrix() const { return fMatrix; } + + // protected so that subclasses can call this during unflattening + Sk2DPathEffect(SkRBuffer&); + +private: + SkMatrix fMatrix, fInverse; + // illegal + Sk2DPathEffect(const Sk2DPathEffect&); + Sk2DPathEffect& operator=(const Sk2DPathEffect&); + + static SkFlattenable* CreateProc(SkRBuffer&); + + friend class Sk2DPathEffectBlitter; + typedef SkPathEffect INHERITED; +}; + +#endif diff --git a/include/graphics/SkAnimator.h b/include/graphics/SkAnimator.h new file mode 100644 index 000000000..7a70c107f --- /dev/null +++ b/include/graphics/SkAnimator.h @@ -0,0 +1,492 @@ +#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 element to draw. Usually, it contains + an block to add some drawing elements to the + display list when the document is first decoded. + + Here's an "Hello World" XML sample: + + + + + + + + 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 + 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 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 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 nil 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, 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 nil 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 nil 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/include/graphics/SkAnimatorView.h b/include/graphics/SkAnimatorView.h new file mode 100644 index 000000000..2fa765760 --- /dev/null +++ b/include/graphics/SkAnimatorView.h @@ -0,0 +1,31 @@ +#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/include/graphics/SkApplication.h b/include/graphics/SkApplication.h new file mode 100644 index 000000000..fbeea4753 --- /dev/null +++ b/include/graphics/SkApplication.h @@ -0,0 +1,10 @@ +#ifndef SkApplication_DEFINED +#define SkApplication_DEFINED + +class SkOSWindow; + +extern SkOSWindow* create_sk_window(void* hwnd); +extern void application_init(); +extern void application_term(); + +#endif // SkApplication_DEFINED diff --git a/include/graphics/SkAvoidXfermode.h b/include/graphics/SkAvoidXfermode.h new file mode 100644 index 000000000..574568b41 --- /dev/null +++ b/include/graphics/SkAvoidXfermode.h @@ -0,0 +1,34 @@ +#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 SkAvoidXfermode : public SkXfermode { +public: + /** This xfermode will draw the src everywhere except on top of the specified + color. + @param opColor the color to avoid (or to target if reverse is true); + @param tolerance How closely we compare a pixel to the opColor. + 0 - we only avoid on an exact match + 255 - maximum gradation (blending) based on how similar + the pixel is to our opColor. + @param reverse true means we target the opColor rather than avoid it. + */ + SkAvoidXfermode(SkColor opColor, U8CPU tolerance, bool reverse); + + virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count, const SkAlpha aa[]); + virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count, const SkAlpha aa[]); + virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count, const SkAlpha aa[]); + +private: + SkColor fOpColor; + uint32_t fDistMul; // x.14 + bool fReverse; +}; + +#endif diff --git a/include/graphics/SkBGViewArtist.h b/include/graphics/SkBGViewArtist.h new file mode 100644 index 000000000..dd6e2633d --- /dev/null +++ b/include/graphics/SkBGViewArtist.h @@ -0,0 +1,25 @@ +#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/include/graphics/SkBML_WXMLParser.h b/include/graphics/SkBML_WXMLParser.h new file mode 100644 index 000000000..706b6b178 --- /dev/null +++ b/include/graphics/SkBML_WXMLParser.h @@ -0,0 +1,38 @@ +#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/include/graphics/SkBML_XMLParser.h b/include/graphics/SkBML_XMLParser.h new file mode 100644 index 000000000..29e7f4e7d --- /dev/null +++ b/include/graphics/SkBML_XMLParser.h @@ -0,0 +1,23 @@ +#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/include/graphics/SkBitmap.h b/include/graphics/SkBitmap.h new file mode 100644 index 000000000..a7de542ff --- /dev/null +++ b/include/graphics/SkBitmap.h @@ -0,0 +1,374 @@ +#ifndef SkBitmap_DEFINED +#define SkBitmap_DEFINED + +#include "SkColor.h" +#include "SkRefCnt.h" + +// Android - we need to run as an embedded product, not X11 +//#ifdef SK_BUILD_FOR_UNIX +//#include +//#endif + + +class SkColorTable; + +/** \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. +*/ +class SkBitmap { +public: + enum Config { + kNo_Config, //!< bitmap has not been configured + kA1_Config, //!< 1-bit per pixel, (0 is transparent, 1 is opaque) + 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_8888_Config, //!< 32-bits per pixel, (see SkColorPriv.h for packing) + + kConfigCount + }; + + /** Default construct creates a bitmap with zero width and height, and no pixels. + Its config is set to kNo_Config. + */ + SkBitmap(); + /** Constructor initializes the new bitmap by copying the src bitmap. All fields are copied, + but ownership of the pixels remains with the src bitmap. + */ + // This method is not exported to java. + SkBitmap(const SkBitmap& src); + /** Destructor that, if getOwnsPixels() returns true, will delete the pixel's memory. + */ + ~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 the config for the bitmap. + */ + Config getConfig() const { return (Config)fConfig; } + /** Return the bitmap's width, in pixels. + */ + unsigned width() const { return fWidth; } + /** Return the bitmap's height, in pixels. + */ + unsigned height() const { return fHeight; } + /** Return the number of bytes between subsequent rows of the bitmap. + */ + unsigned rowBytes() const { return fRowBytes; } + /** Return the address of the pixels for this SkBitmap. This can be set either with + setPixels(), where the caller owns the buffer, or with allocPixels() or resizeAlloc(), + which marks the pixel memory to be owned by the SkBitmap (e.g. will be freed automatically + when the bitmap is destroyed). + */ + void* getPixels() const { return fPixels; } + /** Return the byte size of the pixels, based on the height and rowBytes + */ + size_t getSize() const { return fHeight * fRowBytes; } + + /** 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); + + /** Reset the bitmap to its initial state (see default constructor). If getOwnsPixels() returned + true, then the memory for the pixels is freed. + */ + void reset(); + /** Set the bitmap's config and dimensions. If rowBytes is 0, then an appropriate value + is computed based on the bitmap's config and width. If getOwnsPixels() returned true, + then the pixel's memory is freed. + */ + void setConfig(Config, U16CPU width, U16CPU height, U16CPU rowBytes = 0); + /** Use this to assign a new pixel address for an existing bitmap. If getOwnsPixels() returned + true, then the previous pixel's memory is freed. The new address is "owned" by the called, + and getOwnsPixels() will now return false. This method is not exported to java. + */ + void setPixels(void* p); + /** If this is called, then the bitmap will dynamically allocate memory for its pixels + based on rowBytes and height. The SkBitmap will remember that it allocated + this, and will automatically free it as needed, thus getOwnsPixels() will now return true. + */ + void allocPixels(); + /** Realloc the memory for the pixels based on the specified width and height. This + keeps the old value for config, and computes a rowBytes based on the config and the width. + This is similar, but more efficient than calling setConfig() followed by allocPixels(). + */ +// not implemented +// void resizeAlloc(U16CPU width, U16CPU height); + + /** Returns true if the current pixels have been allocated via allocPixels() + or resizeAlloc(). This method is not exported to java. + */ + bool getOwnsPixels() const; + /** Call this to explicitly change the ownership rule for the pixels. This may be called + after one bitmap is copied into another, to specify which bitmap should handle freeing + the memory. This method is not exported to java. + */ + void setOwnsPixels(bool ownsPixels); + + /** Get the bitmap's colortable object. + + Return the bitmap's colortable (if any). Does not affect the colortable's + reference count. + */ + SkColorTable* getColorTable() const { return fColorTable; } + /** Assign ctable to be the colortable for the bitmap, replacing any existing reference. + The reference count of ctable (if it is not nil) is incremented, and any existing + reference has its reference count decremented. NOTE: colortable's may be assigned + to any bitmap, but are only interpreted for kIndex8_Config bitmaps, where they + are required. + @return the ctable argument + */ + SkColorTable* setColorTable(SkColorTable* ctable); + + /** Initialize the bitmap's pixels with the specified color+alpha, automatically converting into the correct format + for the bitmap's config. If the config is kRGB_565_Config, then the alpha value is ignored. + If the config is kA8_Config, then the r,g,b parameters are ignored. + */ + void eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b); + /** Initialize the bitmap's pixels with the specified color+alpha, automatically converting into the correct format + for the bitmap's config. If the config is kRGB_565_Config, then the alpha value is presumed + to be 0xFF. If the config is kA8_Config, then the r,g,b parameters are ignored and the + pixels are all set to 0xFF. + */ + void eraseRGB(U8CPU r, U8CPU g, U8CPU b) + { + this->eraseARGB(0xFF, r, g, b); + } + /** Initialize the bitmap's pixels with the specified color, automatically converting into the correct format + for the bitmap's config. If the config is kRGB_565_Config, then the color's alpha value is presumed + to be 0xFF. If the config is kA8_Config, then only the color's alpha value is used. + */ + void eraseColor(SkColor c) + { + this->eraseARGB(SkColorGetA(c), SkColorGetR(c), SkColorGetG(c), SkColorGetB(c)); + } + + /** Returns the address of the pixel specified by x,y. + Asserts that x,y are in range, and that the bitmap's config is either kARGB_8888_Config. + */ + // This method is not exported to java. + inline uint32_t* getAddr32(int x, int y) const; + /** Returns the address of the pixel specified by x,y. + Asserts that x,y are in range, and that the bitmap's config is kRGB_565_Config. + */ + // This method is not exported to java. + inline uint16_t* getAddr16(int x, int y) const; + /** Returns the address of the pixel specified by x,y. + Asserts that x,y are in range, and that the bitmap's config is either kA8_Config or kIndex8_Config. + */ + // This method is not exported to java. + inline uint8_t* getAddr8(int x, int y) const; + /** Returns the color corresponding to the pixel specified by x,y. + Asserts that x,y are in range, and that the bitmap's config is kIndex8_Config. + */ + // This method is not exported to java. + inline SkPMColor getIndex8Color(int x, int y) const; + /** Returns the address of the byte containing the pixel specified by x,y. + Asserts that x,y are in range, and that the bitmap's config is kA1_Config. + */ + // This method is not exported to java. + inline uint8_t* getAddr1(int x, int y) const; + + // OS-specific helpers +#ifndef SK_USE_WXWIDGETS +#ifdef SK_BUILD_FOR_WIN + /** On Windows and PocketPC builds, this will draw the SkBitmap onto the + specified HDC + */ + void drawToHDC(HDC, int left, int top) const; +#elif defined(SK_BUILD_FOR_MAC) + /** On Mac OS X and Carbon builds, this will draw the SkBitmap onto the + specified WindowRef + */ + void drawToPort(WindowRef) const; +#endif +#endif + + void buildMipMap(bool forceRebuild); + unsigned countMipLevels() const; + +private: + SkColorTable* fColorTable; // only meaningful for kIndex8 + +#ifdef SK_SUPPORT_MIPMAP + struct MipLevel { + void* fPixels; + uint16_t fWidth, fHeight, fRowBytes; + uint8_t fConfig, fShift; + }; + enum { + kMaxMipLevels = 5 + }; + struct MipMap { + MipLevel fLevel[kMaxMipLevels]; + }; + MipMap* fMipMap; +#endif + + enum Flags { + kWeOwnThePixels_Flag = 0x01, + kWeOwnTheMipMap_Flag = 0x02, + kImageIsOpaque_Flag = 0x04 + }; + + void* fPixels; + uint16_t fWidth, fHeight, fRowBytes; + uint8_t fConfig; + uint8_t fFlags; + + const MipLevel* getMipLevel(unsigned level) const; + + void freePixels(); + + friend class SkBitmapShader; +}; + +/** \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 SkRefCnt { +public: + /** Constructs an empty color table (zero colors). + */ + SkColorTable(); + 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); + + /** 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 != nil && (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(nil, 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(fColorLockCount += 1;) + return fColors; + } + /** Balancing call to lockColors(). If the colors have been changed, pass true. + */ + void unlockColors(bool changed) + { + SkASSERT(fColorLockCount != 0); + SkDEBUGCODE(fColorLockCount -= 1;) + } + + /** Similar to lockColors(), lock16BitCache() returns the array of + RGB16 colors that mirror the 32bit colors. However, this function + will return nil 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); + } + +private: + SkPMColor* fColors; + uint16_t* f16BitCache; + uint16_t fCount; + uint8_t fFlags; + SkDEBUGCODE(int fColorLockCount;) + SkDEBUGCODE(int f16BitCacheLockCount;) + + void inval16BitCache(); +}; + +////////////////////////////////////////////////////////////////////////////////// + +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); + 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/include/graphics/SkBitmapRef.h b/include/graphics/SkBitmapRef.h new file mode 100644 index 000000000..ffecfb6ea --- /dev/null +++ b/include/graphics/SkBitmapRef.h @@ -0,0 +1,58 @@ +#ifndef SkBitmapRef_DEFINED +#define SkBitmapRef_DEFINED + +#include "SkBitmap.h" + +class SkStream; + +/** Helper class to manage a cache of decoded images from the file system +*/ +class SkBitmapRef : public SkRefCnt { +public: + /** Create a non-cached bitmap, trasfering ownership of pixels if needed + */ + SkBitmapRef(const SkBitmap& src, bool transferOwnsPixels); + virtual ~SkBitmapRef(); + + const SkBitmap& bitmap(); + + static SkBitmapRef* create(const SkBitmap& src, bool transferOwnsPixels); + static SkBitmapRef* DecodeFile(const char file[], bool forceDecode); + static SkBitmapRef* DecodeMemory(const void* bytes, size_t len); + static SkBitmapRef* DecodeStream(SkStream* stream); + + /** Frees all cached images, asserting that all references have been removed + */ + static void PurgeCacheAll(); + + /** frees one cached image, returning true, or returns false if none could be freed + */ + static bool PurgeCacheOne(); + +private: + struct Rec; + Rec* fRec; + + SkBitmapRef(Rec*); + + friend class SkBitmapRef_Globals; +}; + +class SkAutoBitmapRef { +public: + SkAutoBitmapRef(const char file[], bool forceDecode) + { + fRef = SkBitmapRef::DecodeFile(file, forceDecode); + } + ~SkAutoBitmapRef() { delete fRef; } + + const SkBitmap* bitmap() const + { + return fRef ? &fRef->bitmap() : nil; + } +private: + SkBitmapRef* fRef; +}; + + +#endif diff --git a/include/graphics/SkBlurMaskFilter.h b/include/graphics/SkBlurMaskFilter.h new file mode 100644 index 000000000..9bbba182c --- /dev/null +++ b/include/graphics/SkBlurMaskFilter.h @@ -0,0 +1,37 @@ +#ifndef SkBlurMaskFilter_DEFINED +#define SkBlurMaskFilter_DEFINED + +#include "SkMaskFilter.h" + +class SkBlurMaskFilter : public SkMaskFilter { +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 + }; + + /** 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 + @return The new blur maskfilter + */ + static SkMaskFilter* Create(SkScalar radius, BlurStyle style); + + /** 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); +}; + +#endif + diff --git a/include/graphics/SkBorderView.h b/include/graphics/SkBorderView.h new file mode 100644 index 000000000..307a91d99 --- /dev/null +++ b/include/graphics/SkBorderView.h @@ -0,0 +1,31 @@ +#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 \ No newline at end of file diff --git a/include/graphics/SkBounder.h b/include/graphics/SkBounder.h new file mode 100644 index 000000000..8bf9dfac7 --- /dev/null +++ b/include/graphics/SkBounder.h @@ -0,0 +1,45 @@ +#ifndef SkBounder_DEFINED +#define SkBounder_DEFINED + +#include "SkTypes.h" +#include "SkRefCnt.h" + +struct SkRect16; +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: + bool doIRect(const SkRect16&, const SkRegion&); + bool doHairline(const SkPoint&, const SkPoint&, const SkPaint&, const SkRegion&); + bool doRect(const SkRect&, const SkPaint&, const SkRegion&); + bool doPath(const SkPath&, const SkPaint&, const SkRegion&, bool doFill); + +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 SkRect16&) = 0; + + /** 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(); + + friend class SkAutoBounderCommit; +}; + +#endif + diff --git a/include/graphics/SkCamera.h b/include/graphics/SkCamera.h new file mode 100644 index 000000000..d39fa8958 --- /dev/null +++ b/include/graphics/SkCamera.h @@ -0,0 +1,80 @@ +#ifndef SkCamera_DEFINED +#define SkCamera_DEFINED + +#include "SkMatrix.h" +#include "Sk64.h" + +#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 + +// Taken from Rob Johnson's most excellent QuickDraw GX library + +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; +}; + +class SkPatch3D { +public: + SkPatch3D(); + + void reset(); + void rotate(SkScalar radX, SkScalar radY, SkScalar radZ); + void rotateDegrees(SkScalar degX, SkScalar degY, SkScalar degZ) + { + this->rotate(SkDegreesToRadians(degX), + SkDegreesToRadians(degY), + SkDegreesToRadians(degZ)); + } + + // dot a unit vector with the patch's normal + SkScalar dotWith(SkScalar dx, SkScalar dy, SkScalar dz) const; + + SkPoint3D fU, fV, fOrigin; +private: + friend class SkCamera3D; +}; + +class SkCamera3D { +public: + SkCamera3D(); + + void update(); + void computeMatrix(const SkPatch3D&, SkMatrix* matrix) const; + + SkPoint3D fLocation; + SkPoint3D fAxis; + SkPoint3D fZenith; + SkPoint3D fObserver; + +private: + SkMatrix fOrientation; +}; + +#endif + diff --git a/include/graphics/SkCanvas.h b/include/graphics/SkCanvas.h new file mode 100644 index 000000000..11dfb9997 --- /dev/null +++ b/include/graphics/SkCanvas.h @@ -0,0 +1,470 @@ +#ifndef SkCanvas_DEFINED +#define SkCanvas_DEFINED + +#include "SkBitmap.h" +#include "SkDeque.h" +#include "SkPaint.h" +#include "SkPorterDuff.h" +#include "SkPath.h" +#include "SkRegion.h" + +class SkBounder; + +/** \class SkCanvas + + The SkCanvas class holds the "draw" calls. To draw something, you need + 4 basic components: A SkBitmap to hold the pixels, a SkCanvas to host + the draw calls (writing into the bitmap), a drawing primitive (e.g. SkRect, SkPath, + text, SkBitmap), and a paint (to describe the colors and styles for the drawing). +*/ +class SkCanvas { +public: + /** Construct an empty canvas. Use setPixels() to specify a bitmap to draw into. + */ + SkCanvas(); + /** Construct a canvas with the specified bitmap to draw into. + @param bitmap Specifies a bitmap for the canvas to draw into. Its contents are copied to the canvas. + */ + SkCanvas(const SkBitmap& bitmap); + ~SkCanvas(); + + /** Return a copy of the bitmap that the canvas draws into. This does not make a copy + of the bitmap's pixels, but just returns the pixel's address. + @param bitmap The bitmap, allocated by the caller, that receives a copy of the canvas' bitmap + (the one specified in the setPixels() call, or in the constructor). + */ + void getPixels(SkBitmap* bitmap) const; + /** Specify a bitmap for the canvas to draw into. This routine makes a copy of the bitmap, + but does not copy the actual pixels. Ownership of the bitmap's pixels stays with the caller's + bitmap. + @param bitmap Specifies a new bitmap for the canvas to draw into. Its contents are copied to the canvas. + */ + void setPixels(const SkBitmap& bitmap); + + /** Return true if the bitmap that the current layer draws into is always opaque + (i.e. does not support per-pixel alpha). e.g. kARGB_8888_Config returns false, + kARGB_565_Config returns true. + @return true if the bitmap that the current layer draws into is always opaque + */ + bool isBitmapOpaque() const; + + /** Return the width of the bitmap that the current layer draws into + @return the width of the bitmap that the current layer draws into + */ + int getBitmapWidth() const { return this->getCurrBitmap().width(); } + /** Return the height of the bitmap that the current layer draws into + @return the height of the bitmap that the current layer draws into + */ + int getBitmapHeight() const { return this->getCurrBitmap().height(); } + + /** This call saves the current matrix and clip information, and pushes a copy onto a + private stack. Subsequent calls to translate,scale,rotate,skew,concat or clipRect,clipPath + all operate on this copy. When the balancing call to restore() is made, this copy is deleted + and the previous matrix/clip state is restored. + @return The value to pass to restoreToCount() to balance this save() + */ + int save(); + /** 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). + Subsequent calls to translate,scale,rotate,skew,concat or clipRect,clipPath + all operate on this copy. When the balancing call to restore() is made, this copy is deleted + and the previous matrix/clip state is restored. + @param bounds The maximum size the offscreen bitmap needs to be (in local coordinates) + @param paint This is copied, and is applied to the offscreen when restore() is called. + @return The value to pass to restoreToCount() to balance this save() + */ + int saveLayer(const SkRect& bounds, const SkPaint& paint); + /** This call balances a previous call to save(), and is used to remove all modifications to + the matrix/clip state since the last save call. It is an error to call restore() more times + than save() was called. + */ + 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); + + /** 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) + */ + bool translate(SkScalar dx, SkScalar dy); + /** Preconcat the current matrix with the specified scale and pivot point. + The pivot is the point that will remain unchanged after the scale is applied. + @param sx The amount to scale in X, about the pivot point (px,py) + @param sy The amount to scale in Y, about the pivot point (px,py) + @param px The pivot's X coordinate + @param py The pivot's Y coordinate + returns true if the operation succeeded (e.g. did not overflow) + */ + bool scale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py); + /** Preconcat the current matrix with the specified rotation and pivot point. + The pivot is the point that will remain unchanged after the rotation is applied. + @param degrees The amount to rotate, in degrees + @param px The pivot's X coordinate + @param py The pivot's Y coordinate + returns true if the operation succeeded (e.g. did not overflow) + */ + bool rotate(SkScalar degrees, SkScalar px, SkScalar py); + /** Preconcat the current matrix with the specified skew and pivot point. + The pivot is the point that will remain unchanged after the skew is applied. + @param sx The amount to skew in X, about the pivot point (px,py) + @param sy The amount to skew in Y, about the pivot point (px,py) + @param px The pivot's X coordinate + @param py The pivot's Y coordinate + returns true if the operation succeeded (e.g. did not overflow) + */ + bool skew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py); + /** 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) + */ + bool concat(const SkMatrix& matrix); + + /** Intersect the current clip with the specified rectangle. + @param rect The rect to intersect with the current clip + */ + void clipRect(const SkRect& rect); + /** Intersect the current clip with the specified rectangle. + @param left The left side of the rectangle to intersect with the current clip + @param top The top side of the rectangle to intersect with the current clip + @param right The right side of the rectangle to intersect with the current clip + @param bottom The bottom side of the rectangle to intersect with the current clip + */ + void clipRect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom); + /** Intersect the current clip with the specified path. + @param path The path to intersect with the current clip + */ + void clipPath(const SkPath& path); + /** Intersect the current clip with the specified region. Note that unlike clipRect() + and clipPath() which transform their arguments by the current matrix, clipDeviceRgn() + assumes its argument is already in the coordinate system of the current layer's bitmap, + and so not transformation is performed. + @param deviceRgn The region to intersect with the current clip + */ + void clipDeviceRgn(const SkRegion& deviceRgn); + + /** 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 + @param antialiased true if the rect should be considered antialiased, since that means it may + affect a larger area (more pixels) than non-antialiased. + @return true if the rect (transformed by the canvas' matrix) does not intersect with the canvas' clip + */ + bool quickReject(const SkRect& rect, bool antialiased = false) 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 doesnot). + @param path The path to compare with the current clip + @param antialiased true if the path should be considered antialiased, since that means it may + affect a larger area (more pixels) than non-antialiased. + @return true if the path (transformed by the canvas' matrix) does not intersect with the canvas' clip + */ + bool quickReject(const SkPath& path, bool antialiased = false) const; + /** 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 left The left side of the rectangle to compare with the current clip + @param top The top side of the rectangle to compare with the current clip + @param right The right side of the rectangle to compare with the current clip + @param bottom The bottom side of the rectangle to compare with the current clip + @param antialiased true if the rect should be considered antialiased, since that means it may + affect a larger area (more pixels) than non-antialiased. + @return true if the rect (transformed by the canvas' matrix) does not intersect with the canvas' clip + */ + bool quickReject(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom, bool antialiased = false) const + { + SkRect r; + r.set(left, top, right, bottom); + return this->quickReject(r, antialiased); + } + + /** Fill the entire canvas' bitmap (restricted to the current clip) with the + specified RGB color, using srcover porterduff mode. + @param r the red component (0..255) of the color used to draw onto the canvas + @param g the green component (0..255) of the color used to draw onto the canvas + @param b the blue component (0..255) of the color used to draw onto the canvas + */ + void drawRGB(U8CPU r, U8CPU g, U8CPU b); + /** Fill the entire canvas' bitmap (restricted to the current clip) with the + specified ARGB color, using srcover porterduff mode. + @param a the alpha component (0..255) of the color used to draw onto the canvas + @param r the red component (0..255) of the color used to draw onto the canvas + @param g the green component (0..255) of the color used to draw onto the canvas + @param b the blue component (0..255) of the color used to draw onto the canvas + */ + void drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b); + /** Fill the entire canvas' bitmap (restricted to the current clip) with the + specified color, using srcover porterduff mode. + @param color the color to draw onto the canvas + */ + void drawColor(SkColor color) + { + this->drawColor(color, SkPorterDuff::kSrcOver_Mode); + } + /** Fill the entire canvas' bitmap (restricted to the current clip) with the + specified color and porter-duff xfermode. + @param color the color to draw with + @param mode the porter-duff mode to apply to the color + */ + void drawColor(SkColor color, SkPorterDuff::Mode mode); + + /** Fill the entire canvas' bitmap (restricted to the current clip) with the + specified paint. This is equivalent (but faster) to drawing an infinitely + large rectangle with the specified paint. + @param paint The paint used to draw onto the canvas + */ + void drawPaint(const SkPaint& paint); + /** Draw a line segment with the specified start and stop points, using the specified + paint. NOTE: since a line is always "framed", the Style is ignored in + the paint. + @param start The start point of the line + @param stop The stop point of the line + @param paint The paint used to draw the line + */ + void drawLine(const SkPoint& start, const SkPoint& stop, const SkPaint& paint); + /** 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 Style is ignored in + the paint. + @param startX The x-coordinate of the start point of the line + @param startY The y-coordinate of the start point of the line + @param endX The x-coordinate of the end point of the line + @param endY The y-coordinate of the end point of the line + @param paint The paint used to draw the line + */ + void drawLine(SkScalar startX, SkScalar startY, SkScalar stopX, SkScalar stopY, const SkPaint& paint); + /** Draw the specified SkRect 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 drawRect(const SkRect& rect, const SkPaint& paint); + /** Draw the specified SkRect 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 drawRect(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 + */ + void drawOval(const SkRect& oval, const SkPaint&); + /** 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 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 + */ + 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. + @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 + */ + void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, const SkPaint& paint); + /** Draw the specified bitmap, with its top/left corner at (x,y), transformed + by the current matrix. Since no paint is specified, the bitmap is drawn with no overriding + alpha or colorfilter, and in srcover porterduff mode. + @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 + */ + void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top); + /** Draw the specified bitmap, with its top/left corner at (x,y), NOT transformed + by the current matrix. This method is not exported to java. + @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 + */ + void drawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint& paint); + /** Draw the utf8-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 UTF8 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) + */ + void drawText(const char text[], size_t byteLength, SkScalar x, SkScalar y, const SkPaint& paint); + /** Draw the utf8-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 UTF16 text to be drawn + @param numberOf16BitValues The number of 16bit values 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) + */ + void drawText16(const uint16_t text[], size_t numberOf16BitValues, SkScalar x, SkScalar y, const SkPaint& paint); + /** Draw the utf8-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 UTF8 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) + */ + void drawPosText(const char text[], size_t byteLength, const SkPoint pos[], const SkPaint& paint); + /** Draw the utf8-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 UTF16 text to be drawn + @param numberOf16BitValues The number of 16bit values 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) + */ + void drawPosText16(const uint16_t text[], size_t numberOf16BitValues, const SkPoint pos[], const SkPaint& paint); + /** Draw the utf8-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 UTF8 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 distance The distance along the path to add to the text's starting position + @param paint The paint used for the text (e.g. color, size, style) + */ + void drawTextOnPath(const char text[], size_t byteLength, const SkPath& path, SkScalar distance, const SkPaint& paint); + /** Draw the utf8-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 UTF16 text to be drawn + @param numberOf16BitValues The number of 16bit values to read from the text parameter + @param path The path the text should follow for its baseline + @param offset The distance along the path to add to the text's starting position + @param paint The paint used for the text (e.g. color, size, style) + */ + void drawText16OnPath(const uint16_t text[], size_t numberOf16BitValues, const SkPath& path, SkScalar distance, const SkPaint& paint); + + /** Return the current set mask, used to temporarily modify the paint's flags + when something is being drawin. + This method is not exported to java. + */ + uint32_t getPaintSetBits() const; + /** Return the current clear mask, used to temporarily modify the paint's flags + when something is being drawin. + This method is not exported to java. + */ + uint32_t getPaintClearBits() const; + /** Set the current set and clear masks, used to temporarily modify the paint's flags + when something is being drawin. The setBits are applied before the clrBits. + This method is not exported to java. + @param setBits A mask of bits to be OR'd into the paint's flag bits + @param clrBits A mask of bits to be cleared from the paint's flag bits + */ + void setPaintSetClearBits(uint32_t setBits, uint32_t clrBits); + /** Helper for getPaintSetClearBits/setPaintSetClearBits. The parameters are OR'd into + the current values, rather than replacing them as with setPaintSetClearBits. + This method is not exported to java. + @param setBits A mask of bits to be OR'd with the existing setBits on the canvas + @param clearBits A mask of bits to be OR'd with the existing clearBits on the canvas + */ + void orPaintSetClearBits(uint32_t setBits, uint32_t clearBits); + + /** Get the current bounder object. +

+ The bounder's reference count is not affected. + @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 + */ + SkBounder* setBounder(SkBounder*); + + /** Return a reference to the bitmap that the current layer draws into. + This method is not exported to java. + @return The a reference to the bitmap that the current layer draws into. + */ + const SkBitmap& getCurrBitmap() const; + /** Return the MapPtProc for the current matrix on the canvas. + This method is not exported to java. + @return the MapPtProc for the current matrix on the canvas. + */ + SkMatrix::MapPtProc getCurrMapPtProc() const; + /** Return the current matrix on the canvas. + This method is not exported to java. + @return The current matrix on the canvas. + */ + const SkMatrix& getTotalMatrix() const; + /** Return the current device clip (concatenation of all clip calls). + This method is not exported to java. + @return the current device clip (concatenation of all clip calls). + */ + const SkRegion& getTotalClip() const; + +private: + struct MCRec; + + SkDeque fMCStack; + MCRec* fMCRec; // points to top of stack + uint32_t fMCRecStorage[32]; // the first N recs that can fit here mean we won't call malloc + + SkBitmap fBitmap; + SkBounder* fBounder; + + friend class SkDraw; +}; + +/** 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 { +public: + SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas) + { + SkASSERT(canvas); + fSaveCount = canvas->getSaveCount(); + if (doSave) + canvas->save(); + } + ~SkAutoCanvasRestore() + { + fCanvas->restoreToCount(fSaveCount); + } + +private: + SkCanvas* fCanvas; + int fSaveCount; +}; + +#endif + diff --git a/include/graphics/SkColor.h b/include/graphics/SkColor.h new file mode 100644 index 000000000..6df71ea40 --- /dev/null +++ b/include/graphics/SkColor.h @@ -0,0 +1,126 @@ +#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 SkColorSetARGB(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); +} + +/** 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) + +#define SkColorGetA(color) ((color) >> 24) //!< return the alpha byte from a SkColor value +#define SkColorGetR(color) ((color) << 8 >> 24) //!< return the red byte from a SkColor value +#define SkColorGetG(color) ((color) << 16 >> 24) //!< return the green byte from a SkColor value +#define SkColorGetB(color) ((color) << 24 >> 24) //!< return the blue byte from a SkColor value + +// common colors + +#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. +*/ +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 +*/ +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 +*/ +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. +*/ +SkPMColor SkPreMultiplyColor(SkColor c); + +/** Define a function pointer type for combining two premultiplied colors +*/ +typedef SkPMColor (*SkXfermodeProc)(SkPMColor src, SkPMColor dst); + +#endif + diff --git a/include/graphics/SkColorFilter.h b/include/graphics/SkColorFilter.h new file mode 100644 index 000000000..91879aeeb --- /dev/null +++ b/include/graphics/SkColorFilter.h @@ -0,0 +1,56 @@ +#ifndef SkColorFilter_DEFINED +#define SkColorFilter_DEFINED + +#include "SkRefCnt.h" +#include "SkColor.h" +#include "SkPorterDuff.h" + +class SkColorFilter : public SkRefCnt { +public: + /** Called with a scanline of colors, as if there was a shader installed. + The implementation writes out its filtered version into result[]. + @param shader array of colors, possibly generated by a shader + @param count the number of entries in the shader[] and result[] arrays + @param result written by the filter, these are the colors that are used to draw + */ + virtual void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]); + + /** Create a colorfilter that uses the specified color and xfermode proc. + @param srcColor The source color passed to the xfermode proc + @param proc The xfermode proc that is applied to each color in the colorfilter's filterSpan method + @return colorfilter object that applies the src color and xfermode proc, or NULL if proc is NULL + */ + static SkColorFilter* CreatXfermodeFilter(SkColor srcColor, SkXfermodeProc proc); + /** Create a colorfilter that uses the specified color and porter-duff mode. + @param srcColor The source color used with the specified porter-duff mode + @param porterDuffMode The porter-duff mode that is applied to each color in the colorfilter's filterSpan method + @return colorfilter object that applies the src color and porter-duff mode, or NULL is mode is out of range + */ + static SkColorFilter* CreatePorterDuffFilter(SkColor srcColor, SkPorterDuff::Mode porterDuffMode); + + /** 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); +}; + +#include "SkShader.h" + +class SkFilterShader : public SkShader { +public: + SkFilterShader(SkShader* shader, SkColorFilter* filter); + virtual ~SkFilterShader(); + + // override + virtual bool setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix); + virtual void shadeSpan(int x, int y, SkPMColor result[], int count); + +private: + SkShader* fShader; + SkColorFilter* fFilter; + + typedef SkShader INHERITED; +}; + +#endif diff --git a/include/graphics/SkColorPriv.h b/include/graphics/SkColorPriv.h new file mode 100644 index 000000000..65b5851d5 --- /dev/null +++ b/include/graphics/SkColorPriv.h @@ -0,0 +1,218 @@ +#ifndef SkColorPriv_DEFINED +#define SkColorPriv_DEFINED + +#include "SkColor.h" + +inline unsigned SkAlpha255To256(U8CPU alpha) +{ + SkASSERT(SkToU8(alpha) == alpha); + return alpha + (alpha >> 7); +} + +#define SkAlphaMul(value, alpha256) ((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) +inline int SkAlphaBlend(int src, int dst, int scale256) +{ + SkASSERT((unsigned)scale256 <= 256); + return dst + SkAlphaMul(src - dst, scale256); +} + +#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) + +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)); +} + +inline int SkShouldDitherXY(int x, int y) +{ + return (x ^ y) & 1; +} + +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); +} + +#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) + +#define SK_R16B16_MASK_IN_PLACE (SK_R16_MASK_IN_PLACE | SK_B16_MASK_IN_PLACE) + +inline U16CPU SkAlphaMulRGB16(U16CPU c, unsigned scale) +{ +#if SK_G16_MASK_IN_PLACE != 0x07E0 + return SkPackRGB16( SkAlphaMul(SkGetPackedR16(c), scale), + SkAlphaMul(SkGetPackedG16(c), scale), + SkAlphaMul(SkGetPackedB16(c), scale)); +#else + scale >>= (8 - SK_G16_BITS); + uint32_t rb = (c & SK_R16B16_MASK_IN_PLACE) * scale >> SK_G16_BITS; + uint32_t g = (c & SK_G16_MASK_IN_PLACE) * scale >> SK_G16_BITS; + return (g & SK_G16_MASK_IN_PLACE) | (rb & SK_R16B16_MASK_IN_PLACE); +#endif +} + +inline U16CPU SkBlendRGB16(U16CPU src, U16CPU dst, unsigned scale) +{ + SkASSERT(scale <= 256); + + return SkPackRGB16( SkAlphaBlend(SkGetPackedR16(src), SkGetPackedR16(dst), scale), + SkAlphaBlend(SkGetPackedG16(src), SkGetPackedG16(dst), scale), + SkAlphaBlend(SkGetPackedB16(src), SkGetPackedB16(dst), scale)); +} + +///////////////////////////////////////////////////////////////////////////////////////////// + +#define SK_A32_BITS 8 +#define SK_R32_BITS 8 +#define SK_G32_BITS 8 +#define SK_B32_BITS 8 + +#ifdef TEST_INTEL_MAC + +#define SK_A32_SHIFT 0 +#define SK_R32_SHIFT 8 +#define SK_G32_SHIFT 16 +#define SK_B32_SHIFT 24 + +#else + +#define SK_A32_SHIFT 24 +#define SK_R32_SHIFT 16 +#define SK_G32_SHIFT 8 +#define SK_B32_SHIFT 0 + +#endif + +#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) + +inline SkPMColor SkPackARGB32(U8CPU a, U8CPU r, U8CPU g, U8CPU b) +{ + SkASSERT(a <= SK_A32_MASK); + 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); +} + +inline uint32_t SkAlphaMulQ(uint32_t c, unsigned scale) +{ + uint32_t rb = ((c & 0xFF00FF) * scale) >> 8; + uint32_t ag = ((c >> 8) & 0xFF00FF) * scale; + return (rb & 0xFF00FF) | (ag & ~0xFF00FF); +} + +inline SkPMColor SkPMSrcOver(SkPMColor src, SkPMColor dst) +{ + return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src))); +} + +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(r) ((unsigned)(r) >> (SK_R32_BITS - SK_R16_BITS)) +#define SkG32ToG16(g) ((unsigned)(g) >> (SK_G32_BITS - SK_G16_BITS)) +#define SkB32ToB16(b) ((unsigned)(b) >> (SK_B32_BITS - SK_B16_BITS)) + +#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) + +inline U16CPU SkPixel32ToPixel16(SkPMColor src) +{ +#if 0 + return (SkPacked32ToR16(src) << SK_R16_SHIFT) | + (SkPacked32ToG16(src) << SK_G16_SHIFT) | + (SkPacked32ToB16(src) << SK_B16_SHIFT); +#else // only works if the components are in the same order in both formats (i.e. foo32_shift >= foo16_shift) + return ((src >> (SK_R32_SHIFT + SK_R32_BITS - SK_R16_BITS - SK_R16_SHIFT)) & (SK_R16_MASK << SK_R16_SHIFT)) | + ((src >> (SK_G32_SHIFT + SK_G32_BITS - SK_G16_BITS - SK_G16_SHIFT)) & (SK_G16_MASK << SK_G16_SHIFT)) | + ((src >> (SK_B32_SHIFT + SK_B32_BITS - SK_B16_BITS - SK_B16_SHIFT)) & (SK_B16_MASK << SK_B16_SHIFT)); +#endif +} + +#define SkPixel32ToPixel16_ToU16(src) SkToU16(SkPixel32ToPixel16(src)) + +//////////////////////////////////////////////////////////////////////////////////////////// +// Convert a 16bit pixel to a 32bit pixel + +inline unsigned SkR16ToR32(unsigned r) +{ + return (r << (8 - SK_R16_BITS)) | (r >> (2 * SK_R16_BITS - 8)); +} +inline unsigned SkG16ToG32(unsigned g) +{ + return (g << (8 - SK_G16_BITS)) | (g >> (2 * SK_G16_BITS - 8)); +} +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)) + +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); +} + +#endif + diff --git a/include/graphics/SkCornerPathEffect.h b/include/graphics/SkCornerPathEffect.h new file mode 100644 index 000000000..4307c707b --- /dev/null +++ b/include/graphics/SkCornerPathEffect.h @@ -0,0 +1,45 @@ +#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 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(); + + // overrides for SkPathEffect + // This method is not exported to java. + virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width); + + // overrides for SkFlattenable + // This method is not exported to java. + virtual Factory getFactory(); + // This method is not exported to java. + virtual void flatten(SkWBuffer&); + +protected: + SkCornerPathEffect(SkRBuffer&); + +private: + SkScalar fRadius; + + static SkFlattenable* CreateProc(SkRBuffer&); + + // illegal + SkCornerPathEffect(const SkCornerPathEffect&); + SkCornerPathEffect& operator=(const SkCornerPathEffect&); + + typedef SkPathEffect INHERITED; +}; + +#endif + diff --git a/include/graphics/SkCullPoints.h b/include/graphics/SkCullPoints.h new file mode 100644 index 000000000..def938d7a --- /dev/null +++ b/include/graphics/SkCullPoints.h @@ -0,0 +1,58 @@ +#ifndef SkCullPoints_DEFINED +#define SkCullPoints_DEFINED + +#include "SkRect.h" + +class SkCullPoints { +public: + SkCullPoints(); + SkCullPoints(const SkRect16& r); + + void reset(const SkRect16& 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, SkPoint16 pts[2]); + +private: + SkRect16 fR; + SkPoint16 fAsQuad[4]; + SkPoint32 fPrevPt; // local 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 SkRect16& r, SkPath* dst); + + void reset(const SkRect16& r, SkPath* dst); + + void moveTo(int x, int y); + void lineTo(int x, int y); + +private: + SkCullPoints fCP; + SkPath* fPath; +}; + +#endif diff --git a/include/graphics/SkDOM.h b/include/graphics/SkDOM.h new file mode 100644 index 000000000..6567a8956 --- /dev/null +++ b/include/graphics/SkDOM.h @@ -0,0 +1,83 @@ +#ifndef SkDOM_DEFINED +#define SkDOM_DEFINED + +#include "SkChunkAlloc.h" +#include "SkMath.h" +#include "SkTemplates.h" + +struct SkDOMNode; +struct SkDOMAttr; + +class SkDOM { +public: + SkDOM(); + ~SkDOM(); + + typedef SkDOMNode Node; + typedef SkDOMAttr Attr; + + /** Returns nil 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[] = nil) const; + const Node* getNextSibling(const Node*, const char elem[] = nil) 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[] = nil) 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 = nil, int tabLevel = 0) const;) + SkDEBUGCODE(static void UnitTest();) + +private: + SkChunkAlloc fAlloc; + Node* fRoot; + friend class AttrIter; + friend class SkDOMParser; +}; + +#endif + diff --git a/include/graphics/SkDashPathEffect.h b/include/graphics/SkDashPathEffect.h new file mode 100644 index 000000000..0e567ef41 --- /dev/null +++ b/include/graphics/SkDashPathEffect.h @@ -0,0 +1,49 @@ +#ifndef SkDashPathEffect_DEFINED +#define SkDashPathEffect_DEFINED + +#include "SkPathEffect.h" + +/** \class SkDashPathEffect + + SkDashPathEffect is a subclass of SkPathEffect that implements dashing +*/ +class SkDashPathEffect : public SkPathEffect { +public: + /** The intervals array must contain an even number of entries (>=2), with the even + indices specifying the "on" intervals, and the odd indices specifying the "off" + intervals. phase is an offset into the intervals array (mod the sum of all of the + intervals). + Note: only affects framed paths + */ + SkDashPathEffect(const SkScalar intervals[], int count, SkScalar phase, bool scaleToFit = false); + virtual ~SkDashPathEffect(); + + // overrides for SkPathEffect + // This method is not exported to java. + virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width); + + // overrides for SkFlattenable + // This method is not exported to java. + virtual Factory getFactory(); + // This method is not exported to java. + virtual void flatten(SkWBuffer&); + +protected: + SkDashPathEffect(SkRBuffer&); + +private: + SkScalar* fIntervals; + int32_t fCount; + // computed from phase + SkScalar fInitialDashLength; + int32_t fInitialDashIndex; + SkScalar fIntervalLength; + bool fScaleToFit; + + static SkFlattenable* CreateProc(SkRBuffer&); + + typedef SkPathEffect INHERITED; +}; + +#endif + diff --git a/include/graphics/SkDeque.h b/include/graphics/SkDeque.h new file mode 100644 index 000000000..09677020a --- /dev/null +++ b/include/graphics/SkDeque.h @@ -0,0 +1,191 @@ +#ifndef SkTDeque_DEFINED +#define SkTDeque_DEFINED + +#include "SkTypes.h" + +template struct sk_trait_trivial_constructor { enum { value = false }; }; +template struct sk_trait_trivial_destructor { enum { value = false }; }; +template struct sk_trait_trivial_copy { enum { value = false }; }; +template struct sk_trait_trivial_assign { enum { value = false }; }; + +template struct sk_traits { + enum { + has_trivial_constructor = sk_trait_trivial_constructor::value, + has_trivial_destructor = sk_trait_trivial_destructor::value, + has_trivial_copy = sk_trait_trivial_copy::value, + has_trivial_assign = sk_trait_trivial_assign::value + }; +}; + +#define SK_SET_BASIC_TRAITS(T) \ + template <> struct sk_trait_trivial_constructor { enum { value = true }; }; \ + template <> struct sk_trait_trivial_destructor { enum { value = true }; }; \ + template <> struct sk_trait_trivial_copy { enum { value = true }; }; \ + template <> struct sk_trait_trivial_assign { enum { value = true }; } + +#define SK_SET_TYPE_TRAITS(T, ctor, dtor, copy, asgn) \ + template <> struct sk_trait_trivial_constructor { enum { value = ctor }; }; \ + template <> struct sk_trait_trivial_destructor { enum { value = dtor }; }; \ + template <> struct sk_trait_trivial_copy { enum { value = copy }; }; \ + template <> struct sk_trait_trivial_assign { enum { value = asgn }; } + +#include + +class SkDeque { +public: + SkDeque(size_t elemSize); + SkDeque(size_t elemSize, void* storage, size_t storageSize); + ~SkDeque(); + + bool empty() const { return fCount == 0; } + int count() const { return fCount; } + + const void* front() const; + const void* back() const; + + void* front() + { + return (void*)((const SkDeque*)this)->front(); + } + void* back() + { + return (void*)((const SkDeque*)this)->back(); + } + + void* push_front(); + void* push_back(); + + void pop_front(); + void pop_back(); + + SkDEBUGCODE(static void UnitTest();) + +private: + struct Head; + +public: + class Iter { + public: + Iter(const SkDeque& d); + void* next(); + + private: + SkDeque::Head* fHead; + char* fPos; + size_t fElemSize; + }; + +private: + Head* fFront; + Head* fBack; + size_t fElemSize; + void* fInitialStorage; + int fCount; + + friend class Iter; +}; + +template class SkTDeque { +public: + SkTDeque() : fD(sizeof(T)) {} + SkTDeque(T storage[], int count) : fD(sizeof(T), storage, count * sizeof(T)) {} + inline ~SkTDeque(); + + bool empty() const { return fD.empty(); } + int count() const { return fD.count(); } + + T* front() { return (T*)fD.front(); } + const T* front() const { return (const T*)fD.front(); } + T* back() { return (T*)fD.back(); } + const T* back() const { return (const T*)fD.back(); } + + T* push_front() + { + T* front = (T*)fD.push_front(); + if (!sk_traits::has_trivial_constructor) { + new(front) T(); + } + return front; + } + T* push_back() + { + T* back = (T*)fD.push_back(); + if (!sk_traits::has_trivial_constructor) { + new(back) T(); + } + return back; + } + + T* push_front(const T& value) + { + T* front = (T*)fD.push_front(); + if (sk_traits::has_trivial_copy) { + *front = value; + } + else { + new(front) T(value); + } + return front; + } + T* push_back(const T& value) + { + T* back = (T*)fD.push_back(); + if (sk_traits::has_trivial_copy) { + *back = value; + } + else { + new(back) T(value); + } + return back; + } + + void pop_front() + { + if (!sk_traits::has_trivial_destructor) { + this->front()->~T(); + } + fD.pop_front(); + } + void pop_back() + { + if (!sk_traits::has_trivial_destructor) { + this->back()->~T(); + } + fD.pop_back(); + } + + class Iter : private SkDeque::Iter { + public: + Iter(const SkTDeque& d) : SkDeque::Iter(d.fD) {} + T* next() { return (T*)SkDeque::Iter::next(); } + }; + +private: + SkDeque fD; + + friend class Iter; +}; + +template class SkSTDeque : public SkTDeque { +public: + SkSTDeque() : SkTDeque((T*)fStorage, COUNT) {} + +private: + uint32_t fStorage[SkAlign4(COUNT * sizeof(T))]; +}; + +//////////////////////////////////////////////////////////////////////////////////// + +template inline SkTDeque::~SkTDeque() +{ + if (!sk_traits::has_trivial_destructor) + { + Iter iter(*this); + T* t; + while ((t = iter.next()) != nil) { + t->~T(); + } + } +} + +#endif diff --git a/include/graphics/SkDescriptor.h b/include/graphics/SkDescriptor.h new file mode 100644 index 000000000..b43114489 --- /dev/null +++ b/include/graphics/SkDescriptor.h @@ -0,0 +1,158 @@ +#ifndef SkDescriptor_DEFINED +#define SkDescriptor_DEFINED + +#include "SkTypes.h" + +class SkDescriptor { +public: + static size_t ComputeOverhead(int entryCount) + { + SkASSERT(entryCount >= 0); + return sizeof(SkDescriptor) + entryCount * sizeof(Entry); + } + + static SkDescriptor* Alloc(size_t length) + { + SkASSERT(SkAlign4(length) == length); + SkDescriptor* desc = (SkDescriptor*)sk_malloc_throw(length); + return desc; + } + + static void Free(SkDescriptor* desc) + { + sk_free(desc); + } + + void init() + { + fLength = sizeof(SkDescriptor); + fCount = 0; + } + + U32 getLength() const { return fLength; } + + void* addEntry(U32 tag, U32 length, const void* data = nil) + { + SkASSERT(tag); + SkASSERT(SkAlign4(length) == length); + SkASSERT(this->findEntry(tag, nil) == nil); + + Entry* entry = (Entry*)((char*)this + fLength); + entry->fTag = tag; + entry->fLen = length; + if (data) + memcpy(entry + 1, data, length); + + fCount += 1; + fLength += sizeof(Entry) + length; + return (entry + 1); // return its data + } + + void computeChecksum() + { + fChecksum = SkDescriptor::ComputeChecksum(this); + } + +#ifdef SK_DEBUG + void assertChecksum() const + { + SkASSERT(fChecksum == SkDescriptor::ComputeChecksum(this)); + } +#endif + + const void* findEntry(U32 tag, U32* length) const + { + const Entry* entry = (const Entry*)(this + 1); + int count = fCount; + + while (--count >= 0) + { + if (entry->fTag == tag) + { + if (length) + *length = entry->fLen; + return entry + 1; + } + entry = (const Entry*)((const char*)(entry + 1) + entry->fLen); + } + return nil; + } + + SkDescriptor* copy() const + { + SkDescriptor* desc = SkDescriptor::Alloc(fLength); + memcpy(desc, this, fLength); + return desc; + } + + friend bool operator==(const SkDescriptor& a, const SkDescriptor& b) + { + return a.fChecksum == b.fChecksum && + a.fLength == b.fLength && + // this assumes that fCount is the beginning of the rest of the descriptor + // (after fCheckSum and fLength) + memcmp(&a.fCount, &b.fCount, a.fLength - 2*sizeof(U32)) == 0; + } + + struct Entry { + U32 fTag; + U32 fLen; + }; + +#ifdef SK_DEBUG + U32 getChecksum() const { return fChecksum; } + U32 getCount() const { return fCount; } +#endif + +private: + U32 fChecksum; // must be first + U32 fLength; // must be second + U32 fCount; + + static U32 ComputeChecksum(const SkDescriptor* desc) + { + const U32* ptr = (const U32*)desc + 1; // skip the checksum field + const U32* stop = (const U32*)((const char*)desc + desc->fLength); + U32 sum = 0; + + SkASSERT(ptr < stop); + do { + sum = (sum << 1) | (sum >> 31); + sum += *ptr++; + } while (ptr < stop); + + return sum; + } +}; + +#include "SkScalerContext.h" + +class SkAutoDescriptor { +public: + SkAutoDescriptor(size_t size) + { + if (size <= kStorageSize) + fDesc = (SkDescriptor*)fStorage; + else + fDesc = SkDescriptor::Alloc(size); + } + ~SkAutoDescriptor() + { + if (fDesc != (SkDescriptor*)fStorage) + SkDescriptor::Free(fDesc); + } + SkDescriptor* getDesc() const { return fDesc; } +private: + enum { + kStorageSize = sizeof(SkDescriptor) + + sizeof(SkDescriptor::Entry) + sizeof(SkScalerContext::Rec) // for rec + + sizeof(SkDescriptor::Entry) + sizeof(void*) // for typeface + + 32 // slop for occational small extras + }; + SkDescriptor* fDesc; + U32 fStorage[kStorageSize >> 2]; +}; + + +#endif + diff --git a/include/graphics/SkDiscretePathEffect.h b/include/graphics/SkDiscretePathEffect.h new file mode 100644 index 000000000..d3586243f --- /dev/null +++ b/include/graphics/SkDiscretePathEffect.h @@ -0,0 +1,40 @@ +#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 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); + + // overrides for SkPathEffect + // This method is not exported to java. + virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width); + + // overrides for SkFlattenable + // This method is not exported to java. + virtual Factory getFactory(); + // This method is not exported to java. + virtual void flatten(SkWBuffer&); + +protected: + SkDiscretePathEffect(SkRBuffer&); + +private: + SkScalar fSegLength, fPerterb; + + static SkFlattenable* CreateProc(SkRBuffer&); + + typedef SkPathEffect INHERITED; +}; + +#endif + diff --git a/include/graphics/SkDrawExtraPathEffect.h b/include/graphics/SkDrawExtraPathEffect.h new file mode 100755 index 000000000..50a43c618 --- /dev/null +++ b/include/graphics/SkDrawExtraPathEffect.h @@ -0,0 +1,6 @@ +#ifndef SK_DRAW_EXTRA_PATH_EFFECT_H +#define SK_DRAW_EXTRA_PATH_EFFECT_H +class SkAnimator; +void InitializeSkExtraPathEffects(SkAnimator* animator); +#endif + diff --git a/include/graphics/SkEmbossMaskFilter.h b/include/graphics/SkEmbossMaskFilter.h new file mode 100644 index 000000000..5cfa145a0 --- /dev/null +++ b/include/graphics/SkEmbossMaskFilter.h @@ -0,0 +1,47 @@ +#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 SkEmbossMaskFilter : public SkMaskFilter { +public: + struct Light { + SkScalar fDirection[3]; // x,y,z + U16 fPad; + U8 fAmbient; + U8 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(); + // This method is not exported to java. + virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix& matrix, SkPoint16* margin); + + // overrides from SkFlattenable + + // This method is not exported to java. + virtual Factory getFactory(); + // This method is not exported to java. + virtual void flatten(SkWBuffer&); + +protected: + SkEmbossMaskFilter(SkRBuffer&); + +private: + Light fLight; + SkScalar fBlurRadius; + + static SkFlattenable* CreateProc(SkRBuffer&); + + typedef SkMaskFilter INHERITED; +}; + +#endif + diff --git a/include/graphics/SkEvent.h b/include/graphics/SkEvent.h new file mode 100644 index 000000000..d171015ff --- /dev/null +++ b/include/graphics/SkEvent.h @@ -0,0 +1,228 @@ +#ifndef SkEvent_DEFINED +#define SkEvent_DEFINED + +#include "SkDOM.h" +#include "SkMetaData.h" +#include "SkString.h" + +//class SkOSWindow; + +/** 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 U32 SkEventSinkID; + +/** \class SkEvent + + SkEvents are used to communicate type-safe information to SkEventSinks. + SkEventSinks (including SkViews) each have a unique ID, which is stored + in an event. This ID is used to target the event once it has been "posted". +*/ +class SkEvent { +public: + /** Default construct, creating an empty event. + */ + SkEvent(); + /** Construct a new event with the specified type. + */ + explicit SkEvent(const SkString& type); + /** Construct a new event with the specified type. + */ + explicit SkEvent(const char type[]); + /** Construct a new event by copying the fields from the src event. + */ + SkEvent(const SkEvent& src); + ~SkEvent(); + +// /** Return the event's type (will never be nil) */ +// const char* getType() const; + /** 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. + In XML, use the "type" attribute. + */ + void setType(const SkString&); + /** Set the event's type to the specified string. + In XML, use the "type" attribute. + */ + void setType(const char type[], size_t len = 0); + + /** Return the event's unnamed 32bit field. Default value is 0 */ + U32 getFast32() const { return f32; } + /** Set the event's unnamed 32bit field. In XML, use + the subelement + */ + 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-nil). If there is no matching named field, return false + and ignore the value parameter. + */ + bool findS32(const char name[], int32_t* value = nil) 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-nil). If there is no matching named field, return false + and ignore the value parameter. + */ + bool findScalar(const char name[], SkScalar* value = nil) 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-nil), and return the number of SkScalars in count (if count is non-nil). + 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[] = nil) const { return fMeta.findScalars(name, count, values); } + /** Return the value of the named string field, or if no matching named field exists, return nil. + */ + 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-nil). 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); } + + /** 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); } + + /** Add/replace the named 32bit field to the event. In XML use the subelement */ + 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 */ + 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[] = nil) { return fMeta.setScalars(name, count, values); } + /** Add/replace the named string field to the event. In XML use the subelement + 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. + @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, + TileMode mode, + SkUnitMapper* mapper = NULL); + + /** Returns a shader that generates a radial gradient given the center and radius. +

+ 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. + @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, + TileMode mode, + SkUnitMapper* mapper = NULL); +}; + +#endif + diff --git a/include/graphics/SkGraphics.h b/include/graphics/SkGraphics.h new file mode 100644 index 000000000..96c3f1153 --- /dev/null +++ b/include/graphics/SkGraphics.h @@ -0,0 +1,30 @@ +#ifndef SkGraphics_DEFINED +#define SkGraphics_DEFINED + +#include "SkTypes.h" + +class SkGraphics { +public: + static void Init(bool runUnitTests); + static void Term(); + + /** Call this if the heap that the graphics engine uses is low on memory. + It will attempt to free some of its caches. Returns true if it was + able to, or false if it could do nothing. + + This may be called from any thread, and guarantees not to call + new or sk_malloc (though it will hopefully call delete and/or sk_free). + It also will never throw an exception. + */ + static bool FreeCaches(size_t bytesNeeded); + +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(); +}; + +#endif + diff --git a/include/graphics/SkImageDecoder.h b/include/graphics/SkImageDecoder.h new file mode 100644 index 000000000..e5c7f3cb0 --- /dev/null +++ b/include/graphics/SkImageDecoder.h @@ -0,0 +1,130 @@ +#ifndef SkImageDecoder_DEFINED +#define SkImageDecoder_DEFINED + +#include "SkBitmap.h" +#include "SkBitmapRef.h" + +class SkStream; + +/** \class SkImageDecoder + + Base class for decoding compressed images into a SkBitmap +*/ +class SkImageDecoder { +public: + virtual ~SkImageDecoder(); + + /** Decode the image stored in the specified file, and store the result + in bitmap. Return true for success or false on failure. + + If pref is kNo_Config, then the decoder is free to choose the most natural + config given the image data. If pref something other than kNo_Config, + the decoder will attempt to decode the image into that format, unless + there is a conflict (e.g. the image has per-pixel alpha and the bitmap's + config does not support that), in which case the decoder will choose a + closest match configuration. + */ + static bool DecodeFile(const char file[], SkBitmap* bitmap, + SkBitmap::Config pref = SkBitmap::kNo_Config); + /** Decode the image stored in the specified memory buffer, and store the result + in bitmap. Return true for success or false on failure. + + If pref is kNo_Config, then the decoder is free to choose the most natural + config given the image data. If pref something other than kNo_Config, + the decoder will attempt to decode the image into that format, unless + there is a conflict (e.g. the image has per-pixel alpha and the bitmap's + config does not support that), in which case the decoder will choose a + closest match configuration. + */ + static bool DecodeMemory(const void* buffer, size_t size, SkBitmap* bitmap, + SkBitmap::Config pref = SkBitmap::kNo_Config); + /** Decode the image stored in the specified SkStream, and store the result + in bitmap. Return true for success or false on failure. + + If pref is kNo_Config, then the decoder is free to choose the most natural + config given the image data. If pref something other than kNo_Config, + the decoder will attempt to decode the image into that format, unless + there is a conflict (e.g. the image has per-pixel alpha and the bitmap's + config does not support that), in which case the decoder will choose a + closest match configuration. + */ + static bool DecodeStream(SkStream*, SkBitmap* bitmap, + SkBitmap::Config pref = SkBitmap::kNo_Config); + + /** Decode the image stored at the specified URL, and store the result + in bitmap. Return true for success or false on failure. The URL restrictions + are device dependent. On Win32 and WinCE, the URL may be ftp, http or + https. + + If pref is kNo_Config, then the decoder is free to choose the most natural + config given the image data. If pref something other than kNo_Config, + the decoder will attempt to decode the image into that format, unless + there is a conflict (e.g. the image has per-pixel alpha and the bitmap's + config does not support that), in which case the decoder will choose a + closest match configuration. + */ + static bool DecodeURL(const char url[], SkBitmap* bitmap, + SkBitmap::Config pref = SkBitmap::kNo_Config); + + /** 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); + + /** @cond UNIT_TEST */ + SkDEBUGCODE(static void UnitTest();) + /** @endcond */ + +protected: + SkImageDecoder(); + + /** Given a stream, decode it into the specified bitmap. + If the decoder can decompress the image, it should call setConfig() on the bitmap, + and then call allocPixels(), which will allocated offscreen memory for the pixels. + It can then set the pixels with the decompressed image. If the image cannot be + decompressed, return false and leave the bitmap unchanged. + */ + virtual bool onDecode(SkStream*, SkBitmap* bitmap, SkBitmap::Config pref) = 0; + +private: + static SkImageDecoder* Factory(SkStream*); +}; + +#ifdef SK_SUPPORT_IMAGE_ENCODE + +class SkWStream; + +class SkImageEncoder { +public: + enum Type { + kJPEG_Type, + kPNG_Type + }; + static SkImageEncoder* Create(Type); + + virtual ~SkImageEncoder(); + + /* Quality ranges from 0..100 */ + + bool encodeFile(const char file[], const SkBitmap&, int quality = 80); + bool encodeStream(SkWStream*, const SkBitmap&, int quality = 80); + +protected: + virtual bool onEncode(SkWStream*, const SkBitmap&, int quality) = 0; +}; + +#endif /* SK_SUPPORT_IMAGE_ENCODE */ + +/////////////////////////////////////////////////////////////////////// + +#endif + diff --git a/include/graphics/SkImageView.h b/include/graphics/SkImageView.h new file mode 100644 index 000000000..78ee5b79d --- /dev/null +++ b/include/graphics/SkImageView.h @@ -0,0 +1,59 @@ +#ifndef SkImageView_DEFINED +#define SkImageView_DEFINED + +#include "SkView.h" +#include "SkString.h" + +class SkAnimator; +class SkBitmap; +struct 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; // nil or copy of caller's matrix ,,,,, + union { + SkAnimator* fAnim; + SkBitmap* fBitmap; + } fData; + U8 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/include/graphics/SkInterpolator.h b/include/graphics/SkInterpolator.h new file mode 100644 index 000000000..c224c8cd6 --- /dev/null +++ b/include/graphics/SkInterpolator.h @@ -0,0 +1,98 @@ +#ifndef SkInterpolator_DEFINED +#define SkInterpolator_DEFINED + +#include "SkMath.h" + +class SkInterpolatorBase { +public: + enum Result { + kNormal_Result, + kFreezeStart_Result, + kFreezeEnd_Result + }; + static SkScalar Blend(SkScalar t, SkScalar blend); +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 no nil, returns the time (in milliseconds) of the + first keyframe. If there are no keyframes, this parameter + is ignored (left unchanged). + @param endTime If no nil, 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 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 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 + }; + static SkScalar ComputeRelativeT(SkMSec time, SkMSec prevTime, SkMSec nextTime, SkScalar blend); + S16 fFrameCount; + U8 fElemCount; + U8 fFlags; + SkScalar fRepeat; + struct SkTimeCode { + SkMSec fTime; + SkScalar fBlend; + }; + 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[], SkScalar blend = SK_Scalar1); + Result timeToValues(SkMSec time, SkScalar values[]) const; + SkDEBUGCODE(static void UnitTest();) +private: + SkScalar* fValues; // pointer into fStorage +#ifdef SK_DEBUG + SkScalar(* fScalarsArray)[10]; +#endif + typedef SkInterpolatorBase INHERITED; +}; + + +#endif + diff --git a/include/graphics/SkJS.h b/include/graphics/SkJS.h new file mode 100644 index 000000000..89fa4d747 --- /dev/null +++ b/include/graphics/SkJS.h @@ -0,0 +1,31 @@ +#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/include/graphics/SkKey.h b/include/graphics/SkKey.h new file mode 100644 index 000000000..4a1297c9a --- /dev/null +++ b/include/graphics/SkKey.h @@ -0,0 +1,47 @@ +#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 +}; + +#endif + diff --git a/include/graphics/SkLayerRasterizer.h b/include/graphics/SkLayerRasterizer.h new file mode 100644 index 000000000..548968a02 --- /dev/null +++ b/include/graphics/SkLayerRasterizer.h @@ -0,0 +1,41 @@ +#ifndef SkLayerRasterizer_DEFINED +#define SkLayerRasterizer_DEFINED + +#include "SkRasterizer.h" +#include "SkDeque.h" +#include "SkScalar.h" + +class SkPaint; + +class SkLayerRasterizer : public SkRasterizer { +public: + SkLayerRasterizer(); + virtual ~SkLayerRasterizer(); + + void addLayer(const SkPaint& paint) + { + this->addLayer(paint, 0, 0); + } + void addLayer(const SkPaint& paint, SkScalar dx, SkScalar dy); + + // overrides from SkFlattenable + virtual Factory getFactory(); + virtual void flatten(SkWBuffer&); + +protected: + SkLayerRasterizer(SkRBuffer&); + + // override from SkRasterizer + virtual bool onRasterize(const SkPath& path, const SkMatrix& matrix, + const SkRect16* clipBounds, + SkMask* mask, SkMask::CreateMode mode); + +private: + SkDeque fLayers; + + static SkFlattenable* CreateProc(SkRBuffer&); + + typedef SkRasterizer INHERITED; +}; + +#endif diff --git a/include/graphics/SkMask.h b/include/graphics/SkMask.h new file mode 100644 index 000000000..8fdf4614f --- /dev/null +++ b/include/graphics/SkMask.h @@ -0,0 +1,65 @@ +#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 + }; + + uint8_t* fImage; + SkRect16 fBounds; + uint16_t fRowBytes; + uint8_t fFormat; // Format + + /** Return the byte size of the mask, assuming only 1 plane. + Does not account for k3D_Format. For that, use computeFormatImageSize() + */ + size_t computeImageSize() const; + /** Return the byte size of the mask, taking into account + any extra planes (e.g. k3D_Format). + */ + 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(fFormat == kBW_Format); + SkASSERT(fBounds.contains(x, y)); + SkASSERT(fImage != nil); + 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* getAddr(int x, int y) const + { + SkASSERT(fFormat != kBW_Format); + SkASSERT(fBounds.contains(x, y)); + SkASSERT(fImage != nil); + return fImage + x - fBounds.fLeft + (y - fBounds.fTop) * fRowBytes; + } + + static uint8_t* AllocImage(size_t bytes); + static void FreeImage(uint8_t* 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 + }; +}; + +#endif + diff --git a/include/graphics/SkMaskFilter.h b/include/graphics/SkMaskFilter.h new file mode 100644 index 000000000..f844e3625 --- /dev/null +++ b/include/graphics/SkMaskFilter.h @@ -0,0 +1,83 @@ +#ifndef SkMaskFilter_DEFINED +#define SkMaskFilter_DEFINED + +#include "SkFlattenable.h" +#include "SkMask.h" + +class SkBlitter; +class SkBounder; +class SkMatrix; +class SkPath; +class SkRegion; + +/** \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 SkMaskFilter : public SkFlattenable { +public: + SkMaskFilter() {} + + /** Returns the format of the resulting mask that this subclass will return + when its filterMask() method is called. + */ + virtual SkMask::Format getFormat() = 0; + + /** Create a new mask by filter the src mask. + If src.fImage == nil, 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 == nil, dst should not allocate its image + @param src the original image to be filtered. + @param matrix the CTM + @param margin if not nil, 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. + @return true if the dst mask was correctly created. + */ + virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&, SkPoint16* margin); + + /** 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 SkRegion& devClip, SkBounder*, SkBlitter* blitter); + +protected: + // empty for now, but lets get our subclass to remember to init us for the future + SkMaskFilter(SkRBuffer&) {} +}; + +/** \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 SkAutoMaskImage { +public: + SkAutoMaskImage(SkMask* mask, bool alloc) + { + if (alloc) + mask->fImage = SkMask::AllocImage(mask->computeImageSize()); + fImage = mask->fImage; + } + ~SkAutoMaskImage() + { + SkMask::FreeImage(fImage); + } +private: + uint8_t* fImage; +}; + +#endif + diff --git a/include/graphics/SkMetaData.h b/include/graphics/SkMetaData.h new file mode 100644 index 000000000..b3b80eb78 --- /dev/null +++ b/include/graphics/SkMetaData.h @@ -0,0 +1,138 @@ +#ifndef SkMetaData_DEFINED +#define SkMetaData_DEFINED + +#include "SkMath.h" + +class SkMetaData { +public: + SkMetaData(); + SkMetaData(const SkMetaData& src); + ~SkMetaData(); + + SkMetaData& operator=(const SkMetaData& src); + + void reset(); + + bool findS32(const char name[], int32_t* value = nil) const; + bool findScalar(const char name[], SkScalar* value = nil) const; + const SkScalar* findScalars(const char name[], int* count, SkScalar values[] = nil) const; + const char* findString(const char name[]) const; + bool findPtr(const char name[], void** value = nil) const; + bool findBool(const char name[], bool* value = nil) 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 == nil && value == nil || + v != nil && value != nil && !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; + } + + 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[] = nil); + void setString(const char name[], const char value[]); + void setPtr(const char name[], void* value); + void setBool(const char name[], bool value); + + 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[]); + + SkDEBUGCODE(static void UnitTest();) + + enum Type { + kS32_Type, + kScalar_Type, + kString_Type, + kPtr_Type, + kBool_Type, + + kTypeCount + }; + + struct Rec; + class Iter; + friend class Iter; + + class Iter { + public: + Iter() : fRec(nil) {} + 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 nil when there are no more elements. If non-nil is returned, then the + element's type is returned (if not nil), and the number of data values + is returned in count (if not nil). + */ + 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 +#ifdef SK_DEBUG + Type fType; +#else + uint8_t fType; +#endif + +#ifdef SK_DEBUG + const char* fName; + union { + int32_t fS32; + SkScalar fScalar; + const char* fString; + void* fPtr; + bool fBool; + } fData; +#endif + + 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/include/graphics/SkNinePatch.h b/include/graphics/SkNinePatch.h new file mode 100644 index 000000000..5cc48c15a --- /dev/null +++ b/include/graphics/SkNinePatch.h @@ -0,0 +1,21 @@ +#ifndef SkNinePatch_DEFINED +#define SkNinePatch_DEFINED + +#include "SkRect.h" + +class SkBitmap; +class SkCanvas; +class SkPaint; + +class SkNinePatch { +public: + static void Draw(SkCanvas* canvas, const SkRect& dst, + const SkBitmap& bitmap, const SkRect16& margin, + const SkPaint* paint = NULL); + + static void Draw(SkCanvas* canvas, const SkRect& dst, + const SkBitmap& bitmap, int cx, int cy, + const SkPaint* paint = NULL); +}; + +#endif diff --git a/include/graphics/SkOSFile.h b/include/graphics/SkOSFile.h new file mode 100644 index 000000000..6baef7d0d --- /dev/null +++ b/include/graphics/SkOSFile.h @@ -0,0 +1,70 @@ +// Copyright Skia Inc. 2004 - 2005 +// +#ifndef SkOSFile_DEFINED +#define SkOSFile_DEFINED + +#include "SkString.h" + +#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_UNIX) + #include +#endif + +struct SkFILE; + +enum SkFILE_Flags { + kRead_SkFILE_Flag = 0x01, + kWrite_SkFILE_Flag = 0x02 +}; + +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*); +void sk_fflush(SkFILE*); + +int sk_fseek( SkFILE*, size_t, int ); +size_t sk_ftell( SkFILE* ); + +class SkOSFile { +public: + class Iter { + public: + Iter(); + Iter(const char path[], const char suffix[] = nil); + ~Iter(); + + void reset(const char path[], const char suffix[] = nil); + bool next(SkString* name, bool getDir = false); + + private: +#ifdef SK_BUILD_FOR_WIN + HANDLE fHandle; + U16* fPath16; +#elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_UNIX) + DIR* fDIR; + SkString fPath, fSuffix; +#endif + }; +}; + +class SkUTF16_Str { +public: + SkUTF16_Str(const char src[]); + ~SkUTF16_Str() + { + sk_free(fStr); + } + const U16* get() const { return fStr; } + +private: + U16* fStr; +}; + +#endif + diff --git a/include/graphics/SkOSMenu.h b/include/graphics/SkOSMenu.h new file mode 100644 index 000000000..4cf52e769 --- /dev/null +++ b/include/graphics/SkOSMenu.h @@ -0,0 +1,39 @@ +#ifndef SkOSMenu_DEFINED +#define SkOSMenu_DEFINED + +#include "SkEvent.h" +#include "SkTDArray.h" + +class SkOSMenu { +public: + explicit SkOSMenu(const char title[]); + ~SkOSMenu(); + + const char* getTitle() const { return fTitle; } + + void appendItem(const char title[], const char eventType[], S32 eventData); + + // called by SkOSWindow when it receives an OS menu event + int countItems() const; + const char* getItem(int index, U32* cmdID) const; + + SkEvent* createEvent(U32 os_cmd); + +private: + const char* fTitle; + + struct Item { + const char* fTitle; + const char* fEventType; + U32 fEventData; + U32 fOSCmd; // internal + }; + SkTDArray fItems; + + // illegal + SkOSMenu(const SkOSMenu&); + SkOSMenu& operator=(const SkOSMenu&); +}; + +#endif + diff --git a/include/graphics/SkOSSound.h b/include/graphics/SkOSSound.h new file mode 100644 index 000000000..2e4262be6 --- /dev/null +++ b/include/graphics/SkOSSound.h @@ -0,0 +1,20 @@ +#ifndef SkOSSound_DEFINED +#define SkOSSound_DEFINED + +#include "SkTypes.h" + +class SkOSSound { +public: + static void Play(const char path[]); + static void Pause(); + static void Resume(); + static bool TogglePause(); // returns true if we are now playing, or false if we're now paused + static void Stop(); + + // volume runs from 0 (silent) to 0xFF (max-volume) + static U8 GetVolume(); + static void SetVolume(U8CPU volume); +}; + +#endif + diff --git a/include/graphics/SkOSWindow_Mac.h b/include/graphics/SkOSWindow_Mac.h new file mode 100644 index 000000000..b37b65206 --- /dev/null +++ b/include/graphics/SkOSWindow_Mac.h @@ -0,0 +1,32 @@ +#ifndef SkOSWindow_Mac_DEFINED +#define SkOSWindow_Mac_DEFINED + +#include "SkWindow.h" + +class SkOSWindow : public SkWindow { +public: + SkOSWindow(void* hwnd); + + void* getHWND() const { return fHWND; } + void updateSize(); + + static bool PostEvent(SkEvent* evt, SkEventSinkID, SkMSec delay); + + static pascal OSStatus SkOSWindow::EventHandler( EventHandlerCallRef inHandler, EventRef inEvent, void* userData ); + +protected: + // overrides from SkWindow + virtual void onHandleInval(const SkRect16&); + // overrides from SkView + virtual void onAddMenu(const SkOSMenu*); + +private: + void* fHWND; + + void doPaint(void* ctx); + + typedef SkWindow INHERITED; +}; + +#endif + diff --git a/include/graphics/SkOSWindow_Unix.h b/include/graphics/SkOSWindow_Unix.h new file mode 100644 index 000000000..5c1b1eb0e --- /dev/null +++ b/include/graphics/SkOSWindow_Unix.h @@ -0,0 +1,44 @@ +#ifndef SkOSWindow_Unix_DEFINED +#define SkOSWindow_Unix_DEFINED + +#include "SkWindow.h" +#include + +struct SkUnixWindow { + Display* fDisplay; + Window fWin; + size_t fOSWin; +}; + +class SkOSWindow : public SkWindow { +public: + SkOSWindow(Display* display, Window win); + + void* getHWND() const { return (void*)fUnixWindow.fWin; } + void* getDisplay() const { return (void*)fUnixWindow.fDisplay; } + void* getUnixWindow() const { return (void*)&fUnixWindow; } + void setSize(int width, int height); + void updateSize(); + + static bool PostEvent(SkEvent* evt, SkEventSinkID, SkMSec delay); + + static bool WndProc(SkUnixWindow* w, XEvent &e); + +protected: + // overrides from SkWindow + virtual void onHandleInval(const SkRect16&); + // overrides from SkView + virtual void onAddMenu(const SkOSMenu*); + +private: + SkUnixWindow fUnixWindow; + + void doPaint(); + + void* fMBar; + + typedef SkWindow INHERITED; +}; + +#endif + diff --git a/include/graphics/SkOSWindow_Win.h b/include/graphics/SkOSWindow_Win.h new file mode 100644 index 000000000..b213a057a --- /dev/null +++ b/include/graphics/SkOSWindow_Win.h @@ -0,0 +1,43 @@ +#ifndef SkOSWindow_Win_DEFINED +#define SkOSWindow_Win_DEFINED + +#include "SkWindow.h" + +class SkOSWindow : public SkWindow { +public: + SkOSWindow(void* hwnd); + + void* getHWND() const { return fHWND; } + void setSize(int width, int height); + void updateSize(); + + static bool PostEvent(SkEvent* evt, SkEventSinkID, SkMSec delay); + + static bool WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + static bool SkOSWindow::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 SkRect16&); + // overrides from SkView + virtual void onAddMenu(const SkOSMenu*); + +private: + void* fHWND; + + void doPaint(void* ctx); + + HMENU fMBar; + + typedef SkWindow INHERITED; +}; + +#endif + diff --git a/include/graphics/SkOSWindow_wxwidgets.h b/include/graphics/SkOSWindow_wxwidgets.h new file mode 100644 index 000000000..1f526c007 --- /dev/null +++ b/include/graphics/SkOSWindow_wxwidgets.h @@ -0,0 +1,37 @@ +/* + * SkOSWindow_wxwidgets.h + * wxwidgets + * + * Created by phanna on 12/14/05. + * Copyright 2005 __MyCompanyName__. All rights reserved. + * + */ + +#ifndef SkOSWindow_wxwidgets_DEFINED +#define SkOSWindow_wxwidgets_DEFINED + +#include "SkWindow.h" +#include "wx/frame.h" + +class SkOSWindow: public SkWindow +{ +public: + SkOSWindow(); + SkOSWindow(const wxString& title, int x, int y, int width, int height); + ~SkOSWindow(); + + wxFrame* getWXFrame() const { return fFrame; } + + void updateSize(); + +protected: + virtual void onHandleInval(const SkRect16&); + virtual void onAddMenu(const SkOSMenu*); + +private: + wxFrame* fFrame; + typedef SkWindow INHERITED; + +}; + +#endif \ No newline at end of file diff --git a/include/graphics/SkPaint.h b/include/graphics/SkPaint.h new file mode 100644 index 000000000..5c1a0364a --- /dev/null +++ b/include/graphics/SkPaint.h @@ -0,0 +1,630 @@ +#ifndef SkPaint_DEFINED +#define SkPaint_DEFINED + +#include "SkColor.h" +#include "SkMath.h" +#include "SkPorterDuff.h" + +class SkColorFilter; +class SkGlyphCache; +class SkMaskFilter; +class SkMatrix; +class SkPath; +class SkPathEffect; +class SkRasterizer; +class SkShader; +class SkTextLayout; +class SkTypeface; +class SkXfermode; + +typedef SkUnichar (*SkUnicodeWalkerProc)(const char** text); + +/** \class SkPaint + + The SkPaint class holds the style and color information about how to draw geometries, text and bitmaps. +*/ +class SkPaint { +public: + SkPaint(); + SkPaint(const SkPaint& paint); + ~SkPaint(); + + SkPaint& operator=(const SkPaint&); + + friend int operator==(const SkPaint& a, const SkPaint& b); + friend int operator!=(const SkPaint& a, const SkPaint& b) { return !(a == b); } + + /** Restores the paint to its initial settings. + */ + void reset(); + + /** FlagShift enum specifies the amount to bit-shift for a given flag setting. + Can be used to slide a boolean value into the correct position (e.g. + flags |= isAntiAlias << kAntiAlias_Shift; + */ + enum FlagShift { + kAntiAlias_Shift, //!< bit position for the flag enabling antialiasing + kLinearText_Shift , //!< bit position for the flag enabling linear-text (no gridding) + kUnderlineText_Shift, //!< bit position for the flag enabling underline text + kStrikeThruText_Shift, //!< bit position for the flag enabling strike-thru text + kFakeBoldText_Shift, //!< bit position for the flag enabling fake-bold text + + kFlagShiftCount + }; + + /** FlagMask enum specifies the bit values that are stored in the paint's flags. + */ + enum FlagMask { + kAntiAlias_Mask = 1 << kAntiAlias_Shift, //!< bit mask for the flag enabling antialiasing + kLinearText_Mask = 1 << kLinearText_Shift, //!< bit mask for the flag enabling linear-text (no gridding) + kUnderlineText_Mask = 1 << kUnderlineText_Shift, //!< bit mask for the flag enabling underline text + kStrikeThruText_Mask= 1 << kStrikeThruText_Shift, //!< bit mask for the flag enabling strike-thru text + kFakeBoldText_Mask = 1 << kFakeBoldText_Shift, //!< bit mask for the flag enabling fake-bold text + + kAllFlagMasks = (1 << kFlagShiftCount) - 1 + }; + + /** Return the paint's flags. Use the FlagMask enum to test flag values. + @return the paint's flags (see enums ending in _Mask for bit masks) + */ + uint32_t getFlags() const { return fFlags; } + /** Set the paint's flags. Use the FlagMask enum to specific flag values. + @param flags The new flag bits for the paint (see enums ending in _Mask for bit masks) + */ + void setFlags(uint32_t flags); + + /** Helper for getFlags(), returning true if kAntiAlias_Mask bit is set + @return true if the antialias bit is set in the paint's flags. + */ + bool isAntiAliasOn() const { return SkToBool(this->getFlags() & kAntiAlias_Mask); } + /** Helper for setFlags(), setting or clearing the kAntiAlias_Mask bit + @param aa true to set the antialias bit in the flags, false to clear it + */ + void setAntiAliasOn(bool aa); + /** Helper for getFlags(), returning true if kLinearText_Mask bit is set + @return true if the lineartext bit is set in the paint's flags + */ + bool isLinearTextOn() const { return SkToBool(this->getFlags() & kLinearText_Mask); } + /** Helper for setFlags(), setting or clearing the kLinearText_Mask bit + @param linearText true to set the linearText bit in the paint's flags, false to clear it. + */ + void setLinearTextOn(bool linearText); + /** Helper for getFlags(), returning true if kUnderlineText_Mask bit is set + @return true if the underlineText bit is set in the paint's flags. + */ + bool isUnderlineTextOn() const { return SkToBool(this->getFlags() & kUnderlineText_Mask); } + /** Helper for setFlags(), setting or clearing the kUnderlineText_Mask bit + @param underlineText true to set the underlineText bit in the paint's flags, false to clear it. + */ + void setUnderlineTextOn(bool underlineText); + /** Helper for getFlags(), returning true if kStrikeThruText_Mask bit is set + @return true if the strikeThruText bit is set in the paint's flags. + */ + bool isStrikeThruTextOn() const { return SkToBool(this->getFlags() & kStrikeThruText_Mask); } + /** Helper for setFlags(), setting or clearing the kStrikeThruText_Mask bit + @param strikeThruText true to set the strikeThruText bit in the paint's flags, false to clear it. + */ + void setStrikeThruTextOn(bool strikeThruText); + /** Helper for getFlags(), returning true if kFakeBoldText_Mask bit is set + @return true if the fakeBoldText bit is set in the paint's flags. + */ + bool isFakeBoldTextOn() const { return SkToBool(this->getFlags() & kFakeBoldText_Mask); } + /** Helper for setFlags(), setting or clearing the kStrikeThruText_Mask bit + @param fakeBoldText true to set the fakeBoldText bit in the paint's flags, false to clear it. + */ + void setFakeBoldTextOn(bool fakeBoldText); + + /** Styles apply to rect, oval, path, and text. + Bitmaps are always drawn in "fill", and lines are always drawn in "stroke" + */ + enum Style { + kFill_Style, //!< fill with the paint's color + kStroke_Style, //!< stroke with the paint's color + kStrokeAndFill_Style, //!< fill and stroke with the paint's color + + kStyleCount, + kDefault_Style = kFill_Style, //!< the default style setting in the paint + }; + /** 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 setting (Fill, Stroke, StrokeAndFill) + */ + 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 (Fill, Stroke, StrokeAndFill) + */ + 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; } + /** 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)); } + /** 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 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. +

+ A value of 0 strokes in hairline mode. + Hairlines always draws a single pixel independent of the canva's 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 draws a single pixel independent of the canva's 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 and end a contour with no extension + kRound_Cap, //!< begin and end a contour with a semi-circle extension + kSquare_Cap, //!< begin and end a contour 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 (respects miter-limit) + 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); + + enum FilterType { + kNo_FilterType, //!< draw bitmaps using nearest-neighbor sampling + kBilinear_FilterType, //!< draw bitmaps using bilinear sampling + + kFilterTypeCount + }; + /** Return the paint's bitmap filter type. This setting affects drawBitmap() and bitmaps + that appear inside a bitmap shader. + @return the paint's filter type, used when drawing bitmaps. + */ + FilterType getFilterType() const { return (FilterType)fFilterType; } + /** Set the paint's bitmap filter type. This setting affects drawBitmap() and bitmaps + that appear inside a bitmap shader. + @param filterType set the new filter type on the paint, used when drawing a bitmap + */ + void setFilterType(FilterType filterType); + + /** Get the paint's shader object. +

+ 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. +

+ 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 new shader to be installed in the paint + @return shader + */ + SkShader* setShader(SkShader* shader); + + /** Get the paint's colorfilter (or NULL). 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. +

+ 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 new filter to be installed in the paint + @return filter + */ + SkColorFilter* setColorFilter(SkColorFilter* filter); + + /** Get the paint's xfermode object. +

+ 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. +

+ 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); + + /** Helper for setXfermode, passing the corresponding xfermode object returned from the + PorterDuff factory. + @param mode The porter-duff mode used to create an xfermode for the paint. + @return the resulting xfermode object (or NULL if the mode is SrcOver) + */ + SkXfermode* setPorterDuffXfermode(SkPorterDuff::Mode mode); + + /** Get the paint's patheffect object. +

+ 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. +

+ 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. +

+ 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. +

+ 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. +

+ 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. +

+ 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 textlayout (or NULL). +

+ The textlayout can modify the spacing between letters and words when measured/drawn. + The textlayout reference count is not affected. + @return the paint's textlayout (or NULL) + */ + SkTextLayout* getTextLayout() const { return fTextLayout; } + /** Set or clear the textlayout object. +

+ Pass NULL to clear any previous textlayout. + As a convenience, the parameter passed is also returned. + If a previous layout exists in the paint, its reference count is decremented. + If layout is not NULL, its reference count is incremented. + @param layout May be NULL. The new layout to be installed in the paint. + @return layout + */ + SkTextLayout* setTextLayout(SkTextLayout* layout); + + /** Get the paint's rasterizer (or NULL). +

+ The raster controls/modifies 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. +

+ 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 r 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); + + enum Align { + kLeft_Align, + kCenter_Align, + kRight_Align, + + kAlignCount + }; + /** 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); + + /** Return the width of the utf8 text. + @param utf8 Address of the utf8 text + @param length Number of bytes of utf8 text to measure + @param above If not NULL, returns the distance above the baseline (ascent) + @param below If not NULL, returns the distance below the baseline (descent) + @return The width of the utf8 text + */ + SkScalar measureText(const char utf8[], size_t length, + SkScalar* above, SkScalar* below) const; + /** Return the width of the utf16 text. + @param utf16 Address of the utf16 text + @param numberOf16BitValues Number of 16bit values to measure + @param above May be NULL. If not NULL, returns the distance above the baseline (ascent) + @param below May be NULL. If not NULL, returns the distance below the baseline (descent) + @return The width of the text + */ + SkScalar measureText16(const uint16_t utf16[], size_t numberOf16BitValues, + SkScalar* above, SkScalar* below) const; + /** Return the distance above (negative) the baseline (ascent) based on the current typeface and text size. + @return the distance above (negative) the baseline (ascent) based on the current typeface and text size. + */ + SkScalar ascent() const; + /** Return the distance below (positive) the baseline (descent) based on the current typeface and text size. + @return the distance below (positive) the baseline (descent) based on the current typeface and text size. + */ + SkScalar descent() const; + + /** Return the width of the utf8 text. + @param text The utf8 text to measure + @param byteLength The number of bytes of text to process + @return the measured width of the specified text. + */ + SkScalar measureText(const char text[], size_t byteLength) const + { + return this->measureText(text, byteLength, NULL, NULL); + } + /** Return the width of the utf16 text. + @param text The utf16 text to measure + @param numberOf16BitValues The number of 16bit values in text to process + @return the measured width of the specified text. + */ + SkScalar measureText16(const uint16_t text[], size_t numberOf16BitValues) const + { + return this->measureText16(text, numberOf16BitValues, NULL, NULL); + } + + /** Return the advance widths for the characters in the string. + @param text UTF8 text + @param byteLength number of bytes to read from the UTF8 text parameter + @param widths array of SkScalars to receive the advance widths of the characters. + May be NULL. If not NULL, must be at least a large as the number + of unichars in the specified text. + @return the number of unichars in the specified text. + */ + int getTextWidths(const char text[], size_t byteLength, SkScalar widths[]) const; + /** Return the advance widths for the characters in the string. + @param text UTF16 text + @param numberOf16BitValues number of 16bit values to read from the UTF16 text parameter + @param widths array of SkScalars to receive the advance widths of the characters. + May be NULL. If not NULL, must be at least a large as the number + of unichars in the specified text. + @return the number of unichars in the specified text. + */ + int getTextWidths16(const uint16_t text[], size_t numberOf16BitValues, SkScalar widths[]) 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 char text[], size_t length, SkScalar x, SkScalar y, SkPath* path) const; + + /** Return the path (outline) for the specified text. + Note: just like SkCanvas::drawText, this will respect the Align setting in the paint. + */ + void getText16Path(const uint16_t text[], size_t numberOf16BitValues, SkScalar x, SkScalar y, SkPath* path) const; + + /** 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) + @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; + +private: + SkTypeface* fTypeface; + SkScalar fTextSize; + SkScalar fTextScaleX; + SkScalar fTextSkewX; + + SkPathEffect* fPathEffect; + SkShader* fShader; + SkXfermode* fXfermode; + SkMaskFilter* fMaskFilter; + SkColorFilter* fColorFilter; + SkTextLayout* fTextLayout; + SkRasterizer* fRasterizer; + + SkColor fColor; + SkScalar fWidth; + SkScalar fMiterLimit; + unsigned fFlags : 5; + unsigned fFilterType : 2; + unsigned fTextAlign : 2; + unsigned fCapType : 2; + unsigned fJoinType : 2; + unsigned fStyle : 2; + + SkScalar privateMeasureText(SkUnicodeWalkerProc, const char text[], size_t byteLength, + SkScalar* above, SkScalar* below) const; + void privateGetTextPath(SkUnicodeWalkerProc, const char text[], size_t length, + SkScalar x, SkScalar y, SkPath* path) const; + int privateGetTextWidths(const char text[], size_t byteLength, + SkScalar widths[], SkUnicodeWalkerProc textProc) const; + + SkGlyphCache* detachCache(const SkMatrix*) const; + + friend class SkGlyphCache; + enum { + kCanonicalTextSizeForPaths = 64 + }; + friend class SkDraw; + friend class SkTextToPathIter; +}; + +class SkAutoRestorePaintFlags { +public: + SkAutoRestorePaintFlags(const SkPaint& paint, uint32_t newFlags) + { + SkASSERT(&paint); + fPaint = (SkPaint*)&paint; // remove constness + fOldFlags = paint.getFlags(); + fPaint->setFlags(newFlags); + } + ~SkAutoRestorePaintFlags() + { + fPaint->setFlags(fOldFlags); + } +private: + SkPaint* fPaint; + uint32_t fOldFlags; +}; + +////////////////////////////////////////////////////////////////////////// + +#include "SkPathEffect.h" + +/** \class SkStrokePathEffect + + SkStrokePathEffect simulates stroking inside a patheffect, allowing the caller to have explicit + control of when to stroke a path. Typically this is used if the caller wants to stroke before + another patheffect is applied (using SkComposePathEffect or SkSumPathEffect). +*/ +class SkStrokePathEffect : public SkPathEffect { +public: + SkStrokePathEffect(const SkPaint&); + SkStrokePathEffect(SkScalar width, SkPaint::Style, SkPaint::Join, SkPaint::Cap, SkScalar miterLimit = -1); + + // overrides + // This method is not exported to java. + virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width); + + // overrides for SkFlattenable + // This method is not exported to java. + virtual void flatten(SkWBuffer&); + // This method is not exported to java. + virtual Factory getFactory(); + +private: + SkScalar fWidth, fMiter; + uint8_t fStyle, fJoin, fCap; + + static SkFlattenable* CreateProc(SkRBuffer&); + SkStrokePathEffect(SkRBuffer&); + + typedef SkPathEffect INHERITED; + + // illegal + SkStrokePathEffect(const SkStrokePathEffect&); + SkStrokePathEffect& operator=(const SkStrokePathEffect&); +}; + +#endif + diff --git a/include/graphics/SkParse.h b/include/graphics/SkParse.h new file mode 100644 index 000000000..9e513fe29 --- /dev/null +++ b/include/graphics/SkParse.h @@ -0,0 +1,29 @@ +#ifndef SkParse_DEFINED +#define SkParse_DEFINED + +#include "SkColor.h" +#include "SkMath.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/include/graphics/SkParsePaint.h b/include/graphics/SkParsePaint.h new file mode 100644 index 000000000..d5f7f68a8 --- /dev/null +++ b/include/graphics/SkParsePaint.h @@ -0,0 +1,18 @@ +#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/include/graphics/SkPath.h b/include/graphics/SkPath.h new file mode 100644 index 000000000..b0a538d13 --- /dev/null +++ b/include/graphics/SkPath.h @@ -0,0 +1,373 @@ +#ifndef SkPath_DEFINED +#define SkPath_DEFINED + +#include "SkMatrix.h" +#include "SkTDArray.h" + +class SkString; + +/** \class SkPath + + The SkPath class encapsulates compound (multiple contour) geometric paths consisting + of straight line segments, quadratic curves, and cubic curves. +*/ +class SkPath { +public: + SkPath(); + SkPath(const SkPath&); + ~SkPath(); + + SkPath& operator=(const SkPath&); + + enum FillType { + kWinding_FillType, //!< Specifies that "inside" is computed by a non-zero sum of signed edge crossings + kEvenOdd_FillType //!< Specifies that "inside" is computed by an odd number of edge crossings + }; + /** 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); } + + /** Clear any lines and curves from the path, making it empty. + This does NOT change the fill-type setting. + */ + void reset(); + /** 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 the path specifies a rectangle. If so, and if rect is not nil, + 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 nil, returns the bounds of the path if it specifies a rectangle + @return true if the path specifies a rectangle + */ + bool isRect(SkRect* rect) 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; + //! Swap contents of this and other. Guaranteed not to throw + void swap(SkPath& other); + + enum BoundsType { + kFast_BoundsType, //!< compute the bounds of the path's control points, may be larger than with kExact_BoundsType, but may be faster to compute + kExact_BoundsType //!< compute the exact bounds of the path, may be smaller than with kFast_BoundsType, but may be slower to compute + }; + /** Compute the bounds of the path, and write the answer into bounds. If the path contains 0 or 1 points, + the bounds is set to (0,0,0,0) + @param bounds Returns the computed bounds of the path + @param btype Specifies if the computed bounds should be exact (slower) or approximate (faster) + */ + void computeBounds(SkRect* bounds, BoundsType btype) 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 that may be added to this path + */ + 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); + /** 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); + /** 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 { + kCW_Direction, //!< clockwise direction for adding closed contours + kCCW_Direction //!< counter-clockwise direction for adding closed contours + }; + /** 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 + */ + 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 + */ + 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 bounds of the oval to add as a closed contour to the path + @param dir The direction to wind the oval's contour + */ + 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 + */ + void addCircle(SkScalar x, SkScalar y, SkScalar radius, Direction dir = kCW_Direction); + /** Add a closed round-rectangle contour to the path + @param rect The bounds of a round-rectangle to add as a closed contour to the path + @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 round-rectangle's contour + */ + void addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, Direction dir = kCW_Direction); + /** 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); + + /** 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 + @return true + */ + bool 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 + @return true + */ + bool offset(SkScalar dx, SkScalar dy) + { + return 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 + @return true + */ + bool transform(const SkMatrix& matrix, SkPath* dst) const; + /** Transform the points in this path by matrix, and write the answer into dst. + @param matrix The matrix to apply to the path + @return true + */ + bool transform(const SkMatrix& matrix) + { + return this->transform(matrix, this); + } + + /** Return the last point on the path. If no points have been added, (0,0) is returned. + @param lastPt The last point on the path is returned here + */ + void 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 Verb { + kMove_Verb, //!< iter.next returns 1 point + kLine_Verb, //!< iter.next returns 2 points + kQuad_Verb, //!< iter.next returns 3 points + kCubic_Verb, //!< iter.next returns 4 points + kClose_Verb, //!< iter.next returns 1 point (the last point) + kDone_Verb //!< iter.next returns 0 points + }; + /** Iterate through all of the segments (lines, quadratics, cubics) of + each contours in a path. + */ + class 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 point(s) representing the current verb and/or segment + @return The verb for the current segment + */ + Verb next(SkPoint pts[4]); + + /** 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 (i.e. has a kClose_Verb) + @return true if the current contour is closed (i.e. has a kClose_Verb) + */ + bool isClosedContour() const; + + private: + const SkPoint* fPts; + const uint8_t* fVerbs; + const uint8_t* fVerbStop; + SkPoint fMoveTo; + SkPoint fLastPt; + SkBool8 fForceClose; + SkBool8 fNeedClose; + SkBool8 fNeedMoveTo; + SkBool8 fCloseLine; + + bool cons_moveTo(SkPoint pts[1]); + Verb autoClose(SkPoint pts[2]); + }; + +#ifdef SK_DEBUG + /** @cond UNIT_TEST */ + void dump(bool forceClose, const char title[] = nil) const; + static void UnitTest(); + /** @endcond */ +#endif + + /** Return the number of bytes (padded to a multiple of 4) needed to + flatten the path into a block of memory. If bufferOrNil is not nil, + the path is written into it. The format of the buffer is private, + and can be used to create a new path by calling unflatten(). + */ + uint32_t flatten(void* bufferOrNil) const; + void unflatten(const void* buffer); + + /** Subdivide the path so that no segment is longer that dist. + If bendLines is true, then turn all line segments into curves. + If dst == nil, then the original path itself is modified (not const!) + */ + void subdivide(SkScalar dist, bool bendLines, SkPath* dst = nil) const; + + /** Return an SVG-compatible string of the path. + */ + void toString(SkString*) const; + +private: + SkTDArray fPts; + SkTDArray fVerbs; + uint8_t fFillType; + + friend class Iter; + void cons_moveto(); + + 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&); + + friend const SkPoint* sk_get_path_points(const SkPath&, int index); +}; + +#endif + diff --git a/include/graphics/SkPathEffect.h b/include/graphics/SkPathEffect.h new file mode 100644 index 000000000..c560f6700 --- /dev/null +++ b/include/graphics/SkPathEffect.h @@ -0,0 +1,143 @@ +#ifndef SkPathEffect_DEFINED +#define SkPathEffect_DEFINED + +#include "SkFlattenable.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 SkPathEffect : public SkFlattenable { +public: + SkPathEffect() {} + + /** Given a src path and a width value, return true if the patheffect + has produced a new path (dst) and a new width value. If false is returned, + ignore dst and width. + On input, width >= 0 means the src should be stroked + On output, width >= 0 means the dst should be stroked + */ + virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width); + /** overrides for SkFlattenable. + Subclasses should override this to (re)create their subclass. + */ + // This method is not exported to java. + virtual Factory getFactory(); + +protected: + // visible to our subclasses + SkPathEffect(SkRBuffer&) {} + +private: + // illegal + SkPathEffect(const SkPathEffect&); + SkPathEffect& operator=(const SkPathEffect&); +}; + +/** \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. +*/ +// This class is not exported to java. +class SkPairPathEffect : public SkPathEffect { +public: + SkPairPathEffect(SkPathEffect* pe0, SkPathEffect* pe1); + virtual ~SkPairPathEffect(); + + // overrides + + // This method is not exported to java. + virtual void flatten(SkWBuffer&); + +protected: + // these are visible to our subclasses + SkPathEffect* fPE0, *fPE1; + SkPairPathEffect(SkRBuffer&); + +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) + : SkPairPathEffect(outer, inner) {} + + // overrides + + virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width); + + // overrides for SkFlattenable + + // This method is not exported to java. + virtual Factory getFactory(); + +private: + SkPathEffect* fOuter, *fInner; + + static SkFlattenable* CreateProc(SkRBuffer&); + SkComposePathEffect(SkRBuffer& buffer) : SkPairPathEffect(buffer) {} + + // 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) + : SkPairPathEffect(first, second) {} + + // overrides + virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width); + + // overrides for SkFlattenable + + // This method is not exported to java. + virtual Factory getFactory(); + +private: + SkPathEffect* fFirst, *fSecond; + + static SkFlattenable* CreateProc(SkRBuffer&); + SkSumPathEffect(SkRBuffer& buffer) : SkPairPathEffect(buffer) {} + + // illegal + SkSumPathEffect(const SkSumPathEffect&); + SkSumPathEffect& operator=(const SkSumPathEffect&); + + typedef SkPairPathEffect INHERITED; +}; + +#endif + diff --git a/include/graphics/SkPathMeasure.h b/include/graphics/SkPathMeasure.h new file mode 100644 index 000000000..7d901a2c6 --- /dev/null +++ b/include/graphics/SkPathMeasure.h @@ -0,0 +1,95 @@ +#ifndef SkPathMeasure_DEFINED +#define SkPathMeasure_DEFINED + +#include "SkPath.h" +#include "SkTDArray.h" + +class SkPathMeasure { +public: + SkPathMeasure(); + SkPathMeasure(const SkPath& path, bool forceClosed); + ~SkPathMeasure(); + + /** Assign a new path, or nil to have none. + */ + void setPath(const SkPath*, bool forceClosed); + + /** Return the total length of the current contour, or 0 if no path + is associated (e.g. resetPath(nil)) + */ + 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 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 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(); + static void UnitTest(); +#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; + unsigned fTValue : 15; + unsigned fType : 2; + + SkScalar getScalarT() const; + }; + SkTDArray fSegments; + + 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); + + // illegal (for now) + SkPathMeasure(const SkPathMeasure&); + SkPathMeasure& operator=(const SkPathMeasure&); +}; + +#endif + diff --git a/include/graphics/SkPorterDuff.h b/include/graphics/SkPorterDuff.h new file mode 100644 index 000000000..6dbcf589c --- /dev/null +++ b/include/graphics/SkPorterDuff.h @@ -0,0 +1,47 @@ +#ifndef SkPorterDuff_DEFINED +#define SkPorterDuff_DEFINED + +#include "SkColor.h" + +class SkXfermode; + +class 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 + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] this is the default mode + kDstOver_Mode, //!< [Sa + (1 - 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\u00B7Da, Sc\u00B7(1 - Da) + Dc\u00B7(1 - Sa) + min(Sc, Dc)] + kLighten_Mode, //!< [Sa + Da - Sa\u00B7Da, Sc\u00B7(1 - Da) + Dc\u00B7(1 - Sa) + max(Sc, Dc)] + + 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); +}; + +#endif + diff --git a/include/graphics/SkPrefix_Debug_Fixed.h b/include/graphics/SkPrefix_Debug_Fixed.h new file mode 100644 index 000000000..72d15e426 --- /dev/null +++ b/include/graphics/SkPrefix_Debug_Fixed.h @@ -0,0 +1,14 @@ +#ifndef SkPrefix_Debug_Fixed_DEFINED +#define SkPrefix_Debug_Fixed_DEFINED + +#define SK_DEBUG + +/* define this to test fixed-point */ +#define SK_SCALAR_IS_FIXED + +/* these are for expat */ +#define MACOS_CLASSIC + +#endif + + diff --git a/include/graphics/SkPrefix_Release_Fixed.h b/include/graphics/SkPrefix_Release_Fixed.h new file mode 100644 index 000000000..81238aba2 --- /dev/null +++ b/include/graphics/SkPrefix_Release_Fixed.h @@ -0,0 +1,26 @@ +#ifndef SkPrefix_Release_Fixed_DEFINED + +#define SkPrefix_Release_Fixed_DEFINED + +/* this means we're a release build */ + +#define NDEBUG + + + +/* define this to test fixed-point */ + +#define SK_SCALAR_IS_FIXED + + + +/* these are for expat */ + +#define MACOS_CLASSIC + + + +#endif + + + diff --git a/include/graphics/SkProgressBarView.h b/include/graphics/SkProgressBarView.h new file mode 100644 index 000000000..64351c8bc --- /dev/null +++ b/include/graphics/SkProgressBarView.h @@ -0,0 +1,41 @@ +#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/include/graphics/SkRasterizer.h b/include/graphics/SkRasterizer.h new file mode 100644 index 000000000..3a323b0b0 --- /dev/null +++ b/include/graphics/SkRasterizer.h @@ -0,0 +1,33 @@ +#ifndef SkRasterizer_DEFINED +#define SkRasterizer_DEFINED + +#include "SkFlattenable.h" +#include "SkMask.h" + +class SkMaskFilter; +class SkMatrix; +class SkPath; +struct SkRect16; + +class SkRasterizer : public SkFlattenable { +public: + SkRasterizer() {} + + /** Turn the path into a mask, respecting the specified local->device matrix. + */ + bool rasterize(const SkPath& path, const SkMatrix& matrix, + const SkRect16* clipBounds, SkMaskFilter* filter, + SkMask* mask, SkMask::CreateMode mode); + +protected: + SkRasterizer(SkRBuffer&); + + virtual bool onRasterize(const SkPath& path, const SkMatrix& matrix, + const SkRect16* clipBounds, + SkMask* mask, SkMask::CreateMode mode); + +private: + typedef SkFlattenable INHERITED; +}; + +#endif diff --git a/include/graphics/SkRefCnt.h b/include/graphics/SkRefCnt.h new file mode 100644 index 000000000..679f955e6 --- /dev/null +++ b/include/graphics/SkRefCnt.h @@ -0,0 +1,87 @@ +#ifndef SkRefCnt_DEFINED +#define SkRefCnt_DEFINED + +#include "SkTypes.h" + +/** \class SkRefCnt + + SkRefCnt is the base class for objects that may be shared by multiple objects. + When a new owner wants 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 SkRefCnt { +public: + /** Default construct, initializing the reference count to 1. + */ + SkRefCnt() : fRefCnt(1) {} + /** Destruct, asserting that the reference count is 1. + */ + virtual ~SkRefCnt() { SkASSERT(fRefCnt == 1); } + + /** Return the reference count. + */ + int getRefCnt() const { return fRefCnt; } + /** Increment the reference count. Must be balanced by a call to unref(). + */ + void ref() const { SkASSERT(fRefCnt > 0); ++fRefCnt; } + /** Decrement the reference count. If the 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 unref() const + { + SkASSERT(fRefCnt > 0); + if (fRefCnt == 1) + delete this; + else + --fRefCnt; + } + + /** Helper version of ref(), that first checks to see if this is not nil. + If this is nil, then do nothing. + */ + void safeRef() const { if (this) this->ref(); } + /** Helper version of unref(), that first checks to see if this is not nil. + If this is nil, then do nothing. + */ + void safeUnref() const { if (this) this->unref(); } + +private: + mutable int fRefCnt; +}; + +/** \class SkAutoUnref + + SkAutoUnref is a stack-helper class that will automatically call unref() on + the object it points to when the SkAutoUnref object goes out of scope. +*/ +class SkAutoUnref { +public: + SkAutoUnref(SkRefCnt* obj) : fObj(obj) {} + ~SkAutoUnref(); + + SkRefCnt* get() const { return fObj; } + bool ref(); + bool unref(); + SkRefCnt* detach(); + +private: + SkRefCnt* fObj; +}; + +/** Helper macro to safely assign one SkRefCnt* to another, checking for + nil 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) + +#endif + diff --git a/include/graphics/SkSVGAttribute.h b/include/graphics/SkSVGAttribute.h new file mode 100644 index 000000000..b6ae0df88 --- /dev/null +++ b/include/graphics/SkSVGAttribute.h @@ -0,0 +1,33 @@ +#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/include/graphics/SkSVGBase.h b/include/graphics/SkSVGBase.h new file mode 100644 index 000000000..83b72d96b --- /dev/null +++ b/include/graphics/SkSVGBase.h @@ -0,0 +1,16 @@ +#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_DEFINED \ No newline at end of file diff --git a/include/graphics/SkSVGPaintState.h b/include/graphics/SkSVGPaintState.h new file mode 100644 index 000000000..4ec018de1 --- /dev/null +++ b/include/graphics/SkSVGPaintState.h @@ -0,0 +1,80 @@ +#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/include/graphics/SkSVGParser.h b/include/graphics/SkSVGParser.h new file mode 100644 index 000000000..b001c2243 --- /dev/null +++ b/include/graphics/SkSVGParser.h @@ -0,0 +1,65 @@ +#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(); + 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& 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& fChildren); + static SkSVGTypes GetType(const char name[], size_t len); + SkSVGPaint* fHead; + SkSVGPaint fEmptyPaint; + SkSVGPaint fLastFlush; + SkString fLastColor; + SkMatrix fLastTransform; + SkTDArray fChildren; + SkTDict fIDs; + SkTDArray fParents; + SkDynamicMemoryWStream fStream; + SkXMLStreamWriter fXMLWriter; + SkSVGElement* fCurrElement; + SkBool8 fInSVG; + SkBool8 fSuppressPaint; + friend class SkSVGPaint; + friend class SkSVGGradient; +}; + +#endif // SkSVGParser_DEFINED diff --git a/include/graphics/SkSVGTypes.h b/include/graphics/SkSVGTypes.h new file mode 100644 index 000000000..b87bfbda7 --- /dev/null +++ b/include/graphics/SkSVGTypes.h @@ -0,0 +1,30 @@ +#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_Use +}; + +#endif // SkSVGTypes_DEFINED diff --git a/include/graphics/SkScalerContext.h b/include/graphics/SkScalerContext.h new file mode 100644 index 000000000..db12c73b7 --- /dev/null +++ b/include/graphics/SkScalerContext.h @@ -0,0 +1,87 @@ +#ifndef SkScalerContext_DEFINED +#define SkScalerContext_DEFINED + +#include "SkMatrix.h" +#include "SkPath.h" +#include "SkPoint.h" + +class SkDescriptor; +class SkMaskFilter; +class SkPaint; +class SkPathEffect; +class SkRasterizer; + +#define SK_UnknownAuxScalerContextID 0 +#define SK_MaxAuxScalerContextID 16 + +struct SkGlyph { + void* fImage; + SkPath* fPath; + SkFixed fAdvanceX, fAdvanceY; + + uint16_t fGlyphID; + uint16_t fWidth, fHeight, fRowBytes; + int16_t fTop, fLeft; + + uint16_t fCharCode; // might go away with line layout. really wants 20bits + uint8_t fMaskFormat; + SkBool8 fUseAuxContext; // just need 1-bit for this field + + size_t computeImageSize() const; +}; + +class SkScalerContext { +public: + struct Rec { + SkScalar fTextSize, fPreScaleX, fPreSkewX; + SkScalar fPost2x2[2][2]; + SkScalar fFrameWidth, fMiterLimit; + SkBool8 fUseHints; + SkBool8 fFrameAndFill; + SkBool8 fDoAA; + uint8_t fStrokeJoin; + + void getMatrixFrom2x2(SkMatrix*) const; + void getLocalMatrix(SkMatrix*) const; + void getSingleMatrix(SkMatrix*) const; + }; + + SkScalerContext(const SkDescriptor* desc); + virtual ~SkScalerContext(); + + void getMetrics(SkGlyph*); + void getImage(const SkGlyph&); + void getPath(const SkGlyph&, SkPath*); + void getLineHeight(SkPoint* above, SkPoint* below); + + static inline void MakeRec(const SkPaint&, const SkMatrix*, Rec* rec); + static SkScalerContext* Create(const SkDescriptor*); + +protected: + Rec fRec; + + virtual void generateMetrics(SkGlyph*) = 0; + virtual void generateImage(const SkGlyph&) = 0; + virtual void generatePath(const SkGlyph&, SkPath*) = 0; + virtual void generateLineHeight(SkPoint* above, SkPoint* below) = 0; + +private: + SkPathEffect* fPathEffect; + SkMaskFilter* fMaskFilter; + SkRasterizer* fRasterizer; + SkScalar fDevFrameWidth; + + void internalGetPath(const SkGlyph& glyph, SkPath* fillPath, SkPath* devPath, SkMatrix* fillToDevMatrix); + + // we index into this with scalerContextID-1 + SkScalerContext* fAuxContext[SK_MaxAuxScalerContextID]; +}; + +#define kRec_SkDescriptorTag SkSetFourByteTag('s', 'r', 'e', 'c') +#define kTypeface_SkDescriptorTag SkSetFourByteTag('t', 'p', 'f', 'c') +#define kPathEffect_SkDescriptorTag SkSetFourByteTag('p', 't', 'h', 'e') +#define kMaskFilter_SkDescriptorTag SkSetFourByteTag('m', 's', 'k', 'f') +#define kRasterizer_SkDescriptorTag SkSetFourByteTag('r', 'a', 's', 't') + +#endif + diff --git a/include/graphics/SkScrollBarView.h b/include/graphics/SkScrollBarView.h new file mode 100644 index 000000000..ee43a3cec --- /dev/null +++ b/include/graphics/SkScrollBarView.h @@ -0,0 +1,35 @@ +#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 \ No newline at end of file diff --git a/include/graphics/SkShader.h b/include/graphics/SkShader.h new file mode 100644 index 000000000..e823a7bb7 --- /dev/null +++ b/include/graphics/SkShader.h @@ -0,0 +1,146 @@ +#ifndef SkShader_DEFINED +#define SkShader_DEFINED + +#include "SkRefCnt.h" +#include "SkBitmap.h" +#include "SkMask.h" +#include "SkMatrix.h" +#include "SkPaint.h" + +class SkPath; + +/** \class SkShader + + SkShader is the based class for objects that return horizontal spans of colors during drawing. + A subclass of SkShader is installed in a SkPaint calling paint.setShader(shader). After that + any object (other than a bitmap) that is drawn with that paint will get its color(s) from the + shader. +*/ +class SkShader : public SkRefCnt { +public: + SkShader(); + virtual ~SkShader(); + + /** Return the shader's optional local matrix, or nil. + */ + const SkMatrix* getLocalMatrix() const { return fLocalMatrix; } + /** Set the shader's optional local matrix. If the specified matrix is identity, then + getLocalMatrix() will return nil. + */ + void setLocalMatrix(const SkMatrix&); + + enum TileMode { + kClamp_TileMode, //!< replicate the edge color if the shader draws outside of its original bounds + kRepeat_TileMode, //!< repeat the shader's image horizontally and vertically + kMirror_TileMode, //!< repeat the shader's image horizontally and vertically, alternating mirror images so that adjacent images always seam + + kTileModeCount + }; + + // override these in your subclass + + enum Flags { + kOpaqueAlpha_Flag = 0x01, //!< set if all of the colors will be opaque (if so, kConstAlpha_Flag will not be set) + kConstAlpha_Flag = 0x02, //!< set if all of the colors have the same (non-opaque) alpha + kHasSpan16_Flag = 0x04, //!< set if this shader's shadeSpanOpaque16() method can be called + + kFlagsMask = kOpaqueAlpha_Flag | kConstAlpha_Flag | kHasSpan16_Flag + }; + + /** 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 U32 getFlags(); + + /** 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. + */ + virtual bool setContext( const SkBitmap& device, + const SkPaint& paint, + const SkMatrix& matrix); + + /** 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; + /** Called only for 16bit devices when getFlags() returns kOpaqueAlphaFlag | kHasSpan16_Flag + */ + virtual void shadeSpanOpaque16(int x, int y, U16[], 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, U8 alpha[], int count); + + /** Helper function that returns true if this shader's shadeSpanOpaque16() method can + be called. + */ + bool canCallShadeSpanOpaque16() + { + return SkShader::CanCallShadeSpanOpaque16(this->getFlags()); + } + + /** Helper to check the flags to know if it is legal to call shadeSpanOpaque16() + */ + static bool CanCallShadeSpanOpaque16(U32 flags) + { + return (flags & (kOpaqueAlpha_Flag | kHasSpan16_Flag)) == (kOpaqueAlpha_Flag | kHasSpan16_Flag); + } + + ////////////////////////////////////////////////////////////////////////// + // Factory methods for stock shaders + + /** Call this to create a new shader that will draw with the specified bitmap. + @param src The bitmap to use inside the shader + @param transferOwnershipOfPixels If true, the shader will call setOwnsPixels(true) on its private bitmap + and setOwnsPixels(false) on the src bitmap, resulting in the bitmap's pixels + being disposed when the shader is deleted. + @param ft The filter type to be used when scaling or rotating the bitmap when it is drawn. + @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 nil. + */ + static SkShader* CreateBitmapShader(const SkBitmap& src, + bool transferOwnershipOfPixels, + SkPaint::FilterType ft, + TileMode tmx, TileMode tmy); + +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 + U8 getPaintAlpha() const { return fPaintAlpha; } + SkBitmap::Config getDeviceConfig() const { return (SkBitmap::Config)fDeviceConfig; } + const SkMatrix& getTotalInverse() const { return fTotalInverse; } + MatrixClass getInverseClass() const { return (MatrixClass)fTotalInverseClass; } + SkMatrix::MapPtProc getInverseMapPtProc() const { return fInverseMapPtProc; } + +private: + SkMatrix* fLocalMatrix; + SkMatrix fTotalInverse; + SkMatrix::MapPtProc fInverseMapPtProc; + U8 fPaintAlpha; + U8 fDeviceConfig; + U8 fTotalInverseClass; + + static SkShader* CreateBitmapShader(const SkBitmap& src, + bool transferOwnershipOfPixels, + SkPaint::FilterType, + TileMode, TileMode, + void* storage, size_t storageSize); + friend class SkAutoBitmapShaderInstall; +}; + +#endif + diff --git a/include/graphics/SkShaderExtras.h b/include/graphics/SkShaderExtras.h new file mode 100644 index 000000000..e914304e8 --- /dev/null +++ b/include/graphics/SkShaderExtras.h @@ -0,0 +1,36 @@ +#ifndef SkShaderExtras_DEFINED +#define SkShaderExtras_DEFINED + +#include "SkShader.h" + +class SkColorCombine : public SkRefCnt { +public: + /** Called with two scanlines of color. The implementation writes out its combination of + those into the result[] scaline. + */ + virtual void combineSpan(const SkPMColor srcA[], const SkPMColor srcB[], int count, SkPMColor result[]) = 0; +}; + +/////////////////////////////////////////////////////////////////////////////////////////// + +class SkComposeShader : public SkShader { +public: + SkComposeShader(SkShader* sA, SkShader* sB, SkColorCombine* combine); + virtual ~SkComposeShader(); + + // override + virtual bool setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix); + virtual void shadeSpan(int x, int y, SkPMColor result[], int count); + +private: + enum { + COUNT = 32 + }; + SkShader* fShaderA; + SkShader* fShaderB; + SkColorCombine* fCombine; + + typedef SkShader INHERITED; +}; + +#endif diff --git a/include/graphics/SkStackViewLayout.h b/include/graphics/SkStackViewLayout.h new file mode 100644 index 000000000..778a32c8b --- /dev/null +++ b/include/graphics/SkStackViewLayout.h @@ -0,0 +1,80 @@ +#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; + U8 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/include/graphics/SkStdLib_Redirect.h b/include/graphics/SkStdLib_Redirect.h new file mode 100644 index 000000000..d5525e122 --- /dev/null +++ b/include/graphics/SkStdLib_Redirect.h @@ -0,0 +1,17 @@ +#ifndef SkStdLib_Redirect_DEFINED +#define SkStdLib_Redirect_DEFINED + +#error + +#include "SkTypes.h" + +#define fread(buffer, count, size, file) sk_stdlib_fread(buffer, count, size, file) +#define qsort +#define tolower +#define setjmp +#define longjmp +#define memmove +#define malloc +#define realloc +#endif + diff --git a/include/graphics/SkStream.h b/include/graphics/SkStream.h new file mode 100644 index 000000000..14c71d3dc --- /dev/null +++ b/include/graphics/SkStream.h @@ -0,0 +1,199 @@ +#ifndef SkStream_DEFINED +#define SkStream_DEFINED + +#include "SkScalar.h" + +class SkStream { +public: + virtual ~SkStream() {} + /** Called to rewind to the beginning of the stream. If this cannot be + done, return false. + */ + virtual bool rewind() = 0; + /** If this stream represents a file, this method returns the file's name. + If it does not, it returns nil (the default behavior). + */ + virtual const char* getFileName(); + /** Called to read or skip size number of bytes. If buffer is nil, skip + the bytes, else copy them into buffer. If this cannot be done, return false. + If buffer is nil and size is zero, return the file length + @param buffer If buffer is nil, ignore and just skip size bytes, otherwise copy size bytes into buffer + @param size The number of bytes to skip or copy + @return bytes read on success + */ + virtual size_t read(void* buffer, size_t size) = 0; + static SkStream* GetURIStream(const char prefix[], const char path[]); + static bool IsAbsoluteURI(const char path[]); +}; + +class SkWStream { +public: + 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 writeText(const char text[]); + bool writeDecAsText(S32); + bool writeHexAsText(U32, int minDigits = 0); + bool writeScalarAsText(SkScalar); + + SkDEBUGCODE(static void UnitTest();) +}; + +//////////////////////////////////////////////////////////////////////////////////////// + +#include "SkString.h" + +struct SkFILE; + +class SkFILEStream : public SkStream { +public: + SkFILEStream(const char path[] = nil); + virtual ~SkFILEStream(); + + /** Returns true if the current path could be opened. + */ + bool isValid() const { return fFILE != nil; } + /** Close the current file, and open a new file with the specified + path. If path is nil, just close the current file. + */ + void setPath(const char path[]); + + SkFILE* getSkFILE() const { return fFILE; } + + virtual bool rewind(); + virtual size_t read(void* buffer, size_t size); + virtual const char* getFileName(); + +private: + SkFILE* fFILE; + SkString fName; +}; + +class SkMemoryStream : public SkStream { +public: + SkMemoryStream(const void* src, size_t length); + + virtual bool rewind(); + virtual size_t read(void* buffer, size_t size); + +private: + const void* fSrc; + size_t fSize, fOffset; +}; + +/** \class SkBufferStream + This is a wrapper class that adds buffering to another stream. + The caller can provide the buffer, or ask SkBufferStream to allocated/free + it automatically. +*/ +class SkBufferStream : public SkStream { +public: + /** Provide the stream to be buffered (proxy), and the size of the buffer that + should be used. This will be allocated and freed automatically. If bufferSize is 0, + a default buffer size will be used. + */ + SkBufferStream(SkStream& proxy, size_t bufferSize = 0); + /** Provide the stream to be buffered (proxy), and a buffer and size to be used. + This buffer is owned by the caller, and must be at least bufferSize bytes big. + Passing nil for buffer will cause the buffer to be allocated/freed automatically. + If buffer is not nil, it is an error for bufferSize to be 0. + */ + SkBufferStream(SkStream& proxy, void* buffer, size_t bufferSize); + virtual ~SkBufferStream(); + + virtual bool rewind(); + virtual const char* getFileName(); + virtual size_t read(void* buffer, size_t size); +private: + enum { + kDefaultBufferSize = 128 + }; + // illegal + SkBufferStream(const SkBufferStream&); + SkBufferStream& operator=(const SkBufferStream&); + + SkStream& fProxy; + char* fBuffer; + size_t fOrigBufferSize, fBufferSize, fBufferOffset; + bool fWeOwnTheBuffer; + + void init(void*, size_t); +}; + +///////////////////////////////////////////////////////////////////////////////////////////// + +class SkFILEWStream : public SkWStream { +public: + SkFILEWStream(const char path[]); + virtual ~SkFILEWStream(); + + /** Returns true if the current path could be opened. + */ + bool isValid() const { return fFILE != nil; } + + virtual bool write(const void* buffer, size_t size); + virtual void flush(); +private: + SkFILE* fFILE; +}; + +class SkMemoryWStream : public SkWStream { +public: + SkMemoryWStream(void* buffer, size_t size); + virtual bool write(const void* buffer, size_t size); + +private: + char* fBuffer; + size_t fMaxLength; + size_t fBytesWritten; +}; + +class SkDynamicMemoryWStream : public SkWStream { +public: + SkDynamicMemoryWStream(); + virtual ~SkDynamicMemoryWStream(); + virtual bool write(const void* buffer, size_t size); + // 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); + size_t getOffset() { return fBytesWritten; } + + // copy what has been written to the stream into dst + void copyTo(void* dst) const; + /* return a cache of the flattened data returned by copyTo(). + This copy is only valid until the next call to write(). + The memory is managed by the stream class. + */ + const char* getStream() const; + +private: + struct Block; + Block* fHead; + Block* fTail; + size_t fBytesWritten; + mutable char* fCopyToCache; +}; + + +class SkDebugWStream : public SkWStream { +public: + // overrides + virtual bool write(const void* buffer, size_t size); + virtual void newline(); +}; + +// for now +typedef SkFILEStream SkURLStream; + +#endif + diff --git a/include/graphics/SkStream_Win.h b/include/graphics/SkStream_Win.h new file mode 100644 index 000000000..8fdef0af2 --- /dev/null +++ b/include/graphics/SkStream_Win.h @@ -0,0 +1,37 @@ +#ifndef SkStream_Win_DEFINED +#define SkStream_Win_DEFINED + +#ifndef SK_BUILD_FOR_WIN +#error "only valid for windows and wince builds" +#endif + +#ifndef SkStream_DEFINED +#include "SkStream.h" +#endif +#include "SkString.h" +#include "Wininet.h" + +/** \cond ZERO */ +class SkURLStream : public SkStream { +public: + SkURLStream(const char url[] = nil); + virtual ~SkURLStream(); + + /** Close the current URL, and open a new URL. + If URL is nil, just close the current URL. + */ + void setURL(const char url[]); + + // overrides + virtual bool rewind(); + virtual size_t read(void* buffer, size_t size); + +private: + SkString fURL; + HINTERNET fConnection; + HINTERNET fURLStream; +}; + +/** \endcond */ +#endif // SkStream_Win_DEFINED + diff --git a/include/graphics/SkString.h b/include/graphics/SkString.h new file mode 100644 index 000000000..84b8493bf --- /dev/null +++ b/include/graphics/SkString.h @@ -0,0 +1,150 @@ +#ifndef SkString_DEFINED +#define SkString_DEFINED + +#include "SkScalar.h" + +/* Some helper functions for C strings +*/ + +bool SkStrStartsWith(const char string[], const char prefix[]); +bool SkStrEndsWith(const char string[], const char suffix[]); +int SkStrStartsWithOneOf(const char string[], const char prefixes[]); + +#define SkStrAppendS32_MaxSize 11 +char* SkStrAppendS32(char buffer[], int32_t); +#define SkStrAppendScalar_MaxSize 11 +char* SkStrAppendScalar(char buffer[], SkScalar); + +/** \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 SkString { +public: + SkString(); + explicit SkString(size_t len); + explicit SkString(const char text[]); + SkString(const char text[], size_t len); + explicit SkString(const SkString&); + ~SkString(); + + bool isEmpty() const { return fRec->fLength == 0; } + size_t size() const { return (size_t) fRec->fLength; } + const char* c_str() const { return fRec->data(); } + + bool equals(const SkString&) const; + bool equals(const char text[]) const; + bool equals(const char text[], size_t len) const; + + bool startsWith(const char prefix[]) const + { + return SkStrStartsWith(fRec->data(), prefix); + } + bool endsWith(const char suffix[]) const + { + return SkStrEndsWith(fRec->data(), suffix); + } + + friend int operator==(const SkString& a, const SkString& b) + { + return a.equals(b); + } + friend int operator!=(const SkString& a, const SkString& b) + { + return !a.equals(b); + } + + // these methods edit the string + + SkString& operator=(const SkString&); + + char* writable_str(); + + void reset(); + void resize(size_t len) { this->set(nil, len); } + void set(const SkString& src) { *this = src; } + void set(const char text[]); + void set(const char text[], size_t len); + void setUTF16(const U16[]); + + 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, S32 value); + void insertHex(size_t offset, U32 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(S32 value) { this->insertS32((size_t)-1, value); } + void appendHex(U32 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(S32 value) { this->insertS32(0, value); } + void prependHex(U32 value, int minDigits = 0) { this->insertHex(0, value, minDigits); } + void prependScalar(SkScalar value) { this->insertScalar((size_t)-1, value); } + + void printf(const char format[], ...); + + void remove(size_t offset, size_t length); + + /** Swap contents between this and other. This function is guaranteed + to never fail or throw. + */ + void swap(SkString& other); + + /** @cond UNIT_TEST */ + SkDEBUGCODE(static void UnitTest();) + /** @endcond */ + +private: +#ifdef SK_DEBUG + const char* fStr; +#endif + struct Rec { + U16 fLength; + U16 fRefCnt; + // data[] + char* data() { return (char*)(this) + sizeof(Rec); } + const char* data() const { return (const char*)(this) + sizeof(Rec); } + }; + Rec* fRec; + +#ifdef SK_DEBUG + void validate() const; +#else + void validate() const {} +#endif + + static Rec* AllocRec(const char text[], U16CPU 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 U16* getUCS2() const { return fUCS2; } + +private: + int fCount; + U16* fUCS2; +}; + +#endif + diff --git a/include/graphics/SkStroke.h b/include/graphics/SkStroke.h new file mode 100644 index 000000000..8b148a4ef --- /dev/null +++ b/include/graphics/SkStroke.h @@ -0,0 +1,58 @@ +#ifndef SkStroke_DEFINED +#define SkStroke_DEFINED + +#include "SkPoint.h" +#include "SkPaint.h" + +struct SkRect; +class SkPath; + +#define SK_DefaultStrokeWidth SK_Scalar1 +#define SK_DefaultMiterLimit SkIntToScalar(4) + + +/** \class SkStroke + SkStroke is the utility class that constructs paths by stroking + geometries (lines, rects, ovals, roundrects, paths). This is + invoked when a geometry or text is drawn in a canvas with the + kStroke_Mask bit set in the paint. +*/ +class SkStroke { +public: + SkStroke(); + SkStroke(const SkPaint&); + SkStroke(const SkPaint&, SkScalar width); // width overrides paint.getStrokeWidth() + + SkPaint::Cap getCap() const { return (SkPaint::Cap)fCap; } + void setCap(SkPaint::Cap); + + SkPaint::Join getJoin() const { return (SkPaint::Join)fJoin; } + void setJoin(SkPaint::Join); + +// SkScalar getMiterLimit() const { return fMiterLimit; } + void setMiterLimit(SkScalar); + +// SkScalar getWidth() const { return fWidth; } + void setWidth(SkScalar); + + bool getDoFill() const { return SkToBool(fDoFill); } + void setDoFill(bool doFill) { fDoFill = SkToU8(doFill); } + + void strokeLine(const SkPoint& start, const SkPoint& end, SkPath*) const; + void strokeRect(const SkRect& rect, SkPath*) const; + void strokeOval(const SkRect& oval, SkPath*) const; + void strokeRRect(const SkRect& rect, SkScalar rx, SkScalar ry, SkPath*) const; + void strokePath(const SkPath& path, SkPath*) const; + + //////////////////////////////////////////////////////////////// + +private: + SkScalar fWidth, fMiterLimit; + U8 fCap, fJoin; + SkBool8 fDoFill; + + friend class SkPaint; +}; + +#endif + diff --git a/include/graphics/SkSystemEventTypes.h b/include/graphics/SkSystemEventTypes.h new file mode 100644 index 000000000..3cf826c4b --- /dev/null +++ b/include/graphics/SkSystemEventTypes.h @@ -0,0 +1,16 @@ +#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/include/graphics/SkTDArray.h b/include/graphics/SkTDArray.h new file mode 100644 index 000000000..d33205b78 --- /dev/null +++ b/include/graphics/SkTDArray.h @@ -0,0 +1,288 @@ +#ifndef SkTDArray_DEFINED +#define SkTDArray_DEFINED + +#include "SkTypes.h" + +template class SkTDArray { +public: + SkTDArray() + { + fReserve = fCount = 0; + fArray = NULL; +#ifdef SK_DEBUG + fData = NULL; +#endif + } + SkTDArray(const T src[], U16CPU 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 = (T (*)[kDebugArraySize]) fArray; + (T*&)fData = fArray; +#endif + memcpy(fArray, src, sizeof(T) * count); + fReserve = fCount = SkToU16(count); + } + } + SkTDArray(const SkTDArray& src) + { + fReserve = fCount = 0; + fArray = NULL; +#ifdef SK_DEBUG + fData = NULL; +#endif + SkTDArray tmp(src.fArray, src.fCount); + this->swap(tmp); + } + ~SkTDArray() + { + sk_free(fArray); + } + + SkTDArray& operator=(const SkTDArray& src) + { + if (this != &src) + { + if (src.fCount > fReserve) + { + SkTDArray tmp(src.fArray, src.fCount); + this->swap(tmp); + } + else + { + memcpy(fArray, src.fArray, sizeof(T) * src.fCount); + fCount = src.fCount; + } + } + return *this; + } + + friend int operator==(const SkTDArray& a, const SkTDArray& b) + { + return a.fCount == b.fCount && + (a.fCount == 0 || !memcmp(a.fArray, b.fArray, a.fCount * sizeof(T))); + } + + void swap(SkTDArray& other) + { + SkTSwap(fArray, other.fArray); +#ifdef SK_DEBUG + SkTSwap(fData, other.fData); +#endif + SkTSwap(fReserve, other.fReserve); + SkTSwap(fCount, other.fCount); + } + + bool isEmpty() const { return fCount == 0; } + int count() const { return fCount; } + T* begin() const { return fArray; } + T* end() const { return fArray ? fArray + fCount : NULL; } + T& operator[](int index) const { SkASSERT((unsigned)index < fCount); return fArray[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 setCount(U16CPU count) + { + if (count > fReserve) + this->growBy(count - fCount); + else + fCount = SkToU16(count); + } + + void setReserve(U16CPU reserve) + { + if (reserve > fReserve) + { + SkASSERT(reserve > fCount); + U16 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(U16CPU count, const T* src = NULL) + { + unsigned 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(U16CPU index) { return this->insert(index, 1, NULL); } + T* insert(U16CPU index, U16CPU count, const T* src = NULL) + { + SkASSERT(count); + int 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(U16CPU index, U16CPU count = 1) + { + SkASSERT(index + count <= fCount); + fCount = SkToU16(fCount - count); + memmove(fArray + index, fArray + index + count, sizeof(T) * (fCount - index)); + } + + void removeShuffle(U16CPU index) + { + SkASSERT(index < fCount); + unsigned newCount = fCount - 1; + fCount = SkToU16(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; + } + + // routines to treat the array like a stack + T* push() { return this->append(); } + void push(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) + { + delete (*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(); + } + +private: +#ifdef SK_DEBUG + enum { + kDebugArraySize = 16 + }; + T(* fData)[kDebugArraySize]; +#endif + T* fArray; + U16 fReserve, fCount; + + void growBy(U16CPU extra) + { + SkASSERT(extra); + SkASSERT(fCount + extra <= 0xFFFF); + + 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 = (T (*)[kDebugArraySize]) fArray; + (T*&)fData = fArray; +#endif + fReserve = SkToU16((U16CPU)size); + } + fCount = SkToU16(fCount + extra); + } +}; + +#endif + diff --git a/include/graphics/SkTDStack.h b/include/graphics/SkTDStack.h new file mode 100644 index 000000000..ccd7b8e79 --- /dev/null +++ b/include/graphics/SkTDStack.h @@ -0,0 +1,104 @@ +#ifndef SkTDStack_DEFINED +#define SkTDStack_DEFINED + +#include "SkTypes.h" + +template class SkTDStack { +public: + SkTDStack() : fCount(0), fTotalCount(0) + { + fInitialRec.fNext = nil; + 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; } + + 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/include/graphics/SkTDict.h b/include/graphics/SkTDict.h new file mode 100644 index 000000000..c717ad15d --- /dev/null +++ b/include/graphics/SkTDict.h @@ -0,0 +1,154 @@ +#ifndef SkTDict_DEFINED +#define SkTDict_DEFINED + +#include "SkChunkAlloc.h" +//#include "SkTemplates.h" +#include "SkTSearch.h" +#include "SkTDArray.h" + +template class SkTDict { +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 + { + Pair* end = fArray.end(); + for (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& dict) + { + fIter = dict.fArray.begin(); + fStop = dict.fArray.end(); + } + const char* next(T* value) + { + const char* name = nil; + if (fIter < fStop) + { + name = fIter->fName; + if (value) + *value = fIter->fValue; + fIter += 1; + } + return name; + } + private: + Pair* fIter; + Pair* fStop; + }; + +private: + SkTDArray 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/include/graphics/SkTSearch.h b/include/graphics/SkTSearch.h new file mode 100644 index 000000000..e76d767d6 --- /dev/null +++ b/include/graphics/SkTSearch.h @@ -0,0 +1,56 @@ +#ifndef SkTSearch_DEFINED +#define SkTSearch_DEFINED + +#include "SkTypes.h" + +template +int SkTSearch(const T* base, int count, T target, size_t elemSize) +{ + SkASSERT(base != nil); + SkASSERT(count >= 0); + + if (count <= 0) + return ~0; + + 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 (*elem < target) + lo = mid + 1; + else + hi = mid; + } + + const T* elem = (const T*)((const char*)base + hi * elemSize); + if (*elem != target) + { + if (*elem < target) + hi += 1; + hi = ~hi; + } + return hi; +} + +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); + +extern "C" { + typedef int (*SkQSortCompareProc)(const void*, const void*); + void SkQSort(void* base, size_t count, size_t elemSize, SkQSortCompareProc); +} + +SkDEBUGCODE(void SkQSort_UnitTest();) + +#endif + diff --git a/include/graphics/SkTextBox.h b/include/graphics/SkTextBox.h new file mode 100644 index 000000000..1a7a3b642 --- /dev/null +++ b/include/graphics/SkTextBox.h @@ -0,0 +1,61 @@ +#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&); + +private: + SkRect fBox; + SkScalar fSpacingMul, fSpacingAdd; + U8 fMode, fSpacingAlign; +}; + +class SkTextLineBreaker { +public: + static int CountLines(const char text[], size_t len, const SkPaint&, SkScalar width); +}; + +#endif + diff --git a/include/graphics/SkTextLayout.h b/include/graphics/SkTextLayout.h new file mode 100644 index 000000000..4aa938e05 --- /dev/null +++ b/include/graphics/SkTextLayout.h @@ -0,0 +1,44 @@ +#ifndef SkTextLayout_DEFINED +#define SkTextLayout_DEFINED + +#include "SkRefCnt.h" +#include "SkPaint.h" +#include "SkScalar.h" + +class SkTextLayout : public SkRefCnt { +public: + /** Create a textlayout that implements the CSS features of letter-spacing + and word-spacing. It takes values to add to the advance width for each + letter (charExtra) and to add to the advance width for each space + (spaceExtra). + @param charExtra amount to add to every character's advance width + @param spaceExtra amount to add to every space character's advance width + @return a new textlayout subclass that implements tracking + */ + static SkTextLayout* CreateTrackingLayout(SkScalar charExtra, SkScalar spaceExtra); + + class Rec; + + int layout( const SkPaint& paint, + const char* text, size_t byteLength, SkUnicodeWalkerProc proc, + Rec rec[]); + + class Rec { + public: + SkUnichar charCode() const { return fCharCode; } + SkScalar fDeltaAdvance; //!< set by the subclass in onLayout() + + private: + SkUnichar fCharCode; + // to be used in the future + uint16_t fGlyphID; + uint16_t fFlags; + + friend class SkTextLayout; + }; + +protected: + virtual void onLayout(const SkPaint& paint, Rec rec[], int count) {} +}; + +#endif diff --git a/include/graphics/SkTime.h b/include/graphics/SkTime.h new file mode 100644 index 000000000..efcef8b29 --- /dev/null +++ b/include/graphics/SkTime.h @@ -0,0 +1,32 @@ +#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 { + U16 fYear; //!< e.g. 2005 + U8 fMonth; //!< 1..12 + U8 fDayOfWeek; //!< 0..6, 0==Sunday + U8 fDay; //!< 1..31 + U8 fHour; //!< 0..23 + U8 fMinute; //!< 0..59 + U8 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 + +#endif + diff --git a/include/graphics/SkTransparentShader.h b/include/graphics/SkTransparentShader.h new file mode 100644 index 000000000..3146caf99 --- /dev/null +++ b/include/graphics/SkTransparentShader.h @@ -0,0 +1,23 @@ +#ifndef SkTransparentShader_DEFINED +#define SkTransparentShader_DEFINED + +#include "SkShader.h" + +class SkTransparentShader : public SkShader { +public: + virtual U32 getFlags(); + virtual bool setContext( const SkBitmap& device, + const SkPaint& paint, + const SkMatrix& matrix); + virtual void shadeSpan(int x, int y, SkPMColor[], int count); + virtual void shadeSpanOpaque16(int x, int y, U16 span[], int count); + +private: + SkBitmap fDevice; + U8 fAlpha; + + typedef SkShader INHERITED; +}; + +#endif + diff --git a/include/graphics/SkTypeface.h b/include/graphics/SkTypeface.h new file mode 100644 index 000000000..cd0c21fba --- /dev/null +++ b/include/graphics/SkTypeface.h @@ -0,0 +1,67 @@ +#ifndef SkTypeface_DEFINED +#define SkTypeface_DEFINED + +#include "SkRefCnt.h" + +/** \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). +*/ +class SkTypeface : public SkRefCnt { +public: + /** Style enum specifies the possible 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 getStyle() const { return (Style)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; } + + /** Create a typeface object given a family name, and option style information. + If NULL is passed for the name, then the "default" font will be chosen. + The resulting typeface object can be queried (getStyle()) to discover what + its "real" style characteristics are. + + @param familyName May be NULL. The name of the font family. + @param s The style (normal, bold, italic) of the type face. + + */ + static SkTypeface* Create(const char familyName[], Style s = kNormal); + /** Create a typeface object that best matches the specified existing typeface + and the specified Style. Use this call if you want to pick a new style + from the same family of an existing typeface object. 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. + */ + static SkTypeface* CreateFromTypeface(const SkTypeface* family, Style s); + +protected: + void setStyle(Style s) { + fStyle = SkToU8(s); + } + + SkTypeface() {} + +private: + uint8_t fStyle; +}; + +#endif diff --git a/include/graphics/SkUnitMapper.h b/include/graphics/SkUnitMapper.h new file mode 100644 index 000000000..0bd00bb03 --- /dev/null +++ b/include/graphics/SkUnitMapper.h @@ -0,0 +1,35 @@ +#ifndef SkUnitMapper_DEFINED +#define SkUnitMapper_DEFINED + +#include "SkRefCnt.h" +#include "SkScalar.h" + +class SkUnitMapper : public SkRefCnt { +public: + /** Given a value in [0..0xFFFF], return a value in the same range. + */ + virtual U16CPU mapUnit16(U16CPU x) = 0; +}; + +/** This returns N values between [0...1] +*/ +class SkDiscreteMapper : public SkUnitMapper { +public: + SkDiscreteMapper(unsigned segments); + // override + virtual U16CPU mapUnit16(U16CPU x); +private: + unsigned fSegments; + SkFract fScale; +}; + +/** This returns 1 - cos(x), to simulate lighting a sphere +*/ +class SkFlipCosineMapper : public SkUnitMapper { +public: + // override + virtual U16CPU mapUnit16(U16CPU x); +}; + +#endif + diff --git a/include/graphics/SkUtils.h b/include/graphics/SkUtils.h new file mode 100644 index 000000000..3ccba3133 --- /dev/null +++ b/include/graphics/SkUtils.h @@ -0,0 +1,85 @@ +#ifndef SkUtils_DEFINED +#define SkUtils_DEFINED + +#include "SkTypes.h" + +#ifdef FMS_ARCH_ANDROID_ARM + #include "utils/memory.h" + + #define SK_MEMSET16_REDIRECT(dst, value, count) android_memset16(dst, value, (count) << 1) + #define SK_MEMSET32_REDIRECT(dst, value, count) android_memset32(dst, value, (count) << 2) +#endif + +/////////////////////////////////////////////////////////////////////////// + +#ifdef SK_MEMSET16_REDIRECT + #define sk_memset16(dst, value, count) SK_MEMSET16_REDIRECT(dst, value, count) +#else + /** Similar to memset(), but this function 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(uint16_t dst[], U16CPU value, int count); +#endif + +#ifdef SK_MEMSET32_REDIRECT + #define sk_memset32(dst, value, count) SK_MEMSET32_REDIRECT(dst, value, count) +#else + /** Similar to memset(), but this function 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(uint32_t dst[], uint32_t value, int count); +#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**); + +/** 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[] = nil); + +///////////////////////////////////////////////////////////////////////////////// + +#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); +SkUnichar SkUTF16_NextUnichar(const U16**); +size_t SkUTF16_FromUnichar(SkUnichar uni, uint16_t utf16[] = nil); + +size_t SkUTF16_ToUTF8(const uint16_t utf16[], int numberOf16BitValues, char utf8[] = nil); + +class SkUtils { +public: +#ifdef SK_DEBUG + static void UnitTest(); +#endif +}; + +#endif + diff --git a/include/graphics/SkView.h b/include/graphics/SkView.h new file mode 100644 index 000000000..a7868d6ec --- /dev/null +++ b/include/graphics/SkView.h @@ -0,0 +1,328 @@ +#ifndef SkView_DEFINED +#define SkView_DEFINED + +#include "SkEventSink.h" +#include "SkRect.h" +#include "SkDOM.h" +#include "SkTDict.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, + + 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 + + kAllFlagMasks = (U32)(0 - 1) >> (32 - kFlagShiftCount) + }; + + SkView(U32 flags = 0); + virtual ~SkView(); + + /** Return the flags associated with the view + */ + U32 getFlags() const { return fFlags; } + /** Set the flags associated with the view + */ + void setFlags(U32 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; } + /** Helper to set/clear the view's kVisible_Mask flag */ + void setVisibleP(bool); + void setEnabledP(bool); + void setFocusableP(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; + + /** 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); } + /** 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. */ + 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 nil, it specifies the entire view bounds. + */ + void inval(SkRect* rectOrNil); + + // 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; + SkPoint16 fIOrig, fIPrev, fICurr; + State fState; + private: + SkEventSinkID fTargetID; + char* fType; + bool fWeOwnTheType; + + void resetType(); + + friend class SkView; + }; + Click* findClickHandler(SkScalar x, SkScalar y); + + static void DoClickDown(Click*, int x, int y); + static void DoClickMoved(Click*, int x, int y); + static void DoClickUp(Click*, int x, int y); + + /** 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, nil is returned. + */ + SkView* sendEventToParents(const SkEvent&); + /** Depricated helper function. Just call event->post(sinkID, delay); + */ + bool postEvent(SkEvent* evt, SkEventSinkID sinkID, SkMSec delay) { return evt->post(sinkID, delay); } + + // View hierarchy management + + /** Return the view's parent, or nil 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 + */ + void globalToLocal(SkPoint* pt) const { if (pt) this->globalToLocal(pt->fX, pt->fY, pt); } + /** Convert the specified x,y from global coordinates into view-local coordinates, returning + the answer in the local parameter. + */ + void 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 nil, 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 nil, 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: + 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*); + }; + /** Return the artist attached to this view (or nil). The artist's reference + count is not affected. + */ + Artist* getArtist() const; + /** Attach the specified artist (or nil) to the view, replacing any existing + artist. If the new artist is not nil, 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: + 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*); + }; + + /** Return the layout attached to this view (or nil). The layout's reference + count is not affected. + */ + Layout* getLayout() const; + /** Attach the specified layout (or nil) to the view, replacing any existing + layout. If the new layout is not nil, 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 , 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& 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&); + /** Override this if you might handle the click + */ + virtual Click* onFindClickHandler(SkScalar x, SkScalar y); + /** 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&); + +public: + // 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; + SkPoint fLoc; + SkView* fParent; + SkView* fFirstChild; + SkView* fNextSibling; + SkView* fPrevSibling; + + U8 fFlags; + U8 fContainsFocus; + + friend class B2FIter; + friend class F2BIter; + + friend class SkLayerView; + + bool setFocusView(SkView* fvOrNil); + SkView* acceptFocus(FocusDirection); + void detachFromParent_NoLayout(); +}; + +#endif + diff --git a/include/graphics/SkViewInflate.h b/include/graphics/SkViewInflate.h new file mode 100644 index 000000000..5bf9f43d9 --- /dev/null +++ b/include/graphics/SkViewInflate.h @@ -0,0 +1,63 @@ +#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 nil, create the root element + as a view, otherwise assume root is that view, and just "inflate" it. + + Returns nil if the tree cannot be built. + */ + SkView* inflate(const SkDOM& dom, const SkDOM::Node* node, SkView* root = nil); + SkView* inflate(const char xml[], size_t len, SkView* root = nil); + + /** Given an id attribute value, return the corresponding view, or nil + 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 fIDs; + + struct IDStr { + SkView* fView; + char* fStr; + }; + SkTDArray fListenTo, fBroadcastTo; + SkChunkAlloc fStrings; + + void addIDStr(SkTDArray* list, SkView*, const char* str); + + void rInflate(const SkDOM& dom, const SkDOM::Node* node, SkView* parent); +}; + +#endif + diff --git a/include/graphics/SkWidget.h b/include/graphics/SkWidget.h new file mode 100644 index 000000000..586eb7ad3 --- /dev/null +++ b/include/graphics/SkWidget.h @@ -0,0 +1,460 @@ +#ifndef SkWidget_DEFINED +#define SkWidget_DEFINED + +#include "SkView.h" +#include "SkBitmap.h" +#include "SkDOM.h" +#include "SkPaint.h" +#include "SkString.h" +#include "SkTDArray.h" + +////////////////////////////////////////////////////////////////////////////// + +class SkWidget : public SkView { +public: + SkWidget(U32 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(); + + // 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(U32 flags = 0) : SkWidget(flags) {} + + size_t getLabel(SkString* label = nil) const; + size_t getLabel(char lable[] = nil) 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(U32 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(U32 flags = 0) : SkButtonWidget(flags) {} + +protected: + virtual bool onEvent(const SkEvent&); + virtual void onDraw(SkCanvas*); + virtual Click* onFindClickHandler(SkScalar x, SkScalar y); + virtual bool onClick(Click* click); + +private: + typedef SkButtonWidget INHERITED; +}; + +class SkCheckBoxWidget : public SkButtonWidget { +public: + SkCheckBoxWidget(U32 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; +}; + +#include "SkTextBox.h" + +class SkStaticTextView : public SkView { +public: + SkStaticTextView(U32 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 = nil) const; + size_t getText(char text[] = nil) 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; + U8 fMode; + U8 fSpacingAlign; + + void computeSize(); + + typedef SkView INHERITED; +}; + +class SkBitmapView : public SkView { +public: + SkBitmapView(U32 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 SkShader; +class SkInterpolator; + +class SkWidgetView : public SkView { +public: + SkWidgetView(U32 flags = 0); + virtual ~SkWidgetView(); + + static const char* GetEventType(); +}; + +class SkSliderView : public SkWidgetView { +public: + SkSliderView(U32 flags = 0); + + U16 getValue() const { return fValue; } + U16 getMax() const { return fMax; } + + void setMax(U16CPU max); + void setValue(U16CPU value); + +protected: + virtual void onDraw(SkCanvas*); + virtual Click* onFindClickHandler(SkScalar x, SkScalar y); + virtual bool onClick(Click*); + +private: + U16 fValue, fMax; + + typedef SkWidgetView 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(U32 flags = 0); + +protected: + virtual void onDraw(SkCanvas*); + virtual void onInflate(const SkDOM& dom, const SkDOM::Node*); +}; + +class SkCheckBoxView : public SkHasLabelView { +public: + SkCheckBoxView(U32 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(U32 flags = 0); + virtual ~SkProgressView(); + + U16 getValue() const { return fValue; } + U16 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: + U16 fValue, fMax; + SkShader* fOnShader, *fOffShader; + SkInterpolator* fInterp; + bool fDoInterp; + + typedef SkView INHERITED; +}; + +class SkTextView : public SkView { +public: + SkTextView(U32 flags = 0); + virtual ~SkTextView(); + + enum AnimaDir { + kNeutral_AnimDir, + kForward_AnimDir, + kBackward_AnimDir, + kAnimDirCount + }; + + void getText(SkString*) const; + void setText(const SkString&, AnimaDir dir = kNeutral_AnimDir); + void setText(const char text[], AnimaDir dir = kNeutral_AnimDir); + void setText(const char text[], size_t len, AnimaDir dir = kNeutral_AnimDir); + + void getMargin(SkPoint* margin) const; + void setMargin(const SkPoint&); + + SkPaint& paint() { return fPaint; } + +protected: + virtual void onDraw(SkCanvas*); + virtual void onInflate(const SkDOM& dom, const SkDOM::Node* node); + +private: + SkString fText; + SkPaint fPaint; + SkPoint fMargin; + + class Interp; + Interp* fInterp; + bool fDoInterp; + // called by the other setText methods. This guy does not check for != + // before doing the assign, so the caller must check for us + void privSetText(const SkString&, AnimaDir dir); + + typedef SkView INHERITED; +}; + +////////////////////////////////////////////////////////// + +class SkEvent; + +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 SkWidgetView { +public: + SkListView(U32 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 nil, 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 nil, 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 SkWidgetView INHERITED; +}; + +////////////////////////////////////////////////////////// + +class SkGridView : public SkWidgetView { +public: + SkGridView(U32 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; + SkPoint16 fVisibleCount; + + int logicalToVisualIndex(int index) const { return index; } + void invalSelection(); + bool getCellRect(int index, SkRect*) const; + void ensureSelectionIsVisible(); + + typedef SkWidgetView INHERITED; +}; + +#endif + diff --git a/include/graphics/SkWidgetViews.h b/include/graphics/SkWidgetViews.h new file mode 100644 index 000000000..52a3e0d24 --- /dev/null +++ b/include/graphics/SkWidgetViews.h @@ -0,0 +1,294 @@ +#ifndef SkWidgetViews_DEFINED +#define SkWidgetViews_DEFINED + +#include "SkView.h" + + +enum SkWidgetEnum { + kBorder_WidgetEnum, //!< + kButton_WidgetEnum, //!< + kImage_WidgetEnum, //!< + kList_WidgetEnum, //!< + kProgress_WidgetEnum, //!< + kScroll_WidgetEnum, //!< + kText_WidgetEnum, //!< + + 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 nil +*/ +SkView* SkWidgetFactory(SkWidgetEnum); +/** Given the inflate/element name of a widget, return an instance of + the specified widget, or nil 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&); +}; + +//////////////////////////////////////////////////////////////////////////////////////////////// + +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: + U8 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 = nil) const; + size_t getText(char text[] = nil) 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; + U8 fMode; + U8 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 != nil; } + 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]; + S16 fScrollIndex, fCurrIndex; + U16 fVisibleRowCount, fBindingCount; + SkBool8 fAnimContentDirty; + SkBool8 fAnimFocusDirty; + + typedef SkWidgetView INHERITED; +}; + +class SkListSource : public SkRefCnt { +public: + 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[]); +}; + +#endif diff --git a/include/graphics/SkWindow.h b/include/graphics/SkWindow.h new file mode 100644 index 000000000..8132b115f --- /dev/null +++ b/include/graphics/SkWindow.h @@ -0,0 +1,84 @@ +#ifndef SkWindow_DEFINED +#define SkWindow_DEFINED + +#include "SkView.h" +#include "SkBitmap.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 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(SkRect16* updateArea); + bool handleClick(int x, int y, Click::State); + bool handleChar(SkUnichar); + bool handleKey(SkKey); + bool handleKeyUp(SkKey); + bool handleMenu(U32 os_cmd); + + void addMenu(SkOSMenu*); + +protected: + virtual bool onEvent(const SkEvent&); + + // called if part of our bitmap is invalidated + virtual void onHandleInval(const SkRect16&); + virtual bool onHandleChar(SkUnichar); + virtual bool onHandleKey(SkKey); + virtual bool onHandleKeyUp(SkKey); + virtual void onAddMenu(const SkOSMenu*) {} + + // 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; + Click* fClick; // to track clicks + + SkTDArray fMenus; + + SkView* fFocusView; + bool fWaitingOnInval; + + typedef SkView INHERITED; +}; + +/////////////////////////////////////////////////////////// + +#ifndef SK_USE_WXWIDGETS +#ifdef SK_BUILD_FOR_MAC + #include "SkOSWindow_Mac.h" +#elif defined(SK_BUILD_FOR_WIN) + #include "SkOSWindow_Win.h" +#elif defined(SK_BUILD_FOR_UNIXx) + #include "SkOSWindow_Unix.h" +#endif +#else + #include "SkOSWindow_wxwidgets.h" +#endif + +#endif + diff --git a/include/graphics/SkXMLParser.h b/include/graphics/SkXMLParser.h new file mode 100644 index 000000000..125582216 --- /dev/null +++ b/include/graphics/SkXMLParser.h @@ -0,0 +1,79 @@ +#ifndef SkXMLParser_DEFINED +#define SkXMLParser_DEFINED + +#include "SkMath.h" +#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 = nil); + 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); +}; + +#endif diff --git a/include/graphics/SkXMLWriter.h b/include/graphics/SkXMLWriter.h new file mode 100644 index 000000000..cc2c55a02 --- /dev/null +++ b/include/graphics/SkXMLWriter.h @@ -0,0 +1,77 @@ +#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[], S32 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[], U32 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 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 + diff --git a/include/graphics/SkXfermode.h b/include/graphics/SkXfermode.h new file mode 100644 index 000000000..9a6faaded --- /dev/null +++ b/include/graphics/SkXfermode.h @@ -0,0 +1,62 @@ +#ifndef SkXfermode_DEFINED +#define SkXfermode_DEFINED + +#include "SkFlattenable.h" +#include "SkColor.h" + +/** \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 SkXfermode : public SkFlattenable { +public: + SkXfermode() {} + + virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count, const SkAlpha aa[]); + virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count, const SkAlpha aa[]); + virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count, const SkAlpha aa[]); + +protected: + SkXfermode(SkRBuffer&) {} + +private: + 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[]); + virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count, const SkAlpha aa[]); + virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count, const SkAlpha aa[]); + + // overrides from SkFlattenable + virtual Factory getFactory(); + virtual void flatten(SkWBuffer&); + +protected: + SkProcXfermode(SkRBuffer&); + +private: + SkXfermodeProc fProc; + + static SkFlattenable* CreateProc(SkRBuffer&); + + typedef SkXfermode INHERITED; +}; + +#endif + diff --git a/libs/corecg/Makefile b/libs/corecg/Makefile new file mode 100644 index 000000000..2e78667e6 --- /dev/null +++ b/libs/corecg/Makefile @@ -0,0 +1,30 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + Sk64.cpp \ + SkBuffer.cpp \ + SkChunkAlloc.cpp \ + SkCordic.cpp \ + SkDebug.cpp \ + SkDebug_stdio.cpp \ + SkFloat.cpp \ + SkMath.cpp \ + SkMatrix.cpp \ + SkMemory_stdlib.cpp \ + SkPoint.cpp \ + SkRect.cpp \ + SkRegion.cpp + +LOCAL_SHARED_LIBRARIES := \ + libutils + +LOCAL_C_INCLUDES += \ + include/corecg + +#LOCAL_CFLAGS+= +#LOCAL_LDFLAGS:= + +LOCAL_TARGET:= libcorecg + +include $(BUILD_SHARED_LIBRARY) diff --git a/libs/corecg/Sk64.cpp b/libs/corecg/Sk64.cpp new file mode 100644 index 000000000..3a557fb60 --- /dev/null +++ b/libs/corecg/Sk64.cpp @@ -0,0 +1,553 @@ +#include "Sk64.h" + +#define shift_left(hi, lo) \ + hi = (hi << 1) | (lo >> 31); \ + lo <<= 1 + +#define shift_left_bits(hi, lo, bits) \ + SkASSERT((unsigned)(bits) < 31); \ + hi = (hi << (bits)) | (lo >> (32 - (bits))); \ + lo <<= (bits) + +////////////////////////////////////////////////////////////////////// + +int Sk64::getClzAbs() const +{ + int32_t hi = fHi; + uint32_t lo = fLo; + + // get abs + if (hi < 0) + { + hi = -hi - Sk32ToBool(lo); + lo = 0 - lo; + } + return hi ? SkCLZ(hi) : SkCLZ(lo) + 32; +} + +void Sk64::shiftLeft(unsigned bits) +{ + SkASSERT(bits <= 63); + if (bits == 0) + return; + + if (bits >= 32) + { + fHi = fLo << (bits - 32); + fLo = 0; + } + else + { + fHi = (fHi << bits) | (fLo >> (32 - bits)); + fLo <<= bits; + } +} + +int32_t Sk64::getShiftRight(unsigned bits) const +{ + SkASSERT(bits <= 63); + + if (bits == 0) + return fLo; + + if (bits >= 32) + return fHi >> (bits - 32); + else + { +#ifdef SK_DEBUG + int32_t tmp = fHi >> bits; + SkASSERT(tmp == 0 || tmp == -1); +#endif + return (fHi << (32 - bits)) | (fLo >> bits); + } +} + +void Sk64::shiftRight(unsigned bits) +{ + SkASSERT(bits <= 63); + if (bits == 0) + return; + + if (bits >= 32) + { + fLo = fHi >> (bits - 32); + fHi >>= 31; + } + else + { + fLo = (fHi << (32 - bits)) | (fLo >> bits); + fHi >>= bits; + } +} + +void Sk64::roundRight(unsigned bits) +{ + SkASSERT(bits <= 63); + if (bits) + { + Sk64 one; + one.set(1); + one.shiftLeft(bits - 1); + this->add(one); + this->shiftRight(bits); + } +} + +int Sk64::shiftToMake32() const +{ + int32_t hi = fHi; + uint32_t lo = fLo; + + if (hi < 0) // make it positive + { + hi = -hi - Sk32ToBool(lo); + lo = 0 - lo; + } + + if (hi == 0) + return lo >> 31; + else + return 33 - SkCLZ(hi); +} + +void Sk64::negate() +{ + fHi = -fHi - Sk32ToBool(fLo); + fLo = 0 - fLo; +} + +void Sk64::abs() +{ + if (fHi < 0) + { + fHi = -fHi - Sk32ToBool(fLo); + fLo = 0 - fLo; + } +} + +//////////////////////////////////////////////////////////////// + +static inline int32_t round_right_16(int32_t hi, uint32_t lo) +{ + uint32_t sum = lo + (1 << 15); + hi += (sum < lo); + return (hi << 16) | (sum >> 16); +} + +SkBool Sk64::isFixed() const +{ + Sk64 tmp = *this; + tmp.roundRight(16); + return tmp.is32(); +} + +SkFract Sk64::getFract() const +{ + Sk64 tmp = *this; + tmp.roundRight(30); + return tmp.get32(); +} + +void Sk64::sub(const Sk64& a) +{ + fHi = fHi - a.fHi - (fLo < a.fLo); + fLo = fLo - a.fLo; +} + +void Sk64::rsub(const Sk64& a) +{ + fHi = a.fHi - fHi - (a.fLo < fLo); + fLo = a.fLo - fLo; +} + +void Sk64::setMul(int32_t a, int32_t b) +{ + int sa = a >> 31; + int sb = b >> 31; + // now make them positive + a = (a ^ sa) - sa; + b = (b ^ sb) - sb; + + uint32_t ah = a >> 16; + uint32_t al = a & 0xFFFF; + uint32_t bh = b >> 16; + uint32_t bl = b & 0xFFFF; + + uint32_t A = ah * bh; + uint32_t B = ah * bl + al * bh; + uint32_t C = al * bl; + + /* [ A ] + [ B ] + [ C ] + */ + fLo = C + (B << 16); + fHi = A + (B >>16) + (fLo < C); + + if (sa != sb) + this->negate(); +} + +void Sk64::div(int32_t denom, DivOptions option) +{ + SkASSERT(denom); + + int32_t hi = fHi; + uint32_t lo = fLo; + int sign = denom ^ hi; + + denom = SkAbs32(denom); + if (hi < 0) + { + hi = -hi - Sk32ToBool(lo); + lo = 0 - lo; + } + + if (option == kRound_DivOption) // add denom/2 + { + uint32_t newLo = lo + (denom >> 1); + hi += (newLo < lo); + lo = newLo; + } + + if (hi == 0) // fast-case + { + if (lo < (uint32_t)denom) + this->set(0, 0); + else + { + this->set(0, lo / denom); + if (sign < 0) + this->negate(); + } + return; + } + + int bits; + + { + int dbits = SkCLZ(denom); + int nbits = SkCLZ(hi); + + bits = 32 + dbits - nbits; + SkASSERT(bits <= 63); + if (bits <= 0) + { + this->set(0, 0); + return; + } + denom <<= (dbits - 1); + shift_left_bits(hi, lo, nbits - 1); + } + + int32_t rhi = 0; + uint32_t rlo = 0; + + do { + shift_left(rhi, rlo); +#ifdef SK_CPU_HAS_CONDITIONAL_INSTR + if ((uint32_t)denom <= (uint32_t)hi) + { + hi -= denom; + rlo |= 1; + } +#else + int32_t diff = (denom - hi - 1) >> 31; + hi -= denom & diff; + rlo -= diff; +#endif + shift_left(hi, lo); + } while (--bits >= 0); + SkASSERT(rhi >= 0); + + fHi = rhi; + fLo = rlo; + if (sign < 0) + this->negate(); +} + +#define shift_left_2(a, b, c) \ + a = (a << 2) | (b >> 30); \ + b = (b << 2) | (c >> 30); \ + c <<= 2 + +int32_t Sk64::getSqrt() const +{ + SkASSERT(!this->isNeg()); + + uint32_t hi = fHi; + uint32_t lo = fLo; + uint32_t sqr = 0; + uint32_t root = 0; + int count = 31; + + do { + root <<= 1; + shift_left_2(sqr, hi, lo); + + uint32_t testDiv = (root << 1) + 1; + if (sqr >= testDiv) + { + sqr -= testDiv; + root++; + } + } while (--count >= 0); + SkASSERT((int32_t)root >= 0); + + return root; +} + +#ifdef SK_CAN_USE_LONGLONG + SkLONGLONG Sk64::getLongLong() const + { + SkLONGLONG value = fHi; + value <<= 32; + return value | fLo; + } +#endif + +SkFixed Sk64::getFixedDiv(const Sk64& denom) const +{ + Sk64 N = *this; + Sk64 D = denom; + int32_t sign = SkExtractSign(N.fHi ^ D.fHi); + SkFixed result; + + N.abs(); + D.abs(); + + // need to knock D down to just 31 bits + // either by rounding it to the right, or shifting N to the left + // then we can just call 64/32 div + + int nclz = N.fHi ? SkCLZ(N.fHi) : 32; + int dclz = D.fHi ? SkCLZ(D.fHi) : (33 - (D.fLo >> 31)); + + int shiftN = nclz - 1; + SkASSERT(shiftN >= 0); + int shiftD = 33 - dclz; + SkASSERT(shiftD >= 0); + + if (shiftD + shiftN < 16) + shiftD = 16 - shiftN; + else + shiftN = 16 - shiftD; + + D.roundRight(shiftD); + if (D.isZero()) + result = SK_MaxS32; + else + { + if (shiftN >= 0) + N.shiftLeft(shiftN); + else + N.roundRight(-shiftN); + N.div(D.get32(), Sk64::kTrunc_DivOption); + if (N.is32()) + result = N.get32(); + else + result = SK_MaxS32; + } + return SkApplySign(result, sign); +} + +/////////////////////////////////////////////////////////////////////// + +#ifdef SK_DEBUG + +#include "SkRandom.h" +#include + +#ifdef SK_SUPPORT_UNITTEST +struct BoolTable { + S8 zero, pos, neg, toBool, sign; +}; + +static void bool_table_test(const Sk64& a, const BoolTable& table) +{ + SkASSERT(a.isZero() != a.nonZero()); + + SkASSERT(!a.isZero() == !table.zero); + SkASSERT(!a.isPos() == !table.pos); + SkASSERT(!a.isNeg() == !table.neg); + SkASSERT(a.sign() == table.sign); +} + +#ifdef SK_CAN_USE_LONGLONG + static SkLONGLONG asLL(const Sk64& a) + { + return ((SkLONGLONG)a.fHi << 32) | a.fLo; + } +#endif +#endif + +void Sk64::UnitTest() +{ +#ifdef SK_SUPPORT_UNITTEST + enum BoolTests { + kZero_BoolTest, + kPos_BoolTest, + kNeg_BoolTest + }; + static const BoolTable gBoolTable[] = { + { 1, 0, 0, 0, 0 }, + { 0, 1, 0, 1, 1 }, + { 0, 0, 1, 1, -1 } + }; + + Sk64 a, b, c; + + a.fHi = a.fLo = 0; + b.set(0); + c.setZero(); + SkASSERT(a == b); + SkASSERT(a == c); + bool_table_test(a, gBoolTable[kZero_BoolTest]); + + a.fHi = 0; a.fLo = 5; + b.set(5); + SkASSERT(a == b); + SkASSERT(a.is32() && a.get32() == 5 && !a.is64()); + bool_table_test(a, gBoolTable[kPos_BoolTest]); + + a.fHi = -1; a.fLo = (uint32_t)-5; + b.set(-5); + SkASSERT(a == b); + SkASSERT(a.is32() && a.get32() == -5 && !a.is64()); + bool_table_test(a, gBoolTable[kNeg_BoolTest]); + + a.setZero(); + b.set(6); + c.set(-6); + SkASSERT(a != b && b != c && a != c); + SkASSERT(!(a == b) && !(a == b) && !(a == b)); + SkASSERT(a < b && b > a && a <= b && b >= a); + SkASSERT(c < a && a > c && c <= a && a >= c); + SkASSERT(c < b && b > c && c <= b && b >= c); + + // Now test add/sub + + SkRandom rand; + int i; + + for (i = 0; i < 1000; i++) + { + int aa = rand.nextS() >> 1; + int bb = rand.nextS() >> 1; + a.set(aa); + b.set(bb); + SkASSERT(a.get32() == aa && b.get32() == bb); + c = a; c.add(bb); + SkASSERT(c.get32() == aa + bb); + c = a; c.add(-bb); + SkASSERT(c.get32() == aa - bb); + c = a; c.add(b); + SkASSERT(c.get32() == aa + bb); + c = a; c.sub(b); + SkASSERT(c.get32() == aa - bb); + } + +#ifdef SK_CAN_USE_LONGLONG + for (i = 0; i < 1000; i++) + { + rand.next64(&a); //a.fHi >>= 1; // avoid overflow + rand.next64(&b); //b.fHi >>= 1; // avoid overflow + + if (!(i & 3)) // want to explicitly test these cases + { + a.fLo = 0; + b.fLo = 0; + } + else if (!(i & 7)) // want to explicitly test these cases + { + a.fHi = 0; + b.fHi = 0; + } + + SkLONGLONG aa = asLL(a); + SkLONGLONG bb = asLL(b); + + SkASSERT((a < b) == (aa < bb)); + SkASSERT((a <= b) == (aa <= bb)); + SkASSERT((a > b) == (aa > bb)); + SkASSERT((a >= b) == (aa >= bb)); + SkASSERT((a == b) == (aa == bb)); + SkASSERT((a != b) == (aa != bb)); + + c = a; c.add(b); + SkASSERT(asLL(c) == aa + bb); + c = a; c.sub(b); + SkASSERT(asLL(c) == aa - bb); + c = a; c.rsub(b); + SkASSERT(asLL(c) == bb - aa); + c = a; c.negate(); + SkASSERT(asLL(c) == -aa); + + int bits = rand.nextU() & 63; + c = a; c.shiftLeft(bits); + SkASSERT(asLL(c) == (aa << bits)); + c = a; c.shiftRight(bits); + SkASSERT(asLL(c) == (aa >> bits)); + c = a; c.roundRight(bits); + + SkLONGLONG tmp; + + tmp = aa; + if (bits > 0) + tmp += (SkLONGLONG)1 << (bits - 1); + SkASSERT(asLL(c) == (tmp >> bits)); + + c.setMul(a.fHi, b.fHi); + tmp = (SkLONGLONG)a.fHi * b.fHi; + SkASSERT(asLL(c) == tmp); + } + + + for (i = 0; i < 100000; i++) + { + Sk64 wide; + int32_t denom = rand.nextS(); + + while (denom == 0) + denom = rand.nextS(); + wide.setMul(rand.nextS(), rand.nextS()); + SkLONGLONG check = wide.getLongLong(); + + wide.div(denom, Sk64::kTrunc_DivOption); + check /= denom; + SkLONGLONG w = wide.getLongLong(); + + SkASSERT(check == w); + +#ifdef SK_CAN_USE_FLOAT + wide.setMul(rand.nextS(), rand.nextS()); + wide.abs(); + denom = wide.getSqrt(); + int32_t ck = (int32_t)sqrt((double)wide.getLongLong()); + int diff = denom - ck; + SkASSERT(SkAbs32(diff) <= 1); + + wide.setMul(rand.nextS(), rand.nextS()); + Sk64 dwide; + dwide.setMul(rand.nextS(), rand.nextS()); + SkFixed fixdiv = wide.getFixedDiv(dwide); + double dnumer = (double)wide.getLongLong(); + double ddenom = (double)dwide.getLongLong(); + double ddiv = dnumer / ddenom; + SkFixed dfixdiv; + if (ddiv >= (double)SK_MaxS32 / (double)SK_Fixed1) + dfixdiv = SK_MaxS32; + else if (ddiv <= -(double)SK_MaxS32 / (double)SK_Fixed1) + dfixdiv = SK_MinS32; + else + dfixdiv = SkFloatToFixed(dnumer / ddenom); + diff = fixdiv - dfixdiv; + SkASSERT(SkAbs32(diff) <= 1); +#endif + } +#endif +#endif +} + +#endif + diff --git a/libs/corecg/SkBuffer.cpp b/libs/corecg/SkBuffer.cpp new file mode 100644 index 000000000..8f4792f3a --- /dev/null +++ b/libs/corecg/SkBuffer.cpp @@ -0,0 +1,106 @@ +#include "SkBuffer.h" + +//////////////////////////////////////////////////////////////////////////////////////// + +void SkRBuffer::readNoSizeCheck(void* buffer, size_t size) +{ + SkASSERT(fData != 0 && fStop == 0 || fPos + size <= fStop); + if (buffer) + memcpy(buffer, fPos, size); + fPos += size; +} + +size_t SkRBuffer::skipToAlign4() +{ + size_t pos = this->pos(); + size_t n = SkAlign4(pos) - pos; + fPos += n; + return n; +} + +void SkWBuffer::writeNoSizeCheck(const void* buffer, size_t size) +{ + SkASSERT(fData == 0 || fStop == 0 || fPos + size <= fStop); + if (fData && buffer) + memcpy(fPos, buffer, size); + fPos += size; +} + +size_t SkWBuffer::padToAlign4() +{ + size_t pos = this->pos(); + size_t n = SkAlign4(pos) - pos; + + if (n && fData) + { + char* p = fPos; + char* stop = p + n; + do { + *p++ = 0; + } while (p < stop); + } + fPos += n; + return n; +} + +#if 0 +#ifdef SK_DEBUG + static void AssertBuffer32(const void* buffer) + { + SkASSERT(buffer); + SkASSERT(((size_t)buffer & 3) == 0); + } +#else + #define AssertBuffer32(buffer) +#endif + +void* sk_buffer_write_int32(void* buffer, int32_t value) +{ + AssertBuffer32(buffer); + *(int32_t*)buffer = value; + return (char*)buffer + sizeof(int32_t); +} + +void* sk_buffer_write_int32(void* buffer, const int32_t values[], int count) +{ + AssertBuffer32(buffer); + SkASSERT(count >= 0); + + memcpy((int32_t*)buffer, values, count * sizeof(int32_t)); + return (char*)buffer + count * sizeof(int32_t); +} + +const void* sk_buffer_read_int32(const void* buffer, int32_t* value) +{ + AssertBuffer32(buffer); + if (value) + *value = *(const int32_t*)buffer; + return (const char*)buffer + sizeof(int32_t); +} + +const void* sk_buffer_read_int32(const void* buffer, int32_t values[], int count) +{ + AssertBuffer32(buffer); + SkASSERT(count >= 0); + + if (values) + memcpy(values, (const int32_t*)buffer, count * sizeof(int32_t)); + return (const char*)buffer + count * sizeof(int32_t); +} + +void* sk_buffer_write_ptr(void* buffer, void* ptr) +{ + AssertBuffer32(buffer); + *(void**)buffer = ptr; + return (char*)buffer + sizeof(void*); +} + +const void* sk_buffer_read_ptr(const void* buffer, void** ptr) +{ + AssertBuffer32(buffer); + if (ptr) + *ptr = *(void**)buffer; + return (const char*)buffer + sizeof(void*); +} + +#endif diff --git a/libs/corecg/SkChunkAlloc.cpp b/libs/corecg/SkChunkAlloc.cpp new file mode 100644 index 000000000..cfeccc00c --- /dev/null +++ b/libs/corecg/SkChunkAlloc.cpp @@ -0,0 +1,45 @@ +#include "SkChunkAlloc.h" + +SkChunkAlloc::~SkChunkAlloc() +{ + this->reset(); +} + +void SkChunkAlloc::reset() +{ + Block* block = fBlock; + + while (block) + { + Block* next = block->fNext; + sk_free(block); + block = next; + } + fBlock = nil; +} + +void* SkChunkAlloc::alloc(size_t bytes, AllocFailType ftype) +{ + bytes = SkAlign4(bytes); + + if (fBlock == nil || bytes > fBlock->fFreeSize) + { + size_t size = SkMax32((S32)bytes, (S32)fMinSize); + Block* block = (Block*)sk_malloc_flags(sizeof(Block) + size, ftype == kThrow_AllocFailType ? SK_MALLOC_THROW : 0); + if (block == nil) + return nil; + + block->fNext = fBlock; + block->fFreeSize = size; + block->fFreePtr = (char*)block + sizeof(Block); + fBlock = block; + } + + SkASSERT(fBlock && bytes <= fBlock->fFreeSize); + void* ptr = fBlock->fFreePtr; + + fBlock->fFreeSize -= bytes; + fBlock->fFreePtr += bytes; + return ptr; +} + diff --git a/libs/corecg/SkCordic.cpp b/libs/corecg/SkCordic.cpp new file mode 100644 index 000000000..32266e9cc --- /dev/null +++ b/libs/corecg/SkCordic.cpp @@ -0,0 +1,284 @@ +#include "SkCordic.h" +#include "SkMath.h" +#include "Sk64.h" + +// 0x20000000 equals pi / 4 +const int32_t kATanDegrees[] = { 0x20000000, + 0x12E4051D, 0x9FB385B, 0x51111D4, 0x28B0D43, 0x145D7E1, 0xA2F61E, 0x517C55, + 0x28BE53, 0x145F2E, 0xA2F98, 0x517CC, 0x28BE6, 0x145F3, 0xA2F9, 0x517C, + 0x28BE, 0x145F, 0xA2F, 0x517, 0x28B, 0x145, 0xA2, 0x51, 0x28, 0x14, + 0xA, 0x5, 0x2, 0x1 }; + +const int32_t kFixedInvGain1 = 0x18bde0bb; // 0.607252935 + +static void SkCircularRotation(int32_t* x0, int32_t* y0, int32_t* z0) +{ + int32_t t = 0; + int32_t x = *x0; + int32_t y = *y0; + int32_t z = *z0; + const int32_t* tanPtr = kATanDegrees; + do { + int32_t x1 = y >> t; + int32_t y1 = x >> t; + int32_t tan = *tanPtr++; + if (z >= 0) { + x -= x1; + y += y1; + z -= tan; + } else { + x += x1; + y -= y1; + z += tan; + } + } while (++t < 16); // 30); + *x0 = x; + *y0 = y; + *z0 = z; +} + +SkFixed SkCordicSinCos(SkFixed radians, SkFixed* cosp) +{ + int32_t scaledRadians = radians * 0x28be; // scale radians to 65536 / PI() + int quadrant = scaledRadians >> 30; + quadrant += 1; + if (quadrant & 2) + scaledRadians = -scaledRadians + 0x80000000; + /* |a| <= 90 degrees as a 1.31 number */ + SkFixed sin = 0; + SkFixed cos = kFixedInvGain1; + SkCircularRotation(&cos, &sin, &scaledRadians); + Sk64 scaled; + scaled.setMul(sin, 0x6488d); + sin = scaled.fHi; + scaled.setMul(cos, 0x6488d); + if (quadrant & 2) + scaled.fHi = - scaled.fHi; + *cosp = scaled.fHi; + return sin; +} + +SkFixed SkCordicTan(SkFixed a) +{ + int32_t cos; + int32_t sin = SkCordicSinCos(a, &cos); + return SkFixedDiv(sin, cos); +} + +static int32_t SkCircularVector(int32_t* y0, int32_t* x0, int32_t vecMode) +{ + int32_t x = *x0; + int32_t y = *y0; + int32_t z = 0; + int32_t t = 0; + const int32_t* tanPtr = kATanDegrees; + do { + int32_t x1 = y >> t; + int32_t y1 = x >> t; + int32_t tan = *tanPtr++; + if (y < vecMode) { + x -= x1; + y += y1; + z -= tan; + } else { + x += x1; + y -= y1; + z += tan; + } + } while (++t < 16); // 30 + Sk64 scaled; + scaled.setMul(z, 0x6488d); // scale back into the SkScalar space (0x100000000/0x28be) + return scaled.fHi; +} + +SkFixed SkCordicASin(SkFixed a) { + int32_t sign = SkExtractSign(a); + int32_t z = SkFixedAbs(a); + if (z >= SK_Fixed1) + return SkApplySign(SK_FixedPI>>1, sign); + int32_t x = kFixedInvGain1; + int32_t y = 0; + z *= 0x28be; + z = SkCircularVector(&y, &x, z); + z = SkApplySign(z, ~sign); + return z; +} + +SkFixed SkCordicACos(SkFixed a) { + int32_t z = SkCordicASin(a); + z = (SK_FixedPI>>1) - z; + return z; +} + +SkFixed SkCordicATan2(SkFixed y, SkFixed x) { + if ((x | y) == 0) + return 0; + int32_t xsign = SkExtractSign(x); + x = SkFixedAbs(x); + int32_t result = SkCircularVector(&y, &x, 0); + if (xsign) { + int32_t rsign = SkExtractSign(result); + if (y == 0) + rsign = 0; + SkFixed pi = SkApplySign(SK_FixedPI, rsign); + result = pi - result; + } + return result; +} + +const int32_t kATanHDegrees[] = { + 0x1661788D, 0xA680D61, 0x51EA6FC, 0x28CBFDD, 0x1460E34, + 0xA2FCE8, 0x517D2E, 0x28BE6E, 0x145F32, + 0xA2F98, 0x517CC, 0x28BE6, 0x145F3, 0xA2F9, 0x517C, + 0x28BE, 0x145F, 0xA2F, 0x517, 0x28B, 0x145, 0xA2, 0x51, 0x28, 0x14, + 0xA, 0x5, 0x2, 0x1 }; + +const int32_t kFixedInvGain2 = 0x31330AAA; // 1.207534495 + +static void SkHyperbolic(int32_t* x0, int32_t* y0, int32_t* z0, int mode) +{ + int32_t t = 1; + int32_t x = *x0; + int32_t y = *y0; + int32_t z = *z0; + const int32_t* tanPtr = kATanHDegrees; + int k = -3; + do { + int32_t x1 = y >> t; + int32_t y1 = x >> t; + int32_t tan = *tanPtr++; + int count = 2 + (k >> 31); + if (++k == 1) + k = -2; + do { + if ((y >> 31) & mode | ~((z >> 31) | mode)) { + x += x1; + y += y1; + z -= tan; + } else { + x -= x1; + y -= y1; + z += tan; + } + } while (--count); + } while (++t < 30); + *x0 = x; + *y0 = y; + *z0 = z; +} + +SkFixed SkCordicLog(SkFixed a) { + a *= 0x28be; + int32_t x = a + 0x28BE60DB; // 1.0 + int32_t y = a - 0x28BE60DB; + int32_t z = 0; + SkHyperbolic(&x, &y, &z, -1); + Sk64 scaled; + scaled.setMul(z, 0x6488d); + z = scaled.fHi; + return z << 1; +} + +SkFixed SkCordicExp(SkFixed a) { + int32_t cosh = kFixedInvGain2; + int32_t sinh = 0; + SkHyperbolic(&cosh, &sinh, &a, 0); + return cosh + sinh; +} + +#ifdef SK_DEBUG + +#ifdef SK_CAN_USE_FLOAT + #include "SkFloatingPoint.h" +#endif + +void SkCordic_UnitTest() +{ +#if defined(SK_SUPPORT_UNITTEST) && defined(SK_CAN_USE_FLOAT) + float val; + for (float angle = -720; angle < 720; angle += 30) { + float radian = angle * 3.1415925358f / 180.0f; + SkFixed f_angle = (int) (radian * 65536.0f); + // sincos + float sine = sinf(radian); + float cosine = cosf(radian); + SkFixed f_cosine; + SkFixed f_sine = SkCordicSinCos(f_angle, &f_cosine); + float sine2 = (float) f_sine / 65536.0f; + float cosine2 = (float) f_cosine / 65536.0f; + float error = fabsf(sine - sine2); + if (error > 0.001) + SkDebugf("sin error : angle = %g ; sin = %g ; cordic = %g\n", angle, sine, sine2); + error = fabsf(cosine - cosine2); + if (error > 0.001) + SkDebugf("cos error : angle = %g ; cos = %g ; cordic = %g\n", angle, cosine, cosine2); + // tan + float _tan = tanf(radian); + SkFixed f_tan = SkCordicTan(f_angle); + float tan2 = (float) f_tan / 65536.0f; + error = fabsf(_tan - tan2); + if (error > 0.05 && fabsf(_tan) < 1e6) + SkDebugf("tan error : angle = %g ; tan = %g ; cordic = %g\n", angle, _tan, tan2); + } + for (val = -1; val <= 1; val += .1f) { + SkFixed f_val = (int) (val * 65536.0f); + // asin + float arcsine = asinf(val); + SkFixed f_arcsine = SkCordicASin(f_val); + float arcsine2 = (float) f_arcsine / 65536.0f; + float error = fabsf(arcsine - arcsine2); + if (error > 0.001) + SkDebugf("asin error : val = %g ; asin = %g ; cordic = %g\n", val, arcsine, arcsine2); + } +#if 1 + for (val = -1; val <= 1; val += .1f) { +#else + val = .5; { +#endif + SkFixed f_val = (int) (val * 65536.0f); + // acos + float arccos = acosf(val); + SkFixed f_arccos = SkCordicACos(f_val); + float arccos2 = (float) f_arccos / 65536.0f; + float error = fabsf(arccos - arccos2); + if (error > 0.001) + SkDebugf("acos error : val = %g ; acos = %g ; cordic = %g\n", val, arccos, arccos2); + } + // atan2 +#if 1 + for (val = -1000; val <= 1000; val += 500.f) { + for (float val2 = -1000; val2 <= 1000; val2 += 500.f) { +#else + val = 0; { + float val2 = -1000; { +#endif + SkFixed f_val = (int) (val * 65536.0f); + SkFixed f_val2 = (int) (val2 * 65536.0f); + float arctan = atan2f(val, val2); + SkFixed f_arctan = SkCordicATan2(f_val, f_val2); + float arctan2 = (float) f_arctan / 65536.0f; + float error = fabsf(arctan - arctan2); + if (error > 0.001) + SkDebugf("atan2 error : val = %g ; val2 = %g ; atan2 = %g ; cordic = %g\n", val, val2, arctan, arctan2); + } + } + // log +#if 1 + for (val = 0.125f; val <= 8.f; val *= 2.0f) { +#else + val = .5; { +#endif + SkFixed f_val = (int) (val * 65536.0f); + // acos + float log = logf(val); + SkFixed f_log = SkCordicLog(f_val); + float log2 = (float) f_log / 65536.0f; + float error = fabsf(log - log2); + if (error > 0.001) + SkDebugf("log error : val = %g ; log = %g ; cordic = %g\n", val, log, log2); + } + // exp +#endif +} + +#endif diff --git a/libs/corecg/SkCordic.h b/libs/corecg/SkCordic.h new file mode 100644 index 000000000..5d8dfe1d6 --- /dev/null +++ b/libs/corecg/SkCordic.h @@ -0,0 +1,20 @@ +#ifndef SkCordic_DEFINED +#define SkCordic_DEFINED + +#include "SkTypes.h" +#include "SkFixed.h" + +SkFixed SkCordicACos(SkFixed a); +SkFixed SkCordicASin(SkFixed a); +SkFixed SkCordicATan2(SkFixed y, SkFixed x); +SkFixed SkCordicExp(SkFixed a); +SkFixed SkCordicLog(SkFixed a); +SkFixed SkCordicSinCos(SkFixed radians, SkFixed* cosp); +SkFixed SkCordicTan(SkFixed a); + +#ifdef SK_DEBUG + void SkCordic_UnitTest(); +#endif + +#endif // SkCordic + diff --git a/libs/corecg/SkDebug.cpp b/libs/corecg/SkDebug.cpp new file mode 100644 index 000000000..65c89105e --- /dev/null +++ b/libs/corecg/SkDebug.cpp @@ -0,0 +1,42 @@ +#include "SkTypes.h" + +#ifdef SK_DEBUG + +int8_t SkToS8(long x) +{ + SkASSERT((int8_t)x == x); + return (int8_t)x; +} + +uint8_t SkToU8(size_t x) +{ + SkASSERT((uint8_t)x == x); + return (uint8_t)x; +} + +int16_t SkToS16(long x) +{ + SkASSERT((int16_t)x == x); + return (int16_t)x; +} + +uint16_t SkToU16(size_t x) +{ + SkASSERT((uint16_t)x == x); + return (uint16_t)x; +} + +int32_t SkToS32(long x) +{ + SkASSERT((int32_t)x == x); + return (int32_t)x; +} + +uint32_t SkToU32(size_t x) +{ + SkASSERT((uint32_t)x == x); + return (uint32_t)x; +} + +#endif + diff --git a/libs/corecg/SkDebug_stdio.cpp b/libs/corecg/SkDebug_stdio.cpp new file mode 100644 index 000000000..6a3585705 --- /dev/null +++ b/libs/corecg/SkDebug_stdio.cpp @@ -0,0 +1,21 @@ +#include "SkTypes.h" + +#if (defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_UNIX)) && defined(SK_DEBUG) + +#include +#include + +void SkDebugf(const char format[], ...) +{ + static const size_t kBufferSize = 256; + + char buffer[kBufferSize + 1]; + va_list args; + va_start(args, format); + vsnprintf(buffer, kBufferSize, format, args); + va_end(args); + fprintf(stderr, buffer); +} + +#endif + diff --git a/libs/corecg/SkFP.h b/libs/corecg/SkFP.h new file mode 100644 index 000000000..8f1f23db6 --- /dev/null +++ b/libs/corecg/SkFP.h @@ -0,0 +1,68 @@ +#ifndef SkFP_DEFINED +#define SkFP_DEFINED + +#include "SkMath.h" + +#ifdef SK_SCALAR_IS_FLOAT + + typedef float SkFP; + + #define SkIntToFloat(n) SkIntToScalar(n) + #define SkFloatRound(x) SkScalarRound(n) + #define SkFloatCeil(x) SkScalarCeil(n) + #define SkFloatFloor(x) SkScalarFloor(n) + + #define SkFloatNeg(x) (-(x)) + #define SkFloatAbs(x) SkScalarAbs(x) + #define SkFloatAdd(a, b) ((a) + (b)) + #define SkFloatSub(a, b) ((a) - (b)) + #define SkFloatMul(a, b) ((a) * (b)) + #define SkFloatMulInt(a, n) ((a) * (n)) + #define SkFloatDiv(a, b) ((a) / (b)) + #define SkFloatDivInt(a, n) ((a) / (n)) + #define SkFloatInvert(x) SkScalarInvert(x) + #define SkFloatSqrt(x) SkScalarSqrt(x) + #define SkFloatCubeRoot(x) pow(x, 1.0f/3) + + #define SkFloatLT(a, b) ((a) < (b)) + #define SkFloatLE(a, b) ((a) <= (b)) + #define SkFloatGT(a, b) ((a) > (b)) + #define SkFloatGE(a, b) ((a) >= (b)) + +#else // scalar is fixed + + #include "SkFloat.h" + + typedef S32 SkFP; + + #define SkIntToFloat(n) SkFloat::SetShift(n, 0) + #define SkFloatRound(x) SkFloat::Round(x); + #define SkFloatCeil(x) SkFloat::Ceil(); + #define SkFloatFloor(x) SkFloat::Floor(); + + #define SkScalarToFloat(n) SkFloat::SetShift(n, -16) + #define SkFloatToScalar(n) SkFloat::GetShift(n, -16) + #define SkFloatNeg(x) SkFloat::Neg(x) + #define SkFloatAbs(x) SkFloat::Abs(x) + #define SkFloatAdd(a, b) SkFloat::Add(a, b) + #define SkFloatSub(a, b) SkFloat::Add(a, SkFloat::Neg(b)) + #define SkFloatMul(a, b) SkFloat::Mul(a, b) + #define SkFloatMulInt(a, n) SkFloat::MulInt(a, n) + #define SkFloatDiv(a, b) SkFloat::Div(a, b) + #define SkFloatDivInt(a, n) SkFloat::DivInt(a, n) + #define SkFloatInvert(x) SkFloat::Invert(x) + #define SkFloatSqrt(x) SkFloat::Sqrt(x) + #define SkFloatCubeRoot(x) SkFloat::CubeRoot(x) + + #define SkFloatLT(a, b) (SkFloat::Cmp(a, b) < 0) + #define SkFloatLE(a, b) (SkFloat::Cmp(a, b) <= 0) + #define SkFloatGT(a, b) (SkFloat::Cmp(a, b) > 0) + #define SkFloatGE(a, b) (SkFloat::Cmp(a, b) >= 0) + +#endif + +#ifdef SK_DEBUG + void SkFP_UnitTest(); +#endif + +#endif diff --git a/libs/corecg/SkFloat.cpp b/libs/corecg/SkFloat.cpp new file mode 100644 index 000000000..044e9824d --- /dev/null +++ b/libs/corecg/SkFloat.cpp @@ -0,0 +1,387 @@ +#include "SkFloat.h" + +#define EXP_BIAS (127+23) + +static int get_unsigned_exp(U32 packed) +{ + return (packed << 1 >> 24); +} + +static unsigned get_unsigned_value(U32 packed) +{ + return (packed << 9 >> 9) | (1 << 23); +} + +static int get_signed_value(S32 packed) +{ + return SkApplySign(get_unsigned_value(packed), SkExtractSign(packed)); +} + +///////////////////////////////////////////////////////////////////////// + +int SkFloat::GetShift(S32 packed, int shift) +{ + if (packed == 0) + return 0; + + int exp = get_unsigned_exp(packed) - EXP_BIAS - shift; + int value = get_unsigned_value(packed); + + if (exp >= 0) + { + if (exp > 8) // overflow + value = SK_MaxS32; + else + value <<= exp; + } + else + { + exp = -exp; + if (exp > 23) // underflow + value = 0; + else + value >>= exp; + } + return SkApplySign(value, SkExtractSign(packed)); +} + +///////////////////////////////////////////////////////////////////////////////////// + +S32 SkFloat::SetShift(int value, int shift) +{ + if (value == 0) + return 0; + + // record the sign and make value positive + int sign = SkExtractSign(value); + value = SkApplySign(value, sign); + + if (value >> 24) // value is too big (has more than 24 bits set) + { + int bias = 8 - SkCLZ(value); + SkASSERT(bias > 0 && bias < 8); + value >>= bias; + shift += bias; + } + else + { + int zeros = SkCLZ(value << 8); + SkASSERT(zeros >= 0 && zeros <= 23); + value <<= zeros; + shift -= zeros; + } + // now value is left-aligned to 24 bits + SkASSERT((value >> 23) == 1); + + shift += EXP_BIAS; + if (shift < 0) // underflow + return 0; + else + { + if (shift > 255) // overflow + { + shift = 255; + value = 0x00FFFFFF; + } + S32 packed = sign << 31; // set the sign-bit + packed |= shift << 23; // store the packed exponent + packed |= ((unsigned)(value << 9) >> 9); // clear 24th bit of value (its implied) + +#ifdef SK_DEBUG + { + int n; + + n = SkExtractSign(packed); + SkASSERT(n == sign); + n = get_unsigned_exp(packed); + SkASSERT(n == shift); + n = get_unsigned_value(packed); + SkASSERT(n == value); + } +#endif + return packed; + } +} + +S32 SkFloat::Neg(S32 packed) +{ + if (packed) + packed = packed ^ (1 << 31); + return packed; +} + +S32 SkFloat::Add(S32 packed_a, S32 packed_b) +{ + if (packed_a == 0) + return packed_b; + if (packed_b == 0) + return packed_a; + + int exp_a = get_unsigned_exp(packed_a); + int exp_b = get_unsigned_exp(packed_b); + int exp_diff = exp_a - exp_b; + + int shift_a = 0, shift_b = 0; + int exp; + + if (exp_diff >= 0) + { + if (exp_diff > 24) // B is too small to contribute + return packed_a; + shift_b = exp_diff; + exp = exp_a; + } + else + { + exp_diff = -exp_diff; + if (exp_diff > 24) // A is too small to contribute + return packed_b; + shift_a = exp_diff; + exp = exp_b; + } + + int value_a = get_signed_value(packed_a) >> shift_a; + int value_b = get_signed_value(packed_b) >> shift_b; + + return SkFloat::SetShift(value_a + value_b, exp - EXP_BIAS); +} + +#include "Sk64.h" + +static inline S32 mul24(S32 a, S32 b) +{ + Sk64 tmp; + + tmp.setMul(a, b); + tmp.roundRight(24); + return tmp.get32(); +} + +S32 SkFloat::Mul(S32 packed_a, S32 packed_b) +{ + if (packed_a == 0 || packed_b == 0) + return 0; + + int exp_a = get_unsigned_exp(packed_a); + int exp_b = get_unsigned_exp(packed_b); + + int value_a = get_signed_value(packed_a); + int value_b = get_signed_value(packed_b); + + return SkFloat::SetShift(mul24(value_a, value_b), exp_a + exp_b - 2*EXP_BIAS + 24); +} + +S32 SkFloat::MulInt(S32 packed, int n) +{ + return Mul(packed, SetShift(n, 0)); +} + +S32 SkFloat::Div(S32 packed_n, S32 packed_d) +{ + SkASSERT(packed_d != 0); + + if (packed_n == 0) + return 0; + + int exp_n = get_unsigned_exp(packed_n); + int exp_d = get_unsigned_exp(packed_d); + + int value_n = get_signed_value(packed_n); + int value_d = get_signed_value(packed_d); + + return SkFloat::SetShift(SkDivBits(value_n, value_d, 24), exp_n - exp_d - 24); +} + +S32 SkFloat::DivInt(S32 packed, int n) +{ + return Div(packed, SetShift(n, 0)); +} + +S32 SkFloat::Invert(S32 packed) +{ + return Div(packed, SetShift(1, 0)); +} + +S32 SkFloat::Sqrt(S32 packed) +{ + if (packed < 0) + { + SkASSERT(!"can't sqrt a negative number"); + return 0; + } + + int exp = get_unsigned_exp(packed); + int value = get_unsigned_value(packed); + + int nexp = exp - EXP_BIAS; + int root = SkSqrtBits(value << (nexp & 1), 26); + nexp >>= 1; + return SkFloat::SetShift(root, nexp - 11); +} + +#if defined _WIN32 && _MSC_VER >= 1300 // disable warning : unreachable code +#pragma warning ( push ) +#pragma warning ( disable : 4702 ) +#endif + +S32 SkFloat::CubeRoot(S32 packed) +{ + sk_throw(); + return 0; +} + +#if defined _WIN32 && _MSC_VER >= 1300 +#pragma warning ( pop ) +#endif + +static inline S32 clear_high_bit(S32 n) +{ + return ((U32)(n << 1)) >> 1; +} + +static inline int int_sign(S32 a, S32 b) +{ + return a > b ? 1 : (a < b ? -1 : 0); +} + +int SkFloat::Cmp(S32 packed_a, S32 packed_b) +{ + packed_a = SkApplySign(clear_high_bit(packed_a), SkExtractSign(packed_a)); + packed_b = SkApplySign(clear_high_bit(packed_b), SkExtractSign(packed_b)); + + return int_sign(packed_a, packed_b); +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +#ifdef SK_DEBUG + +#include "SkRandom.h" +#ifdef SK_CAN_USE_FLOAT + #include "SkFloatingPoint.h" +#endif + +void SkFloat::UnitTest() +{ +#ifdef SK_SUPPORT_UNITTEST + SkFloat a, b, c, d; + int n; + + a.setZero(); + n = a.getInt(); + SkASSERT(n == 0); + + b.setInt(5); + n = b.getInt(); + SkASSERT(n == 5); + + c.setInt(-3); + n = c.getInt(); + SkASSERT(n == -3); + + d.setAdd(c, b); + SkDebugf("SkFloat: %d + %d = %d\n", c.getInt(), b.getInt(), d.getInt()); + + SkRandom rand; + +#ifdef SK_CAN_USE_FLOAT + int i; + for (i = 0; i < 1000; i++) + { + float fa, fb; + int aa = rand.nextS() >> 14; + int bb = rand.nextS() >> 14; + a.setInt(aa); + b.setInt(bb); + SkASSERT(a.getInt() == aa); + SkASSERT(b.getInt() == bb); + + c.setAdd(a, b); + int cc = c.getInt(); + SkASSERT(cc == aa + bb); + + c.setSub(a, b); + cc = c.getInt(); + SkASSERT(cc == aa - bb); + + aa >>= 5; + bb >>= 5; + a.setInt(aa); + b.setInt(bb); + c.setMul(a, b); + cc = c.getInt(); + SkASSERT(cc == aa * bb); + ///////////////////////////////////// + + aa = rand.nextS() >> 11; + a.setFixed(aa); + cc = a.getFixed(); + SkASSERT(aa == cc); + + bb = rand.nextS() >> 11; + b.setFixed(bb); + cc = b.getFixed(); + SkASSERT(bb == cc); + + cc = SkFixedMul(aa, bb); + c.setMul(a, b); + SkFixed dd = c.getFixed(); + int diff = cc - dd; + SkASSERT(SkAbs32(diff) <= 1); + + fa = (float)aa / 65536.0f; + fb = (float)bb / 65536.0f; + a.assertEquals(fa); + b.assertEquals(fb); + fa = a.getFloat(); + fb = b.getFloat(); + + c.assertEquals(fa * fb, 1); + + c.setDiv(a, b); + cc = SkFixedDiv(aa, bb); + dd = c.getFixed(); + diff = cc - dd; + SkASSERT(SkAbs32(diff) <= 3); + + c.assertEquals(fa / fb, 1); + + SkASSERT((aa == bb) == (a == b)); + SkASSERT((aa != bb) == (a != b)); + SkASSERT((aa < bb) == (a < b)); + SkASSERT((aa <= bb) == (a <= b)); + SkASSERT((aa > bb) == (a > b)); + SkASSERT((aa >= bb) == (a >= b)); + + if (aa < 0) + { + aa = -aa; + fa = -fa; + } + a.setFixed(aa); + c.setSqrt(a); + cc = SkFixedSqrt(aa); + dd = c.getFixed(); + SkASSERT(dd == cc); + + c.assertEquals(sk_float_sqrt(fa), 2); + + // cuberoot +#if 0 + a.setInt(1); + a.cubeRoot(); + a.assertEquals(1.0f, 0); + a.setInt(8); + a.cubeRoot(); + a.assertEquals(2.0f, 0); + a.setInt(27); + a.cubeRoot(); + a.assertEquals(3.0f, 0); +#endif + } +#endif +#endif +} + +#endif diff --git a/libs/corecg/SkFloat.h b/libs/corecg/SkFloat.h new file mode 100644 index 000000000..6ff252dc3 --- /dev/null +++ b/libs/corecg/SkFloat.h @@ -0,0 +1,91 @@ +#ifndef SkFloat_DEFINED +#define SkFloat_DEFINED + +#include "SkMath.h" + +class SkFloat { +public: + SkFloat() {} + + void setZero() { fPacked = 0; } +// void setShift(int value, int shift) { fPacked = SetShift(value, shift); } + void setInt(int value) { fPacked = SetShift(value, 0); } + void setFixed(SkFixed value) { fPacked = SetShift(value, -16); } + void setFract(SkFract value) { fPacked = SetShift(value, -30); } + +// int getShift(int shift) const { return GetShift(fPacked, shift); } + int getInt() const { return GetShift(fPacked, 0); } + SkFixed getFixed() const { return GetShift(fPacked, -16); } + SkFract getFract() const { return GetShift(fPacked, -30); } + + void abs() { fPacked = Abs(fPacked); } + void negate() { fPacked = Neg(fPacked); } + + void shiftLeft(int bits) { fPacked = Shift(fPacked, bits); } + void setShiftLeft(const SkFloat& a, int bits) { fPacked = Shift(a.fPacked, bits); } + + void shiftRight(int bits) { fPacked = Shift(fPacked, -bits); } + void setShiftRight(const SkFloat& a, int bits) { fPacked = Shift(a.fPacked, -bits); } + + void add(const SkFloat& a) { fPacked = Add(fPacked, a.fPacked); } + void setAdd(const SkFloat& a, const SkFloat& b) { fPacked = Add(a.fPacked, b.fPacked); } + + void sub(const SkFloat& a) { fPacked = Add(fPacked, Neg(a.fPacked)); } + void setSub(const SkFloat& a, const SkFloat& b) { fPacked = Add(a.fPacked, Neg(b.fPacked)); } + + void mul(const SkFloat& a) { fPacked = Mul(fPacked, a.fPacked); } + void setMul(const SkFloat& a, const SkFloat& b) { fPacked = Mul(a.fPacked, b.fPacked); } + + void div(const SkFloat& a) { fPacked = Div(fPacked, a.fPacked); } + void setDiv(const SkFloat& a, const SkFloat& b) { fPacked = Div(a.fPacked, b.fPacked); } + + void sqrt() { fPacked = Sqrt(fPacked); } + void setSqrt(const SkFloat& a) { fPacked = Sqrt(a.fPacked); } + void cubeRoot() { fPacked = CubeRoot(fPacked); } + void setCubeRoot(const SkFloat& a) { fPacked = CubeRoot(a.fPacked); } + + friend bool operator==(const SkFloat& a, const SkFloat& b) { return a.fPacked == b.fPacked; } + friend bool operator!=(const SkFloat& a, const SkFloat& b) { return a.fPacked != b.fPacked; } + friend bool operator<(const SkFloat& a, const SkFloat& b) { return Cmp(a.fPacked, b.fPacked) < 0; } + friend bool operator<=(const SkFloat& a, const SkFloat& b) { return Cmp(a.fPacked, b.fPacked) <= 0; } + friend bool operator>(const SkFloat& a, const SkFloat& b) { return Cmp(a.fPacked, b.fPacked) > 0; } + friend bool operator>=(const SkFloat& a, const SkFloat& b) { return Cmp(a.fPacked, b.fPacked) >= 0; } + +#ifdef SK_DEBUG + static void UnitTest(); + + void assertEquals(float f, int tolerance = 0) + { + S32 s = *(S32*)&f; + int d = s - fPacked; + SkASSERT(SkAbs32(d) <= tolerance); + } + float getFloat() const + { + return *(float*)&fPacked; + } +#endif + +private: + S32 fPacked; + + SkFloat(S32 packed) : fPacked(fPacked) {} + +public: + static int GetShift(S32 packed, int shift); + static S32 SetShift(int value, int shift); + static S32 Neg(S32); + static S32 Abs(S32 packed) { return (U32)(packed << 1) >> 1; } + static S32 Shift(S32, int bits); + static S32 Add(S32, S32); + static S32 Mul(S32, S32); + static S32 MulInt(S32, int); + static S32 Div(S32, S32); + static S32 DivInt(S32, int); + static S32 Invert(S32); + static S32 Sqrt(S32); + static S32 CubeRoot(S32); + static int Cmp(S32, S32); +}; + +#endif diff --git a/libs/corecg/SkMath.cpp b/libs/corecg/SkMath.cpp new file mode 100644 index 000000000..822131054 --- /dev/null +++ b/libs/corecg/SkMath.cpp @@ -0,0 +1,703 @@ +#include "SkMath.h" +#include "SkCordic.h" +#include "SkFloatingPoint.h" +#include "Sk64.h" + +#ifdef SK_SCALAR_IS_FLOAT + const uint32_t gIEEENotANumber = 0x7FFFFFFF; + const uint32_t gIEEEInfinity = 0x7F800000; +#endif + +int SkCLZ(uint32_t x) +{ +#if defined(__arm__) && !defined(__thumb) && defined(__ARM_ARCH_5T__) + asm( "clz %0,%0" : "=r"(x) : "0"(x) : ); + return x; +#else + if (x == 0) + return 32; + + SkDEBUGCODE(uint32_t n = x;) + + int zeros = ((x >> 16) - 1) >> 31 << 4; + x <<= zeros; + + int nonzero = ((x >> 24) - 1) >> 31 << 3; + zeros += nonzero; + x <<= nonzero; + + nonzero = ((x >> 28) - 1) >> 31 << 2; + zeros += nonzero; + x <<= nonzero; + + nonzero = ((x >> 30) - 1) >> 31 << 1; + zeros += nonzero; + x <<= nonzero; + +// zeros += ((x >> 31) - 1) >> 31; + zeros += (~x) >> 31; + +#ifdef SK_DEBUG + int slow_zeros; + + if (n == 0) + slow_zeros = 32; + else + { + slow_zeros = 0; + while ((int32_t)n > 0) + { + slow_zeros += 1; + n <<= 1; + } + } + SkASSERT(zeros == slow_zeros); +#endif + return zeros; +#endif +} + +int32_t SkMulDiv(int32_t numer1, int32_t numer2, int32_t denom) +{ + SkASSERT(denom); + + Sk64 tmp; + tmp.setMul(numer1, numer2); + tmp.div(denom, Sk64::kTrunc_DivOption); + return tmp.get32(); +} + +int32_t SkMulShift(int32_t a, int32_t b, unsigned shift) +{ + int sign = SkExtractSign(a ^ b); + + if (shift > 63) + return sign; + + a = SkAbs32(a); + b = SkAbs32(b); + + uint32_t ah = a >> 16; + uint32_t al = a & 0xFFFF; + uint32_t bh = b >> 16; + uint32_t bl = b & 0xFFFF; + + uint32_t A = ah * bh; + uint32_t B = ah * bl + al * bh; + uint32_t C = al * bl; + + /* [ A ] + [ B ] + [ C ] + */ + uint32_t lo = C + (B << 16); + int32_t hi = A + (B >> 16) + (lo < C); + + if (sign < 0) + { + hi = -hi - Sk32ToBool(lo); + lo = 0 - lo; + } + + if (shift == 0) + { +#ifdef SK_DEBUGx + SkASSERT(((int32_t)lo >> 31) == hi); +#endif + return lo; + } + else if (shift >= 32) + return hi >> (shift - 32); + else + { +#ifdef SK_DEBUGx + int32_t tmp = hi >> shift; + SkASSERT(tmp == 0 || tmp == -1); +#endif + return (hi << (32 - shift)) | (lo >> shift); + } +} + +#if !defined(SK_BUILD_FOR_BREW) || defined(AEE_SIMULATOR) +SkFixed SkFixedMul(SkFixed a, SkFixed b) +{ +#if 0 + Sk64 tmp; + + tmp.setMul(a, b); + tmp.shiftRight(16); + return tmp.fLo; +#else + int sa = SkExtractSign(a); + int sb = SkExtractSign(b); + // now make them positive + a = SkApplySign(a, sa); + b = SkApplySign(b, sb); + + uint32_t ah = a >> 16; + uint32_t al = a & 0xFFFF; + uint32_t bh = b >> 16; + uint32_t bl = b & 0xFFFF; + + uint32_t R = ah * b + al * bh + (al * bl >> 16); + + return SkApplySign(R, sa ^ sb); +#endif +} + +SkFract SkFractMul(SkFract a, SkFract b) +{ +#if 0 + Sk64 tmp; + tmp.setMul(a, b); + return tmp.getFract(); +#else + int sa = SkExtractSign(a); + int sb = SkExtractSign(b); + // now make them positive + a = SkApplySign(a, sa); + b = SkApplySign(b, sb); + + uint32_t ah = a >> 16; + uint32_t al = a & 0xFFFF; + uint32_t bh = b >> 16; + uint32_t bl = b & 0xFFFF; + + uint32_t A = ah * bh; + uint32_t B = ah * bl + al * bh; + uint32_t C = al * bl; + + /* [ A ] + [ B ] + [ C ] + */ + uint32_t Lo = C + (B << 16); + uint32_t Hi = A + (B >>16) + (Lo < C); + + SkASSERT((Hi >> 29) == 0); // else overflow + + int32_t R = (Hi << 2) + (Lo >> 30); + + return SkApplySign(R, sa ^ sb); +#endif +} +#endif + +int SkFixedMulCommon(SkFixed a, int b, int bias) +{ + // this function only works if b is 16bits + SkASSERT(b == (S16)b); + SkASSERT(b >= 0); + + int sa = SkExtractSign(a); + a = SkApplySign(a, sa); + uint32_t ah = a >> 16; + uint32_t al = a & 0xFFFF; + uint32_t R = ah * b + ((al * b + bias) >> 16); + return SkApplySign(R, sa); +} + +int32_t SkDivBits(int32_t numer, int32_t denom, int shift_bias) +{ + SkASSERT(denom != 0); + if (numer == 0) + return 0; + + SkFixed result; + int32_t sign; + + // make numer and denom positive, and sign hold the resulting sign + sign = SkExtractSign(numer ^ denom); + numer = SkAbs32(numer); + denom = SkAbs32(denom); + +#if 0 // faster assuming we have HW divide + if ((numer >> (32 - shift_bias)) == 0) + { + result = (uint32_t)(numer << shift_bias) / denom; + } + else +#endif + { + int nbits = SkCLZ(numer) - 1; + int dbits = SkCLZ(denom) - 1; + int bits = shift_bias - nbits + dbits; + + if (bits <= 0) // answer will underflow + return 0; + if (bits > 31) // answer will overflow + return SkApplySign(SK_MaxS32, sign); + + denom <<= dbits; + numer <<= nbits; + result = 0; + do { + result <<= 1; + #ifdef SK_CPU_HAS_CONDITIONAL_INSTR + if ((uint32_t)denom <= (uint32_t)numer) + { + numer -= denom; + result |= 1; + } + #else + int32_t diff = (denom - numer - 1) >> 31; + result -= diff; + numer -= denom & diff; + #endif + numer <<= 1; + } while (--bits >= 0); + } + + if (result < 0) + result = SK_MaxS32; + return SkApplySign(result, sign); +} + +/* mod(float numer, float denom) seems to always return the sign + of the numer, so that's what we do too +*/ +SkFixed SkFixedMod(SkFixed numer, SkFixed denom) +{ + int sn = SkExtractSign(numer); + int sd = SkExtractSign(denom); + + numer = SkApplySign(numer, sn); + denom = SkApplySign(denom, sd); + + if (numer < denom) + return SkApplySign(numer, sn); + else if (numer == denom) + return 0; + else + { + SkFixed div = SkFixedDiv(numer, denom); + return SkApplySign(SkFixedMul(denom, div & 0xFFFF), sn); + } +} + +/* www.worldserver.com/turk/computergraphics/FixedSqrt.pdf +*/ +int32_t SkSqrtBits(int32_t x, int count) +{ + SkASSERT(x >= 0 && count > 0 && (unsigned)count <= 30); + + uint32_t root = 0; + uint32_t remHi = 0; + uint32_t remLo = x; + + do { + root <<= 1; + + remHi = (remHi<<2) | (remLo>>30); + remLo <<= 2; + + uint32_t testDiv = (root << 1) + 1; + if (remHi >= testDiv) + { + remHi -= testDiv; + root++; + } + } while (--count >= 0); + + return root; +} + +int32_t SkCubeRootBits(int32_t value, int bits) +{ + SkASSERT(bits > 0); + + int sign = SkExtractSign(value); + value = SkApplySign(value, sign); + + uint32_t root = 0; + uint32_t curr = (uint32_t)value >> 30; + value <<= 2; + + do { + root <<= 1; + uint32_t guess = root * root + root; + guess = (guess << 1) + guess; // guess *= 3 + if (guess < curr) + { curr -= guess + 1; + root |= 1; + } + curr = (curr << 3) | ((uint32_t)value >> 29); + value <<= 3; + } while (--bits); + + return SkApplySign(root, sign); +} + +SkFixed SkFixedMean(SkFixed a, SkFixed b) +{ + Sk64 tmp; + + tmp.setMul(a, b); + return tmp.getSqrt(); +} + +//////////////////////////////////////////////////////////////////////////// + +#ifdef SK_SCALAR_IS_FLOAT +float SkScalarSinCos(float radians, float* cosValue) +{ + float sinValue = sk_float_sin(radians); + + if (cosValue) + *cosValue = sk_float_cos(radians); + + if (SkScalarNearlyZero(*cosValue)) + *cosValue = 0; + + if (SkScalarNearlyZero(sinValue)) + sinValue = 0; + + return sinValue; +} +#endif + +#define INTERP_SINTABLE +#define BUILD_TABLE_AT_RUNTIMEx + +#define kTableSize 256 + +#ifdef BUILD_TABLE_AT_RUNTIME + static uint16_t gSkSinTable[kTableSize]; + + static void build_sintable(uint16_t table[]) + { + for (int i = 0; i < kTableSize; i++) + { + double rad = i * 3.141592653589793 / (2*kTableSize); + double val = sin(rad); + int ival = (int)(val * SK_Fixed1); + table[i] = SkToU16(ival); + } + } +#else + #include "SkSinTable.h" +#endif + +#define SK_Fract1024SizeOver2PI 0x28BE60 /* floatToFract(1024 / 2PI) */ + +#ifdef INTERP_SINTABLE +static SkFixed interp_table(const uint16_t table[], int index, int partial256) +{ + SkASSERT((unsigned)index < kTableSize); + + SkFixed lower = table[index]; + SkFixed upper = (index == kTableSize - 1) ? SK_Fixed1 : table[index + 1]; + + SkASSERT(lower < upper); + SkASSERT(lower >= 0); + SkASSERT(upper <= SK_Fixed1); + SkASSERT((unsigned)partial256 <= 255); + + return lower + ((upper - lower) * partial256 >> 8); +} +#endif + +SkFixed SkFixedSinCos(SkFixed radians, SkFixed* cosValuePtr) +{ + SkASSERT(SK_ARRAY_COUNT(gSkSinTable) == kTableSize); + +#ifdef BUILD_TABLE_AT_RUNTIME + static bool gFirstTime = true; + if (gFirstTime) + { + build_sintable(gSinTable); + gFirstTime = false; + } +#endif + + // make radians positive + SkFixed sinValue, cosValue; + int32_t cosSign = 0; + int32_t sinSign = SkExtractSign(radians); + radians = SkApplySign(radians, sinSign); + // scale it to 0...1023 ... + +#ifdef INTERP_SINTABLE + radians = SkMulDiv(radians, 2 * kTableSize * 256, SK_FixedPI); + int findex = radians & (kTableSize * 256 - 1); + int index = findex >> 8; + int partial = findex & 255; + sinValue = interp_table(gSkSinTable, index, partial); + + findex = kTableSize * 256 - findex - 1; + index = findex >> 8; + partial = findex & 255; + cosValue = interp_table(gSkSinTable, index, partial); + + int quad = ((unsigned)radians / (kTableSize * 256)) & 3; +#else + radians = SkMulDiv(radians, 2 * kTableSize, SK_FixedPI); + int index = radians & (kTableSize - 1); + + if (index == 0) + { + sinValue = 0; + cosValue = SK_Fixed1; + } + else + { + sinValue = gSkSinTable[index]; + cosValue = gSkSinTable[kTableSize - index]; + } + int quad = ((unsigned)radians / kTableSize) & 3; +#endif + + if (quad & 1) + SkTSwap(sinValue, cosValue); + if (quad & 2) + sinSign = ~sinSign; + if (((quad - 1) & 2) == 0) + cosSign = ~cosSign; + + sinValue = SkApplySign(sinValue, sinSign); + cosValue = SkApplySign(cosValue, cosSign); + +#ifdef SK_DEBUG + if (1) + { + SkFixed sin2 = SkFixedMul(sinValue, sinValue); + SkFixed cos2 = SkFixedMul(cosValue, cosValue); + int diff = cos2 + sin2 - SK_Fixed1; + SkASSERT(SkAbs32(diff) <= 8); + } +#endif + + // restore the sign for negative angles + if (cosValuePtr) + *cosValuePtr = cosValue; + return sinValue; +} + +//////////////////////////////////////////////////////////////////////////// + +SkFixed SkFixedTan(SkFixed radians) { return SkCordicTan(radians); } +SkFixed SkFixedASin(SkFixed x) { return SkCordicASin(x); } +SkFixed SkFixedACos(SkFixed x) { return SkCordicACos(x); } +SkFixed SkFixedATan2(SkFixed y, SkFixed x) { return SkCordicATan2(y, x); } +SkFixed SkFixedExp(SkFixed x) { return SkCordicExp(x); } +SkFixed SkFixedLog(SkFixed x) { return SkCordicLog(x); } + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +#ifdef SK_DEBUG + +#include "SkRandom.h" + +#ifdef SK_CAN_USE_LONGLONG +static int symmetric_fixmul(int a, int b) +{ + int sa = SkExtractSign(a); + int sb = SkExtractSign(b); + + a = SkApplySign(a, sa); + b = SkApplySign(b, sb); + +#if 1 + int c = (int)(((SkLONGLONG)a * b) >> 16); + + return SkApplySign(c, sa ^ sb); +#else + SkLONGLONG ab = (SkLONGLONG)a * b; + if (sa ^ sb) + ab = -ab; + return ab >> 16; +#endif +} +#endif + +void SkMath::UnitTest() +{ +#ifdef SK_SUPPORT_UNITTEST + int i; + int32_t x; + SkRandom rand; + + SkToS8(127); SkToS8(-128); SkToU8(255); + SkToS16(32767); SkToS16(-32768); SkToU16(65535); + SkToS32(2*1024*1024); SkToS32(-2*1024*1024); SkToU32(4*1024*1024); + + SkCordic_UnitTest(); + + // these should assert +#if 0 + SkToS8(128); + SkToS8(-129); + SkToU8(256); + SkToU8(-5); + + SkToS16(32768); + SkToS16(-32769); + SkToU16(65536); + SkToU16(-5); + + if (sizeof(size_t) > 4) + { + SkToS32(4*1024*1024); + SkToS32(-4*1024*1024); + SkToU32(5*1024*1024); + SkToU32(-5); + } +#endif + + { + SkScalar x = SK_ScalarNaN; + SkASSERT(SkScalarIsNaN(x)); + } + + for (i = 1; i <= 10; i++) + { + x = SkCubeRootBits(i*i*i, 11); + SkASSERT(x == i); + } + + x = SkFixedSqrt(SK_Fixed1); + SkASSERT(x == SK_Fixed1); + x = SkFixedSqrt(SK_Fixed1/4); + SkASSERT(x == SK_Fixed1/2); + x = SkFixedSqrt(SK_Fixed1*4); + SkASSERT(x == SK_Fixed1*2); + + x = SkFractSqrt(SK_Fract1); + SkASSERT(x == SK_Fract1); + x = SkFractSqrt(SK_Fract1/4); + SkASSERT(x == SK_Fract1/2); + x = SkFractSqrt(SK_Fract1/16); + SkASSERT(x == SK_Fract1/4); + + for (i = 1; i < 100; i++) + { + x = SkFixedSqrt(SK_Fixed1 * i * i); + SkASSERT(x == SK_Fixed1 * i); + } + + for (i = 0; i < 1000; i++) + { + int value = rand.nextS16(); + int max = rand.nextU16(); + + int clamp = SkClampMax(value, max); + int clamp2 = value < 0 ? 0 : (value > max ? max : value); + SkASSERT(clamp == clamp2); + } + +#ifdef SK_CAN_USE_LONGLONG + for (i = 0; i < 100000; i++) + { + SkFixed numer = rand.nextS(); + SkFixed denom = rand.nextS(); + SkFixed result = SkFixedDiv(numer, denom); + SkLONGLONG check = ((SkLONGLONG)numer << 16) / denom; + + (void)SkCLZ(numer); + (void)SkCLZ(denom); + + SkASSERT(result != (SkFixed)SK_NaN32); + if (check > SK_MaxS32) + check = SK_MaxS32; + else if (check < -SK_MaxS32) + check = SK_MinS32; + SkASSERT(result == check); + + result = SkFractDiv(numer, denom); + check = ((SkLONGLONG)numer << 30) / denom; + + SkASSERT(result != (SkFixed)SK_NaN32); + if (check > SK_MaxS32) + check = SK_MaxS32; + else if (check < -SK_MaxS32) + check = SK_MinS32; + SkASSERT(result == (int32_t)check); + + // make them <= 2^24, so we don't overflow in fixmul + numer = numer << 8 >> 8; + denom = denom << 8 >> 8; + + result = SkFixedMul(numer, denom); + SkFixed r2 = symmetric_fixmul(numer, denom); + SkASSERT(result == r2); + + result = SkFixedMul(numer, numer); + r2 = SkFixedSquare(numer); + SkASSERT(result == r2); + +#ifdef SK_CAN_USE_FLOAT + if (numer >= 0 && denom >= 0) + { + SkFixed mean = SkFixedMean(numer, denom); + float fm = sk_float_sqrt(sk_float_abs(SkFixedToFloat(numer) * SkFixedToFloat(denom))); + SkFixed mean2 = SkFloatToFixed(fm); + int diff = SkAbs32(mean - mean2); + SkASSERT(diff <= 1); + } + + { + SkFixed mod = SkFixedMod(numer, denom); + float n = SkFixedToFloat(numer); + float d = SkFixedToFloat(denom); + float m = sk_float_mod(n, d); +#if 0 + SkDebugf("%g mod %g = %g [%g]\n", + SkFixedToFloat(numer), SkFixedToFloat(denom), + SkFixedToFloat(mod), m); +#endif + SkASSERT(mod == 0 || (mod < 0) == (m < 0)); // ensure the same sign + int diff = SkAbs32(mod - SkFloatToFixed(m)); + SkASSERT((diff >> 7) == 0); + } +#endif + } +#endif + +#ifdef SK_CAN_USE_FLOAT + for (i = 0; i < 100000; i++) + { + SkFract x = rand.nextU() >> 1; + double xx = (double)x / SK_Fract1; + SkFract xr = SkFractSqrt(x); + SkFract check = SkFloatToFract(sqrt(xx)); + SkASSERT(xr == check || xr == check-1 || xr == check+1); + + xr = SkFixedSqrt(x); + xx = (double)x / SK_Fixed1; + check = SkFloatToFixed(sqrt(xx)); + SkASSERT(xr == check || xr == check-1); + + xr = SkSqrt32(x); + xx = (double)x; + check = (int32_t)sqrt(xx); + SkASSERT(xr == check || xr == check-1); + } +#endif + +#if !defined(SK_SCALAR_IS_FLOAT) && defined(SK_CAN_USE_FLOAT) + int maxDiff = 0; + for (i = 0; i < 10000; i++) + { + SkFixed rads = rand.nextS() >> 10; + double frads = SkFixedToFloat(rads); + + SkFixed s, c; + s = SkScalarSinCos(rads, &c); + + double fs = sin(frads); + double fc = cos(frads); + + SkFixed is = SkFloatToFixed(fs); + SkFixed ic = SkFloatToFixed(fc); + + maxDiff = SkMax32(maxDiff, SkAbs32(is - s)); + maxDiff = SkMax32(maxDiff, SkAbs32(ic - c)); + } + SkDebugf("SinCos: maximum error = %d\n", maxDiff); +#endif +#endif +} + +#endif + diff --git a/libs/corecg/SkMatrix.cpp b/libs/corecg/SkMatrix.cpp new file mode 100644 index 000000000..f510e9fbd --- /dev/null +++ b/libs/corecg/SkMatrix.cpp @@ -0,0 +1,1220 @@ +#include "SkMatrix.h" +#include "Sk64.h" + +#ifdef SK_SCALAR_IS_FLOAT + #define kMatrix22Elem SK_Scalar1 +#else + #define kMatrix22Elem SK_Fract1 +#endif + +/* [scale-x skew-x trans-x] [X] [X'] + [skew-y scale-y trans-y] * [Y] = [Y'] + [persp-0 persp-1 persp-2] [1] [1 ] +*/ + +enum { + kMScaleX, + kMSkewX, + kMTransX, + kMSkewY, + kMScaleY, + kMTransY, + kMPersp0, + kMPersp1, + kMPersp2 +}; + +void SkMatrix::reset() +{ + fMat[kMScaleX] = fMat[kMScaleY] = SK_Scalar1; + fMat[kMSkewX] = fMat[kMSkewY] = + fMat[kMTransX] = fMat[kMTransY] = + fMat[kMPersp0] = fMat[kMPersp1] = 0; + fMat[kMPersp2] = kMatrix22Elem; +} + +static inline int has_perspective(const SkScalar mat[9]) +{ +#ifdef SK_SCALAR_IS_FLOAT + return mat[kMPersp0] || mat[kMPersp1] || mat[kMPersp2] != kMatrix22Elem; +#else + return mat[kMPersp0] | mat[kMPersp1] | (mat[kMPersp2] - kMatrix22Elem); +#endif +} + +SkMatrix::TypeMask SkMatrix::getType() const +{ + unsigned type = 0; + + type |= (fMat[kMPersp0] || fMat[kMPersp1] || fMat[kMPersp2] != kMatrix22Elem) << kPerspective_Shift; + type |= (fMat[kMSkewX] || fMat[kMSkewY]) << kAffine_Shift; + type |= (fMat[kMScaleX] != SK_Scalar1 || fMat[kMScaleY] != SK_Scalar1) << kScale_Shift; + type |= (fMat[kMTransX] || fMat[kMTransY]) << kTranslate_Shift; + + return (TypeMask)type; +} + +static inline bool is_identity(const SkScalar fMat[9]) +{ +#ifdef SK_SCALAR_IS_FLOAT + return fMat[kMPersp0] == 0 && fMat[kMPersp1] == 0 && fMat[kMPersp2] == kMatrix22Elem && + fMat[kMSkewX] == 0 && fMat[kMSkewY] == 0 && fMat[kMTransX] == 0 && fMat[kMTransY] == 0 && + fMat[kMScaleX] == SK_Scalar1 && fMat[kMScaleY] == SK_Scalar1; +#else + return !(fMat[kMPersp0] | fMat[kMPersp1] | (fMat[kMPersp2] - kMatrix22Elem) | + fMat[kMSkewX] | fMat[kMSkewY] | fMat[kMTransX] | fMat[kMTransY] | + (fMat[kMScaleX] - SK_Scalar1) | (fMat[kMScaleY] - SK_Scalar1)); +#endif +} + +bool SkMatrix::isIdentity() const +{ + return is_identity(fMat); +} + +//////////////////////////////////////////////////////////////////////////////////// + +void SkMatrix::setTranslate(SkScalar dx, SkScalar dy) +{ + fMat[kMTransX] = dx; + fMat[kMTransY] = dy; + + fMat[kMScaleX] = fMat[kMScaleY] = SK_Scalar1; + fMat[kMSkewX] = fMat[kMSkewY] = + fMat[kMPersp0] = fMat[kMPersp1] = 0; + fMat[kMPersp2] = kMatrix22Elem; +} + +bool SkMatrix::preTranslate(SkScalar dx, SkScalar dy) +{ + if (has_perspective(fMat)) + { + SkMatrix m; + m.setTranslate(dx, dy); + return this->preConcat(m); + } + else + { + fMat[kMTransX] += SkScalarMul(fMat[kMScaleX], dx) + SkScalarMul(fMat[kMSkewX], dy); + fMat[kMTransY] += SkScalarMul(fMat[kMSkewY], dx) + SkScalarMul(fMat[kMScaleY], dy); + return true; + } +} + +bool SkMatrix::postTranslate(SkScalar dx, SkScalar dy) +{ + if (has_perspective(fMat)) + { + SkMatrix m; + m.setTranslate(dx, dy); + return this->postConcat(m); + } + else + { + fMat[kMTransX] += dx; + fMat[kMTransY] += dy; + return true; + } +} + +//////////////////////////////////////////////////////////////////////////////////// + +void SkMatrix::setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) +{ + fMat[kMScaleX] = sx; + fMat[kMScaleY] = sy; + fMat[kMTransX] = px - SkScalarMul(sx, px); + fMat[kMTransY] = py - SkScalarMul(sy, py); + + fMat[kMSkewX] = fMat[kMSkewY] = + fMat[kMPersp0] = fMat[kMPersp1] = 0; + fMat[kMPersp2] = kMatrix22Elem; +} + +bool SkMatrix::preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) +{ + SkMatrix m; + m.setScale(sx, sy, px, py); + return this->preConcat(m); +} + +bool SkMatrix::postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) +{ + SkMatrix m; + m.setScale(sx, sy, px, py); + return this->postConcat(m); +} + +//////////////////////////////////////////////////////////////////////////////////// + +void SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV, SkScalar px, SkScalar py) +{ + fMat[kMScaleX] = cosV; + fMat[kMSkewX] = -sinV; + fMat[kMTransX] = SkScalarMul(sinV, py) + SkScalarMul(SK_Scalar1 - cosV, px); + + fMat[kMSkewY] = sinV; + fMat[kMScaleY] = cosV; + fMat[kMTransY] = SkScalarMul(-sinV, px) + SkScalarMul(SK_Scalar1 - cosV, py); + + fMat[kMPersp0] = fMat[kMPersp1] = 0; + fMat[kMPersp2] = kMatrix22Elem; +} + +void SkMatrix::setRotate(SkScalar degrees, SkScalar px, SkScalar py) +{ + SkScalar sinV, cosV; + sinV = SkScalarSinCos(SkDegreesToRadians(degrees), &cosV); + this->setSinCos(sinV, cosV, px, py); +} + +bool SkMatrix::preRotate(SkScalar degrees, SkScalar px, SkScalar py) +{ + SkMatrix m; + m.setRotate(degrees, px, py); + return this->preConcat(m); +} + +bool SkMatrix::postRotate(SkScalar degrees, SkScalar px, SkScalar py) +{ + SkMatrix m; + m.setRotate(degrees, px, py); + return this->postConcat(m); +} + +//////////////////////////////////////////////////////////////////////////////////// + +void SkMatrix::setSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) +{ + fMat[kMScaleX] = SK_Scalar1; + fMat[kMSkewX] = sx; + fMat[kMTransX] = SkScalarMul(-sx, py); + + fMat[kMSkewY] = sy; + fMat[kMScaleY] = SK_Scalar1; + fMat[kMTransY] = SkScalarMul(-sy, px); + + fMat[kMPersp0] = fMat[kMPersp1] = 0; + fMat[kMPersp2] = kMatrix22Elem; +} + +bool SkMatrix::preSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) +{ + SkMatrix m; + m.setSkew(sx, sy, px, py); + return this->preConcat(m); +} + +bool SkMatrix::postSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) +{ + SkMatrix m; + m.setSkew(sx, sy, px, py); + return this->postConcat(m); +} + +//////////////////////////////////////////////////////////////////////////////////// + +bool SkMatrix::setRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit align) +{ + if (src.isEmpty()) + { + this->reset(); + return false; + } + + if (dst.isEmpty()) + memset(fMat, 0, 8 * sizeof(SkScalar)); + else + { + SkScalar tx, sx = SkScalarDiv(dst.width(), src.width()); + SkScalar ty, sy = SkScalarDiv(dst.height(), src.height()); + bool xLarger = false; + + if (align != kFill_ScaleToFit) + { + if (sx > sy) + { + xLarger = true; + sx = sy; + } + else + sy = sx; + } + + tx = dst.fLeft - SkScalarMul(src.fLeft, sx); + ty = dst.fTop - SkScalarMul(src.fTop, sy); + if (align == kCenter_ScaleToFit || align == kEnd_ScaleToFit) + { + SkScalar diff; + + if (xLarger) + diff = dst.width() - SkScalarMul(src.width(), sy); + else + diff = dst.height() - SkScalarMul(src.height(), sy); + + if (align == kCenter_ScaleToFit) + diff = SkScalarHalf(diff); + + if (xLarger) + tx += diff; + else + ty += diff; + } + + fMat[kMScaleX] = sx; + fMat[kMScaleY] = sy; + fMat[kMTransX] = tx; + fMat[kMTransY] = ty; + fMat[kMSkewX] = fMat[kMSkewY] = + fMat[kMPersp0] = fMat[kMPersp1] = 0; + } + // shared cleanup + fMat[kMPersp2] = kMatrix22Elem; + return true; +} + +//////////////////////////////////////////////////////////////////////////////////// + +#ifdef SK_SCALAR_IS_FLOAT + static inline int fixmuladdmul(float a, float b, float c, float d, float* result) + { + *result = a * b + c * d; + return true; + } + static inline int fixmuladdmulshiftmul(float a, float b, float c, float d, + int /*shift not used*/, float scale, float* result) + { + *result = (a * b + c * d) * scale; + return true; + } + static inline float rowcol3(const float row[], const float col[]) + { + return row[0] * col[0] + row[1] * col[3] + row[2] * col[6]; + } + static inline int negifaddoverflows(float& result, float a, float b) + { + result = a + b; + return 0; + } +#else + static inline bool fixmuladdmul(SkFixed a, SkFixed b, SkFixed c, SkFixed d, SkFixed* result) + { + Sk64 tmp1, tmp2; + tmp1.setMul(a, b); + tmp2.setMul(c, d); + tmp1.add(tmp2); + if (tmp1.isFixed()) + { + *result = tmp1.getFixed(); + return true; + } + return false; + } + static inline bool fixmuladdmulshiftmul(SkFixed a, SkFixed b, SkFixed c, SkFixed d, + int shift, SkFixed scale, SkFixed* result) + { + Sk64 tmp1, tmp2; + tmp1.setMul(a, b); + tmp2.setMul(c, d); + tmp1.add(tmp2); + + S32 hi = SkAbs32(tmp1.fHi); + int afterShift = 16; + if (hi >> 15) + { + int clz = 17 - SkCLZ(hi); + SkASSERT(clz > 0 && clz <= 16); + afterShift -= clz; + shift += clz; + } + + tmp1.roundRight(shift + 16); + SkASSERT(tmp1.is32()); + + tmp1.setMul(tmp1.get32(), scale); + tmp1.roundRight(afterShift); + if (tmp1.is32()) + { + *result = tmp1.get32(); + return true; + } + return false; + } + static inline SkFixed fracmuladdmul(SkFixed a, SkFract b, SkFixed c, SkFract d) + { + Sk64 tmp1, tmp2; + tmp1.setMul(a, b); + tmp2.setMul(c, d); + tmp1.add(tmp2); + return tmp1.getFract(); + } + + static inline SkFixed rowcol3(const SkFixed row[], const SkFixed col[]) + { + Sk64 tmp1, tmp2; + + tmp1.setMul(row[0], col[0]); // N * fixed + tmp2.setMul(row[1], col[3]); // N * fixed + tmp1.add(tmp2); + + tmp2.setMul(row[2], col[6]); // N * fract + tmp2.roundRight(14); // make it fixed + tmp1.add(tmp2); + + return tmp1.getFixed(); + } + static inline int negifaddoverflows(SkFixed& result, SkFixed a, SkFixed b) + { + SkFixed c = a + b; + result = c; + SkASSERT(((c ^ a) & (c ^ b)) >= 0); + return (c ^ a) & (c ^ b); + } +#endif + +static void normalize_perspective(SkScalar mat[9]) +{ + if (SkScalarAbs(mat[kMPersp2]) > kMatrix22Elem) + { + for (int i = 0; i < 9; i++) + mat[i] = SkScalarHalf(mat[i]); + } +} + +bool SkMatrix::setConcat(const SkMatrix& a, const SkMatrix& b) +{ + TypeMask aType = a.getType(); + TypeMask bType = b.getType(); + + if (aType == kIdentity_Mask) + *this = b; + else if (bType == kIdentity_Mask) + *this = a; + else + { + SkMatrix tmp; + SkMatrix* c = this; + + if (this == &a || this == &b) + c = &tmp; + + if ((aType | bType) & kPerspective_Mask) + { + c->fMat[kMScaleX] = rowcol3(&a.fMat[0], &b.fMat[0]); + c->fMat[kMSkewX] = rowcol3(&a.fMat[0], &b.fMat[1]); + c->fMat[kMTransX] = rowcol3(&a.fMat[0], &b.fMat[2]); + + c->fMat[kMSkewY] = rowcol3(&a.fMat[3], &b.fMat[0]); + c->fMat[kMScaleY] = rowcol3(&a.fMat[3], &b.fMat[1]); + c->fMat[kMTransY] = rowcol3(&a.fMat[3], &b.fMat[2]); + + c->fMat[kMPersp0] = rowcol3(&a.fMat[6], &b.fMat[0]); + c->fMat[kMPersp1] = rowcol3(&a.fMat[6], &b.fMat[1]); + c->fMat[kMPersp2] = rowcol3(&a.fMat[6], &b.fMat[2]); + + normalize_perspective(c->fMat); + } + else // not perspective + { + if (!fixmuladdmul(a.fMat[kMScaleX], b.fMat[kMScaleX], a.fMat[kMSkewX], b.fMat[kMSkewY], &c->fMat[kMScaleX])) + return false; + if (!fixmuladdmul(a.fMat[kMScaleX], b.fMat[kMSkewX], a.fMat[kMSkewX], b.fMat[kMScaleY], &c->fMat[kMSkewX])) + return false; + if (!fixmuladdmul(a.fMat[kMScaleX], b.fMat[kMTransX], a.fMat[kMSkewX], b.fMat[kMTransY], &c->fMat[kMTransX])) + return false; + if (negifaddoverflows(c->fMat[kMTransX], c->fMat[kMTransX], a.fMat[kMTransX]) < 0) + return false; + + if (!fixmuladdmul(a.fMat[kMSkewY], b.fMat[kMScaleX], a.fMat[kMScaleY], b.fMat[kMSkewY], &c->fMat[kMSkewY])) + return false; + if (!fixmuladdmul(a.fMat[kMSkewY], b.fMat[kMSkewX], a.fMat[kMScaleY], b.fMat[kMScaleY], &c->fMat[kMScaleY])) + return false; + if (!fixmuladdmul(a.fMat[kMSkewY], b.fMat[kMTransX], a.fMat[kMScaleY], b.fMat[kMTransY], &c->fMat[kMTransY])) + return false; + if (negifaddoverflows(c->fMat[kMTransY], c->fMat[kMTransY], a.fMat[kMTransY]) < 0) + return false; + + c->fMat[kMPersp0] = c->fMat[kMPersp1] = 0; + c->fMat[kMPersp2] = kMatrix22Elem; + } + + if (c == &tmp) + *this = tmp; + } + return true; +} + +bool SkMatrix::preConcat(const SkMatrix& mat) +{ + return this->setConcat(*this, mat); +} + +bool SkMatrix::postConcat(const SkMatrix& mat) +{ + return this->setConcat(mat, *this); +} + + +//////////////////////////////////////////////////////////////////////////////////// + +#ifdef SK_SCALAR_IS_FLOAT + #define SkPerspMul(a, b) SkScalarMul(a, b) + #define SkScalarMulShift(a, b, s) SkScalarMul(a, b) + static float sk_inv_determinant(const float mat[9], int isPerspective, int* /* (only used in Fixed case) */) + { + double det; + + if (isPerspective) + det = mat[kMScaleX] * ((double)mat[kMScaleY] * mat[kMPersp2] - (double)mat[kMTransY] * mat[kMPersp1]) + + mat[kMSkewX] * ((double)mat[kMTransY] * mat[kMPersp0] - (double)mat[kMSkewY] * mat[kMPersp2]) + + mat[kMTransX] * ((double)mat[kMSkewY] * mat[kMPersp1] - (double)mat[kMScaleY] * mat[kMPersp0]); + else + det = (double)mat[kMScaleX] * mat[kMScaleY] - (double)mat[kMSkewX] * mat[kMSkewY]; + + if (SkScalarNearlyZero((float)det)) + return 0; + return (float)(1.0 / det); + } +#else + #define SkPerspMul(a, b) SkFractMul(a, b) + #define SkScalarMulShift(a, b, s) SkMulShift(a, b, s) + static void set_muladdmul(Sk64* dst, S32 a, S32 b, S32 c, S32 d) + { + Sk64 tmp; + + dst->setMul(a, b); + tmp.setMul(c, d); + dst->add(tmp); + } + static SkFixed sk_inv_determinant(const SkFixed mat[9], int isPerspective, int* shift) + { + Sk64 tmp1, tmp2; + + if (isPerspective) + { + tmp1.setMul(mat[kMScaleX], fracmuladdmul(mat[kMScaleY], mat[kMPersp2], -mat[kMTransY], mat[kMPersp1])); + tmp2.setMul(mat[kMSkewX], fracmuladdmul(mat[kMTransY], mat[kMPersp0], -mat[kMSkewY], mat[kMPersp2])); + tmp1.add(tmp2); + tmp2.setMul(mat[kMTransX], fracmuladdmul(mat[kMSkewY], mat[kMPersp1], -mat[kMScaleY], mat[kMPersp0])); + tmp1.add(tmp2); + } + else + { + tmp1.setMul(mat[kMScaleX], mat[kMScaleY]); + tmp2.setMul(mat[kMSkewX], mat[kMSkewY]); + tmp1.sub(tmp2); + } + + int s = tmp1.getClzAbs(); + *shift = s; + + SkFixed denom; + if (s <= 32) + denom = tmp1.getShiftRight(33 - s); + else + denom = (S32)tmp1.fLo << (s - 33); + + if (denom == 0) + return 0; + /** This could perhaps be a special fractdiv function, since both of its + arguments are known to have bit 31 clear and bit 30 set (when they + are made positive), thus eliminating the need for calling clz() + */ + return SkFractDiv(SK_Fract1, denom); + } +#endif + +bool SkMatrix::invert(SkMatrix* inv) const +{ + int isPersp = has_perspective(fMat); + int shift; + SkScalar scale = sk_inv_determinant(fMat, isPersp, &shift); + + if (scale == 0) // underflow + return false; + + if (inv) + { + SkMatrix tmp; + if (inv == this) + inv = &tmp; + + if (isPersp) + { + shift = 61 - shift; + inv->fMat[kMScaleX] = SkScalarMulShift(SkPerspMul(fMat[kMScaleY], fMat[kMPersp2]) - SkPerspMul(fMat[kMTransY], fMat[kMPersp1]), scale, shift); + inv->fMat[kMSkewX] = SkScalarMulShift(SkPerspMul(fMat[kMTransX], fMat[kMPersp1]) - SkPerspMul(fMat[kMSkewX], fMat[kMPersp2]), scale, shift); + inv->fMat[kMTransX] = SkScalarMulShift(SkScalarMul(fMat[kMSkewX], fMat[kMTransY]) - SkScalarMul(fMat[kMTransX], fMat[kMScaleY]), scale, shift); + + inv->fMat[kMSkewY] = SkScalarMulShift(SkPerspMul(fMat[kMTransY], fMat[kMPersp0]) - SkPerspMul(fMat[kMSkewY], fMat[kMPersp2]), scale, shift); + inv->fMat[kMScaleY] = SkScalarMulShift(SkPerspMul(fMat[kMScaleX], fMat[kMPersp2]) - SkPerspMul(fMat[kMTransX], fMat[kMPersp0]), scale, shift); + inv->fMat[kMTransY] = SkScalarMulShift(SkScalarMul(fMat[kMTransX], fMat[kMSkewY]) - SkScalarMul(fMat[kMScaleX], fMat[kMTransY]), scale, shift); + + inv->fMat[kMPersp0] = SkScalarMulShift(SkScalarMul(fMat[kMSkewY], fMat[kMPersp1]) - SkScalarMul(fMat[kMScaleY], fMat[kMPersp0]), scale, shift); + inv->fMat[kMPersp1] = SkScalarMulShift(SkScalarMul(fMat[kMSkewX], fMat[kMPersp0]) - SkScalarMul(fMat[kMScaleX], fMat[kMPersp1]), scale, shift); + inv->fMat[kMPersp2] = SkScalarMulShift(SkScalarMul(fMat[kMScaleX], fMat[kMScaleY]) - SkScalarMul(fMat[kMSkewX], fMat[kMSkewY]), scale, shift); +#ifdef SK_SCALAR_IS_FIXED + if (SkAbs32(inv->fMat[kMPersp2]) > SK_Fixed1) + { + Sk64 tmp; + + tmp.set(SK_Fract1); + tmp.shiftLeft(16); + tmp.div(inv->fMat[kMPersp2], Sk64::kRound_DivOption); + + SkFract scale = tmp.get32(); + + for (int i = 0; i < 9; i++) + inv->fMat[i] = SkFractMul(inv->fMat[i], scale); + } + inv->fMat[kMPersp2] = SkFixedToFract(inv->fMat[kMPersp2]); +#endif + } + else // not perspective + { +#ifdef SK_SCALAR_IS_FIXED + Sk64 tx, ty; + int clzNumer; + + // check the 2x2 for overflow + { + S32 value = SkAbs32(fMat[kMScaleY]); + value |= SkAbs32(fMat[kMSkewX]); + value |= SkAbs32(fMat[kMScaleX]); + value |= SkAbs32(fMat[kMSkewY]); + clzNumer = SkCLZ(value); + if (shift - clzNumer > 31) + return false; // overflow + } + + set_muladdmul(&tx, fMat[kMSkewX], fMat[kMTransY], -fMat[kMScaleY], fMat[kMTransX]); + set_muladdmul(&ty, fMat[kMSkewY], fMat[kMTransX], -fMat[kMScaleX], fMat[kMTransY]); + // check tx,ty for overflow + clzNumer = SkCLZ(SkAbs32(tx.fHi) | SkAbs32(ty.fHi)); + if (shift - clzNumer > 14) + return false; // overflow + + int fixedShift = 61 - shift; + int sk64shift = 44 - shift + clzNumer; + + inv->fMat[kMScaleX] = SkMulShift(fMat[kMScaleY], scale, fixedShift); + inv->fMat[kMSkewX] = SkMulShift(-fMat[kMSkewX], scale, fixedShift); + inv->fMat[kMTransX] = SkMulShift(tx.getShiftRight(33 - clzNumer), scale, sk64shift); + + inv->fMat[kMSkewY] = SkMulShift(-fMat[kMSkewY], scale, fixedShift); + inv->fMat[kMScaleY] = SkMulShift(fMat[kMScaleX], scale, fixedShift); + inv->fMat[kMTransY] = SkMulShift(ty.getShiftRight(33 - clzNumer), scale, sk64shift); +#else + inv->fMat[kMScaleX] = SkScalarMul(fMat[kMScaleY], scale); + inv->fMat[kMSkewX] = SkScalarMul(-fMat[kMSkewX], scale); + if (!fixmuladdmulshiftmul(fMat[kMSkewX], fMat[kMTransY], -fMat[kMScaleY], fMat[kMTransX], shift, scale, &inv->fMat[kMTransX])) + return false; + + inv->fMat[kMSkewY] = SkScalarMul(-fMat[kMSkewY], scale); + inv->fMat[kMScaleY] = SkScalarMul(fMat[kMScaleX], scale); + if (!fixmuladdmulshiftmul(fMat[kMSkewY], fMat[kMTransX], -fMat[kMScaleX], fMat[kMTransY], shift, scale, &inv->fMat[kMTransY])) + return false; +#endif + inv->fMat[kMPersp0] = 0; + inv->fMat[kMPersp1] = 0; + inv->fMat[kMPersp2] = kMatrix22Elem; + } + + if (inv == &tmp) + *(SkMatrix*)this = tmp; + } + return true; +} + +//////////////////////////////////////////////////////////////////////////////////// + +bool SkMatrix::mapPoints(SkPoint dst[], const SkPoint src[], int count, TypeMask typeMask) const +{ + SkASSERT(dst && src && count > 0 || count == 0); + SkASSERT(src == dst || SkAbs32((S32)(src - dst)) >= count); // no partial overlap + + if (count <= 0) + return true; + + bool ok = true; + + if (typeMask & kPerspective_Mask) + { +#ifdef SK_SCALAR_IS_FIXED + SkFixed persp2 = SkFractToFixed(fMat[kMPersp2]); +#endif + for (int i = count - 1; i >= 0; --i) + { + SkScalar sx = src[i].fX; + SkScalar sy = src[i].fY; + SkScalar x = SkScalarMul(sx, fMat[kMScaleX]) + SkScalarMul(sy, fMat[kMSkewX]) + fMat[kMTransX]; + SkScalar y = SkScalarMul(sx, fMat[kMSkewY]) + SkScalarMul(sy, fMat[kMScaleY]) + fMat[kMTransY]; +#ifdef SK_SCALAR_IS_FIXED + SkFixed z = SkFractMul(sx, fMat[kMPersp0]) + SkFractMul(sy, fMat[kMPersp1]) + persp2; +#else + float z = SkScalarMul(sx, fMat[kMPersp0]) + SkScalarMul(sy, fMat[kMPersp1]) + fMat[kMPersp2]; +#endif + if (z) + z = SkScalarInvert(z); + dst[i].fX = SkScalarMul(x, z); + dst[i].fY = SkScalarMul(y, z); + } + } + else if (typeMask & kAffine_Mask) + { + for (int i = count - 1; i >= 0; --i) + { + SkScalar sx = src[i].fX; + SkScalar sy = src[i].fY; + dst[i].fX = SkScalarMul(sx, fMat[kMScaleX]) + SkScalarMul(sy, fMat[kMSkewX]) + fMat[kMTransX]; + dst[i].fY = SkScalarMul(sx, fMat[kMSkewY]) + SkScalarMul(sy, fMat[kMScaleY]) + fMat[kMTransY]; + } + } + else if (typeMask & kScale_Mask) + { + for (int i = count - 1; i >= 0; --i) + { + dst[i].fX = SkScalarMul(src[i].fX, fMat[kMScaleX]) + fMat[kMTransX]; + dst[i].fY = SkScalarMul(src[i].fY, fMat[kMScaleY]) + fMat[kMTransY]; + } + } + else if (typeMask & kTranslate_Mask) + { + for (int i = count - 1; i >= 0; --i) + { + dst[i].fX = src[i].fX + fMat[kMTransX]; + dst[i].fY = src[i].fY + fMat[kMTransY]; + } + } + else + { + SkASSERT(typeMask == 0); + if (dst != src) + memcpy(dst, src, count * sizeof(SkPoint)); + } + return ok; +} + +bool SkMatrix::mapVectors(SkPoint dst[], const SkPoint src[], int count, TypeMask maskType) const +{ + bool ok; + + if (maskType & kPerspective_Mask) + { + SkPoint origin; + + origin.set(0, 0); + ok = this->mapPoints(&origin, &origin, 1, maskType); + + for (int i = count - 1; i >= 0; --i) + { + SkPoint tmp; + + ok &= this->mapPoints(&tmp, &src[i], 1, maskType); + dst[i].set(tmp.fX - origin.fX, tmp.fY - origin.fY); + } + } + else + { + SkMatrix tmp = *this; + + tmp.fMat[kMTransX] = tmp.fMat[kMTransY] = 0; + ok = tmp.mapPoints(dst, src, count, maskType); + } + return ok; +} + +bool SkMatrix::mapRect(SkRect* dst, const SkRect& src, TypeMask maskType) const +{ + SkASSERT(dst && &src); + + bool ok; + + if (RectStaysRect(maskType)) + { + ok = this->mapPoints((SkPoint*)dst, (const SkPoint*)&src, 2, maskType); + dst->sort(); + } + else + { + SkPoint quad[4]; + + src.toQuad(quad); + ok = this->mapPoints(quad, quad, 4, maskType); + dst->set(quad, 4); + } + return ok; +} + +SkScalar SkMatrix::mapRadius(SkScalar radius) const +{ + SkVector vec[2]; + + vec[0].set(radius, 0); + vec[1].set(0, radius); + this->mapVectors(vec, 2); + + SkScalar d0 = vec[0].length(); + SkScalar d1 = vec[1].length(); + + return SkScalarMean(d0, d1); +} + +////////////////////////////////////////////////////////////////////////////////////////// + +void SkMatrix::Perspective_ptProc(const SkMatrix& m, SkScalar sx, SkScalar sy, SkPoint* pt) +{ + SkASSERT(m.getType() & kPerspective_Mask); + + SkScalar x = SkScalarMul(sx, m.fMat[kMScaleX]) + SkScalarMul(sy, m.fMat[kMSkewX]) + m.fMat[kMTransX]; + SkScalar y = SkScalarMul(sx, m.fMat[kMSkewY]) + SkScalarMul(sy, m.fMat[kMScaleY]) + m.fMat[kMTransY]; +#ifdef SK_SCALAR_IS_FIXED + SkFixed z = SkFractMul(sx, m.fMat[kMPersp0]) + SkFractMul(sy, m.fMat[kMPersp1]) + SkFractToFixed(m.fMat[kMPersp2]); +#else + float z = SkScalarMul(sx, m.fMat[kMPersp0]) + SkScalarMul(sy, m.fMat[kMPersp1]) + m.fMat[kMPersp2]; +#endif + if (z) + z = SkScalarInvert(z); + pt->fX = SkScalarMul(x, z); + pt->fY = SkScalarMul(y, z); +} + +#ifdef SK_SCALAR_IS_FIXED +static SkFixed fixmuladdmul(SkFixed a, SkFixed b, SkFixed c, SkFixed d) +{ + Sk64 tmp, tmp1; + + tmp.setMul(a, b); + tmp1.setMul(c, d); + return tmp.addGetFixed(tmp1); +// tmp.add(tmp1); +// return tmp.getFixed(); +} +#endif + +void SkMatrix::Affine_ptProc(const SkMatrix& m, SkScalar sx, SkScalar sy, SkPoint* pt) +{ + SkASSERT((m.getType() & (kAffine_Mask | kPerspective_Mask)) == kAffine_Mask); + +#ifdef SK_SCALAR_IS_FIXED + pt->fX = fixmuladdmul(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) + m.fMat[kMTransX]; + pt->fY = fixmuladdmul(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) + m.fMat[kMTransY]; +#else + pt->fX = SkScalarMul(sx, m.fMat[kMScaleX]) + SkScalarMul(sy, m.fMat[kMSkewX]) + m.fMat[kMTransX]; + pt->fY = SkScalarMul(sx, m.fMat[kMSkewY]) + SkScalarMul(sy, m.fMat[kMScaleY]) + m.fMat[kMTransY]; +#endif +} + +void SkMatrix::Scale_ptProc(const SkMatrix& m, SkScalar sx, SkScalar sy, SkPoint* pt) +{ + SkASSERT((m.getType() & (kScale_Mask | kAffine_Mask | kPerspective_Mask)) == kScale_Mask); + + pt->fX = SkScalarMul(sx, m.fMat[kMScaleX]) + m.fMat[kMTransX]; + pt->fY = SkScalarMul(sy, m.fMat[kMScaleY]) + m.fMat[kMTransY]; +} + +void SkMatrix::Translate_ptProc(const SkMatrix& m, SkScalar sx, SkScalar sy, SkPoint* pt) +{ + SkASSERT(m.getType() == kTranslate_Mask); + + pt->fX = sx + m.fMat[kMTransX]; + pt->fY = sy + m.fMat[kMTransY]; +} + +void SkMatrix::Identity_ptProc(const SkMatrix& m, SkScalar sx, SkScalar sy, SkPoint* pt) +{ + SkASSERT(m.getType() == kIdentity_Mask); + + pt->fX = sx; + pt->fY = sy; +} + +SkMatrix::MapPtProc SkMatrix::getMapPtProc() const +{ + TypeMask typeMask = this->getType(); + + if (typeMask & kPerspective_Mask) + return Perspective_ptProc; + if (typeMask & kAffine_Mask) + return Affine_ptProc; + if (typeMask & kScale_Mask) + return Scale_ptProc; + if (typeMask & kTranslate_Mask) + return Translate_ptProc; + return Identity_ptProc; +} + +////////////////////////////////////////////////////////////////////////////////////////// + +// if its nearly zero (just made up 24 for that, perhaps it should be bigger or smaller) +#ifdef SK_SCALAR_IS_FIXED + typedef SkFract SkPerspElemType; + #define PerspNearlyZero(x) (SkAbs32(x) < (SK_Fract1 >> 26)) +#else + typedef float SkPerspElemType; + #define PerspNearlyZero(x) SkScalarNearlyZero(x, (1.0f / (1 << 26))) +#endif + +bool SkMatrix::fixedStepInX(SkScalar y, SkFixed* stepX, SkFixed* stepY) const +{ + if (PerspNearlyZero(fMat[kMPersp0])) + { + if (stepX || stepY) + { + if (PerspNearlyZero(fMat[kMPersp1]) && PerspNearlyZero(fMat[kMPersp2] - kMatrix22Elem)) + { + if (stepX) + *stepX = SkScalarToFixed(fMat[kMScaleX]); + if (stepY) + *stepY = SkScalarToFixed(fMat[kMSkewY]); + } + else + { +#ifdef SK_SCALAR_IS_FIXED + SkFixed z = SkFractMul(y, fMat[kMPersp1]) + SkFractToFixed(fMat[kMPersp2]); +#else + float z = y * fMat[kMPersp1] + fMat[kMPersp2]; +#endif + if (stepX) + *stepX = SkScalarToFixed(SkScalarDiv(fMat[kMScaleX], z)); + if (stepY) + *stepY = SkScalarToFixed(SkScalarDiv(fMat[kMSkewY], z)); + } + } + return true; + } + return false; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +#ifdef SK_SCALAR_IS_FIXED + +static inline void poly_to_point(SkPoint* pt, const SkPoint poly[], int count) +{ + SkFixed x = SK_Fixed1, y = SK_Fixed1; + SkPoint pt1, pt2; + Sk64 w1, w2; + + if (count > 1) + { pt1.fX = poly[1].fX - poly[0].fX; + pt1.fY = poly[1].fY - poly[0].fY; + y = SkPoint::Length(pt1.fX, pt1.fY); + switch (count) { + case 2: + break; + case 3: + pt2.fX = poly[0].fY - poly[2].fY; + pt2.fY = poly[2].fX - poly[0].fX; + goto CALC_X; + default: + pt2.fX = poly[0].fY - poly[3].fY; + pt2.fY = poly[3].fX - poly[0].fX; + CALC_X: + w1.setMul(pt1.fX, pt2.fX); + w2.setMul(pt1.fY, pt2.fY); + w1.add(w2); + w1.div(y, Sk64::kRound_DivOption); + x = w1.get32(); + break; + } + } + pt->set(x, y); +} + +static inline void Map1Pt(const SkPoint source[], SkMatrix* dst) +{ + dst->setTranslate(source[0].fX, source[0].fY); +} + +void SkMatrix::Map2Pt(const SkPoint srcPt[], SkMatrix* dst, SkFixed scale) +{ + dst->fMat[kMScaleX] = SkFixedDiv(srcPt[1].fY - srcPt[0].fY, scale); + dst->fMat[kMSkewY] = SkFixedDiv(srcPt[0].fX - srcPt[1].fX, scale); + dst->fMat[kMPersp0] = 0; + dst->fMat[kMSkewX] = SkFixedDiv(srcPt[1].fX - srcPt[0].fX, scale); + dst->fMat[kMScaleY] = SkFixedDiv(srcPt[1].fY - srcPt[0].fY, scale); + dst->fMat[kMPersp1] = 0; + dst->fMat[kMTransX] = srcPt[0].fX; + dst->fMat[kMTransY] = srcPt[0].fY; + dst->fMat[kMPersp2] = SK_Fract1; +} + +void SkMatrix::Map3Pt(const SkPoint srcPt[], SkMatrix* dst, SkFixed scaleX, SkFixed scaleY) +{ + dst->fMat[kMScaleX] = SkFixedDiv(srcPt[2].fX - srcPt[0].fX, scaleX); + dst->fMat[kMSkewY] = SkFixedDiv(srcPt[2].fY - srcPt[0].fY, scaleX); + dst->fMat[kMPersp0] = 0; + dst->fMat[kMSkewX] = SkFixedDiv(srcPt[1].fX - srcPt[0].fX, scaleY); + dst->fMat[kMScaleY] = SkFixedDiv(srcPt[1].fY - srcPt[0].fY, scaleY); + dst->fMat[kMPersp1] = 0; + dst->fMat[kMTransX] = srcPt[0].fX; + dst->fMat[kMTransY] = srcPt[0].fY; + dst->fMat[kMPersp2] = SK_Fract1; +} + +void SkMatrix::Map4Pt(const SkPoint srcPt[], SkMatrix* dst, SkFixed scaleX, SkFixed scaleY) +{ + SkFract a1, a2; + SkFixed x0, y0, x1, y1, x2, y2; + + x0 = srcPt[2].fX - srcPt[0].fX; + y0 = srcPt[2].fY - srcPt[0].fY; + x1 = srcPt[2].fX - srcPt[1].fX; + y1 = srcPt[2].fY - srcPt[1].fY; + x2 = srcPt[2].fX - srcPt[3].fX; + y2 = srcPt[2].fY - srcPt[3].fY; + + /* check if abs(x2) > abs(y2) */ + if ( x2 > 0 ? y2 > 0 ? x2 > y2 : x2 > -y2 : y2 > 0 ? -x2 > y2 : x2 < y2) + a1 = SkFractDiv(SkMulDiv(x0 - x1, y2, x2) - y0 + y1, SkMulDiv(x1, y2, x2) - y1); + else + a1 = SkFractDiv(x0 - x1 - SkMulDiv(y0 - y1, x2, y2), x1 - SkMulDiv(y1, x2, y2)); + + /* check if abs(x1) > abs(y1) */ + if ( x1 > 0 ? y1 > 0 ? x1 > y1 : x1 > -y1 : y1 > 0 ? -x1 > y1 : x1 < y1) + a2 = SkFractDiv(y0 - y2 - SkMulDiv(x0 - x2, y1, x1), y2 - SkMulDiv(x2, y1, x1)); + else + a2 = SkFractDiv(SkMulDiv(y0 - y2, x1, y1) - x0 + x2, SkMulDiv(y2, x1, y1) - x2); + + dst->fMat[kMScaleX] = SkFixedDiv(SkFractMul(a2, srcPt[3].fX) + srcPt[3].fX - srcPt[0].fX, scaleX); + dst->fMat[kMSkewY] = SkFixedDiv(SkFractMul(a2, srcPt[3].fY) + srcPt[3].fY - srcPt[0].fY, scaleX); + dst->fMat[kMPersp0] = SkFixedDiv(a2, scaleX); + dst->fMat[kMSkewX] = SkFixedDiv(SkFractMul(a1, srcPt[1].fX) + srcPt[1].fX - srcPt[0].fX, scaleY); + dst->fMat[kMScaleY] = SkFixedDiv(SkFractMul(a1, srcPt[1].fY) + srcPt[1].fY - srcPt[0].fY, scaleY); + dst->fMat[kMPersp1] = SkFixedDiv(a1, scaleY); + dst->fMat[kMTransX] = srcPt[0].fX; + dst->fMat[kMTransY] = srcPt[0].fY; + dst->fMat[kMPersp2] = SK_Fract1; +} + +#else /* Scalar is float */ + +static inline void poly_to_point(SkPoint* pt, const SkPoint poly[], int count) +{ + float x = 1, y = 1; + SkPoint pt1, pt2; + + if (count > 1) + { pt1.fX = poly[1].fX - poly[0].fX; + pt1.fY = poly[1].fY - poly[0].fY; + y = SkPoint::Length(pt1.fX, pt1.fY); + switch (count) { + case 2: + break; + case 3: + pt2.fX = poly[0].fY - poly[2].fY; + pt2.fY = poly[2].fX - poly[0].fX; + goto CALC_X; + default: + pt2.fX = poly[0].fY - poly[3].fY; + pt2.fY = poly[3].fX - poly[0].fX; + CALC_X: + x = SkScalarDiv(SkScalarMul(pt1.fX, pt2.fX) + SkScalarMul(pt1.fY, pt2.fY), y); + break; + } + } + pt->set(x, y); +} + +static inline void Map1Pt(const SkPoint source[], SkMatrix* dst) +{ + dst->setTranslate(source[0].fX, source[0].fY); +} + +void SkMatrix::Map2Pt(const SkPoint srcPt[], SkMatrix* dst, float scale) +{ + float invScale = 1 / scale; + + dst->fMat[kMScaleX] = (srcPt[1].fY - srcPt[0].fY) * invScale; + dst->fMat[kMSkewY] = (srcPt[0].fX - srcPt[1].fX) * invScale; + dst->fMat[kMPersp0] = 0; + dst->fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale; + dst->fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale; + dst->fMat[kMPersp1] = 0; + dst->fMat[kMTransX] = srcPt[0].fX; + dst->fMat[kMTransY] = srcPt[0].fY; + dst->fMat[kMPersp2] = 1; +} + +void SkMatrix::Map3Pt(const SkPoint srcPt[], SkMatrix* dst, float scaleX, float scaleY) +{ + float invScale = 1 / scaleX; + + dst->fMat[kMScaleX] = (srcPt[2].fX - srcPt[0].fX) * invScale; + dst->fMat[kMSkewY] = (srcPt[2].fY - srcPt[0].fY) * invScale; + dst->fMat[kMPersp0] = 0; + invScale = 1 / scaleY; + dst->fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale; + dst->fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale; + dst->fMat[kMPersp1] = 0; + dst->fMat[kMTransX] = srcPt[0].fX; + dst->fMat[kMTransY] = srcPt[0].fY; + dst->fMat[kMPersp2] = 1; +} + +void SkMatrix::Map4Pt(const SkPoint srcPt[], SkMatrix* dst, float scaleX, float scaleY) +{ + float a1, a2; + float x0, y0, x1, y1, x2, y2; + + x0 = srcPt[2].fX - srcPt[0].fX; + y0 = srcPt[2].fY - srcPt[0].fY; + x1 = srcPt[2].fX - srcPt[1].fX; + y1 = srcPt[2].fY - srcPt[1].fY; + x2 = srcPt[2].fX - srcPt[3].fX; + y2 = srcPt[2].fY - srcPt[3].fY; + + /* check if abs(x2) > abs(y2) */ + if ( x2 > 0 ? y2 > 0 ? x2 > y2 : x2 > -y2 : y2 > 0 ? -x2 > y2 : x2 < y2) + a1 = SkScalarDiv(SkScalarMulDiv(x0 - x1, y2, x2) - y0 + y1, SkScalarMulDiv(x1, y2, x2) - y1); + else + a1 = SkScalarDiv(x0 - x1 - SkScalarMulDiv(y0 - y1, x2, y2), x1 - SkScalarMulDiv(y1, x2, y2)); + + /* check if abs(x1) > abs(y1) */ + if ( x1 > 0 ? y1 > 0 ? x1 > y1 : x1 > -y1 : y1 > 0 ? -x1 > y1 : x1 < y1) + a2 = SkScalarDiv(y0 - y2 - SkScalarMulDiv(x0 - x2, y1, x1), y2 - SkScalarMulDiv(x2, y1, x1)); + else + a2 = SkScalarDiv(SkScalarMulDiv(y0 - y2, x1, y1) - x0 + x2, SkScalarMulDiv(y2, x1, y1) - x2); + + scaleX = 1 / scaleX; + dst->fMat[kMScaleX] = SkScalarMul(SkScalarMul(a2, srcPt[3].fX) + srcPt[3].fX - srcPt[0].fX, scaleX); + dst->fMat[kMSkewY] = SkScalarMul(SkScalarMul(a2, srcPt[3].fY) + srcPt[3].fY - srcPt[0].fY, scaleX); + dst->fMat[kMPersp0] = SkScalarMul(a2, scaleX); + scaleY = 1 / scaleY; + dst->fMat[kMSkewX] = SkScalarMul(SkScalarMul(a1, srcPt[1].fX) + srcPt[1].fX - srcPt[0].fX, scaleY); + dst->fMat[kMScaleY] = SkScalarMul(SkScalarMul(a1, srcPt[1].fY) + srcPt[1].fY - srcPt[0].fY, scaleY); + dst->fMat[kMPersp1] = SkScalarMul(a1, scaleY); + dst->fMat[kMTransX] = srcPt[0].fX; + dst->fMat[kMTransY] = srcPt[0].fY; + dst->fMat[kMPersp2] = 1; +} + +#endif + +/* Taken from Rob Johnson's original sample code in QuickDraw GX +*/ +bool SkMatrix::setPolyToPoly(const SkPoint dst[], const SkPoint src[], int count) +{ + SkASSERT((unsigned)count <= 4); + + SkPoint tempPt; + SkMatrix tempMap; + + poly_to_point(&tempPt, src, count); + switch (count) { + case 0: + this->reset(); + break; + case 1: + this->setTranslate(dst[0].fX - src[0].fX, dst[0].fY - src[0].fY); + break; + case 2: + Map2Pt(src, &tempMap, tempPt.fY); + if (tempMap.invert(this) == false) + return false; + Map2Pt(dst, &tempMap, tempPt.fY); + goto mapMap; + case 3: + Map3Pt(src, &tempMap, tempPt.fX, tempPt.fY); + if (tempMap.invert(this) == false) + return false; + Map3Pt(dst, &tempMap, tempPt.fX, tempPt.fY); + goto mapMap; + default: + Map4Pt(src, &tempMap, tempPt.fX, tempPt.fY); + if (tempMap.invert(this) == false) + return false; + Map4Pt(dst, &tempMap, tempPt.fX, tempPt.fY); + mapMap: + this->setConcat(tempMap, *this); + break; + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// + +#ifdef SK_DEBUG + +void SkMatrix::dump() const +{ + static const char* gTypeNames[] = { + "translate", + "scale", + "rotate", + "perspective" + }; + + SkDebugf("SkMatrix mask = "); + unsigned mask = this->getType(); + + if (mask == 0) + SkDebugf("identity\n"); + else + { + for (int i = 0; i < kShiftCount; i++) + { + if (mask & (1 << i)) + SkDebugf(" %s", gTypeNames[i]); + } + SkDebugf("\n"); + } + +#ifdef SK_CAN_USE_FLOAT + SkDebugf("[%8.4f %8.4f %8.4f]\n[%8.4f %8.4f %8.4f]\n[%8.4f %8.4f %8.4f]\n", +#ifdef SK_SCALAR_IS_FLOAT + fMat[0], fMat[1], fMat[2], fMat[3], fMat[4], fMat[5], + fMat[6], fMat[7], fMat[8]); +#else + SkFixedToFloat(fMat[0]), SkFixedToFloat(fMat[1]), SkFixedToFloat(fMat[2]), + SkFixedToFloat(fMat[3]), SkFixedToFloat(fMat[4]), SkFixedToFloat(fMat[5]), + SkFractToFloat(fMat[6]), SkFractToFloat(fMat[7]), SkFractToFloat(fMat[8])); +#endif +#else // can't use float + SkDebugf("[%x %x %x]\n[%x %x %x]\n[%x %x %x]\n", + fMat[0], fMat[1], fMat[2], fMat[3], fMat[4], fMat[5], + fMat[6], fMat[7], fMat[8]); +#endif +} + +void SkMatrix::UnitTest() +{ +#ifdef SK_SUPPORT_UNITTEST + SkMatrix mat, inverse, iden1, iden2; + + mat.reset(); + mat.setTranslate(SK_Scalar1, SK_Scalar1); + mat.invert(&inverse); + inverse.dump(); + iden1.setConcat(mat, inverse); + iden1.dump(); + + mat.setScale(SkIntToScalar(2), SkIntToScalar(2), 0, 0); + mat.invert(&inverse); + inverse.dump(); + iden1.setConcat(mat, inverse); + iden1.dump(); + + mat.setScale(SK_Scalar1/2, SK_Scalar1/2, 0, 0); + mat.invert(&inverse); + inverse.dump(); + iden1.setConcat(mat, inverse); + iden1.dump(); + + mat.setScale(SkIntToScalar(3), SkIntToScalar(5), SkIntToScalar(20), 0); + mat.postRotate(SkIntToScalar(25), 0, 0); + + SkASSERT(mat.invert(nil)); + mat.invert(&inverse); + + iden1.setConcat(mat, inverse); + iden2.setConcat(inverse, mat); + + iden1.dump(); + iden2.dump(); +#endif +} + +#endif diff --git a/libs/corecg/SkMemory_stdlib.cpp b/libs/corecg/SkMemory_stdlib.cpp new file mode 100644 index 000000000..5a03dacf3 --- /dev/null +++ b/libs/corecg/SkMemory_stdlib.cpp @@ -0,0 +1,79 @@ +#include "SkTypes.h" +#include +#include + +void sk_throw() +{ +#ifdef ANDROID + fprintf(stderr, "throwing...\n"); +#endif + abort(); +} + +void sk_out_of_memory(void) +{ +#ifdef ANDROID + fprintf(stderr,"- out of memory in SGL -\n"); +#endif + abort(); +} + +void* sk_malloc_throw(size_t size) +{ + return sk_malloc_flags(size, SK_MALLOC_THROW); +} + +void* sk_realloc_throw(void* addr, size_t size) +{ + SkDEBUGCODE(if (size) size += 4;) + SkDEBUGCODE(if (addr) addr = (char*)addr - 4;) + + void* p = realloc(addr, size); + if (size == 0) + return p; + + if (p == NULL) + sk_throw(); +#ifdef SK_DEBUG + else + { + memcpy(p, "skia", 4); + p = (char*)p + 4; + } +#endif + return p; +} + +void sk_free(void* p) +{ + if (p) + { +#ifdef SK_DEBUG + SkDEBUGCODE(p = (char*)p - 4;) + SkASSERT(memcmp(p, "skia", 4) == 0); +#endif + free(p); + } +} + +void* sk_malloc_flags(size_t size, unsigned flags) +{ + SkDEBUGCODE(size += 4;) + + void* p = malloc(size); + if (p == NULL) + { + if (flags & SK_MALLOC_THROW) + sk_throw(); + } +#ifdef SK_DEBUG + else + { + memcpy(p, "skia", 4); + p = (char*)p + 4; + memset(p, 0xCD, size - 4); + } +#endif + return p; +} + diff --git a/libs/corecg/SkPoint.cpp b/libs/corecg/SkPoint.cpp new file mode 100644 index 000000000..b76c4b3bf --- /dev/null +++ b/libs/corecg/SkPoint.cpp @@ -0,0 +1,238 @@ +#include "SkPoint.h" + +void SkPoint16::rotateCW(SkPoint16* dst) const +{ + SkASSERT(dst); + + // use a tmp in case this == dst + S16 tmp = fX; + dst->fX = -fY; + dst->fY = tmp; +} + +void SkPoint16::rotateCCW(SkPoint16* dst) const +{ + SkASSERT(dst); + + // use a tmp in case this == dst + S16 tmp = fX; + dst->fX = fY; + dst->fY = -tmp; +} + +///////////////////////////////////////////////////////////////////// + +void SkPoint::rotateCW(SkPoint* dst) const +{ + SkASSERT(dst); + + // use a tmp in case this == dst + SkScalar tmp = fX; + dst->fX = -fY; + dst->fY = tmp; +} + +void SkPoint::rotateCCW(SkPoint* dst) const +{ + SkASSERT(dst); + + // use a tmp in case this == dst + SkScalar tmp = fX; + dst->fX = fY; + dst->fY = -tmp; +} + +void SkPoint::scale(SkScalar scale, SkPoint* dst) const +{ + SkASSERT(dst); + dst->set(SkScalarMul(fX, scale), SkScalarMul(fY, scale)); +} + +#define kNearlyZero (SK_Scalar1 / 8092) + +bool SkPoint::normalize() +{ + return this->setLength(fX, fY, SK_Scalar1); +} + +bool SkPoint::setUnit(SkScalar x, SkScalar y) +{ + return this->setLength(x, y, SK_Scalar1); +} + +bool SkPoint::setLength(SkScalar length) +{ + return this->setLength(fX, fY, length); +} + +#ifdef SK_SCALAR_IS_FLOAT + +SkScalar SkPoint::Length(SkScalar dx, SkScalar dy) +{ + return sk_float_sqrt(dx * dx + dy * dy); +} + +bool SkPoint::setLength(float x, float y, float length) +{ + float mag = sk_float_sqrt(x * x + y * y); + if (mag > kNearlyZero) + { + length /= mag; + fX = x * length; + fY = y * length; + return true; + } + return false; +} + +#else + +#include "Sk64.h" + +SkScalar SkPoint::Length(SkScalar dx, SkScalar dy) +{ + Sk64 tmp1, tmp2; + + tmp1.setMul(dx, dx); + tmp2.setMul(dy, dy); + tmp1.add(tmp2); + + return tmp1.getSqrt(); +} + +#ifdef SK_DEBUGx +static SkFixed fixlen(SkFixed x, SkFixed y) +{ + float fx = (float)x; + float fy = (float)y; + + return (int)floorf(sqrtf(fx*fx + fy*fy) + 0.5f); +} +#endif + +static inline U32 squarefixed(unsigned x) +{ + x >>= 16; + return x*x; +} + +/* + Normalize x,y, and then scale them by length. + + The obvious way to do this would be the following: + S64 tmp1, tmp2; + tmp1.setMul(x,x); + tmp2.setMul(y,y); + tmp1.add(tmp2); + len = tmp1.getSqrt(); + x' = SkFixedDiv(x, len); + y' = SkFixedDiv(y, len); + This is fine, but slower than what we do below. + + The present technique does not compute the starting length, but + rather fiddles with x,y iteratively, all the while checking its + magnitude^2 (avoiding a sqrt). + + We normalize by first shifting x,y so that at least one of them + has bit 31 set (after taking the abs of them). + Then we loop, refining x,y by squaring them and comparing + against a very large 1.0 (1 << 28), and then adding or subtracting + a delta (which itself is reduced by half each time through the loop). + For speed we want the squaring to be with a simple integer mul. To keep + that from overflowing we shift our coordinates down until we are dealing + with at most 15 bits (2^15-1)^2 * 2 says withing 32 bits) + When our square is close to 1.0, we shift x,y down into fixed range. +*/ +bool SkPoint::setLength(SkFixed ox, SkFixed oy, SkFixed length) +{ + if (ox == 0) + { + if (oy == 0) + return false; + this->set(0, SkApplySign(length, SkExtractSign(oy))); + return true; + } + if (oy == 0) + { + this->set(SkApplySign(length, SkExtractSign(ox)), 0); + return true; + } + + SkFixed x = SkAbs32(ox); + SkFixed y = SkAbs32(oy); + + // shift x,y so that the greater of them is 15bits (1.14 fixed point) + { + int shift = SkCLZ(x | y); + // make them .30 + x <<= shift - 1; + y <<= shift - 1; + } + + SkFixed dx = x; + SkFixed dy = y; + + for (int i = 0; i < 17; i++) + { + dx >>= 1; + dy >>= 1; + + U32 len2 = squarefixed(x) + squarefixed(y); + if (len2 >> 28) + { + x -= dx; + y -= dy; + } + else + { + x += dx; + y += dy; + } + } + x >>= 14; + y >>= 14; + +#ifdef SK_DEBUGx // measure how far we are from unit-length + { + static int gMaxError; + static int gMaxDiff; + + SkFixed len = fixlen(x, y); + int err = len - SK_Fixed1; + err = SkAbs32(err); + + if (err > gMaxError) + { + gMaxError = err; + SkDebugf("gMaxError %d\n", err); + } + + float fx = SkAbs32(ox)/65536.0f; + float fy = SkAbs32(oy)/65536.0f; + float mag = sqrtf(fx*fx + fy*fy); + fx /= mag; + fy /= mag; + SkFixed xx = (int)floorf(fx * 65536 + 0.5f); + SkFixed yy = (int)floorf(fy * 65536 + 0.5f); + err = SkMax32(SkAbs32(xx-x), SkAbs32(yy-y)); + if (err > gMaxDiff) + { + gMaxDiff = err; + SkDebugf("gMaxDiff %d\n", err); + } + } +#endif + + x = SkApplySign(x, SkExtractSign(ox)); + y = SkApplySign(y, SkExtractSign(oy)); + if (length != SK_Fixed1) + { + x = SkFixedMul(x, length); + y = SkFixedMul(y, length); + } + this->set(x, y); + return true; +} + +#endif + diff --git a/libs/corecg/SkRect.cpp b/libs/corecg/SkRect.cpp new file mode 100644 index 000000000..0a093930e --- /dev/null +++ b/libs/corecg/SkRect.cpp @@ -0,0 +1,103 @@ +#include "SkRect.h" + +bool SkRect16::intersect(S16CPU left, S16CPU top, S16CPU right, S16CPU bottom) +{ + if (fLeft < right && left < fRight && fTop < bottom && top < fBottom) + { + if (fLeft < left) fLeft = SkToS16(left); + if (fTop < top) fTop = SkToS16(top); + if (fRight > right) fRight = SkToS16(right); + if (fBottom > bottom) fBottom = SkToS16(bottom); + return true; + } + return false; +} + +bool SkRect16::intersect(const SkRect16& r) +{ + SkASSERT(&r); + return this->intersect(r.fLeft, r.fTop, r.fRight, r.fBottom); +} + +bool SkRect16::intersect(const SkRect16& a, const SkRect16& b) +{ + SkASSERT(&a && &b); + + *this = a; + return this->intersect(b.fLeft, b.fTop, b.fRight, b.fBottom); +} + +void SkRect16::sort() +{ + if (fLeft > fRight) + SkTSwap(fLeft, fRight); + if (fTop > fBottom) + SkTSwap(fTop, fBottom); +} + +///////////////////////////////////////////////////////////////////////////// + +void SkRect::sort() +{ + if (fLeft > fRight) + SkTSwap(fLeft, fRight); + if (fTop > fBottom) + SkTSwap(fTop, fBottom); +} + +void SkRect::toQuad(SkPoint quad[4]) const +{ + SkASSERT(quad); + + quad[0].set(fLeft, fTop); + quad[1].set(fRight, fTop); + quad[2].set(fRight, fBottom); + quad[3].set(fLeft, fBottom); +} + +void SkRect::set(const SkPoint pts[], int count) +{ + SkASSERT(pts && count > 0 || count == 0); + + if (count <= 0) + memset(this, 0, sizeof(SkRect)); + else + { + SkScalar l, t, r, b; + + l = r = pts[0].fX; + t = b = pts[0].fY; + + for (int i = 1; i < count; i++) + { + SkScalar x = pts[i].fX; + SkScalar y = pts[i].fY; + + if (x < l) l = x; else if (x > r) r = x; + if (y < t) t = y; else if (y > b) b = y; + } + this->set(l, t, r, b); + } +} + +bool SkRect::intersect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) +{ + if (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; +} + +bool SkRect::intersect(const SkRect& r) +{ + SkASSERT(&r); + return this->intersect(r.fLeft, r.fTop, r.fRight, r.fBottom); +} + + + diff --git a/libs/corecg/SkRegion.cpp b/libs/corecg/SkRegion.cpp new file mode 100644 index 000000000..20c7c739f --- /dev/null +++ b/libs/corecg/SkRegion.cpp @@ -0,0 +1,1168 @@ +#include "SkRegionPriv.h" +#include "SkTemplates.h" +#include "SkThread.h" + +SkDEBUGCODE(int32_t gRgnAllocCounter;) + +///////////////////////////////////////////////////////////////////////////////////////////////// + +static SkRegion::RunType* skip_scanline(const SkRegion::RunType runs[]) +{ + while (runs[0] != kRunTypeSentinel) + { + SkASSERT(runs[0] < runs[1]); // valid span + runs += 2; + } + return (SkRegion::RunType*)(runs + 1); // return past the X-sentinel +} + +static SkRegion::RunType* find_y(const SkRegion::RunType runs[], int y) +{ + int top = *runs++; + if (top <= y) + { + for (;;) + { + int bot = *runs++; + if (bot > y) + { + if (bot == kRunTypeSentinel || *runs == kRunTypeSentinel) + break; + return (SkRegion::RunType*)runs; + } + top = bot; + runs = skip_scanline(runs); + } + } + return nil; +} + +// returns true if runs are a rect +bool SkRegion::compute_run_bounds(const SkRegion::RunType runs[], int count, SkRect16* bounds) +{ + assert_sentinel(runs[0], false); // top + + if (count == kRectRegionRuns) + { + assert_sentinel(runs[1], false); // bottom + assert_sentinel(runs[2], false); // left + assert_sentinel(runs[3], false); // right + assert_sentinel(runs[4], true); + assert_sentinel(runs[5], true); + + SkASSERT(runs[0] < runs[1]); // valid height + SkASSERT(runs[2] < runs[3]); // valid width + + bounds->set(runs[2], runs[0], runs[3], runs[1]); + return true; + } + + int left = SK_MaxS32; + int rite = SK_MinS32; + int bot; + + bounds->fTop = *runs++; + do { + bot = *runs++; + if (*runs < kRunTypeSentinel) + { + if (left > *runs) + left = *runs; + runs = skip_scanline(runs); + if (rite < runs[-2]) + rite = runs[-2]; + } + else + runs += 1; // skip X-sentinel + } while (runs[0] < kRunTypeSentinel); + bounds->fLeft = SkToS16(left); + bounds->fRight = SkToS16(rite); + bounds->fBottom = SkToS16(bot); + return false; +} + +////////////////////////////////////////////////////////////////////////// + +SkRegion::SkRegion() +{ + fBounds.set(0, 0, 0, 0); + fRunHead = SkRegion_gEmptyRunHeadPtr; +} + +SkRegion::SkRegion(const SkRegion& src) +{ + fRunHead = SkRegion_gEmptyRunHeadPtr; // just need a value that won't trigger sk_free(fRunHead) + this->setRegion(src); +} + +SkRegion::SkRegion(const SkRect16& rect) +{ + fRunHead = SkRegion_gEmptyRunHeadPtr; // just need a value that won't trigger sk_free(fRunHead) + this->setRect(rect); +} + +SkRegion::~SkRegion() +{ + this->freeRuns(); +} + +void SkRegion::freeRuns() +{ + if (fRunHead->isComplex()) + { + SkASSERT(fRunHead->fRefCnt >= 1); + if (sk_atomic_dec(&fRunHead->fRefCnt) == 1) + { + //SkASSERT(gRgnAllocCounter > 0); + //SkDEBUGCODE(sk_atomic_dec(&gRgnAllocCounter)); + //SkDEBUGF(("************** gRgnAllocCounter::free %d\n", gRgnAllocCounter)); + sk_free(fRunHead); + } + } +} + +void SkRegion::allocateRuns(int count) +{ + fRunHead = RunHead::Alloc(count); +} + +SkRegion& SkRegion::operator=(const SkRegion& src) +{ + (void)this->setRegion(src); + return *this; +} + +void SkRegion::swap(SkRegion& other) +{ + SkTSwap(fBounds, other.fBounds); + SkTSwap(fRunHead, other.fRunHead); +} + +bool SkRegion::setEmpty() +{ + this->freeRuns(); + fBounds.set(0, 0, 0, 0); + fRunHead = SkRegion_gEmptyRunHeadPtr; + return false; +} + +bool SkRegion::setRect(S16CPU left, S16CPU top, S16CPU right, S16CPU bottom) +{ + if (left >= right || top >= bottom) + return this->setEmpty(); + + this->freeRuns(); + fBounds.set(left, top, right, bottom); + fRunHead = SkRegion_gRectRunHeadPtr; + return true; +} + +bool SkRegion::setRect(const SkRect16& r) +{ + return this->setRect(r.fLeft, r.fTop, r.fRight, r.fBottom); +} + +bool SkRegion::setRegion(const SkRegion& src) +{ + if (this != &src) + { + this->freeRuns(); + + fBounds = src.fBounds; + fRunHead = src.fRunHead; + if (fRunHead->isComplex()) + sk_atomic_inc(&fRunHead->fRefCnt); + } + return fRunHead != SkRegion_gEmptyRunHeadPtr; +} + +bool SkRegion::op(const SkRect16& rect, Op op) +{ + SkRegion tmp(rect); + + return this->op(*this, tmp, op); +} + +bool SkRegion::op(const SkRect16& rect, const SkRegion& rgn, Op op) +{ + SkRegion tmp(rect); + + return this->op(tmp, rgn, op); +} + +////////////////////////////////////////////////////////////////////////////////////// + +int SkRegion::count_runtype_values(int* itop, int* ibot) const +{ + if (this == nil) + { + *itop = SK_MinS16; + *ibot = SK_MaxS16; + return 0; + } + + int maxT; + + if (this->isRect()) + maxT = 2; + else + { + SkASSERT(this->isComplex()); + // skip the top + const RunType* runs = fRunHead->runs() + 1; + maxT = 0; + + do { + const RunType* next = skip_scanline(runs + 1); + SkASSERT(next > runs); + int T = (int)(next - runs - 1); + if (maxT < T) + maxT = T; + runs = next; + } while (runs[0] < kRunTypeSentinel); + } + *itop = fBounds.fTop; + *ibot = fBounds.fBottom; + return maxT; +} + +bool SkRegion::setRuns(RunType runs[], int count) +{ + SkASSERT(count > 0); + + if (count <= 2) + { + // SkDEBUGF(("setRuns: empty\n")); + assert_sentinel(runs[count-1], true); + return this->setEmpty(); + } + + // trim off any empty spans from the top and bottom + // weird I should need this, perhaps op() could be smarter... + if (count > kRectRegionRuns) + { + RunType* stop = runs + count; + assert_sentinel(runs[0], false); // top + assert_sentinel(runs[1], false); // bottom + if (runs[2] == kRunTypeSentinel) // should be first left... + { + runs += 2; // skip empty initial span + runs[0] = runs[-1]; // set new top to prev bottom + assert_sentinel(runs[1], false); // bot: a sentinal would mean two in a row + assert_sentinel(runs[2], false); // left + assert_sentinel(runs[3], false); // right + } + + // now check for a trailing empty span + assert_sentinel(stop[-1], true); + assert_sentinel(stop[-2], true); + assert_sentinel(stop[-3], false); // should be last right + if (stop[-4] == kRunTypeSentinel) // eek, stop[-3] was a bottom with no x-runs + { + stop[-3] = kRunTypeSentinel; // kill empty last span + stop -= 2; + assert_sentinel(stop[-1], true); + assert_sentinel(stop[-2], true); + assert_sentinel(stop[-3], false); + assert_sentinel(stop[-4], false); + assert_sentinel(stop[-5], false); + } + count = (int)(stop - runs); + } + + SkASSERT(count >= kRectRegionRuns); + + if (compute_run_bounds(runs, count, &fBounds)) + { + // SkDEBUGF(("setRuns: rect[%d %d %d %d]\n", fBounds.fLeft, fBounds.fTop, fBounds.fRight, fBounds.fBottom)); + return this->setRect(fBounds); + } + + // if we get here, we need to become a complex region + + if (!fRunHead->isComplex() || fRunHead->fRunCount != count) + { +#ifdef SK_DEBUGx + SkDebugf("setRuns: rgn ["); + { + const RunType* r = runs; + + SkDebugf(" top: %d\n", *r++); + while (*r < kRunTypeSentinel) + { + SkDebugf(" bottom: %d", *r++); + while (*r < kRunTypeSentinel) + { + SkDebugf(" [%d %d]", r[0], r[1]); + r += 2; + } + SkDebugf("\n"); + } + } +#endif + this->freeRuns(); + this->allocateRuns(count); + } + memcpy(fRunHead->runs(), runs, count * sizeof(RunType)); + + SkDEBUGCODE(this->validate();) + + return true; +} + +void SkRegion::build_rect_runs(const SkRect16& bounds, + RunType runs[kRectRegionRuns]) +{ + runs[0] = bounds.fTop; + runs[1] = bounds.fBottom; + runs[2] = bounds.fLeft; + runs[3] = bounds.fRight; + runs[4] = kRunTypeSentinel; + runs[5] = kRunTypeSentinel; +} + +static SkRegion::RunType* find_scanline(const SkRegion::RunType runs[], S16CPU y) +{ + SkASSERT(y >= runs[0]); // if this fails, we didn't do a quick check on the boudns + + runs += 1; // skip top-Y + for (;;) + { + if (runs[0] == kRunTypeSentinel) + break; + if (y < runs[0]) + return (SkRegion::RunType*)&runs[1]; + runs = skip_scanline(runs); + } + return nil; +} + +bool SkRegion::contains(S16CPU x, S16CPU y) const +{ + if (!fBounds.contains(x, y)) + return false; + + if (this->isRect()) + return true; + + SkASSERT(this->isComplex()); + const RunType* runs = find_scanline(fRunHead->runs(), y); + + if (runs) + { for (;;) + { if (x < runs[0]) + break; + if (x < runs[1]) + return true; + runs += 2; + } + } + return false; +} + +const SkRegion::RunType* SkRegion::getRuns(RunType tmpStorage[], int* count) const +{ + SkASSERT(tmpStorage && count); + + if (this->isEmpty()) + { + tmpStorage[0] = kRunTypeSentinel; + *count = 1; + } + else if (this->isRect()) + { + build_rect_runs(fBounds, tmpStorage); + *count = kRectRegionRuns; + } + else + { + *count = fRunHead->fRunCount; + tmpStorage = fRunHead->runs(); + } + return tmpStorage; +} + +///////////////////////////////////////////////////////////////////////////////////// + +int operator==(const SkRegion& a, const SkRegion& b) +{ + SkDEBUGCODE(a.validate();) + SkDEBUGCODE(b.validate();) + + if (&a == &b) + return true; + if (a.fBounds != b.fBounds) + return false; + + const SkRegion::RunHead* ah = a.fRunHead; + const SkRegion::RunHead* bh = b.fRunHead; + + // this catches empties and rects being equal + if (ah == bh) + return true; + + // now we insist that both are complex (but different ptrs) + if (!ah->isComplex() || !bh->isComplex()) + return false; + + return ah->fRunCount == bh->fRunCount && + !memcmp(ah->runs(), bh->runs(), ah->fRunCount * sizeof(SkRegion::RunType)); +} + +void SkRegion::translate(int dx, int dy, SkRegion* dst) const +{ + SkDEBUGCODE(this->validate();) + + if (dst == nil) + return; + + if (this->isEmpty()) + dst->setEmpty(); + else if (this->isRect()) + dst->setRect(fBounds.fLeft + dx, fBounds.fTop + dy, + fBounds.fRight + dx, fBounds.fBottom + dy); + else + { + if (this == dst) + { + dst->fRunHead = dst->fRunHead->ensureWritable(); + } + else + { + SkRegion tmp; + tmp.allocateRuns(fRunHead->fRunCount); + tmp.fBounds = fBounds; + dst->swap(tmp); + } + + dst->fBounds.offset(dx, dy); + + const RunType* sruns = fRunHead->runs(); + RunType* druns = dst->fRunHead->runs(); + + *druns++ = SkToS16(*sruns++ + dy); // top + for (;;) + { + int bottom = *sruns++; + if (bottom == kRunTypeSentinel) + break; + *druns++ = SkToS16(bottom + dy); // bottom; + for (;;) + { + int x = *sruns++; + if (x == kRunTypeSentinel) + break; + *druns++ = SkToS16(x + dx); + *druns++ = SkToS16(*sruns++ + dx); + } + *druns++ = kRunTypeSentinel; // x sentinel + } + *druns++ = kRunTypeSentinel; // y sentinel + + SkASSERT(sruns - fRunHead->runs() == fRunHead->fRunCount); + SkASSERT(druns - dst->fRunHead->runs() == dst->fRunHead->fRunCount); + } +} + +///////////////////////////////////////////////////////////////////////////////////// + +#if defined _WIN32 && _MSC_VER >= 1300 // disable warning : local variable used without having been initialized +#pragma warning ( push ) +#pragma warning ( disable : 4701 ) +#endif + +#ifdef SK_DEBUG +static void assert_valid_pair(S16CPU left, S16CPU rite) +{ + SkASSERT(left == kRunTypeSentinel || left < rite); +} +#else + #define assert_valid_pair(left, rite) +#endif + +struct spanRec { + const SkRegion::RunType* fA_runs; + const SkRegion::RunType* fB_runs; + int fA_left, fA_rite, fB_left, fB_rite; + int fLeft, fRite, fInside; + + void init(const SkRegion::RunType a_runs[], const SkRegion::RunType b_runs[]) + { + fA_left = *a_runs++; + fA_rite = *a_runs++; + fB_left = *b_runs++; + fB_rite = *b_runs++; + + fA_runs = a_runs; + fB_runs = b_runs; + } + + bool done() const + { + SkASSERT(fA_left <= kRunTypeSentinel); + SkASSERT(fB_left <= kRunTypeSentinel); + return fA_left == kRunTypeSentinel && fB_left == kRunTypeSentinel; + } + + void next() + { + assert_valid_pair(fA_left, fA_rite); + assert_valid_pair(fB_left, fB_rite); + + int inside, left, rite SK_INIT_TO_AVOID_WARNING; + bool a_flush = false; + bool b_flush = false; + + int a_left = fA_left; + int a_rite = fA_rite; + int b_left = fB_left; + int b_rite = fB_rite; + + if (a_left < b_left) + { + inside = 1; + left = a_left; + if (a_rite <= b_left) // [...] <...> + { + rite = a_rite; + a_flush = true; + } + else // [...<..]...> or [...<...>...] + rite = a_left = b_left; + } + else if (b_left < a_left) + { + inside = 2; + left = b_left; + if (b_rite <= a_left) // [...] <...> + { + rite = b_rite; + b_flush = true; + } + else // [...<..]...> or [...<...>...] + rite = b_left = a_left; + } + else // a_left == b_left + { + inside = 3; + left = a_left; // or b_left + if (a_rite <= b_rite) + { + rite = b_left = a_rite; + a_flush = true; + } + if (b_rite <= a_rite) + { + rite = a_left = b_rite; + b_flush = true; + } + } + + if (a_flush) + { + a_left = *fA_runs++; + a_rite = *fA_runs++; + } + if (b_flush) + { + b_left = *fB_runs++; + b_rite = *fB_runs++; + } + + SkASSERT(left <= rite); + + // now update our state + fA_left = a_left; + fA_rite = a_rite; + fB_left = b_left; + fB_rite = b_rite; + + fLeft = left; + fRite = rite; + fInside = inside; + } +}; + +static SkRegion::RunType* operate_on_span(const SkRegion::RunType a_runs[], + const SkRegion::RunType b_runs[], + SkRegion::RunType dst[], + int min, int max) +{ + spanRec rec; + bool firstInterval = true; + + rec.init(a_runs, b_runs); + + while (!rec.done()) + { + rec.next(); + + int left = rec.fLeft; + int rite = rec.fRite; + + // add left,rite to our dst buffer (checking for coincidence + if ((unsigned)(rec.fInside - min) <= (unsigned)(max - min) && + left < rite) // skip if equal + { + if (firstInterval || dst[-1] < left) + { + *dst++ = SkToS16(left); + *dst++ = SkToS16(rite); + firstInterval = false; + } + else // update the right edge + dst[-1] = SkToS16(rite); + } + } + + *dst++ = kRunTypeSentinel; + return dst; +} + +#if defined _WIN32 && _MSC_VER >= 1300 +#pragma warning ( pop ) +#endif + +class RgnOper { +public: + RgnOper(S16CPU top, SkRegion::RunType dst[], SkRegion::Op op) + { + fStartDst = dst; + fPrevDst = dst + 1; + fPrevLen = 0; // will never match a length from operate_on_span + fTop = SkToS16(top); // just a first guess, we might update this + + static const struct { + U8 fMin; + U8 fMax; + } gOpMinMax[] = { + { 1, 1 }, // Difference + { 3, 3 }, // Intersection + { 1, 3 }, // Union + { 1, 2 } // XOR + }; + + SkASSERT((unsigned)op < SkRegion::kOpCount); + fMin = gOpMinMax[op].fMin; + fMax = gOpMinMax[op].fMax; + } + + void addSpan(S16CPU bottom, const SkRegion::RunType a_runs[], const SkRegion::RunType b_runs[]) + { + SkRegion::RunType* start = fPrevDst + fPrevLen + 1; // skip X values and slot for the next Y + SkRegion::RunType* stop = operate_on_span(a_runs, b_runs, start, fMin, fMax); + size_t len = stop - start; + + if (fPrevLen == len && !memcmp(fPrevDst, start, len * sizeof(SkRegion::RunType))) // update Y value + fPrevDst[-1] = SkToS16(bottom); + else // accept the new span + { + if (len == 1 && fPrevLen == 0) + fTop = SkToS16(bottom); // just update our bottom + else + { + start[-1] = SkToS16(bottom); + fPrevDst = start; + fPrevLen = len; + } + } + } + + int flush() + { + fStartDst[0] = fTop; + fPrevDst[fPrevLen] = kRunTypeSentinel; + return (int)(fPrevDst - fStartDst + fPrevLen + 1); + } + + U8 fMin, fMax; + +private: + SkRegion::RunType* fStartDst; + SkRegion::RunType* fPrevDst; + size_t fPrevLen; + SkRegion::RunType fTop; +}; + +static int operate( const SkRegion::RunType a_runs[], + const SkRegion::RunType b_runs[], + SkRegion::RunType dst[], + SkRegion::Op op) +{ + const SkRegion::RunType sentinel = kRunTypeSentinel; + + int a_top = *a_runs++; + int a_bot = *a_runs++; + int b_top = *b_runs++; + int b_bot = *b_runs++; + + assert_sentinel(a_top, false); + assert_sentinel(a_bot, false); + assert_sentinel(b_top, false); + assert_sentinel(b_bot, false); + + RgnOper oper(SkMin32(a_top, b_top), dst, op); + + bool firstInterval = true; + int prevBot = kRunTypeSentinel; // so we fail the first test + + while (a_bot < kRunTypeSentinel || b_bot < kRunTypeSentinel) + { + int top, bot SK_INIT_TO_AVOID_WARNING; + const SkRegion::RunType* run0 = &sentinel; + const SkRegion::RunType* run1 = &sentinel; + bool a_flush = false; + bool b_flush = false; + int inside; + + if (a_top < b_top) + { + inside = 1; + top = a_top; + run0 = a_runs; + if (a_bot <= b_top) // [...] <...> + { + bot = a_bot; + a_flush = true; + } + else // [...<..]...> or [...<...>...] + bot = a_top = b_top; + } + else if (b_top < a_top) + { + inside = 2; + top = b_top; + run1 = b_runs; + if (b_bot <= a_top) // [...] <...> + { + bot = b_bot; + b_flush = true; + } + else // [...<..]...> or [...<...>...] + bot = b_top = a_top; + } + else // a_top == b_top + { + inside = 3; + top = a_top; // or b_top + run0 = a_runs; + run1 = b_runs; + if (a_bot <= b_bot) + { + bot = b_top = a_bot; + a_flush = true; + } + if (b_bot <= a_bot) + { + bot = a_top = b_bot; + b_flush = true; + } + } + + if (top > prevBot) + oper.addSpan(top, &sentinel, &sentinel); + +// if ((unsigned)(inside - oper.fMin) <= (unsigned)(oper.fMax - oper.fMin)) + { + oper.addSpan(bot, run0, run1); + firstInterval = false; + } + + if (a_flush) + { + a_runs = skip_scanline(a_runs); + a_top = a_bot; + a_bot = *a_runs++; + if (a_bot == kRunTypeSentinel) + a_top = a_bot; + } + if (b_flush) + { + b_runs = skip_scanline(b_runs); + b_top = b_bot; + b_bot = *b_runs++; + if (b_bot == kRunTypeSentinel) + b_top = b_bot; + } + + prevBot = bot; + } + return oper.flush(); +} + +bool SkRegion::op(const SkRegion& rgna, const SkRegion& rgnb, Op op) +{ + SkDEBUGCODE(this->validate();) + + SkASSERT((unsigned)op < kOpCount); + + SkRect16 bounds; + bool a_empty = rgna.isEmpty(); + bool b_empty = rgnb.isEmpty(); + bool a_rect = rgna.isRect(); + bool b_rect = rgnb.isRect(); + + switch (op) { + case kDifference_Op: + if (a_empty) + return this->setEmpty(); + if (b_empty || !SkRect16::Intersects(rgna.fBounds, rgnb.fBounds)) + return this->setRegion(rgna); + break; + + case kIntersect_Op: + if ((a_empty | b_empty) || !bounds.intersect(rgna.fBounds, rgnb.fBounds)) + return this->setEmpty(); + if (a_rect & b_rect) + return this->setRect(bounds); + break; + + case kUnion_Op: + if (a_empty) + return this->setRegion(rgnb); + if (b_empty) + return this->setRegion(rgna); + if (a_rect && rgna.fBounds.contains(rgnb.fBounds)) + return this->setRegion(rgna); + if (b_rect && rgnb.fBounds.contains(rgna.fBounds)) + return this->setRegion(rgnb); + break; + + case kXOR_Op: + if (a_empty) + return this->setRegion(rgnb); + if (b_empty) + return this->setRegion(rgna); + break; + default: + break; + } + + RunType tmpA[kRectRegionRuns]; + RunType tmpB[kRectRegionRuns]; + + int a_count, b_count; + const RunType* a_runs = rgna.getRuns(tmpA, &a_count); + const RunType* b_runs = rgnb.getRuns(tmpB, &b_count); + + int dstCount = 3 * SkMax32(a_count, b_count); + SkAutoSTMalloc<32, RunType> array(dstCount); + + int count = operate(a_runs, b_runs, array.get(), op); + SkASSERT(count <= dstCount); + return this->setRuns(array.get(), count); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include "SkBuffer.h" + +size_t SkRegion::computeBufferSize() const +{ + size_t size = sizeof(int32_t); // -1 (empty), 0 (rect), runCount + + if (!this->isEmpty()) + { + size += sizeof(fBounds); + if (this->isComplex()) + size += fRunHead->fRunCount * sizeof(RunType); + } + return size; +} + +size_t SkRegion::writeToBuffer(void* storage) const +{ + SkWBuffer buffer(storage); + + if (this->isEmpty()) + { + buffer.write32(-1); + } + else + { + bool isRect = this->isRect(); + + buffer.write32(isRect ? 0 : fRunHead->fRunCount); + buffer.write(&fBounds, sizeof(fBounds)); + + if (!isRect) + { + buffer.write(fRunHead->runs(), fRunHead->fRunCount * sizeof(RunType)); + } + } + return buffer.pos(); +} + +size_t SkRegion::readFromBuffer(const void* storage) +{ + SkRBuffer buffer(storage); + SkRegion tmp; + int32_t count; + + count = buffer.readS32(); + if (count >= 0) + { + buffer.read(&tmp.fBounds, sizeof(tmp.fBounds)); + if (count == 0) + { + tmp.fRunHead = SkRegion_gRectRunHeadPtr; + } + else + { + tmp.allocateRuns(count); + buffer.read(tmp.fRunHead->runs(), count * sizeof(RunType)); + } + } + this->swap(tmp); + return buffer.pos(); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef SK_DEBUG + +static const SkRegion::RunType* validate_line(const SkRegion::RunType run[], const SkRect16& bounds) +{ + SkASSERT(*run >= bounds.fTop); + SkASSERT(*run <= bounds.fBottom); + run += 1; + while (*run < kRunTypeSentinel) + { + SkASSERT(run[0] < run[1]); + SkASSERT(run[0] >= bounds.fLeft); + SkASSERT(run[1] <= bounds.fRight); + run += 2; + } + return run + 1; // skip sentinel +} + +void SkRegion::validate() const +{ + if (this->isEmpty()) + { + // check for explicit empty (the zero rect), so we can compare rects to know when + // two regions are equal (i.e. emptyRectA == emptyRectB) + // this is stricter than just asserting fBounds.isEmpty() + SkASSERT(fBounds.fLeft == 0 && fBounds.fTop == 0 && fBounds.fRight == 0 && fBounds.fBottom == 0); + } + else + { + SkASSERT(!fBounds.isEmpty()); + if (!this->isRect()) + { + SkASSERT(fRunHead->fRefCnt >= 1); + SkASSERT(fRunHead->fRunCount >= kRectRegionRuns); + + const RunType* run = fRunHead->runs(); + const RunType* stop = run + fRunHead->fRunCount; + + SkASSERT(*run++ == fBounds.fTop); + do { + run = validate_line(run, fBounds); + } while (*run < kRunTypeSentinel); + SkASSERT(run + 1 == stop); + } + } +} + +void SkRegion::dump() const +{ + if (this->isEmpty()) + SkDebugf(" rgn: empty\n"); + else + { + SkDebugf(" rgn: [%d %d %d %d]", fBounds.fLeft, fBounds.fTop, fBounds.fRight, fBounds.fBottom); + if (this->isComplex()) + { + const RunType* runs = fRunHead->runs(); + for (int i = 0; i < fRunHead->fRunCount; i++) + SkDebugf(" %d", runs[i]); + } + SkDebugf("\n"); + } +} + +#endif + +///////////////////////////////////////////////////////////////////////////////////// + +SkRegion::Iterator::Iterator(const SkRegion& rgn) +{ + if (rgn.isEmpty()) + fDone = true; + else + { + fDone = false; + if (rgn.isRect()) + { + fRect = rgn.fBounds; + fRuns = nil; + } + else + { + fRuns = rgn.fRunHead->runs(); + fRect.set(fRuns[2], fRuns[0], fRuns[3], fRuns[1]); + fRuns += 4; + } + } +} + +void SkRegion::Iterator::next() +{ + if (fDone) return; + + if (fRuns == nil) // rect case + { + fDone = true; + return; + } + + const RunType* runs = fRuns; + + if (runs[0] < kRunTypeSentinel) // valid X value + { + fRect.fLeft = runs[0]; + fRect.fRight = runs[1]; + runs += 2; + } + else // we're at the end of a line + { + runs += 1; + if (runs[0] < kRunTypeSentinel) // valid Y value + { + if (runs[1] == kRunTypeSentinel) // empty line + { + fRect.fTop = runs[0]; + runs += 2; + } + else + fRect.fTop = fRect.fBottom; + + fRect.fBottom = runs[0]; + assert_sentinel(runs[1], false); + fRect.fLeft = runs[1]; + fRect.fRight = runs[2]; + runs += 3; + } + else // end of rgn + fDone = true; + } + fRuns = runs; +} + +SkRegion::Cliperator::Cliperator(const SkRegion& rgn, const SkRect16& clip) + : fIter(rgn), fClip(clip), fDone(true) +{ + const SkRect16& r = fIter.rect(); + + while (!fIter.done()) + { + if (r.fTop >= clip.fBottom) + break; + if (fRect.intersect(clip, r)) + { + fDone = false; + break; + } + fIter.next(); + } +} + +void SkRegion::Cliperator::next() +{ + if (fDone) return; + + const SkRect16& r = fIter.rect(); + + fDone = true; + fIter.next(); + while (!fIter.done()) + { + if (r.fTop >= fClip.fBottom) + break; + if (fRect.intersect(fClip, r)) + { + fDone = false; + break; + } + fIter.next(); + } +} + +////////////////////////////////////////////////////////////////////// + +SkRegion::Spanerator::Spanerator(const SkRegion& rgn, int y, int left, int right) +{ + const SkRect16& r = rgn.getBounds(); + + fDone = true; + if (!rgn.isEmpty() && y >= r.fTop && y < r.fBottom && right > r.fLeft && left < r.fRight) + { + if (rgn.isRect()) + { + if (left < r.fLeft) + left = r.fLeft; + if (right > r.fRight) + right = r.fRight; + + fLeft = left; + fRight = right; + fRuns = nil; // means we're a rect, not a rgn + fDone = false; + } + else + { + const SkRegion::RunType* runs = find_y(rgn.fRunHead->runs(), y); + if (runs) + { + for (;;) + { + if (runs[0] >= right) // runs[0..1] is to the right of the span, so we're done + break; + if (runs[1] <= left) // runs[0..1] is to the left of the span, so continue + { + runs += 2; + continue; + } + // runs[0..1] intersects the span + fRuns = runs; + fLeft = left; + fRight = right; + fDone = false; + break; + } + } + } + } +} + +bool SkRegion::Spanerator::next(int* left, int* right) +{ + if (fDone) return false; + + if (fRuns == nil) // we're a rect + { + fDone = true; // ok, now we're done + if (left) *left = fLeft; + if (right) *right = fRight; + return true; // this interval is legal + } + + const SkRegion::RunType* runs = fRuns; + + if (runs[0] >= fRight) + { + fDone = true; + return false; + } + + SkASSERT(runs[1] > fLeft); + + if (left) + *left = SkMax32(fLeft, runs[0]); + if (right) + *right = SkMin32(fRight, runs[1]); + fRuns = runs + 2; + return true; +} + diff --git a/libs/corecg/SkRegionPriv.h b/libs/corecg/SkRegionPriv.h new file mode 100644 index 000000000..7626a3597 --- /dev/null +++ b/libs/corecg/SkRegionPriv.h @@ -0,0 +1,70 @@ +#ifndef SkRegionPriv_DEFINED +#define SkRegionPriv_DEFINED + +#include "SkRegion.h" +#include "SkThread.h" + +#define kRunTypeSentinel 0x7FFF +#define assert_sentinel(value, isSentinel) SkASSERT(((value) == kRunTypeSentinel) == isSentinel) + +//SkDEBUGCODE(extern int32_t gRgnAllocCounter;) + +struct SkRegion::RunHead { + int32_t fRefCnt; + int32_t fRunCount; + + static RunHead* Alloc(int count) + { + //SkDEBUGCODE(sk_atomic_inc(&gRgnAllocCounter);) + //SkDEBUGF(("************** gRgnAllocCounter::alloc %d\n", gRgnAllocCounter)); + + SkASSERT(count >= SkRegion::kRectRegionRuns); + + RunHead* head = (RunHead*)sk_malloc_throw(sizeof(RunHead) + count * sizeof(RunType)); + head->fRefCnt = 1; + head->fRunCount = count; + return head; + } + + bool isComplex() const + { + return this != SkRegion_gEmptyRunHeadPtr && this != SkRegion_gRectRunHeadPtr; + } + + SkRegion::RunType* runs() + { + SkASSERT(this->isComplex()); + return (SkRegion::RunType*)(this + 1); + } + const SkRegion::RunType* runs() const + { + SkASSERT(this->isComplex()); + return (const SkRegion::RunType*)(this + 1); + } + + RunHead* ensureWritable() + { + SkASSERT(this->isComplex()); + + RunHead* writable = this; + if (fRefCnt > 1) + { + // We need to alloc & copy the current region before we call + // sk_atomic_dec because it could be freed in the meantime, + // otherwise. + writable = Alloc(fRunCount); + memcpy(writable->runs(), this->runs(), fRunCount * sizeof(RunType)); + + // fRefCount might have changed since we last checked. + // If we own the last reference at this point, we need to + // free the memory. + if (sk_atomic_dec(&fRefCnt) == 1) + { + sk_free(this); + } + } + return writable; + } +}; + +#endif diff --git a/libs/corecg/SkSinTable.h b/libs/corecg/SkSinTable.h new file mode 100644 index 000000000..2c4c11d48 --- /dev/null +++ b/libs/corecg/SkSinTable.h @@ -0,0 +1,268 @@ +#ifndef SkSinTable_DEFINED +#define SkSinTable_DEFINED + +#include "SkTypes.h" + +/* Fixed point values (low 16 bits) of sin(radians) for + radians in [0...PI/2) +*/ +static const U16 gSkSinTable[256] = { + 0x0000, + 0x0192, + 0x0324, + 0x04B6, + 0x0648, + 0x07DA, + 0x096C, + 0x0AFE, + 0x0C8F, + 0x0E21, + 0x0FB2, + 0x1144, + 0x12D5, + 0x1466, + 0x15F6, + 0x1787, + 0x1917, + 0x1AA7, + 0x1C37, + 0x1DC7, + 0x1F56, + 0x20E5, + 0x2273, + 0x2402, + 0x2590, + 0x271D, + 0x28AA, + 0x2A37, + 0x2BC4, + 0x2D50, + 0x2EDB, + 0x3066, + 0x31F1, + 0x337B, + 0x3505, + 0x368E, + 0x3817, + 0x399F, + 0x3B26, + 0x3CAD, + 0x3E33, + 0x3FB9, + 0x413E, + 0x42C3, + 0x4447, + 0x45CA, + 0x474D, + 0x48CE, + 0x4A50, + 0x4BD0, + 0x4D50, + 0x4ECF, + 0x504D, + 0x51CA, + 0x5347, + 0x54C3, + 0x563E, + 0x57B8, + 0x5931, + 0x5AAA, + 0x5C22, + 0x5D98, + 0x5F0E, + 0x6083, + 0x61F7, + 0x636A, + 0x64DC, + 0x664D, + 0x67BD, + 0x692D, + 0x6A9B, + 0x6C08, + 0x6D74, + 0x6EDF, + 0x7049, + 0x71B1, + 0x7319, + 0x7480, + 0x75E5, + 0x774A, + 0x78AD, + 0x7A0F, + 0x7B70, + 0x7CD0, + 0x7E2E, + 0x7F8B, + 0x80E7, + 0x8242, + 0x839C, + 0x84F4, + 0x864B, + 0x87A1, + 0x88F5, + 0x8A48, + 0x8B9A, + 0x8CEA, + 0x8E39, + 0x8F87, + 0x90D3, + 0x921E, + 0x9368, + 0x94B0, + 0x95F6, + 0x973C, + 0x987F, + 0x99C2, + 0x9B02, + 0x9C42, + 0x9D7F, + 0x9EBC, + 0x9FF6, + 0xA12F, + 0xA267, + 0xA39D, + 0xA4D2, + 0xA605, + 0xA736, + 0xA866, + 0xA994, + 0xAAC0, + 0xABEB, + 0xAD14, + 0xAE3B, + 0xAF61, + 0xB085, + 0xB1A8, + 0xB2C8, + 0xB3E7, + 0xB504, + 0xB620, + 0xB73A, + 0xB852, + 0xB968, + 0xBA7C, + 0xBB8F, + 0xBCA0, + 0xBDAE, + 0xBEBC, + 0xBFC7, + 0xC0D0, + 0xC1D8, + 0xC2DE, + 0xC3E2, + 0xC4E3, + 0xC5E4, + 0xC6E2, + 0xC7DE, + 0xC8D8, + 0xC9D1, + 0xCAC7, + 0xCBBB, + 0xCCAE, + 0xCD9F, + 0xCE8D, + 0xCF7A, + 0xD064, + 0xD14D, + 0xD233, + 0xD318, + 0xD3FA, + 0xD4DB, + 0xD5B9, + 0xD695, + 0xD770, + 0xD848, + 0xD91E, + 0xD9F2, + 0xDAC4, + 0xDB94, + 0xDC61, + 0xDD2D, + 0xDDF6, + 0xDEBE, + 0xDF83, + 0xE046, + 0xE106, + 0xE1C5, + 0xE282, + 0xE33C, + 0xE3F4, + 0xE4AA, + 0xE55E, + 0xE60F, + 0xE6BE, + 0xE76B, + 0xE816, + 0xE8BF, + 0xE965, + 0xEA09, + 0xEAAB, + 0xEB4B, + 0xEBE8, + 0xEC83, + 0xED1C, + 0xEDB2, + 0xEE46, + 0xEED8, + 0xEF68, + 0xEFF5, + 0xF080, + 0xF109, + 0xF18F, + 0xF213, + 0xF294, + 0xF314, + 0xF391, + 0xF40B, + 0xF484, + 0xF4FA, + 0xF56D, + 0xF5DE, + 0xF64D, + 0xF6BA, + 0xF724, + 0xF78B, + 0xF7F1, + 0xF853, + 0xF8B4, + 0xF912, + 0xF96E, + 0xF9C7, + 0xFA1E, + 0xFA73, + 0xFAC5, + 0xFB14, + 0xFB61, + 0xFBAC, + 0xFBF5, + 0xFC3B, + 0xFC7E, + 0xFCBF, + 0xFCFE, + 0xFD3A, + 0xFD74, + 0xFDAB, + 0xFDE0, + 0xFE13, + 0xFE43, + 0xFE70, + 0xFE9B, + 0xFEC4, + 0xFEEA, + 0xFF0E, + 0xFF2F, + 0xFF4E, + 0xFF6A, + 0xFF84, + 0xFF9C, + 0xFFB1, + 0xFFC3, + 0xFFD3, + 0xFFE1, + 0xFFEC, + 0xFFF4, + 0xFFFB, + 0xFFFE +}; + +#endif diff --git a/libs/corecg/SkTSort.h b/libs/corecg/SkTSort.h new file mode 100644 index 000000000..bdfbf6daf --- /dev/null +++ b/libs/corecg/SkTSort.h @@ -0,0 +1,48 @@ +#ifndef SkTSort_DEFINED +#define SkTSort_DEFINED + +#include "SkTypes.h" + +template +void SkTHeapSort_SiftDown(T array[], int root, int bottom) +{ + int root2 = root << 1; + + while (root2 <= bottom) + { + int maxChild; + + if (root2 == bottom) + maxChild = root2; + else if (array[root2] > array[root2 + 1]) + maxChild = root2; + else + maxChild = root2 + 1; + + if (array[root] < array[maxChild]) + { + SkTSwap(array[root], array[maxChild]); + root = maxChild; + root2 = root << 1; + } + else + break; + } +} + +template +void SkTHeapSort(T array[], int count) +{ + int i; + + for (i = count/2 - 1; i >= 0; --i) + SkTHeapSort_SiftDown(array, i, count); + + for (i = count - 2; i >= 0; --i) + { + SkTSwap(array[0], array[i + 1]); + SkTHeapSort_SiftDown(array, 0, i); + } +} + +#endif diff --git a/libs/graphics/Makefile b/libs/graphics/Makefile new file mode 100644 index 000000000..7bccd3a34 --- /dev/null +++ b/libs/graphics/Makefile @@ -0,0 +1,137 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + effects/Sk1DPathEffect.cpp \ + effects/Sk2DPathEffect.cpp \ + effects/SkBlurMask.cpp \ + effects/SkBlurMaskFilter.cpp \ + effects/SkCamera.cpp \ + effects/SkColorFilters.cpp \ + effects/SkCornerPathEffect.cpp \ + effects/SkDashPathEffect.cpp \ + effects/SkDiscretePathEffect.cpp \ + effects/SkEmbossMask.cpp \ + effects/SkEmbossMaskFilter.cpp \ + effects/SkGradientShader.cpp \ + effects/SkLayerRasterizer.cpp \ + effects/SkNinePatch.cpp \ + effects/SkShaderExtras.cpp \ + effects/SkTransparentShader.cpp \ + images/SkBitmapRef.cpp \ + images/SkImageDecoder.cpp \ + images/SkImageDecoder_libgif.cpp \ + images/SkImageDecoder_libjpeg.cpp \ + images/SkImageDecoder_libpng.cpp \ + images/SkStream.cpp \ + sgl/SkAlphaRuns.cpp \ + sgl/SkBitmap.cpp \ + sgl/SkBitmapSampler.cpp \ + sgl/SkBitmapShader.cpp \ + sgl/SkBlitter.cpp \ + sgl/SkBlitter_A1.cpp \ + sgl/SkBlitter_A8.cpp \ + sgl/SkBlitter_ARGB32.cpp \ + sgl/SkBlitter_RGB16.cpp \ + sgl/SkBlitter_Sprite.cpp \ + sgl/SkCanvas.cpp \ + sgl/SkColor.cpp \ + sgl/SkColorFilter.cpp \ + sgl/SkColorTable.cpp \ + sgl/SkDeque.cpp \ + sgl/SkDraw.cpp \ + sgl/SkEdge.cpp \ + sgl/SkFilterProc.cpp \ + sgl/SkGeometry.cpp \ + sgl/SkGlobals.cpp \ + sgl/SkGlyphCache.cpp \ + sgl/SkGraphics.cpp \ + sgl/SkMaskFilter.cpp \ + sgl/SkPaint.cpp \ + sgl/SkPath.cpp \ + sgl/SkPathEffect.cpp \ + sgl/SkPathMeasure.cpp \ + sgl/SkProcSpriteBlitter.cpp \ + sgl/SkRasterizer.cpp \ + sgl/SkRefCnt.cpp \ + sgl/SkRegion_path.cpp \ + sgl/SkScalerContext.cpp \ + sgl/SkScan.cpp \ + sgl/SkScan_AntiPath.cpp \ + sgl/SkScan_Antihair.cpp \ + sgl/SkScan_Hairline.cpp \ + sgl/SkScan_Path.cpp \ + sgl/SkShader.cpp \ + sgl/SkSpriteBlitter_ARGB32.cpp \ + sgl/SkSpriteBlitter_RGB16.cpp \ + sgl/SkString.cpp \ + sgl/SkStroke.cpp \ + sgl/SkStrokerPriv.cpp \ + sgl/SkTSearch.cpp \ + sgl/SkTextLayout.cpp \ + sgl/SkUtils.cpp \ + sgl/SkXfermode.cpp \ + views/SkEvent.cpp \ + views/SkEventSink.cpp \ + views/SkMetaData.cpp \ + views/SkTagList.cpp \ + views/SkTextBox.cpp \ + ports/SkImageDecoder_Factory.cpp \ + ports/SkFontHost.cpp \ + ports/SkFontHost_FreeType.cpp \ + ports/SkGlobals_global.cpp \ + ports/SkOSFile_stdio.cpp \ + ports/SkOSEvent_android.cpp \ + ports/SkTime_Unix.cpp \ + ports/SkXMLParser_expat.cpp \ + xml/SkDOM.cpp \ + xml/SkXMLParser.cpp \ + xml/SkXMLWriter.cpp \ + xml/SkParseColor.cpp \ + xml/SkParse.cpp + +LOCAL_SHARED_LIBRARIES := \ + libutils \ + libcorecg \ + libpng \ + libgif \ + libjpeg \ + libft2 \ + libexpat \ + libz + +LOCAL_C_INCLUDES += \ + $(LOCAL_PATH)/animator \ + $(LOCAL_PATH)/sgl \ + $(LOCAL_PATH)/images \ + $(LOCAL_PATH)/ports \ + include/graphics \ + include/corecg \ + libs/corecg \ + extlibs/freetype-2.1.10/include \ + extlibs/zlib-1.2.3 \ + extlibs/libpng-1.2.8 \ + extlibs/libgif-4.0 \ + extlibs/jpeg-6b \ + extlibs/expat-2.0.0/lib + +ifeq ($(DEVICE_OS),darwin) + LOCAL_CFLAGS += -fPIC +else + LOCAL_CFLAGS += -fpic +endif + +ifeq ($(DEVICE_ARCH),arm) + LOCAL_CFLAGS += -DFMS_ARCH_ANDROID_ARM +endif + +# TODO RELEASE_BUILD isn't right +ifeq ($(RELEASE_BUILD),true) + LOCAL_CFLAGS += -O2 +endif + +LOCAL_LDLIBS += -lpthread + +LOCAL_TARGET:= libsgl + +include $(BUILD_SHARED_LIBRARY) diff --git a/libs/graphics/animator/SkAnimate.h b/libs/graphics/animator/SkAnimate.h new file mode 100644 index 000000000..aa593bfe6 --- /dev/null +++ b/libs/graphics/animator/SkAnimate.h @@ -0,0 +1,26 @@ +#ifndef SkAnimate_DEFINED +#define SkAnimate_DEFINED + +#include "SkAnimateBase.h" +#include "SkDisplayType.h" +#include "SkIntArray.h" +#include "SkUtils.h" + +class SkAnimate : public SkAnimateBase { + DECLARE_MEMBER_INFO(Animate); + SkAnimate(); + virtual ~SkAnimate(); + virtual int components(); +#ifdef SK_DUMP_ENABLED + virtual void dump(SkAnimateMaker* ); +#endif + virtual void onEndElement(SkAnimateMaker& maker); +protected: + bool resolveCommon(SkAnimateMaker& ); + int fComponents; +private: + typedef SkAnimateBase INHERITED; +}; + +#endif // SkAnimateField_DEFINED + diff --git a/libs/graphics/animator/SkAnimate3DSchema.xsd b/libs/graphics/animator/SkAnimate3DSchema.xsd new file mode 100644 index 000000000..5063b7572 --- /dev/null +++ b/libs/graphics/animator/SkAnimate3DSchema.xsd @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/graphics/animator/SkAnimate3DSchema.xsx b/libs/graphics/animator/SkAnimate3DSchema.xsx new file mode 100644 index 000000000..ceb7d890c --- /dev/null +++ b/libs/graphics/animator/SkAnimate3DSchema.xsx @@ -0,0 +1,3 @@ + + + diff --git a/libs/graphics/animator/SkAnimateActive.cpp b/libs/graphics/animator/SkAnimateActive.cpp new file mode 100644 index 000000000..85f676f3c --- /dev/null +++ b/libs/graphics/animator/SkAnimateActive.cpp @@ -0,0 +1,492 @@ +#include "SkAnimateActive.h" +#include "SkAnimateBase.h" +#include "SkAnimateMaker.h" +#include "SkAnimateSet.h" +#include "SkDrawGroup.h" +#ifdef SK_DEBUG +#include "SkTime.h" +#endif + +// SkActive holds array of interpolators + +SkActive::SkActive(SkApply& apply, SkAnimateMaker& maker) : fApply(apply), + fMaxTime(0), fMaker(maker), fDrawIndex(0), fDrawMax(0) { +} + +void SkActive::init() +{ + fAnimators = fApply.fAnimators; + int animators = fAnimators.count(); + fInterpolators.setCount(animators); + memset(fInterpolators.begin(), 0, animators * sizeof(SkOperandInterpolator*)); + fState.setCount(animators); + int index; + for (index = 0; index < animators; index++) + fInterpolators[index] = SkNEW(SkOperandInterpolator); + initState(&fApply, 0); +// for (index = 0; index < animators; index++) +// fState[index].bumpSave(); + SkASSERT(fInterpolators.count() == fAnimators.count()); +} + +SkActive::~SkActive() { + int index; + for (index = 0; index < fSaveRestore.count(); index++) + delete[] fSaveRestore[index]; + for (index = 0; index < fSaveInterpolators.count(); index++) + delete[] fSaveInterpolators[index]; + for (index = 0; index < fInterpolators.count(); index++) + delete fInterpolators[index]; +} + +void SkActive::advance() { + if (fDrawMax < fDrawIndex) + fDrawMax = fDrawIndex; + fDrawIndex += fAnimators.count(); +} + +void SkActive::append(SkApply* apply) { + int oldCount = fAnimators.count(); + SkTDAnimateArray& animates = apply->fAnimators; + int newCount = animates.count(); + int index; + int total = oldCount + newCount; + if (total == 0) + return; + fInterpolators.setCount(total); + memset(&fInterpolators.begin()[oldCount], 0, newCount * sizeof(SkOperandInterpolator*)); + for (index = oldCount; index < total; index++) + fInterpolators[index] = SkNEW(SkOperandInterpolator); + fAnimators.setCount(total); + memcpy(&fAnimators[oldCount], animates.begin(), sizeof(fAnimators[0]) * + newCount); + fState.setCount(total); + initState(apply, oldCount); + SkASSERT(fApply.scope == apply->scope); + for (index = 0; index < newCount; index++) { + SkAnimateBase* test = animates[index]; +// SkASSERT(fApply.scope == test->fTarget || fApply.scope->contains(test->fTarget)); + SkActive::SkState& testState = fState[oldCount + index]; + for (int inner = 0; inner < oldCount; inner++) { + SkAnimateBase* oldGuard = fAnimators[inner]; + SkActive::SkState& oldState = fState[inner]; + if (oldGuard->fTarget == test->fTarget && oldGuard->fFieldInfo == test->fFieldInfo && + testState.fBegin == oldState.fBegin) { + delete fInterpolators[inner]; + fInterpolators.remove(inner); + fAnimators.remove(inner); + testState.fSave = oldState.fSave; + if (oldState.fUnpostedEndEvent) { +// SkDEBUGF(("%8x %8x active append: post on end\n", this, oldGuard)); + fMaker.postOnEnd(oldGuard, oldState.fBegin + oldState.fDuration); + } + fState.remove(inner); + if (fApply.restore) { + int saveIndex = fSaveRestore.count(); + SkASSERT(fSaveInterpolators.count() == saveIndex); + saveIndex += inner; + do { + saveIndex -= oldCount; + delete[] fSaveRestore[saveIndex]; + fSaveRestore.remove(saveIndex); + delete[] fSaveInterpolators[saveIndex]; + fSaveInterpolators.remove(saveIndex); + } while (saveIndex > 0); + } + oldCount--; + break; + } + } + } +// total = oldCount + newCount; +// for (index = oldCount; index < total; index++) +// fState[index].bumpSave(); + SkASSERT(fInterpolators.count() == fAnimators.count()); +} + +void SkActive::appendSave(int oldCount) { + SkASSERT(fDrawMax == 0); // if true, we can optimize below quite a bit + int newCount = fAnimators.count(); + int saveIndex = fSaveRestore.count(); + SkASSERT(fSaveInterpolators.count() == saveIndex); + int records = saveIndex / oldCount; + int newTotal = records * newCount; + fSaveRestore.setCount(newTotal); + do { + saveIndex -= oldCount; + newTotal -= newCount; + SkASSERT(saveIndex >= 0); + SkASSERT(newTotal >= 0); + memmove(&fSaveRestore[newTotal], &fSaveRestore[saveIndex], oldCount); + memset(&fSaveRestore[newTotal + oldCount], 0, + sizeof(fSaveRestore[0]) * (newCount - oldCount)); + memmove(&fSaveInterpolators[newTotal], + &fSaveInterpolators[saveIndex], oldCount); + memset(&fSaveInterpolators[newTotal + oldCount], 0, + sizeof(fSaveRestore[0]) * (newCount - oldCount)); + } while (saveIndex > 0); + SkASSERT(newTotal == 0); +} + +void SkActive::calcDurations(int index) +{ + SkAnimateBase* animate = fAnimators[index]; + SkMSec duration = animate->dur; + SkState& state = fState[index]; + if (state.fMode == SkApply::kMode_immediate || state.fMode == SkApply::kMode_create) + duration = state.fSteps ? state.fSteps * SK_MSec1 : 1; +// else if (state.fMode == SkApply::kMode_hold) { +// int entries = animate->entries(); +// SkScriptValue value; +// value.fOperand = animate->getValues()[entries - 1]; +// value.fType = animate->getValuesType(); +// bool result = SkScriptEngine::ConvertTo(nil, SkType_Int, &value); +// SkASSERT(result); +// duration = value.fOperand.fS32 * SK_MSec1; +// } + state.fDuration = duration; + SkMSec maxTime = state.fBegin + duration; + if (fMaxTime < maxTime) + fMaxTime = maxTime; +} + +void SkActive::create(SkDrawable* drawable, SkMSec time) { + fApply.fLastTime = time; + fApply.refresh(fMaker); + for (int index = 0; index < fAnimators.count(); index++) { + SkAnimateBase* animate = fAnimators[index]; + SkOperandInterpolator& interpolator = *fInterpolators[index]; + int count = animate->components(); + if (animate->formula.size() > 0) { + SkTDOperandArray values; + values.setCount(count); + bool success = animate->fFieldInfo->setValue(fMaker, &values, 0, 0, nil, + animate->getValuesType(), animate->formula); + SkASSERT(success); + fApply.applyValues(index, values.begin(), count, animate->getValuesType(), time); + } else { + SkAutoSTMalloc<16, SkOperand> values(count); + interpolator.timeToValues(time, values.get()); + fApply.applyValues(index, values.get(), count, animate->getValuesType(), time); + } + } + drawable->enable(fMaker); + SkASSERT(fAnimators.count() == fInterpolators.count()); +} + +bool SkActive::immediate(bool enable) { + SkMSec time = 0; + bool result = false; + SkDrawable* drawable = fApply.scope; + SkMSec final = fMaxTime; + do { + bool applied = fAnimators.count() == 0; + fApply.fLastTime = time; + fApply.refresh(fMaker); + for (int index = 0; index < fAnimators.count(); index++) { + SkAnimateBase* animate = fAnimators[index]; + SkState& state = fState[index]; + if (state.fMode != SkApply::kMode_immediate) + continue; + if (state.fBegin > time) + continue; + if (time > state.fBegin + state.fDuration) + continue; + applied = true; + SkOperandInterpolator& interpolator = *fInterpolators[index]; + int count = animate->components(); + if (animate->formula.size() > 0) { + SkTDOperandArray values; + values.setCount(count); + bool success = animate->fFieldInfo->setValue(fMaker, &values, 0, 0, nil, + animate->getValuesType(), animate->formula); + SkASSERT(success); + fApply.applyValues(index, values.begin(), count, animate->getValuesType(), time); + } else { + SkAutoSTMalloc<16, SkOperand> values(count); + interpolator.timeToValues(time, values.get()); + fApply.applyValues(index, values.get(), count, animate->getValuesType(), time); + } + } + if (enable) + drawable->enable(fMaker); + else if (applied) + result |= drawable->draw(fMaker); + time += SK_MSec1; + } while (time <= final); + return result; +} + +void SkActive::fixInterpolator(SkBool save) { + int animators = fAnimators.count(); + for (int index = 0; index < animators; index++) { + SkAnimateBase* animate = fAnimators[index]; + if (save) { // saved slots increased + animate->refresh(fMaker); + SkOperand* values = animate->getValues(); + setInterpolator(index, values); + saveInterpolatorValues(index); + } else + restoreInterpolatorValues(index); + } +} + +SkMSec SkActive::getTime(SkMSec inTime, int animatorIndex) { + fState[animatorIndex].fTicks = inTime; + return inTime - fState[animatorIndex].fStartTime; +} + +bool SkActive::initializeSave() { + int animators = fAnimators.count(); + int activeTotal = fDrawIndex + animators; + int oldCount = fSaveRestore.count(); + if (oldCount < activeTotal) { + fSaveRestore.setCount(activeTotal); + memset(&fSaveRestore[oldCount], 0, sizeof(fSaveRestore[0]) * (activeTotal - oldCount)); + SkASSERT(fSaveInterpolators.count() == oldCount); + fSaveInterpolators.setCount(activeTotal); + memset(&fSaveInterpolators[oldCount], 0, + sizeof(fSaveInterpolators[0]) * (activeTotal - oldCount)); + return true; + } + return false; +} + +void SkActive::initState(SkApply* apply, int offset) { + int count = fState.count(); + for (int index = offset; index < count; index++) { + SkState& state = fState[index]; + SkAnimateBase* animate = fAnimators[index]; +#if 0 // def SK_DEBUG + if (animate->fHasEndEvent) + SkDebugf("%8x %8x active initState:\n", this, animate); +#endif + SkOperand* from = animate->getValues(); + state.fStartTime = state.fBegin = apply->begin + animate->begin; + state.fMode = apply->mode; + state.fTransition = apply->transition; +#if 0 + state.fPickup = (SkBool8) apply->pickup; +#endif + state.fRestore = (SkBool8) apply->restore; + state.fSave = apply->begin; + state.fStarted = false; + state.fSteps = apply->steps; + state.fTicks = 0; + state.fUnpostedEndEvent = (SkBool8) animate->fHasEndEvent; + calcDurations(index); + setInterpolator(index, from); + } + if (count == 0 && (apply->mode == SkApply::kMode_immediate || apply->mode == SkApply::kMode_create)) + fMaxTime = apply->begin + apply->steps * SK_MSec1; +} + +void SkActive::pickUp(SkActive* existing) { + SkTDOperandArray existingValues; + for (int index = 0; index < fAnimators.count(); index++) { + SkAnimateBase* animate = fAnimators[index]; + SkASSERT(animate->getValuesType() == SkType_Float); + int components = animate->components(); + SkOperand* from = animate->getValues(); + SkOperand* to = &from[animate->components()]; + existingValues.setCount(components); + existing->fInterpolators[index]->timeToValues( + existing->fState[index].fTicks - existing->fState[index].fStartTime, existingValues.begin()); + SkScalar originalSum = 0; + SkScalar workingSum = 0; + for (int cIndex = 0; cIndex < components; cIndex++) { + SkScalar delta = to[cIndex].fScalar - from[cIndex].fScalar; + originalSum += SkScalarMul(delta, delta); + delta = to[cIndex].fScalar - existingValues[cIndex].fScalar; + workingSum += SkScalarMul(delta, delta); + } + if (workingSum < originalSum) { + SkScalar originalDistance = SkScalarSqrt(originalSum); + SkScalar workingDistance = SkScalarSqrt(workingSum); + existing->fState[index].fDuration = (SkMSec) SkScalarMulDiv(fState[index].fDuration, + workingDistance, originalDistance); + } + fInterpolators[index]->reset(components, 2, SkType_Float); + fInterpolators[index]->setKeyFrame(0, 0, existingValues.begin(), animate->blend[0]); + fInterpolators[index]->setKeyFrame(1, fState[index].fDuration, to, animate->blend[0]); + } +} + +void SkActive::resetInterpolators() { + int animators = fAnimators.count(); + for (int index = 0; index < animators; index++) { + SkAnimateBase* animate = fAnimators[index]; + SkOperand* values = animate->getValues(); + setInterpolator(index, values); + } +} + +void SkActive::resetState() { + fDrawIndex = 0; + int count = fState.count(); + for (int index = 0; index < count; index++) { + SkState& state = fState[index]; + SkAnimateBase* animate = fAnimators[index]; +#if 0 // def SK_DEBUG + if (animate->fHasEndEvent) + SkDebugf("%8x %8x active resetState: has end event\n", this, animate); +#endif + state.fStartTime = state.fBegin = fApply.begin + animate->begin; + state.fStarted = false; + state.fTicks = 0; + } +} + +void SkActive::restoreInterpolatorValues(int index) { + SkOperandInterpolator& interpolator = *fInterpolators[index]; + index += fDrawIndex ; + int count = interpolator.getValuesCount(); + memcpy(interpolator.getValues(), fSaveInterpolators[index], count * sizeof(SkOperand)); +} + +void SkActive::saveInterpolatorValues(int index) { + SkOperandInterpolator& interpolator = *fInterpolators[index]; + index += fDrawIndex ; + int count = interpolator.getValuesCount(); + SkOperand* cache = new SkOperand[count]; // this should use sk_malloc/sk_free since SkOperand does not have a constructor/destructor + fSaveInterpolators[index] = cache; + memcpy(cache, interpolator.getValues(), count * sizeof(SkOperand)); +} + +void SkActive::setInterpolator(int index, SkOperand* from) { + if (from == nil) // legitimate for set string + return; + SkAnimateBase* animate = fAnimators[index]; + int entries = animate->entries(); + SkASSERT(entries > 0); + SkMSec duration = fState[index].fDuration; + int components = animate->components(); + SkOperandInterpolator& interpolator = *fInterpolators[index]; + interpolator.reset(components, entries == 1 ? 2 : entries, animate->getValuesType()); + interpolator.setMirror(SkToBool(animate->fMirror)); + interpolator.setReset(SkToBool(animate->fReset)); + interpolator.setRepeatCount(animate->repeat); + if (entries == 1) { + interpolator.setKeyFrame(0, 0, from, animate->blend[0]); + interpolator.setKeyFrame(1, duration, from, animate->blend[0]); + return; + } + for (int entry = 0; entry < entries; entry++) { + int blendIndex = SkMin32(animate->blend.count() - 1, entry); + interpolator.setKeyFrame(entry, entry * duration / (entries - 1), from, + animate->blend[blendIndex]); + from += components; + } +} + +void SkActive::setSteps(int steps) { + int count = fState.count(); + fMaxTime = 0; + for (int index = 0; index < count; index++) { + SkState& state = fState[index]; + state.fSteps = steps; + calcDurations(index); + } +} + +void SkActive::start() { + int count = fState.count(); + SkASSERT(count == fAnimators.count()); + SkASSERT(count == fInterpolators.count()); + for (int index = 0; index < count; index++) { + SkState& state = fState[index]; + if (state.fStarted) + continue; + state.fStarted = true; +#if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING + SkString debugOut; + SkMSec time = fMaker.getAppTime(); + debugOut.appendS32(time - fMaker.fDebugTimeBase); + debugOut.append(" active start adjust delay id="); + debugOut.append(fApply._id); + debugOut.append("; "); + debugOut.append(fAnimators[index]->_id); + debugOut.append("="); + debugOut.appendS32(fAnimators[index]->fStart - fMaker.fDebugTimeBase); + debugOut.append(":"); + debugOut.appendS32(state.fStartTime); +#endif + if (state.fStartTime > 0) { + SkMSec future = fAnimators[index]->fStart + state.fStartTime; + if (future > fMaker.fEnableTime) + fMaker.notifyInvalTime(future); + else + fMaker.notifyInval(); +#if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING + debugOut.append(":"); + debugOut.appendS32(future - fMaker.fDebugTimeBase); +#endif + } + if (state.fStartTime >= fMaker.fAdjustedStart) { + state.fStartTime -= fMaker.fAdjustedStart; +#if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING + debugOut.append(" (less adjust = "); + debugOut.appendS32(fMaker.fAdjustedStart); +#endif + } + state.fStartTime += fAnimators[index]->fStart; +#if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING + debugOut.append(") new start = "); + debugOut.appendS32(state.fStartTime - fMaker.fDebugTimeBase); + SkDebugf("%s\n", debugOut.c_str()); +// SkASSERT((int) (state.fStartTime - fMaker.fDebugTimeBase) >= 0); +#endif + } + SkASSERT(fAnimators.count() == fInterpolators.count()); +} + +#ifdef SK_DEBUG +void SkActive::validate() { + int count = fState.count(); + SkASSERT(count == fAnimators.count()); + SkASSERT(count == fInterpolators.count()); + for (int index = 0; index < count; index++) { + SkASSERT(fAnimators[index]); + SkASSERT(fInterpolators[index]); +// SkAnimateBase* test = fAnimators[index]; +// SkASSERT(fApply.scope == test->fTarget || fApply.scope->contains(test->fTarget)); + } +} +#endif + +// think about this +// there should only be one animate object, not two, to go up and down +// when the apply with reverse came into play, it needs to pick up the value +// of the existing animate object then remove it from the list +// the code below should only be bumping fSave, and there shouldn't be anything +// it needs to be synchronized with + +// however, if there are two animates both operating on the same field, then +// when one replaces the other, it may make sense to pick up the old value as a starting +// value for the new one somehow. + +//void SkActive::SkState::bumpSave() { +// if (fMode != SkApply::kMode_hold) +// return; +// if (fTransition == SkApply::kTransition_reverse) { +// if (fSave > 0) +// fSave -= SK_MSec1; +// } else if (fSave < fDuration) +// fSave += SK_MSec1; +//} + +SkMSec SkActive::SkState::getRelativeTime(SkMSec time) { + SkMSec result = time; +// if (fMode == SkApply::kMode_hold) +// result = fSave; +// else + if (fTransition == SkApply::kTransition_reverse) { + if (SkMSec_LT(fDuration, time)) + result = 0; + else + result = fDuration - time; + } + return result; +} + + diff --git a/libs/graphics/animator/SkAnimateActive.h b/libs/graphics/animator/SkAnimateActive.h new file mode 100644 index 000000000..3bdf9330d --- /dev/null +++ b/libs/graphics/animator/SkAnimateActive.h @@ -0,0 +1,70 @@ +#ifndef SkAnimateActive_DEFINED +#define SkAnimateActive_DEFINED + +#include "SkDisplayApply.h" +#include "SkOperandInterpolator.h" +#include "SkIntArray.h" + +class SkAnimateMaker; + +class SkActive { +public: + SkActive(SkApply& , SkAnimateMaker& ); + ~SkActive(); + void advance(); + void append(SkApply* ); + void calcDurations(int index); + void create(SkDrawable* scope, SkMSec time); + bool draw() { return immediate(false); } + bool enable() { return immediate(true); } + void init( ); + SkMSec getTime(SkMSec inTime, int animatorIndex); + void pickUp(SkActive* existing); + void reset() { fDrawIndex = 0; } + void setInterpolator(int index, SkOperand* from); + void start(); +#ifdef SK_DEBUG + void validate(); +#endif +private: + void appendSave(int oldCount); + void fixInterpolator(SkBool save); + bool immediate(bool enable); + bool initializeSave(); + void initState(SkApply* , int offset); + void resetInterpolators(); + void resetState(); + void restoreInterpolatorValues(int index); + void saveInterpolatorValues(int index); + void setSteps(int steps); + struct SkState { +// void bumpSave(); + SkMSec getRelativeTime(SkMSec time); + SkApply::Mode fMode; + SkApply::Transition fTransition; + SkBool8 fPickup; + SkBool8 fRestore; + SkBool8 fStarted; + SkBool8 fUnpostedEndEvent; + S32 fSteps; + SkMSec fBegin; + SkMSec fStartTime; + SkMSec fDuration; + SkMSec fSave; + SkMSec fTicks; + }; + SkActive& operator= (const SkActive& ); + SkTDArray fInterpolators; + SkApply& fApply; + SkTDArray fState; // one per animator + SkTDOperandPtrArray fSaveRestore; // if apply has restore="true" + SkTDOperandPtrArray fSaveInterpolators; + SkTDAnimateArray fAnimators; + SkMSec fMaxTime; // greatest of all animation durations; only used by immediate mode + SkAnimateMaker& fMaker; + int fDrawIndex; + int fDrawMax; + friend class SkApply; +}; + +#endif // SkAnimateActive_DEFINED diff --git a/libs/graphics/animator/SkAnimateBase.cpp b/libs/graphics/animator/SkAnimateBase.cpp new file mode 100644 index 000000000..fd3bd67a4 --- /dev/null +++ b/libs/graphics/animator/SkAnimateBase.cpp @@ -0,0 +1,230 @@ +#include "SkAnimateBase.h" +#include "SkAnimateMaker.h" +#include "SkAnimateProperties.h" +#include "SkAnimatorScript.h" +#include "SkDisplayApply.h" +#include "SkDrawable.h" + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkAnimateBase::fInfo[] = { + SK_MEMBER(begin, MSec), + SK_MEMBER_ARRAY(blend, Float), + SK_MEMBER(dur, MSec), + SK_MEMBER_PROPERTY(dynamic, Boolean), + SK_MEMBER(field, String), // name of member info in target + SK_MEMBER(formula, DynamicString), + SK_MEMBER(from, DynamicString), + SK_MEMBER(lval, DynamicString), + SK_MEMBER_PROPERTY(mirror, Boolean), + SK_MEMBER(repeat, Float), + SK_MEMBER_PROPERTY(reset, Boolean), + SK_MEMBER_PROPERTY(step, Int), + SK_MEMBER(target, DynamicString), + SK_MEMBER(to, DynamicString), + SK_MEMBER_PROPERTY(values, DynamicString) +}; + +#endif + +DEFINE_GET_MEMBER(SkAnimateBase); + +SkAnimateBase::SkAnimateBase() : begin(0), dur(1), repeat(SK_Scalar1), + fApply(nil), fFieldInfo(nil), fFieldOffset(0), fStart((SkMSec) -1), fTarget(nil), + fChanged(0), fDelayed(0), fDynamic(0), fHasEndEvent(0), fHasValues(0), + fMirror(0), fReset(0), fResetPending(0), fTargetIsScope(0) { + blend.setCount(1); + blend[0] = SK_Scalar1; +} + +SkAnimateBase::~SkAnimateBase() { + SkDisplayTypes type = fValues.getType(); + if (type == SkType_String || type == SkType_DynamicString) { + SkASSERT(fValues.count() == 1); + delete fValues[0].fString; + } +} + +int SkAnimateBase::components() { + return 1; +} + +SkDisplayable* SkAnimateBase::deepCopy(SkAnimateMaker* maker) { + SkAnimateBase* result = (SkAnimateBase*) INHERITED::deepCopy(maker); + result->fApply = fApply; + result->fFieldInfo =fFieldInfo; + result->fHasValues = false; + return result; +} + +void SkAnimateBase::dirty() { + fChanged = true; +} + +#ifdef SK_DUMP_ENABLED +void SkAnimateBase::dump(SkAnimateMaker* maker) { + dumpBase(maker); + if (target.size() > 0) + SkDebugf("target=\"%s\" ", target.c_str()); + else if (fTarget && strcmp(fTarget->id, "")) + SkDebugf("target=\"%s\" ", fTarget->id); + if (lval.size() > 0) + SkDebugf("lval=\"%s\" ", lval.c_str()); + if (field.size() > 0) + SkDebugf("field=\"%s\" ", field.c_str()); + else if (fFieldInfo) + SkDebugf("field=\"%s\" ", fFieldInfo->fName); + if (formula.size() > 0) + SkDebugf("formula=\"%s\" ", formula.c_str()); + else { + if (from.size() > 0) + SkDebugf("from=\"%s\" ", from.c_str()); + SkDebugf("to=\"%s\" ", to.c_str()); + } + if (begin != 0) { +#ifdef SK_CAN_USE_FLOAT + SkDebugf("begin=\"%g\" ", SkScalarToFloat(SkScalarDiv(begin,1000))); +#else + SkDebugf("begin=\"%x\" ", SkScalarDiv(begin,1000)); +#endif + } +} +#endif + +SkDisplayable* SkAnimateBase::getParent() const { + return (SkDisplayable*) fApply; +} + +bool SkAnimateBase::getProperty(int index, SkScriptValue* value) const { + int boolResult; + switch (index) { + case SK_PROPERTY(dynamic): + boolResult = fDynamic; + goto returnBool; + case SK_PROPERTY(mirror): + boolResult = fMirror; + goto returnBool; + case SK_PROPERTY(reset): + boolResult = fReset; +returnBool: + value->fOperand.fS32 = SkToBool(boolResult); + value->fType = SkType_Boolean; + break; + case SK_PROPERTY(step): + if (fApply == nil) + return false; // !!! notify there's an error? + fApply->getStep(value); + break; + case SK_PROPERTY(values): + value->fOperand.fString = (SkString*) &to; + value->fType = SkType_String; + break; + default: + SkASSERT(0); + return false; + } + return true; +} + +bool SkAnimateBase::hasExecute() const +{ + return false; +} + +void SkAnimateBase::onEndElement(SkAnimateMaker& maker) { + fChanged = false; + setTarget(maker); + if (field.size()) { + SkASSERT(fTarget); + fFieldInfo = fTarget->getMember(field.c_str()); + field.reset(); + } + if (lval.size()) { + // lval must be of the form x[y] + const char* lvalStr = lval.c_str(); + const char* arrayEnd = strchr(lvalStr, '['); + if (arrayEnd == nil) + return; //should this return an error? + size_t arrayNameLen = arrayEnd - lvalStr; + SkString arrayStr(lvalStr, arrayNameLen); + SkASSERT(fTarget); //this return an error? + fFieldInfo = fTarget->getMember(arrayStr.c_str()); + SkString scriptStr(arrayEnd + 1, lval.size() - arrayNameLen - 2); + SkAnimatorScript::EvaluateInt(maker, this, scriptStr.c_str(), &fFieldOffset); + } +} + +void SkAnimateBase::packARGB(SkScalar array[], int count, SkTDOperandArray* converted) +{ + SkASSERT(count == 4); + converted->setCount(1); + SkColor color = SkColorSetARGB(SkScalarRound(array[0]), SkScalarRound(array[1]), + SkScalarRound(array[2]), SkScalarRound(array[3])); + (*converted)[0].fS32 = color; +} + + + +void SkAnimateBase::refresh(SkAnimateMaker& ) { +} + +bool SkAnimateBase::setParent(SkDisplayable* apply) { + SkASSERT(apply->isApply()); + fApply = (SkApply*) apply; + return false; +} + +bool SkAnimateBase::setProperty(int index, SkScriptValue& value) { + bool boolValue = SkToBool(value.fOperand.fS32); + switch (index) { + case SK_PROPERTY(dynamic): + fDynamic = boolValue; + goto checkForBool; + case SK_PROPERTY(values): + fHasValues = true; + SkASSERT(value.fType == SkType_String); + to = *value.fOperand.fString; + break; + case SK_PROPERTY(mirror): + fMirror = boolValue; + goto checkForBool; + case SK_PROPERTY(reset): + fReset = boolValue; +checkForBool: + SkASSERT(value.fType == SkType_Boolean); + break; + default: + return false; + } + return true; +} + +void SkAnimateBase::setTarget(SkAnimateMaker& maker) { + if (target.size()) { + SkAnimatorScript engine(maker, this, SkType_Displayable); + const char* script = target.c_str(); + SkScriptValue scriptValue; + bool success = engine.evaluateScript(&script, &scriptValue); + if (success && scriptValue.fType == SkType_Displayable) + fTarget = scriptValue.fOperand.fDrawable; + else if (maker.find(target.c_str(), (SkDisplayable**) &fTarget) == false) { + if (fApply->getMode() == SkApply::kMode_create) + return; // may not be an error + if (engine.getError() != SkScriptEngine::kNoError) + maker.setScriptError(engine); + else { + maker.setErrorNoun(target); + maker.setErrorCode(SkDisplayXMLParserError::kTargetIDNotFound); + } + return; + } + if (fApply && fApply->getMode() != SkApply::kMode_create) + target.reset(); + } +} + +bool SkAnimateBase::targetNeedsInitialization() const { + return false; +} + + diff --git a/libs/graphics/animator/SkAnimateBase.h b/libs/graphics/animator/SkAnimateBase.h new file mode 100644 index 000000000..510b59362 --- /dev/null +++ b/libs/graphics/animator/SkAnimateBase.h @@ -0,0 +1,74 @@ +#ifndef SkAnimateBase_DEFINED +#define SkAnimateBase_DEFINED + +#include "SkDisplayable.h" +#include "SkMath.h" +#include "SkMemberInfo.h" +#include "SkTypedArray.h" + +class SkApply; +class SkDrawable; + +class SkAnimateBase : public SkDisplayable { +public: + DECLARE_MEMBER_INFO(AnimateBase); + SkAnimateBase(); + virtual ~SkAnimateBase(); + virtual int components(); + virtual SkDisplayable* deepCopy(SkAnimateMaker* ); + virtual void dirty(); +#ifdef SK_DUMP_ENABLED + virtual void dump(SkAnimateMaker* ); +#endif + int entries() { return fValues.count() / components(); } + virtual bool hasExecute() const; + bool isDynamic() const { return SkToBool(fDynamic); } + virtual SkDisplayable* getParent() const; + virtual bool getProperty(int index, SkScriptValue* value) const; + SkMSec getStart() const { return fStart; } + SkOperand* getValues() { return fValues.begin(); } + SkDisplayTypes getValuesType() { return fValues.getType(); } + virtual void onEndElement(SkAnimateMaker& ); + void packARGB(SkScalar [], int count, SkTDOperandArray* ); + virtual void refresh(SkAnimateMaker& ); + void setChanged(bool changed) { fChanged = changed; } + void setHasEndEvent() { fHasEndEvent = true; } + virtual bool setParent(SkDisplayable* ); + virtual bool setProperty(int index, SkScriptValue& value); + void setTarget(SkAnimateMaker& ); + virtual bool targetNeedsInitialization() const; +protected: + SkMSec begin; + SkTDScalarArray blend; + SkMSec dur; + // !!! make field part of a union with fFieldInfo, or fValues, something known later? + SkString field; // temporary; once target is known, this is reset + SkString formula; + SkString from; + SkString lval; + SkScalar repeat; + SkString target; // temporary; once target is known, this is reset + SkString to; + SkApply* fApply; + const SkMemberInfo* fFieldInfo; + int fFieldOffset; + SkMSec fStart; // corrected time when this apply was enabled + SkDrawable* fTarget; + SkTypedArray fValues; + unsigned fChanged : 1; // true when value referenced by script has changed + unsigned fDelayed : 1; // enabled, but undrawn pending delay + unsigned fDynamic : 1; + unsigned fHasEndEvent : 1; + unsigned fHasValues : 1; // set if 'values' passed instead of 'to' + unsigned fMirror : 1; + unsigned fReset : 1; + unsigned fResetPending : 1; + unsigned fTargetIsScope : 1; +private: + typedef SkDisplayable INHERITED; + friend class SkActive; + friend class SkApply; + friend class SkDisplayList; +}; + +#endif // SkAnimateBase_DEFINED diff --git a/libs/graphics/animator/SkAnimateField.cpp b/libs/graphics/animator/SkAnimateField.cpp new file mode 100644 index 000000000..b2b63555c --- /dev/null +++ b/libs/graphics/animator/SkAnimateField.cpp @@ -0,0 +1,113 @@ +#include "SkAnimate.h" +#include "SkAnimateMaker.h" +#include "SkDrawable.h" +#include "SkParse.h" + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkAnimate::fInfo[] = { + SK_MEMBER_INHERITED +}; + +#endif + +DEFINE_GET_MEMBER(SkAnimate); + +SkAnimate::SkAnimate() : fComponents(0) { +} + +SkAnimate::~SkAnimate() { +} + +int SkAnimate::components() { + return fComponents; +} + +#ifdef SK_DUMP_ENABLED +void SkAnimate::dump(SkAnimateMaker* maker) { + INHERITED::dump(maker); //from animateBase + //SkSet inherits from this class + if (getType() != SkType_Set) { + if (fMirror) + SkDebugf("mirror=\"true\" "); + if (fReset) + SkDebugf("reset=\"true\" "); +#ifdef SK_CAN_USE_FLOAT + SkDebugf("dur=\"%g\" ", SkScalarToFloat(SkScalarDiv(dur,1000))); + if (repeat != SK_Scalar1) + SkDebugf("repeat=\"%g\" ", SkScalarToFloat(repeat)); +#else + SkDebugf("dur=\"%x\" ", SkScalarDiv(dur,1000)); + if (repeat != SK_Scalar1) + SkDebugf("repeat=\"%x\" ", repeat); +#endif + //if (fHasValues) + // SkDebugf("values=\"%s\" ", values); + if (blend.count() != 1 || blend[0] != SK_Scalar1) { + SkDebugf("blend=\"["); + bool firstElem = true; + for (int i = 0; i < blend.count(); i++) { + if (!firstElem) + SkDebugf(","); + firstElem = false; +#ifdef SK_CAN_USE_FLOAT + SkDebugf("%g", SkScalarToFloat(blend[i])); +#else + SkDebugf("%x", blend[i]); +#endif + } + SkDebugf("]\" "); + } + SkDebugf("/>\n");//i assume that if it IS, we will do it separately + } +} +#endif + +bool SkAnimate::resolveCommon(SkAnimateMaker& maker) { + if (fTarget == nil) // if nil, recall onEndElement after apply closes and sets target to scope + return false; + INHERITED::onEndElement(maker); + return maker.hasError() == false; +} + +void SkAnimate::onEndElement(SkAnimateMaker& maker) { + bool resolved = resolveCommon(maker); + if (resolved && fFieldInfo == nil) { + maker.setErrorNoun(field); + maker.setErrorCode(SkDisplayXMLParserError::kFieldNotInTarget); + } + if (resolved == false || fFieldInfo == nil) + return; + SkDisplayTypes outType = fFieldInfo->getType(); + if (fHasValues) { + SkASSERT(to.size() > 0); + fFieldInfo->setValue(maker, &fValues, 0, 0, nil, outType, to); + SkASSERT(0); + // !!! this needs to set fComponents + return; + } + fComponents = fFieldInfo->getCount(); + if (fFieldInfo->fType == SkType_Array) { + SkTypedArray* array = (SkTypedArray*) fFieldInfo->memberData(fTarget); + int count = array->count(); + if (count > 0) + fComponents = count; + } + if (outType == SkType_ARGB) { + fComponents <<= 2; // four color components + outType = SkType_Float; + } + fValues.setType(outType); + if (formula.size() > 0){ + fComponents = 1; + from.set("0"); + to.set("dur"); + outType = SkType_MSec; + } + int max = fComponents * 2; + fValues.setCount(max); + memset(fValues.begin(), 0, max * sizeof(fValues.begin()[0])); + fFieldInfo->setValue(maker, &fValues, fFieldOffset, max, this, outType, from); + fFieldInfo->setValue(maker, &fValues, fComponents + fFieldOffset, max, this, outType, to); +} + diff --git a/libs/graphics/animator/SkAnimateMaker.cpp b/libs/graphics/animator/SkAnimateMaker.cpp new file mode 100644 index 000000000..e66f7df47 --- /dev/null +++ b/libs/graphics/animator/SkAnimateMaker.cpp @@ -0,0 +1,356 @@ +#include "SkAnimateMaker.h" +#include "SkAnimator.h" +#include "SkAnimatorScript.h" +#include "SkDisplayable.h" +#include "SkDisplayApply.h" +#include "SkDisplayList.h" +#include "SkDisplayMovie.h" +#include "SkDisplayType.h" +#include "SkExtras.h" +#include "SkMemberInfo.h" +#include "SkStream.h" +#include "SkSystemEventTypes.h" +#include "SkTime.h" + +class DefaultTimeline : public SkAnimator::Timeline { + virtual SkMSec getMSecs() const { + return SkTime::GetMSecs(); + } +} gDefaultTimeline; + +SkAnimateMaker::SkAnimateMaker(SkAnimator* animator, SkCanvas* canvas, SkPaint* paint) + : fActiveEvent(NULL), fAdjustedStart(0), fCanvas(canvas), fEnableTime(0), + fHostEventSinkID(0), fMinimumInterval((SkMSec) -1), fPaint(paint), fParentMaker(NULL), + fTimeline(&gDefaultTimeline), fInInclude(false), fInMovie(false), + fFirstScriptError(false), fLoaded(false), fIDs(256), fAnimator(animator) +{ + fScreenplay.time = 0; +#if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING + fDebugTimeBase = (SkMSec) -1; +#endif +#ifdef SK_DUMP_ENABLED + fDumpEvents = fDumpGConditions = fDumpPosts = false; +#endif +} + +SkAnimateMaker::~SkAnimateMaker() { + deleteMembers(); +} + +#if 0 +SkMSec SkAnimateMaker::adjustDelay(SkMSec expectedBase, SkMSec delay) { + SkMSec appTime = (*fTimeCallBack)(); + if (appTime) + delay -= appTime - expectedBase; + if (delay < 0) + delay = 0; + return delay; +} +#endif + +void SkAnimateMaker::appendActive(SkActive* active) { + fDisplayList.append(active); +} + +void SkAnimateMaker::clearExtraPropertyCallBack(SkDisplayTypes type) { + SkExtras** end = fExtras.end(); + for (SkExtras** extraPtr = fExtras.begin(); extraPtr < end; extraPtr++) { + SkExtras* extra = *extraPtr; + if (extra->definesType(type)) { + extra->fExtraCallBack = NULL; + extra->fExtraStorage = NULL; + break; + } + } +} + +bool SkAnimateMaker::computeID(SkDisplayable* displayable, SkDisplayable* parent, SkString* newID) { + const char* script; + if (findKey(displayable, &script) == false) + return true; + return SkAnimatorScript::EvaluateString(*this, displayable, parent, script, newID); +} + +SkDisplayable* SkAnimateMaker::createInstance(const char name[], size_t len) { + SkDisplayTypes type = SkDisplayType::GetType(this, name, len ); + if ((int)type >= 0) + return SkDisplayType::CreateInstance(this, type); + return NULL; +} + +// differs from SkAnimator::decodeStream in that it does not reset error state +bool SkAnimateMaker::decodeStream(SkStream* stream) +{ + SkDisplayXMLParser parser(*this); + return parser.parse(*stream); +} + +// differs from SkAnimator::decodeURI in that it does not set URI base +bool SkAnimateMaker::decodeURI(const char uri[]) { +// SkDebugf("animator decode %s\n", uri); + SkStream* stream = SkStream::GetURIStream(fPrefix.c_str(), uri); + SkAutoTDelete autoDel(stream); + bool success = decodeStream(stream); + if (hasError() && fError.hasNoun() == false) + fError.setNoun(uri); + return success; +} + +#if defined SK_DEBUG && 0 +//used for the if'd out section of deleteMembers +#include "SkTSearch.h" + +extern "C" { + int compare_disp(const void* a, const void* b) { + return *(const SkDisplayable**)a - *(const SkDisplayable**)b; + } +} +#endif + +void SkAnimateMaker::delayEnable(SkApply* apply, SkMSec time) { + int index = fDelayed.find(apply); + if (index < 0) + *fDelayed.append() = apply; + (new SkEvent(SK_EventType_Delay))->postTime(fAnimator->getSinkID(), time); +} + +void SkAnimateMaker::deleteMembers() { + int index; +#if defined SK_DEBUG && 0 + //this code checks to see if helpers are among the children, but it is not complete - + //it should check the children of the children + int result; + SkTDArray children(fChildren.begin(), fChildren.count()); + SkQSort(children.begin(), children.count(), sizeof(SkDisplayable*),compare_disp); + for (index = 0; index < fHelpers.count(); index++) { + SkDisplayable* helper = fHelpers[index]; + result = SkTSearch(children.begin(), children.count(), helper, sizeof(SkDisplayable*)); + SkASSERT(result < 0); + } +#endif + for (index = 0; index < fChildren.count(); index++) { + SkDisplayable* child = fChildren[index]; + delete child; + } + for (index = 0; index < fHelpers.count(); index++) { + SkDisplayable* helper = fHelpers[index]; + delete helper; + } + for (index = 0; index < fExtras.count(); index++) { + SkExtras* extras = fExtras[index]; + delete extras; + } +} + +void SkAnimateMaker::doDelayedEvent() { + fEnableTime = getAppTime(); + for (int index = 0; index < fDelayed.count(); ) { + SkDisplayable* child = fDelayed[index]; + SkASSERT(child->isApply()); + SkApply* apply = (SkApply*) child; + apply->interpolate(*this, fEnableTime); + if (apply->hasDelayedAnimator()) + index++; + else + fDelayed.remove(index); + } +} + +bool SkAnimateMaker::doEvent(const SkEvent& event) { + return (!fInMovie || fLoaded) && fAnimator->doEvent(event); +} + +#ifdef SK_DUMP_ENABLED +void SkAnimateMaker::dump(const char* match) { + SkTDict::Iter iter(fIDs); + const char* name; + SkDisplayable* result; + while ((name = iter.next(&result)) != NULL) { + if (strcmp(match,name) == 0) + result->dump(this); + } +} +#endif + +int SkAnimateMaker::dynamicProperty(SkString& nameStr, SkDisplayable** displayablePtr ) { + const char* name = nameStr.c_str(); + const char* dot = strchr(name, '.'); + SkASSERT(dot); + SkDisplayable* displayable; + if (find(name, dot - name, &displayable) == false) { + SkASSERT(0); + return 0; + } + const char* fieldName = dot + 1; + const SkMemberInfo* memberInfo = displayable->getMember(fieldName); + *displayablePtr = displayable; + return (int) memberInfo->fOffset; +} + +SkMSec SkAnimateMaker::getAppTime() const { + return fTimeline->getMSecs(); +} + +#ifdef SK_DEBUG +SkAnimator* SkAnimateMaker::getRoot() +{ + SkAnimateMaker* maker = this; + while (maker->fParentMaker) + maker = maker->fParentMaker; + return maker == this ? NULL : maker->fAnimator; +} +#endif + +void SkAnimateMaker::helperAdd(SkDisplayable* trackMe) { + SkASSERT(fHelpers.find(trackMe) < 0); + *fHelpers.append() = trackMe; +} + +void SkAnimateMaker::helperRemove(SkDisplayable* alreadyTracked) { + int helperIndex = fHelpers.find(alreadyTracked); + if (helperIndex >= 0) + fHelpers.remove(helperIndex); +} + +#if 0 +void SkAnimateMaker::loadMovies() { + for (SkDisplayable** dispPtr = fMovies.begin(); dispPtr < fMovies.end(); dispPtr++) { + SkDisplayable* displayable = *dispPtr; + SkASSERT(displayable->getType() == SkType_Movie); + SkDisplayMovie* movie = (SkDisplayMovie*) displayable; + SkAnimateMaker* movieMaker = movie->fMovie.fMaker; + movieMaker->fEvents.doEvent(*movieMaker, SkDisplayEvent::kOnload, NULL); + movieMaker->fEvents.removeEvent(SkDisplayEvent::kOnload, NULL); + movieMaker->loadMovies(); + } +} +#endif + +void SkAnimateMaker::notifyInval() { + if (fHostEventSinkID) + fAnimator->onEventPost(new SkEvent(SK_EventType_Inval), fHostEventSinkID); +} + +void SkAnimateMaker::notifyInvalTime(SkMSec time) { + if (fHostEventSinkID) + fAnimator->onEventPostTime(new SkEvent(SK_EventType_Inval), fHostEventSinkID, time); +} + +void SkAnimateMaker::postOnEnd(SkAnimateBase* animate, SkMSec end) { + SkEvent evt; + evt.setS32("time", animate->getStart() + end); + evt.setPtr("anim", animate); + evt.setType(SK_EventType_OnEnd); + SkEventSinkID sinkID = fAnimator->getSinkID(); + fAnimator->onEventPost(new SkEvent(evt), sinkID); +} + +void SkAnimateMaker::reset() { + deleteMembers(); + fChildren.reset(); + fHelpers.reset(); + fIDs.reset(); + fEvents.reset(); + fDisplayList.hardReset(); +} + +void SkAnimateMaker::removeActive(SkActive* active) { + if (active == NULL) + return; + fDisplayList.remove(active); +} + +bool SkAnimateMaker::resolveID(SkDisplayable* displayable, SkDisplayable* original) { + SkString newID; + bool success = computeID(original, NULL, &newID); + if (success) + setID(displayable, newID); + return success; +} + +void SkAnimateMaker::setErrorString() { + fErrorString.reset(); + if (fError.hasError()) { + SkString err; + if (fFileName.size() > 0) + fErrorString.set(fFileName.c_str()); + else + fErrorString.set("screenplay error"); + int line = fError.getLineNumber(); + if (line >= 0) { + fErrorString.append(", "); + fErrorString.append("line "); + fErrorString.appendS32(line); + } + fErrorString.append(": "); + fError.getErrorString(&err); + fErrorString.append(err); +#if defined SK_DEBUG + SkDebugf("%s\n", fErrorString.c_str()); +#endif + } +} + +void SkAnimateMaker::setEnableTime(SkMSec appTime, SkMSec expectedTime) { +#if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING + SkString debugOut; + SkMSec time = getAppTime(); + debugOut.appendS32(time - fDebugTimeBase); + debugOut.append(" set enable old enable="); + debugOut.appendS32(fEnableTime - fDebugTimeBase); + debugOut.append(" old adjust="); + debugOut.appendS32(fAdjustedStart); + debugOut.append(" new enable="); + debugOut.appendS32(expectedTime - fDebugTimeBase); + debugOut.append(" new adjust="); + debugOut.appendS32(appTime - expectedTime); + SkDebugf("%s\n", debugOut.c_str()); +#endif + fAdjustedStart = appTime - expectedTime; + fEnableTime = expectedTime; + SkDisplayable** firstMovie = fMovies.begin(); + SkDisplayable** endMovie = fMovies.end(); + for (SkDisplayable** ptr = firstMovie; ptr < endMovie; ptr++) { + SkDisplayMovie* movie = (SkDisplayMovie*) *ptr; + movie->fMovie.fMaker->setEnableTime(appTime, expectedTime); + } +} + +void SkAnimateMaker::setExtraPropertyCallBack(SkDisplayTypes type, + SkScriptEngine::_propertyCallBack callBack, void* userStorage) { + SkExtras** end = fExtras.end(); + for (SkExtras** extraPtr = fExtras.begin(); extraPtr < end; extraPtr++) { + SkExtras* extra = *extraPtr; + if (extra->definesType(type)) { + extra->fExtraCallBack = callBack; + extra->fExtraStorage = userStorage; + break; + } + } +} + +void SkAnimateMaker::setID(SkDisplayable* displayable, const SkString& newID) { + fIDs.set(newID.c_str(), displayable); +#ifdef SK_DEBUG + displayable->_id.set(newID); + displayable->id = displayable->_id.c_str(); +#endif +} + +void SkAnimateMaker::setScriptError(const SkScriptEngine& engine) { + SkString errorString; +#ifdef SK_DEBUG + engine.getErrorString(&errorString); +#endif + setErrorNoun(errorString); + setErrorCode(SkDisplayXMLParserError::kErrorInScript); +} + +bool SkAnimateMaker::GetStep(const char* token, size_t len, void* stepPtr, SkScriptValue* value) { + if (SK_LITERAL_STR_EQUAL("step", token, len)) { + value->fOperand.fS32 = *(S32*) stepPtr; + value->fType = SkType_Int; + return true; + } + return false; +} diff --git a/libs/graphics/animator/SkAnimateMaker.h b/libs/graphics/animator/SkAnimateMaker.h new file mode 100644 index 000000000..acc2c54b9 --- /dev/null +++ b/libs/graphics/animator/SkAnimateMaker.h @@ -0,0 +1,153 @@ +#ifndef SkAnimateMaker_DEFINED +#define SkAnimateMaker_DEFINED + +// #define SK_DEBUG_ANIMATION_TIMING + +#include "SkAnimator.h" +#include "SkBitmap.h" +#include "SkIntArray.h" +#include "SkDisplayEvents.h" +#include "SkDisplayList.h" +#include "SkDisplayScreenplay.h" +#include "SkDisplayXMLParser.h" +#include "SkScript.h" +#include "SkString.h" +#include "SkTDict.h" + +// not sure where this little helper macro should go + + +class SkActive; +class SkAnimate; +class SkCanvas; +class SkDisplayable; +class SkDrawable; +class SkDump; +class SkEvent; +class SkEventSink; +class SkExtras; +class SkGroup; +class SkPaint; +class SkStream; + +class SkAnimateMaker { +public: + SkAnimateMaker(SkAnimator* animator, SkCanvas* canvas, SkPaint* paint); + ~SkAnimateMaker(); + void appendActive(SkActive* ); + void childrenAdd(SkDisplayable* child) { *fChildren.append() = child; } + void clearExtraPropertyCallBack(SkDisplayTypes type); + bool computeID(SkDisplayable* displayable, SkDisplayable* parent, SkString* newID); + SkDisplayable* createInstance(const char name[], size_t len); + bool decodeStream(SkStream* stream); + bool decodeURI(const char uri[]); + void delayEnable(SkApply* apply, SkMSec time); + void doDelayedEvent(); + bool doEvent(const SkEvent& event); +#ifdef SK_DUMP_ENABLED + void dump(const char* match); +#endif + int dynamicProperty(SkString& nameStr, SkDisplayable** ); + bool find(const char* str, SkDisplayable** displayablePtr) const { + return fIDs.find(str, displayablePtr); + } + bool find(const char* str, size_t len, SkDisplayable** displayablePtr) const { + return fIDs.find(str, len, displayablePtr); + } + bool findKey(SkDisplayable* displayable, const char** string) const { + return fIDs.findKey(displayable, string); + } +// bool find(SkString& string, SkDisplayable** displayablePtr) { +// return fIDs.find(string.c_str(), displayablePtr); +// } + SkAnimator* getAnimator() { return fAnimator; } + SkMSec getAppTime() const; // call caller to get current time +#ifdef SK_DEBUG + SkAnimator* getRoot(); +#endif + SkXMLParserError::ErrorCode getErrorCode() const { return fError.getErrorCode(); } + SkMSec getInTime() { return fDisplayList.getTime(); } + int getNativeCode() const { return fError.getNativeCode(); } + bool hasError() { return fError.hasError(); } + void helperAdd(SkDisplayable* trackMe); + void helperRemove(SkDisplayable* alreadyTracked); + void idsSet(const char* attrValue, size_t len, SkDisplayable* displayable) { + fIDs.set(attrValue, len, displayable); } +// void loadMovies(); + void notifyInval(); + void notifyInvalTime(SkMSec time); + void postOnEnd(SkAnimateBase* animate, SkMSec end); + void removeActive(SkActive* ); + void reset(); + bool resolveID(SkDisplayable* displayable, SkDisplayable* original); + void setEnableTime(SkMSec appTime, SkMSec expectedTime); + void setErrorCode(SkXMLParserError::ErrorCode err) { if (fError.hasError() == false) fError.INHERITED::setCode(err); } + void setErrorCode(SkDisplayXMLParserError::ErrorCode err) { if (fError.hasError() == false) fError.setCode(err); } + void setErrorNoun(const SkString& str) { if (fError.hasError() == false) fError.setNoun(str); } + void setErrorString(); + void setExtraPropertyCallBack(SkDisplayTypes type, SkScriptEngine::_propertyCallBack , void* userStorage); + void setID(SkDisplayable* displayable, const SkString& newID); + void setInnerError(SkAnimateMaker* maker, const SkString& str) { fError.setInnerError(maker, str); } + void setScriptError(const SkScriptEngine& ); +#ifdef SK_DEBUG + void validate() { fDisplayList.validate(); } +#else + void validate() {} +#endif + SkDisplayEvent* fActiveEvent; + SkMSec fAdjustedStart; + SkBitmap fBitmap; + SkCanvas* fCanvas; + SkMSec fEnableTime; + int fEndDepth; // passed parameter to onEndElement + SkEvents fEvents; + SkDisplayList fDisplayList; + SkEventSinkID fHostEventSinkID; + SkMSec fMinimumInterval; + SkPaint* fPaint; + SkAnimateMaker* fParentMaker; + SkString fPrefix; + SkDisplayScreenplay fScreenplay; + const SkAnimator::Timeline* fTimeline; + SkBool8 fInInclude; + SkBool8 fInMovie; + SkBool8 fFirstScriptError; +#if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING + SkMSec fDebugTimeBase; +#endif +#ifdef SK_DUMP_ENABLED + SkString fDumpAnimated; + SkBool8 fDumpEvents; + SkBool8 fDumpGConditions; + SkBool8 fDumpPosts; +#endif +private: + void deleteMembers(); + static bool GetStep(const char* token, size_t len, void* stepPtr, SkScriptValue* ); + SkAnimateMaker& operator=(SkAnimateMaker& ); + SkTDDisplayableArray fChildren; + SkTDDisplayableArray fDelayed; // SkApply that contain delayed enable events + SkDisplayXMLParserError fError; + SkString fErrorString; + SkTDArray fExtras; + SkString fFileName; + SkTDDisplayableArray fHelpers; // helper displayables + SkBool8 fLoaded; + SkTDDisplayableArray fMovies; + SkTDict fIDs; + SkAnimator* fAnimator; + friend class SkAdd; + friend class SkAnimateBase; + friend class SkDisplayXMLParser; + friend class SkAnimator; + friend class SkAnimatorScript; + friend class SkApply; + friend class SkDisplayMovie; + friend class SkDisplayType; + friend class SkEvents; + friend class SkGroup; + friend struct SkMemberInfo; +}; + +#endif // SkAnimateMaker_DEFINED + diff --git a/libs/graphics/animator/SkAnimateProperties.h b/libs/graphics/animator/SkAnimateProperties.h new file mode 100644 index 000000000..17bc7771b --- /dev/null +++ b/libs/graphics/animator/SkAnimateProperties.h @@ -0,0 +1,12 @@ +#ifndef SkAnimateProperties_DEFINED +#define SkAnimateProperties_DEFINED + +enum SkAnimateBase_Properties { + SK_PROPERTY(dynamic), + SK_PROPERTY(mirror), + SK_PROPERTY(reset), + SK_PROPERTY(step), + SK_PROPERTY(values) +}; + +#endif // SkAnimateProperties_DEFINED diff --git a/libs/graphics/animator/SkAnimateSchema.xsd b/libs/graphics/animator/SkAnimateSchema.xsd new file mode 100644 index 000000000..2c75eb4a8 --- /dev/null +++ b/libs/graphics/animator/SkAnimateSchema.xsd @@ -0,0 +1,2787 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/graphics/animator/SkAnimateSchema.xsx b/libs/graphics/animator/SkAnimateSchema.xsx new file mode 100644 index 000000000..ceb7d890c --- /dev/null +++ b/libs/graphics/animator/SkAnimateSchema.xsx @@ -0,0 +1,3 @@ + + + diff --git a/libs/graphics/animator/SkAnimateSet.cpp b/libs/graphics/animator/SkAnimateSet.cpp new file mode 100644 index 000000000..4de2de560 --- /dev/null +++ b/libs/graphics/animator/SkAnimateSet.cpp @@ -0,0 +1,81 @@ +#include "SkAnimateSet.h" +#include "SkAnimateMaker.h" +#include "SkAnimateProperties.h" +#include "SkParse.h" + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkSet::fInfo[] = { + SK_MEMBER(begin, MSec), + SK_MEMBER(dur, MSec), + SK_MEMBER_PROPERTY(dynamic, Boolean), + SK_MEMBER(field, String), +// SK_MEMBER(formula, DynamicString), + SK_MEMBER(lval, DynamicString), +// SK_MEMBER_PROPERTY(reset, Boolean), + SK_MEMBER_PROPERTY(step, Int), + SK_MEMBER(target, DynamicString), + SK_MEMBER(to, DynamicString) +}; + +#endif + +DEFINE_GET_MEMBER(SkSet); + +SkSet::SkSet() { + dur = 1; +} + +#ifdef SK_DUMP_ENABLED +void SkSet::dump(SkAnimateMaker* maker) { + INHERITED::dump(maker); + if (dur != 1) { +#ifdef SK_CAN_USE_FLOAT + SkDebugf("dur=\"%g\" ", SkScalarToFloat(SkScalarDiv(dur,1000))); +#else + SkDebugf("dur=\"%x\" ", SkScalarDiv(dur,1000)); +#endif + } + //don't want double />\n's + SkDebugf("/>\n"); + +} +#endif + +void SkSet::refresh(SkAnimateMaker& maker) { + fFieldInfo->setValue(maker, &fValues, 0, fFieldInfo->fCount, nil, + fFieldInfo->getType(), to); +} + +void SkSet::onEndElement(SkAnimateMaker& maker) { + if (resolveCommon(maker) == false) + return; + if (fFieldInfo == nil) { + maker.setErrorCode(SkDisplayXMLParserError::kFieldNotInTarget); + return; + } + fReset = dur != 1; + SkDisplayTypes outType = fFieldInfo->getType(); + int comps = outType == SkType_String || outType == SkType_DynamicString ? 1 : + fFieldInfo->getSize((const SkDisplayable*) fTarget) / sizeof(int); + if (fValues.getType() == SkType_Unknown) { + fValues.setType(outType); + fValues.setCount(comps); + if (outType == SkType_String || outType == SkType_DynamicString) + fValues[0].fString = SkNEW(SkString); + else + memset(fValues.begin(), 0, fValues.count() * sizeof(fValues.begin()[0])); + } else { + SkASSERT(fValues.getType() == outType); + if (fFieldInfo->fType == SkType_Array) + comps = fValues.count(); + else + SkASSERT(fValues.count() == comps); + } + if (formula.size() > 0) { + comps = 1; + outType = SkType_MSec; + } + fFieldInfo->setValue(maker, &fValues, fFieldOffset, comps, this, outType, formula.size() > 0 ? formula : to); + fComponents = fValues.count(); +} diff --git a/libs/graphics/animator/SkAnimateSet.h b/libs/graphics/animator/SkAnimateSet.h new file mode 100644 index 000000000..476459f5b --- /dev/null +++ b/libs/graphics/animator/SkAnimateSet.h @@ -0,0 +1,19 @@ +#ifndef SkAnimateSet_DEFINED +#define SkAnimateSet_DEFINED + +#include "SkAnimate.h" + +class SkSet : public SkAnimate { + DECLARE_MEMBER_INFO(Set); + SkSet(); +#ifdef SK_DUMP_ENABLED + virtual void dump(SkAnimateMaker* ); +#endif + virtual void onEndElement(SkAnimateMaker& ); + virtual void refresh(SkAnimateMaker& ); +private: + typedef SkAnimate INHERITED; +}; + +#endif // SkAnimateSet_DEFINED + diff --git a/libs/graphics/animator/SkAnimator.cpp b/libs/graphics/animator/SkAnimator.cpp new file mode 100644 index 000000000..17f685535 --- /dev/null +++ b/libs/graphics/animator/SkAnimator.cpp @@ -0,0 +1,705 @@ +#include "SkAnimator.h" +#include "SkAnimateMaker.h" +#include "SkCanvas.h" +#include "SkDisplayApply.h" +#include "SkDisplayMovie.h" +#include "SkDisplayTypes.h" +#include "SkDisplayXMLParser.h" +#include "SkStream.h" +#include "SkScript.h" +#include "SkScript2.h" // compiled script experiment +#include "SkSystemEventTypes.h" +#include "SkTypedArray.h" +#ifdef ANDROID +#include "SkDrawExtraPathEffect.h" +#endif +#ifdef SK_DEBUG +#include "SkTime.h" +#endif + +#if defined SK_BUILD_FOR_WIN32 && defined SK_DEBUG + #define _static + extern const char gMathPrimerText[]; + extern const char gMathPrimerBinary[]; +#else + #define _static static +#endif + +#if !defined SK_BUILD_FOR_BREW || defined SK_DEBUG + _static const char gMathPrimerText[] = + "" + "" + "" + ""; +#endif + +#if defined SK_BUILD_FOR_BREW || defined SK_DEBUG + _static const char gMathPrimerBinary[] = + "\x0Ascreenplay\x04Mathbid\x04Math@@"; // !!! now out of date -- does not include Number +#endif + +#if defined SK_BUILD_FOR_BREW + #define gMathPrimer gMathPrimerBinary +#else + #define gMathPrimer gMathPrimerText +#endif + +SkAnimator::SkAnimator() : fMaker(nil) { + initialize(); +} + +SkAnimator::~SkAnimator() { + SkDELETE(fMaker); +} + +void SkAnimator::addExtras(SkExtras* extras) { + *fMaker->fExtras.append() = extras; +} + +bool SkAnimator::appendStream(SkStream* stream) { + return decodeStream(stream); +} + +bool SkAnimator::decodeMemory(const void* buffer, size_t size) +{ + fMaker->fFileName.reset(); + SkDisplayXMLParser parser(*fMaker); + return parser.parse((const char*)buffer, size); +} + +bool SkAnimator::decodeStream(SkStream* stream) +{ + SkDisplayXMLParser parser(*fMaker); + bool result = parser.parse(*stream); + fMaker->setErrorString(); + return result; +} + +bool SkAnimator::decodeDOM(const SkDOM& dom, const SkDOMNode* node) +{ + fMaker->fFileName.reset(); + SkDisplayXMLParser parser(*fMaker); + return parser.parse(dom, node); +} + +bool SkAnimator::decodeURI(const char uri[]) { +// SkDebugf("animator decode %s\n", uri); + SkStream* stream = SkStream::GetURIStream(fMaker->fPrefix.c_str(), uri); + SkAutoTDelete autoDel(stream); + setURIBase(uri); + return decodeStream(stream); +} + +bool SkAnimator::doCharEvent(SkUnichar code) { + if (code == 0) + return false; + struct SkEventState state; + state.fCode = code; + fMaker->fEnableTime = fMaker->getAppTime(); + bool result = fMaker->fEvents.doEvent(*fMaker, SkDisplayEvent::kKeyChar, &state); + fMaker->notifyInval(); + return result; +} + +bool SkAnimator::doClickEvent(int clickState, SkScalar x, SkScalar y) { + SkASSERT(clickState >= 0 && clickState <= 2); + struct SkEventState state; + state.fX = x; + state.fY = y; + fMaker->fEnableTime = fMaker->getAppTime(); + bool result = fMaker->fEvents.doEvent(*fMaker, + clickState == 0 ? SkDisplayEvent::kMouseDown : + clickState == 1 ? SkDisplayEvent::kMouseDrag : + SkDisplayEvent::kMouseUp, &state); + fMaker->notifyInval(); + return result; +} + +bool SkAnimator::doKeyEvent(SkKey code) { + if (code == 0) + return false; + struct SkEventState state; + state.fCode = code; + fMaker->fEnableTime = fMaker->getAppTime(); + bool result = fMaker->fEvents.doEvent(*fMaker, SkDisplayEvent::kKeyPress, &state); + fMaker->notifyInval(); + return result; +} + +bool SkAnimator::doKeyUpEvent(SkKey code) { + if (code == 0) + return false; + struct SkEventState state; + state.fCode = code; + fMaker->fEnableTime = fMaker->getAppTime(); + bool result = fMaker->fEvents.doEvent(*fMaker, SkDisplayEvent::kKeyPressUp, &state); + fMaker->notifyInval(); + return result; +} + +bool SkAnimator::doUserEvent(const SkEvent& evt) { + fMaker->fEnableTime = fMaker->getAppTime(); + return onEvent(evt); +} + +SkAnimator::DifferenceType SkAnimator::draw(SkCanvas* canvas, SkPaint* paint, SkMSec time) { + if (paint == nil) + return draw(canvas, time); + fMaker->fScreenplay.time = time; + fMaker->fCanvas = canvas; + fMaker->fPaint = paint; + fMaker->fCanvas->getPixels(&fMaker->fBitmap); + fMaker->fDisplayList.fHasUnion = false; + int result = fMaker->fDisplayList.draw(*fMaker, time); + if (result) + result += fMaker->fDisplayList.fHasUnion; + return (DifferenceType) result; +} + +SkAnimator::DifferenceType SkAnimator::draw(SkCanvas* canvas, SkMSec time) { + SkPaint paint; + return draw(canvas, &paint, time); +} + +#ifdef SK_DEBUG +void SkAnimator::eventDone(const SkEvent& ) { +} +#endif + +bool SkAnimator::findClickEvent(SkScalar x, SkScalar y) { + struct SkEventState state; + state.fDisable = true; + state.fX = x; + state.fY = y; + fMaker->fEnableTime = fMaker->getAppTime(); + bool result = fMaker->fEvents.doEvent(*fMaker, SkDisplayEvent::kMouseDown, &state); + fMaker->notifyInval(); + return result; +} + +const SkAnimator* SkAnimator::getAnimator(const SkDisplayable* displayable) const { + if (displayable->getType() != SkType_Movie) + return nil; + const SkDisplayMovie* movie = (const SkDisplayMovie*) displayable; + return movie->getAnimator(); +} + +const SkDisplayable* SkAnimator::getElement(const char* id) { + SkDisplayable* element; + if (fMaker->find(id, &element) == false) + return nil; + return (const SkDisplayable*) element; +} + +SkElementType SkAnimator::getElementType(const SkDisplayable* ae) { + SkDisplayable* element = (SkDisplayable*) ae; + const SkMemberInfo* info = SkDisplayType::GetMembers(fMaker, element->getType(), nil); + return (SkElementType) SkDisplayType::Find(fMaker, info); +} + +SkElementType SkAnimator::getElementType(const char* id) { + const SkDisplayable* element = getElement(id); + return getElementType(element); +} + +const SkMemberInfo* SkAnimator::getField(const SkDisplayable* ae, const char* field) { + SkDisplayable* element = (SkDisplayable*) ae; + const SkMemberInfo* info = element->getMember(field); + return (const SkMemberInfo*) info; +} + +const SkMemberInfo* SkAnimator::getField(const char* elementID, const char* field) { + const SkDisplayable* element = getElement(elementID); + return getField(element, field); +} + +SkFieldType SkAnimator::getFieldType(const SkMemberInfo* ai) { + const SkMemberInfo* info = (const SkMemberInfo*) ai; + return (SkFieldType) info->getType(); +} + +SkFieldType SkAnimator::getFieldType(const char* id, const char* fieldID) { + const SkMemberInfo* field = getField(id, fieldID); + return getFieldType(field); +} + + static bool getArrayCommon(const SkDisplayable* ae, const SkMemberInfo* ai, + int index, SkOperand* operand, SkDisplayTypes type) { + const SkDisplayable* element = (const SkDisplayable*) ae; + const SkMemberInfo* info = (const SkMemberInfo*) ai; + SkASSERT(info->fType == SkType_Array); + return info->getArrayValue(element, index, operand); +} + +int32_t SkAnimator::getArrayInt(const SkDisplayable* ae, + const SkMemberInfo* ai, int index) { + SkOperand operand; + bool result = getArrayCommon(ae, ai, index, &operand, SkType_Int); + return result ? operand.fS32 : SK_NaN32; +} + +int32_t SkAnimator::getArrayInt(const char* id, const char* fieldID, int index) { + const SkDisplayable* element = getElement(id); + if (element == nil) + return SK_NaN32; + const SkMemberInfo* field = getField(element, fieldID); + if (field == nil) + return SK_NaN32; + return getArrayInt(element, field, index); +} + +SkScalar SkAnimator::getArrayScalar(const SkDisplayable* ae, + const SkMemberInfo* ai, int index) { + SkOperand operand; + bool result = getArrayCommon(ae, ai, index, &operand, SkType_Float); + return result ? operand.fScalar : SK_ScalarNaN; +} + +SkScalar SkAnimator::getArrayScalar(const char* id, const char* fieldID, int index) { + const SkDisplayable* element = getElement(id); + if (element == nil) + return SK_ScalarNaN; + const SkMemberInfo* field = getField(element, fieldID); + if (field == nil) + return SK_ScalarNaN; + return getArrayScalar(element, field, index); +} + +const char* SkAnimator::getArrayString(const SkDisplayable* ae, + const SkMemberInfo* ai, int index) { + SkOperand operand; + bool result = getArrayCommon(ae, ai, index, &operand, SkType_String); + return result ? operand.fString->c_str() : nil; +} + +const char* SkAnimator::getArrayString(const char* id, const char* fieldID, int index) { + const SkDisplayable* element = getElement(id); + if (element == nil) + return nil; + const SkMemberInfo* field = getField(element, fieldID); + if (field == nil) + return nil; + return getArrayString(element, field, index); +} + +SkMSec SkAnimator::getInterval() { + return fMaker->fMinimumInterval == (SkMSec) -1 ? 0 : fMaker->fMinimumInterval; +} + +void SkAnimator::getInvalBounds(SkRect* inval) { + if (fMaker->fDisplayList.fHasUnion) { + inval->fLeft = SkIntToScalar(fMaker->fDisplayList.fInvalBounds.fLeft); + inval->fTop = SkIntToScalar(fMaker->fDisplayList.fInvalBounds.fTop); + inval->fRight = SkIntToScalar(fMaker->fDisplayList.fInvalBounds.fRight); + inval->fBottom = SkIntToScalar(fMaker->fDisplayList.fInvalBounds.fBottom); + } else { + inval->fLeft = inval->fTop = -SK_ScalarMax; + inval->fRight = inval->fBottom = SK_ScalarMax; + } +} + +const SkXMLParserError* SkAnimator::getParserError() { + return &fMaker->fError; +} + +const char* SkAnimator::getParserErrorString() { + if (fMaker->fErrorString.size() == 0 && fMaker->fError.hasError()) + fMaker->setErrorString(); + return fMaker->fErrorString.c_str(); +} + +int32_t SkAnimator::getInt(const SkDisplayable* element, const SkMemberInfo* info) { + if (info->fType != SkType_MemberProperty) { + SkOperand operand; + if (info->getType() == SkType_Int) { + info->getValue(element, &operand, 1); + return operand.fS32; + } + return SK_NaN32; + } + SkScriptValue scriptValue; + bool success = element->getProperty(info->propertyIndex(), &scriptValue); + if (success && scriptValue.fType == SkType_Int) + return scriptValue.fOperand.fS32; + return SK_NaN32; +} + +int32_t SkAnimator::getInt(const char* id, const char* fieldID) { + const SkDisplayable* element = getElement(id); + if (element == nil) + return SK_NaN32; + const SkMemberInfo* field = getField(element, fieldID); + if (field == nil) + return SK_NaN32; + return getInt(element, field); +} + +SkScalar SkAnimator::getScalar(const SkDisplayable* element, const SkMemberInfo* info) { + if (info->fType != SkType_MemberProperty) { + SkOperand operand; + if (info->getType() == SkType_Float) { + info->getValue(element, &operand, 1); + return operand.fScalar; + } + return SK_ScalarNaN; + } + SkScriptValue scriptValue; + bool success = element->getProperty(info->propertyIndex(), &scriptValue); + if (success && scriptValue.fType == SkType_Float) + return scriptValue.fOperand.fScalar; + return SK_ScalarNaN; +} + +SkScalar SkAnimator::getScalar(const char* id, const char* fieldID) { + const SkDisplayable* element = getElement(id); + if (element == nil) + return SK_ScalarNaN; + const SkMemberInfo* field = getField(element, fieldID); + if (field == nil) + return SK_ScalarNaN; + return getScalar(element, field); +} + +const char* SkAnimator::getString(const SkDisplayable* ae, + const SkMemberInfo* ai) { + const SkDisplayable* element = (const SkDisplayable*) ae; + const SkMemberInfo* info = (const SkMemberInfo*) ai; + SkString* temp; + info->getString(element, &temp); + return temp->c_str(); +} + +const char* SkAnimator::getString(const char* id, const char* fieldID) { + const SkDisplayable* element = getElement(id); + if (element == nil) + return nil; + const SkMemberInfo* field = getField(element, fieldID); + if (field == nil) + return nil; + return getString(element, field); +} + +const char* SkAnimator::getURIBase() { + return fMaker->fPrefix.c_str(); +} + +void SkAnimator::initialize() { + SkDELETE(fMaker); + fMaker = SkNEW_ARGS(SkAnimateMaker, (this, nil, nil)); + decodeMemory(gMathPrimer, sizeof(gMathPrimer)-1); +#ifdef ANDROID + InitializeSkExtraPathEffects(this); +#endif +} + + +#ifdef SK_DEBUG +bool SkAnimator::isTrackingEvents() { + return false; +} +#endif + +bool SkAnimator::onEvent(const SkEvent& evt) { +#ifdef SK_DEBUG + SkAnimator* root = fMaker->getRoot(); + if (root == nil) + root = this; + if (root->isTrackingEvents()) + root->eventDone(evt); +#endif + if (evt.isType(SK_EventType_OnEnd)) { + SkEventState eventState; + bool success = evt.findPtr("anim", (void**) &eventState.fDisplayable); + SkASSERT(success); + success = evt.findS32("time", (int32_t*) &fMaker->fEnableTime); + SkASSERT(success); + fMaker->fAdjustedStart = fMaker->getAppTime() - fMaker->fEnableTime; + fMaker->fEvents.doEvent(*fMaker, SkDisplayEvent::kOnEnd, &eventState); + fMaker->fAdjustedStart = 0; + goto inval; + } + if (evt.isType(SK_EventType_Delay)) { + fMaker->doDelayedEvent(); + goto inval; + } + { + const char* id = evt.findString("id"); + if (id == nil) + return false; + SkDisplayable** firstMovie = fMaker->fMovies.begin(); + SkDisplayable** endMovie = fMaker->fMovies.end(); + for (SkDisplayable** ptr = firstMovie; ptr < endMovie; ptr++) { + SkDisplayMovie* movie = (SkDisplayMovie*) *ptr; + movie->doEvent(evt); + } + { + SkDisplayable* event; + if (fMaker->find(id, &event) == false) + return false; + #if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING + SkString debugOut; + SkMSec realTime = fMaker->getAppTime(); + debugOut.appendS32(realTime - fMaker->fDebugTimeBase); + debugOut.append(" onEvent id="); + debugOut.append(id); + #endif + SkMSec time = evt.getFast32(); + if (time != 0) { + SkMSec app = fMaker->getAppTime(); + fMaker->setEnableTime(app, time); + #if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING + debugOut.append(" time="); + debugOut.appendS32(time - fMaker->fDebugTimeBase); + debugOut.append(" adjust="); + debugOut.appendS32(fMaker->fAdjustedStart); + #endif + } + #if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING + SkDebugf("%s\n", debugOut.c_str()); + #endif + SkASSERT(event->isEvent()); + SkDisplayEvent* displayEvent = (SkDisplayEvent*) event; + displayEvent->populateInput(*fMaker, evt); + displayEvent->enableEvent(*fMaker); + } + } +inval: + fMaker->notifyInval(); + return true; +} + +void SkAnimator::onEventPost(SkEvent* evt, SkEventSinkID sinkID) +{ +#ifdef SK_DEBUG + SkAnimator* root = fMaker->getRoot(); + if (root) { + root->onEventPost(evt, sinkID); + return; + } +#else + SkASSERT(sinkID == this->getSinkID() || this->getHostEventSinkID() == sinkID); +#endif + SkEvent::Post(evt, sinkID); +} + +void SkAnimator::onEventPostTime(SkEvent* evt, SkEventSinkID sinkID, SkMSec time) +{ +#ifdef SK_DEBUG + SkAnimator* root = fMaker->getRoot(); + if (root) { + root->onEventPostTime(evt, sinkID, time); + return; + } +#else + SkASSERT(sinkID == this->getSinkID() || this->getHostEventSinkID() == sinkID); +#endif + SkEvent::PostTime(evt, sinkID, time); +} + +void SkAnimator::reset() { + fMaker->fDisplayList.reset(); +} + +SkEventSinkID SkAnimator::getHostEventSinkID() const { + return fMaker->fHostEventSinkID; +} + +void SkAnimator::setHostEventSinkID(SkEventSinkID target) { + fMaker->fHostEventSinkID = target; +} + +void SkAnimator::onSetHostHandler(Handler ) { +} + +void SkAnimator::setJavaOwner(Handler ) { +} + +bool SkAnimator::setArrayString(const char* id, const char* fieldID, const char** array, int num) +{ + SkTypedArray tArray(SkType_String); + tArray.setCount(num); + for (int i = 0; i < num; i++) { + SkOperand op; + op.fString = new SkString(array[i]); + tArray[i] = op; + } + return setArray(id, fieldID, tArray); +} +bool SkAnimator::setArrayInt(const char* id, const char* fieldID, const int* array, int num) +{ + SkTypedArray tArray(SkType_Int); + tArray.setCount(num); + for (int i = 0; i < num; i++) { + SkOperand op; + op.fS32 = array[i]; + tArray[i] = op; + } + return setArray(id, fieldID, tArray); +} + +bool SkAnimator::setArray(SkDisplayable* element, const SkMemberInfo* info, SkTypedArray array) { + if (info->fType != SkType_Array) + return false; //the field is not an array + //i think we can handle the case where the displayable itself is an array differently from the + //case where it has an array - for one thing, if it is an array, i think we can change its type + //if it's not, we cannot + SkDisplayTypes type = element->getType(); + if (type == SkType_Array) { + SkDisplayArray* dispArray = (SkDisplayArray*) element; + dispArray->values = array; + return true; + } + else + return false; //currently i don't care about this case +} + +bool SkAnimator::setArray(const char* id, const char* fieldID, SkTypedArray array) { + SkDisplayable* element = (SkDisplayable*) getElement(id); + //should I go ahead and change all 'nil's to 'NULL'? + if (element == nil) + return false; + const SkMemberInfo* field = getField(element, fieldID); + if (field == nil) + return false; + return setArray(element, field, array); +} + +bool SkAnimator::setInt(SkDisplayable* element, const SkMemberInfo* info, int32_t s32) { + if (info->fType != SkType_MemberProperty) { + SkOperand operand; + operand.fS32 = s32; + SkASSERT(info->getType() == SkType_Int); + info->setValue(element, &operand, 1); + } else { + SkScriptValue scriptValue; + scriptValue.fType = SkType_Int; + scriptValue.fOperand.fS32 = s32; + element->setProperty(info->propertyIndex(), scriptValue); + } + return true; +} + +bool SkAnimator::setInt(const char* id, const char* fieldID, int32_t s32) { + SkDisplayable* element = (SkDisplayable*) getElement(id); + if (element == nil) + return false; + const SkMemberInfo* field = getField(element, fieldID); + if (field == nil) + return false; + return setInt(element, field, s32); +} + +bool SkAnimator::setScalar(SkDisplayable* element, const SkMemberInfo* info, SkScalar scalar) { + if (info->fType != SkType_MemberProperty) { + SkOperand operand; + operand.fScalar = scalar; + SkASSERT(info->getType() == SkType_Float); + info->setValue(element, &operand, 1); + } else { + SkScriptValue scriptValue; + scriptValue.fType = SkType_Float; + scriptValue.fOperand.fScalar = scalar; + element->setProperty(info->propertyIndex(), scriptValue); + } + return true; +} + +bool SkAnimator::setScalar(const char* id, const char* fieldID, SkScalar scalar) { + SkDisplayable* element = (SkDisplayable*) getElement(id); + if (element == nil) + return false; + const SkMemberInfo* field = getField(element, fieldID); + if (field == nil) + return false; + return setScalar(element, field, scalar); +} + +bool SkAnimator::setString(SkDisplayable* element, + const SkMemberInfo* info, const char* str) { + // !!! until this is fixed, can't call script with global references from here + info->setValue(*fMaker, nil, 0, info->fCount, element, info->getType(), str, strlen(str)); + return true; +} + +bool SkAnimator::setString(const char* id, const char* fieldID, const char* str) { + SkDisplayable* element = (SkDisplayable*) getElement(id); + if (element == nil) + return false; + const SkMemberInfo* field = getField(element, fieldID); + if (field == nil) + return false; + return setString(element, field, str); +} + +void SkAnimator::setTimeline(const Timeline& timeline) { + fMaker->fTimeline = &timeline; +} + +void SkAnimator::setURIBase(const char* uri) { + if (uri) + { + const char* tail = strrchr(uri, '/'); + if (tail) { + SkString prefix(uri, tail - uri + 1); + if (SkStream::IsAbsoluteURI(uri)) + fMaker->fPrefix.reset(); + fMaker->fPrefix.append(prefix); + fMaker->fFileName.set(tail + 1); + } else + fMaker->fFileName.set(uri); + } +} + +#ifdef SK_DEBUG +bool SkAnimator::NoLeaks() { +#ifdef SK_BUILD_FOR_MAC + if (SkDisplayable::fAllocations.count() == 0) + return true; +// return SkDisplayable::fAllocationCount == 0; + SkDebugf("!!! leaked %d displayables:\n", SkDisplayable::fAllocations.count()); + for (SkDisplayable** leak = SkDisplayable::fAllocations.begin(); leak < SkDisplayable::fAllocations.end(); leak++) + SkDebugf("%08x %s\n", *leak, (*leak)->id); +#endif + return false; +} +#endif + +#ifdef SK_SUPPORT_UNITTEST +#include "SkAnimatorScript.h" +#include "SkBase64.h" +#include "SkParse.h" +#include "SkMemberInfo.h" + +#define unittestline(type) { #type , type::UnitTest } +#endif + + +void SkAnimator::Init(bool runUnitTests) { +#ifdef SK_SUPPORT_UNITTEST + if (runUnitTests == false) + return; + static const struct { + const char* fTypeName; + void (*fUnitTest)( ); + } gUnitTests[] = { + unittestline(SkBase64), + unittestline(SkDisplayType), + unittestline(SkParse), + unittestline(SkScriptEngine), +// unittestline(SkScriptEngine2), // compiled script experiment + unittestline(SkAnimatorScript) + }; + for (int i = 0; i < (int)SK_ARRAY_COUNT(gUnitTests); i++) + { + SkDebugf("SkAnimator: Running UnitTest for %s\n", gUnitTests[i].fTypeName); + gUnitTests[i].fUnitTest(); + SkDebugf("SkAnimator: End UnitTest for %s\n", gUnitTests[i].fTypeName); + } +#endif +} + +void SkAnimator::Term() { +} + + + diff --git a/libs/graphics/animator/SkAnimatorScript.cpp b/libs/graphics/animator/SkAnimatorScript.cpp new file mode 100644 index 000000000..cce572341 --- /dev/null +++ b/libs/graphics/animator/SkAnimatorScript.cpp @@ -0,0 +1,590 @@ +#include "SkAnimatorScript.h" +#include "SkAnimateBase.h" +#include "SkAnimateMaker.h" +#include "SkDisplayTypes.h" +#include "SkExtras.h" +#include "SkMemberInfo.h" +#include "SkParse.h" + +static const SkDisplayEnumMap gEnumMaps[] = { + { SkType_AddMode, "indirect|immediate" }, + { SkType_Align, "left|center|right" }, + { SkType_ApplyMode, "create|immediate|once" }, + { SkType_ApplyTransition, "normal|reverse" }, + { SkType_BitmapEncoding, "jpeg|png" }, + { SkType_BitmapFormat, "none|A1|A8|Index8|RGB16|RGB32" }, + { SkType_Boolean, "false|true" }, + { SkType_Cap, "butt|round|square" }, + { SkType_EventCode, "none|leftSoftKey|rightSoftKey|home|back|send|end|key0|key1|key2|key3|key4|key5|key6|key7|key8|key9|star|hash|up|down|left|right|OK|volUp|volDown|camera" }, + { SkType_EventKind, "none|keyChar|keyPress|keyPressUp|mouseDown|mouseDrag|mouseMove|mouseUp|onEnd|onLoad|user" }, + { SkType_EventMode, "deferred|immediate" }, + { SkType_FillType, "winding|evenOdd" }, + { SkType_FilterType, "none|bilinear" }, + { SkType_FontStyle, "normal|bold|italic|boldItalic" }, + { SkType_FromPathMode, "normal|angle|position" }, + { SkType_Join, "miter|round|blunt" }, + { SkType_MaskFilterBlurStyle, "normal|solid|outer|inner" }, + { SkType_PathDirection, "cw|ccw" }, + { SkType_Style, "fill|stroke|strokeAndFill" }, + { SkType_TextBoxAlign, "start|center|end" }, + { SkType_TextBoxMode, "oneLine|lineBreak" }, + { SkType_TileMode, "clamp|repeat|mirror" }, + { SkType_Xfermode, "clear|src|dst|srcOver|dstOver|srcIn|dstIn|srcOut|dstOut|" + "srcATop|dstATop|xor|darken|lighten" }, +}; + +static int gEnumMapCount = SK_ARRAY_COUNT(gEnumMaps); + +SkAnimatorScript::SkAnimatorScript(SkAnimateMaker& maker, SkDisplayable* working, SkDisplayTypes type) + : SkScriptEngine(SkScriptEngine::ToOpType(type)), fMaker(maker), fParent(NULL), fWorking(working) +{ + memberCallBack(EvalMember, (void*) this); + memberFunctionCallBack(EvalMemberFunction, (void*) this); + boxCallBack(Box, (void*) this); + unboxCallBack(Unbox, (void*) &maker); + propertyCallBack(EvalID, (void*) this); // must be first (entries are prepended, will be last), since it never fails + propertyCallBack(Infinity, (void*) this); + propertyCallBack(NaN, (void*) this); + functionCallBack(Eval, (void*) this); + functionCallBack(IsFinite, (void*) this); + functionCallBack(IsNaN, (void*) this); + if (type == SkType_ARGB) { + functionCallBack(EvalRGB, (void*) this); + propertyCallBack(EvalNamedColor, (void*) &maker.fIDs); + } + if (SkDisplayType::IsEnum(&maker, type)) { + // !!! for SpiderMonkey, iterate through the enum values, and map them to globals + const SkDisplayEnumMap& map = GetEnumValues(type); + propertyCallBack(EvalEnum, (void*) map.fValues); + } + for (SkExtras** extraPtr = maker.fExtras.begin(); extraPtr < maker.fExtras.end(); extraPtr++) { + SkExtras* extra = *extraPtr; + if (extra->fExtraCallBack) + propertyCallBack(extra->fExtraCallBack, extra->fExtraStorage); + } +} + +SkAnimatorScript::~SkAnimatorScript() { + for (SkDisplayable** dispPtr = fTrackDisplayable.begin(); dispPtr < fTrackDisplayable.end(); dispPtr++) + delete *dispPtr; +} + +bool SkAnimatorScript::evaluate(const char* original, SkScriptValue* result, SkDisplayTypes type) { + const char* script = original; + bool success = evaluateScript(&script, result); + if (success == false || result->fType != type) { + fMaker.setScriptError(*this); + return false; + } + return true; +} + +bool SkAnimatorScript::Box(void* user, SkScriptValue* scriptValue) { + SkAnimatorScript* engine = (SkAnimatorScript*) user; + SkDisplayTypes type = scriptValue->fType; + SkDisplayable* displayable; + switch (type) { + case SkType_Array: { + SkDisplayArray* boxedValue = new SkDisplayArray(*scriptValue->fOperand.fArray); + displayable = boxedValue; + } break; + case SkType_Boolean: { + SkDisplayBoolean* boxedValue = new SkDisplayBoolean; + displayable = boxedValue; + boxedValue->value = !! scriptValue->fOperand.fS32; + } break; + case SkType_Int: { + SkDisplayInt* boxedValue = new SkDisplayInt; + displayable = boxedValue; + boxedValue->value = scriptValue->fOperand.fS32; + } break; + case SkType_Float: { + SkDisplayFloat* boxedValue = new SkDisplayFloat; + displayable = boxedValue; + boxedValue->value = scriptValue->fOperand.fScalar; + } break; + case SkType_String: { + SkDisplayString* boxedValue = new SkDisplayString(*scriptValue->fOperand.fString); + displayable = boxedValue; + } break; + case SkType_Displayable: + scriptValue->fOperand.fObject = scriptValue->fOperand.fDisplayable; + scriptValue->fType = SkType_Displayable; + return true; + default: + SkASSERT(0); + return false; + } + engine->track(displayable); + scriptValue->fOperand.fObject = displayable; + scriptValue->fType = SkType_Displayable; + return true; +} + +bool SkAnimatorScript::Eval(const char* function, size_t len, SkTDArray& params, + void* eng, SkScriptValue* value) { + if (SK_LITERAL_STR_EQUAL("eval", function, len) == false) + return false; + if (params.count() != 1) + return false; + SkAnimatorScript* host = (SkAnimatorScript*) eng; + SkAnimatorScript engine(host->fMaker, host->fWorking, SkScriptEngine::ToDisplayType(host->fReturnType)); + SkScriptValue* scriptValue = params.begin(); + bool success = true; + if (scriptValue->fType == SkType_String) { + const char* script = scriptValue->fOperand.fString->c_str(); + success = engine.evaluateScript(&script, value); + } else + *value = *scriptValue; + return success; +} + +bool SkAnimatorScript::EvalEnum(const char* token, size_t len, void* callBack, SkScriptValue* value) { + const char* tokens = (const char*) callBack; + value->fType = SkType_Int; + if (MapEnums(tokens, token, len, (int*)&value->fOperand.fS32)) + return true; + return false; +} + +bool SkAnimatorScript::EvalID(const char* token, size_t len, void* user, SkScriptValue* value) { + SkAnimatorScript* engine = (SkAnimatorScript*) user; + SkTDict* ids = &engine->fMaker.fIDs; + SkDisplayable* displayable; + bool success = ids->find(token, len, &displayable); + if (success == false) { + displayable = engine->fWorking; + if (SK_LITERAL_STR_EQUAL("parent", token, len)) { + SkDisplayable* parent = displayable->getParent(); + if (parent == false) + parent = engine->fParent; + if (parent) { + value->fOperand.fDisplayable = parent; + value->fType = SkType_Displayable; + return true; + } + } + if (displayable && EvalMember(token, len, displayable, engine, value)) + return true; + value->fOperand.fString = NULL; + value->fType = SkType_String; + } else { + SkDisplayable* working = engine->fWorking; + value->fOperand.fDisplayable = displayable; + value->fType = SkType_Displayable; + if (displayable->canContainDependents() && working && working->isAnimate()) { + SkAnimateBase* animator = (SkAnimateBase*) working; + if (animator->isDynamic()) { + SkDisplayDepend* depend = (SkDisplayDepend* ) displayable; + depend->addDependent(working); + } + } + } + return true; +} + +bool SkAnimatorScript::EvalNamedColor(const char* token, size_t len, void* callback, SkScriptValue* value) { + value->fType = SkType_Int; + if (SkParse::FindNamedColor(token, len, (SkColor*) &value->fOperand.fS32) != NULL) + return true; + return false; +} + +bool SkAnimatorScript::EvalRGB(const char* function, size_t len, SkTDArray& params, + void* eng, SkScriptValue* value) { + if (SK_LITERAL_STR_EQUAL("rgb", function, len) == false) + return false; + if (params.count() != 3) + return false; + SkScriptEngine* engine = (SkScriptEngine*) eng; + unsigned result = 0xFF000000; + int shift = 16; + for (SkScriptValue* valuePtr = params.begin(); valuePtr < params.end(); valuePtr++) { + engine->convertTo(SkType_Int, valuePtr); + result |= SkClampMax(valuePtr->fOperand.fS32, 255) << shift; + shift -= 8; + } + value->fOperand.fS32 = result; + value->fType = SkType_Int; + return true; +} + +bool SkAnimatorScript::EvalMemberCommon(SkScriptEngine* engine, const SkMemberInfo* info, + SkDisplayable* displayable, SkScriptValue* value) { + SkDisplayTypes original; + SkDisplayTypes type = original = (SkDisplayTypes) info->getType(); + if (info->fType == SkType_Array) + type = SkType_Array; + switch (type) { + case SkType_ARGB: + type = SkType_Int; + case SkType_Boolean: + case SkType_Int: + case SkType_MSec: + case SkType_Float: + SkASSERT(info->getCount() == 1); + if (info->fType != SkType_MemberProperty && info->fType != SkType_MemberFunction) + value->fOperand.fS32 = *(int32_t*) info->memberData(displayable); // OK for SkScalar too + if (type == SkType_MSec) { + value->fOperand.fScalar = SkScalarDiv((SkScalar) value->fOperand.fS32, 1000); // dividing two ints is the same as dividing two scalars + type = SkType_Float; + } + break; + case SkType_String: { + SkString* displayableString; + if (info->fType != SkType_MemberProperty && info->fType != SkType_MemberFunction) { + info->getString(displayable, &displayableString); + value->fOperand.fString = new SkString(*displayableString); + } + } break; + case SkType_Array: { + SkASSERT(info->fType != SkType_MemberProperty); // !!! incomplete + SkTDOperandArray* displayableArray = (SkTDOperandArray*) info->memberData(displayable); + if (displayable->getType() == SkType_Array) { + SkDisplayArray* typedArray = (SkDisplayArray*) displayable; + original = typedArray->values.getType(); + } + SkASSERT(original != SkType_Unknown); + SkTypedArray* array = value->fOperand.fArray = new SkTypedArray(original); + engine->track(array); + int count = displayableArray->count(); + if (count > 0) { + array->setCount(count); + memcpy(array->begin(), displayableArray->begin(), count * sizeof(SkOperand)); + } + } break; + default: + SkASSERT(0); // unimplemented + } + value->fType = type; + return true; +} + +bool SkAnimatorScript::EvalMember(const char* member, size_t len, void* object, void* eng, + SkScriptValue* value) { + SkScriptEngine* engine = (SkScriptEngine*) eng; + SkDisplayable* displayable = (SkDisplayable*) object; + SkString name(member, len); + SkDisplayable* named = displayable->contains(name); + if (named) { + value->fOperand.fDisplayable = named; + value->fType = SkType_Displayable; + return true; + } + const SkMemberInfo* info = displayable->getMember(name.c_str()); + if (info == NULL) + return false; + if (info->fType == SkType_MemberProperty) { + if (displayable->getProperty(info->propertyIndex(), value) == false) { + SkASSERT(0); + return false; + } + } + return EvalMemberCommon(engine, info, displayable, value); +} + +bool SkAnimatorScript::EvalMemberFunction(const char* member, size_t len, void* object, + SkTDArray& params, void* eng, SkScriptValue* value) { + SkScriptEngine* engine = (SkScriptEngine*) eng; + SkDisplayable* displayable = (SkDisplayable*) object; + SkString name(member, len); + const SkMemberInfo* info = displayable->getMember(name.c_str()); + SkASSERT(info != NULL); /* !!! error handling unimplemented */ + if (info->fType != SkType_MemberFunction) { + SkASSERT(0); + return false; + } + displayable->executeFunction(displayable, info->functionIndex(), params, info->getType(), + value); + return EvalMemberCommon(engine, info, displayable, value); +} + +bool SkAnimatorScript::EvaluateDisplayable(SkAnimateMaker& maker, SkDisplayable* displayable, const char* script, SkDisplayable** result) { + SkAnimatorScript engine(maker, displayable, SkType_Displayable); + SkScriptValue value; + bool success = engine.evaluate(script, &value, SkType_Displayable); + if (success) + *result = value.fOperand.fDisplayable; + return success; +} + +bool SkAnimatorScript::EvaluateInt(SkAnimateMaker& maker, SkDisplayable* displayable, const char* script, int32_t* result) { + SkAnimatorScript engine(maker, displayable, SkType_Int); + SkScriptValue value; + bool success = engine.evaluate(script, &value, SkType_Int); + if (success) + *result = value.fOperand.fS32; + return success; +} + +bool SkAnimatorScript::EvaluateFloat(SkAnimateMaker& maker, SkDisplayable* displayable, const char* script, SkScalar* result) { + SkAnimatorScript engine(maker, displayable, SkType_Float); + SkScriptValue value; + bool success = engine.evaluate(script, &value, SkType_Float); + if (success) + *result = value.fOperand.fScalar; + return success; +} + +bool SkAnimatorScript::EvaluateString(SkAnimateMaker& maker, SkDisplayable* displayable, const char* script, SkString* result) { + SkAnimatorScript engine(maker, displayable, SkType_String); + SkScriptValue value; + bool success = engine.evaluate(script, &value, SkType_String); + if (success) + result->set(*(value.fOperand.fString)); + return success; +} + +bool SkAnimatorScript::EvaluateString(SkAnimateMaker& maker, SkDisplayable* displayable, SkDisplayable* parent, const char* script, SkString* result) { + SkAnimatorScript engine(maker, displayable, SkType_String); + engine.fParent = parent; + SkScriptValue value; + bool success = engine.evaluate(script, &value, SkType_String); + if (success) + result->set(*(value.fOperand.fString)); + return success; +} + +const SkDisplayEnumMap& SkAnimatorScript::GetEnumValues(SkDisplayTypes type) { + int index = SkTSearch(&gEnumMaps[0].fType, gEnumMapCount, type, + sizeof(SkDisplayEnumMap)); + SkASSERT(index >= 0); + return gEnumMaps[index]; +} + +bool SkAnimatorScript::Infinity(const char* token, size_t len, void* user, SkScriptValue* value) { + if (SK_LITERAL_STR_EQUAL("Infinity", token, len) == false) + return false; + value->fType = SkType_Float; + value->fOperand.fScalar = SK_ScalarInfinity; + return true; +} + +bool SkAnimatorScript::IsFinite(const char* function, size_t len, SkTDArray& params, + void* eng, SkScriptValue* value) { + if (SK_LITERAL_STR_EQUAL(function, "isFinite", len) == false) + return false; + if (params.count() != 1) + return false; + SkScriptValue* scriptValue = params.begin(); + SkDisplayTypes type = scriptValue->fType; + SkScalar scalar = scriptValue->fOperand.fScalar; + value->fType = SkType_Int; + value->fOperand.fS32 = type == SkType_Float ? SkScalarIsNaN(scalar) == false && + SkScalarAbs(scalar) != SK_ScalarInfinity : type == SkType_Int; + return true; +} + +bool SkAnimatorScript::IsNaN(const char* function, size_t len, SkTDArray& params, + void* eng, SkScriptValue* value) { + if (SK_LITERAL_STR_EQUAL("isNaN", function, len) == false) + return false; + if (params.count() != 1) + return false; + SkScriptValue* scriptValue = params.begin(); + value->fType = SkType_Int; + value->fOperand.fS32 = scriptValue->fType == SkType_Float ? SkScalarIsNaN(scriptValue->fOperand.fScalar) : 0; + return true; +} + +bool SkAnimatorScript::MapEnums(const char* ptr, const char* match, size_t len, int* value) { + int index = 0; + bool more = true; + do { + const char* last = strchr(ptr, '|'); + if (last == NULL) { + last = &ptr[strlen(ptr)]; + more = false; + } + size_t length = last - ptr; + if (len == length && strncmp(ptr, match, length) == 0) { + *value = index; + return true; + } + index++; + ptr = last + 1; + } while (more); + return false; +} + +bool SkAnimatorScript::NaN(const char* token, size_t len, void* user, SkScriptValue* value) { + if (SK_LITERAL_STR_EQUAL("NaN", token, len) == false) + return false; + value->fType = SkType_Float; + value->fOperand.fScalar = SK_ScalarNaN; + return true; +} + +#if 0 +bool SkAnimatorScript::ObjectToString(void* object, void* user, SkScriptValue* value) { + SkTDict* ids = (SkTDict*) user; + SkDisplayable* displayable = (SkDisplayable*) object; + const char* key; + bool success = ids->findKey(displayable, &key); + if (success == false) + return false; + value->fOperand.fString = new SkString(key); + value->fType = SkType_String; + return true; +} +#endif + +bool SkAnimatorScript::Unbox(void* m, SkScriptValue* scriptValue) { + SkAnimateMaker* maker = (SkAnimateMaker*) m; + SkASSERT((unsigned) scriptValue->fType == (unsigned) SkType_Displayable); + SkDisplayable* displayable = (SkDisplayable*) scriptValue->fOperand.fObject; + SkDisplayTypes type = displayable->getType(); + switch (displayable->getType()) { + case SkType_Array: { + SkDisplayArray* boxedValue = (SkDisplayArray*) displayable; + scriptValue->fOperand.fArray = &boxedValue->values; + } break; + case SkType_Boolean: { + SkDisplayBoolean* boxedValue = (SkDisplayBoolean*) displayable; + scriptValue->fOperand.fS32 = boxedValue->value; + } break; + case SkType_Int: { + SkDisplayInt* boxedValue = (SkDisplayInt*) displayable; + scriptValue->fOperand.fS32 = boxedValue->value; + } break; + case SkType_Float: { + SkDisplayFloat* boxedValue = (SkDisplayFloat*) displayable; + scriptValue->fOperand.fScalar = boxedValue->value; + } break; + case SkType_String: { + SkDisplayString* boxedValue = (SkDisplayString*) displayable; + scriptValue->fOperand.fString = SkNEW_ARGS(SkString, (boxedValue->value)); + } break; + default: { + const char* id; + bool success = maker->findKey(displayable, &id); + SkASSERT(success); + scriptValue->fOperand.fString = SkNEW_ARGS(SkString, (id)); + type = SkType_String; + } + } + scriptValue->fType = type; + return true; +} + +#if defined SK_SUPPORT_UNITTEST + +#include "SkAnimator.h" + +static const char scriptTestSetup[] = +"\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" +""; + +#if !defined(SK_BUILD_FOR_BREW) + +#define DEFAULT_ANSWER , 0 + +static const SkScriptNAnswer scriptTests[] = { + { "label.text.length == 4", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, +// { "labelPaint.measureText(label.text) > 0 ? labelPaint.measureText(label.text)+10 : 40", SkType_Float, 0, SkIntToScalar(0x23) }, + { "Number.POSITIVE_INFINITY >= Number.MAX_VALUE ? 1 : 0", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, + { "Infinity >= Number.MAX_VALUE ? 1 : 0", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, + { "Number.NEGATIVE_INFINITY <= -Number.MAX_VALUE ? 1 : 0", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, + { "Number.MIN_VALUE > 0 ? 1 : 0", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, + { "isNaN(Number.NaN)", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, + { "isNaN(NaN)", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, + { "Math.sin(0)", SkType_Float, 0, SkIntToScalar(0) DEFAULT_ANSWER }, + { "alpha+alpha", SkType_String, 0, 0, "abcabc" }, + { "intArray[4]", SkType_Unknown DEFAULT_ANSWER DEFAULT_ANSWER DEFAULT_ANSWER }, + { "emptyArray[4]", SkType_Unknown DEFAULT_ANSWER DEFAULT_ANSWER DEFAULT_ANSWER }, + { "idx", SkType_Int, 2 DEFAULT_ANSWER DEFAULT_ANSWER }, + { "intArray.length", SkType_Int, 3 DEFAULT_ANSWER DEFAULT_ANSWER }, + { "intArray.values[0]", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, + { "intArray[0]", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, + { "idx.value", SkType_Int, 2 DEFAULT_ANSWER DEFAULT_ANSWER }, + { "alpha.value", SkType_String, 0, 0, "abc" }, + { "alpha", SkType_String, 0, 0, "abc" }, + { "alpha.value+alpha.value", SkType_String, 0, 0, "abcabc" }, + { "alpha+idx", SkType_String, 0, 0, "abc2" }, + { "idx+alpha", SkType_String, 0, 0, "2abc" }, + { "intArray[idx]", SkType_Int, 6 DEFAULT_ANSWER DEFAULT_ANSWER }, + { "alpha.slice(1,2)", SkType_String, 0, 0, "b" }, + { "alpha.value.slice(1,2)", SkType_String, 0, 0, "b" }, + { "testRect.left+2", SkType_Float, 0, SkIntToScalar(3) DEFAULT_ANSWER }, + { "0 ? Math.sin(0) : 1", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, + { "0 ? intArray[0] : 1", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, + { "0 ? intArray.values[0] : 1", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, + { "0 ? idx : 1", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, + { "0 ? idx.value : 1", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, + { "0 ? alpha.slice(1,2) : 1", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, + { "0 ? alpha.value.slice(1,2) : 1", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, + { "idy", SkType_Int, 3 DEFAULT_ANSWER DEFAULT_ANSWER } +}; +#endif + +#define SkScriptNAnswer_testCount SK_ARRAY_COUNT(scriptTests) + +void SkAnimatorScript::UnitTest() { +#if !defined(SK_BUILD_FOR_BREW) && defined(SK_SUPPORT_UNITTEST) + SkAnimator animator; + SkASSERT(animator.decodeMemory(scriptTestSetup, sizeof(scriptTestSetup)-1)); + SkEvent evt; + evt.setString("id", "evt"); + evt.setS32("x", 3); + animator.doUserEvent(evt); + // set up animator with memory script above, then run value tests + for (unsigned index = 0; index < SkScriptNAnswer_testCount; index++) { + SkAnimatorScript engine(*animator.fMaker, NULL, scriptTests[index].fType); + SkScriptValue value; + const char* script = scriptTests[index].fScript; + bool success = engine.evaluateScript(&script, &value); + if (success == false) { + SkDebugf("script failed: %s\n", scriptTests[index].fScript); + SkASSERT(scriptTests[index].fType == SkType_Unknown); + continue; + } + SkASSERT(value.fType == scriptTests[index].fType); + SkScalar error; + switch (value.fType) { + case SkType_Int: + SkASSERT(value.fOperand.fS32 == scriptTests[index].fIntAnswer); + break; + case SkType_Float: + error = SkScalarAbs(value.fOperand.fScalar - scriptTests[index].fScalarAnswer); + SkASSERT(error < SK_Scalar1 / 10000); + break; + case SkType_String: + SkASSERT(strcmp(value.fOperand.fString->c_str(), scriptTests[index].fStringAnswer) == 0); + break; + default: + SkASSERT(0); + } + } +#endif +} + +#endif + + diff --git a/libs/graphics/animator/SkAnimatorScript.h b/libs/graphics/animator/SkAnimatorScript.h new file mode 100644 index 000000000..2a02a2f5e --- /dev/null +++ b/libs/graphics/animator/SkAnimatorScript.h @@ -0,0 +1,67 @@ +#ifndef SkAnimatorScript_DEFINED +#define SkAnimatorScript_DEFINED + +#include "SkDisplayable.h" +#include "SkScript.h" +#include "SkTypedArray.h" + +class SkAnimateMaker; +struct SkMemberInfo; + +struct SkDisplayEnumMap { + SkDisplayTypes fType; + const char* fValues; +}; + +class SkAnimatorScript : public SkScriptEngine { +public: + SkAnimatorScript(SkAnimateMaker& , SkDisplayable* , SkDisplayTypes type); + ~SkAnimatorScript(); + bool evaluate(const char* script, SkScriptValue* , SkDisplayTypes type); + void track(SkDisplayable* displayable) { + SkASSERT(fTrackDisplayable.find(displayable) < 0); + *fTrackDisplayable.append() = displayable; } + static bool EvaluateDisplayable(SkAnimateMaker& , SkDisplayable* , const char* script, SkDisplayable** ); + static bool EvaluateFloat(SkAnimateMaker& , SkDisplayable* , const char* script, SkScalar* ); + static bool EvaluateInt(SkAnimateMaker& , SkDisplayable* , const char* script, int32_t* ); + static bool EvaluateString(SkAnimateMaker& , SkDisplayable* , const char* script, SkString* ); + static bool EvaluateString(SkAnimateMaker& , SkDisplayable* , SkDisplayable* parent, const char* script, SkString* ); + static bool MapEnums(const char* ptr, const char* match, size_t len, int* value); +protected: + static bool Box(void* user, SkScriptValue* ); + static bool Eval(const char* function, size_t len, SkTDArray& params, + void* callBack, SkScriptValue* ); + static bool EvalEnum(const char* token, size_t len, void* callBack, SkScriptValue* ); + static bool EvalID(const char* token, size_t len, void* callBack, SkScriptValue* ); + static bool EvalMember(const char* member, size_t len, void* object, void* eng, + SkScriptValue* value); + static bool EvalMemberCommon(SkScriptEngine* , const SkMemberInfo* info, + SkDisplayable* displayable, SkScriptValue* value); + static bool EvalMemberFunction(const char* member, size_t len, void* object, + SkTDArray& params, void* user, SkScriptValue* value); + static bool EvalNamedColor(const char* token, size_t len, void* callBack, SkScriptValue* ); + static bool EvalRGB(const char* function, size_t len, SkTDArray& params, + void* callBack, SkScriptValue* ); + static const SkDisplayEnumMap& GetEnumValues(SkDisplayTypes type); + static bool Infinity(const char* token, size_t len, void* callBack, SkScriptValue* ); + static bool IsFinite(const char* function, size_t len, SkTDArray& params, + void* callBack, SkScriptValue* ); + static bool IsNaN(const char* function, size_t len, SkTDArray& params, + void* callBack, SkScriptValue* ); + static bool NaN(const char* token, size_t len, void* callBack, SkScriptValue* ); + static bool Unbox(void* , SkScriptValue* scriptValue); + SkTDDisplayableArray fTrackDisplayable; + SkAnimateMaker& fMaker; + SkDisplayable* fParent; + SkDisplayable* fWorking; +private: + friend class SkDump; + friend struct SkScriptNAnswer; +#ifdef SK_SUPPORT_UNITTEST +public: + static void UnitTest(); +#endif +}; + +#endif // SkAnimatorScript_DEFINED + diff --git a/libs/graphics/animator/SkAnimatorScript2.cpp b/libs/graphics/animator/SkAnimatorScript2.cpp new file mode 100755 index 000000000..a3aeaf6fa --- /dev/null +++ b/libs/graphics/animator/SkAnimatorScript2.cpp @@ -0,0 +1,618 @@ +#include "SkAnimatorScript2.h" +#include "SkAnimateBase.h" +#include "SkAnimateMaker.h" +#include "SkDisplayTypes.h" +#include "SkExtras.h" +#include "SkMemberInfo.h" +#include "SkOpArray.h" +#include "SkParse.h" +#include "SkScript2.h" +#include "SkScriptCallBack.h" + +static const SkDisplayEnumMap gEnumMaps[] = { + { SkType_AddMode, "indirect|immediate" }, + { SkType_Align, "left|center|right" }, + { SkType_ApplyMode, "immediate|once" }, + { SkType_ApplyTransition, "reverse" }, + { SkType_BitmapEncoding, "jpeg|png" }, + { SkType_BitmapFormat, "none|A1|A8|Index8|RGB16|RGB32" }, + { SkType_Boolean, "false|true" }, + { SkType_Cap, "butt|round|square" }, + { SkType_EventCode, "none|up|down|left|right|back|end|OK|send|leftSoftKey|rightSoftKey|key0|key1|key2|key3|key4|key5|key6|key7|key8|key9|star|hash" }, + { SkType_EventKind, "none|keyChar|keyPress|mouseDown|mouseDrag|mouseMove|mouseUp|onEnd|onLoad|user" }, + { SkType_EventMode, "deferred|immediate" }, + { SkType_FillType, "winding|evenOdd" }, + { SkType_FilterType, "none|bilinear" }, + { SkType_FromPathMode, "normal|angle|position" }, + { SkType_Join, "miter|round|blunt" }, + { SkType_MaskFilterBlurStyle, "normal|solid|outer|inner" }, + { SkType_PathDirection, "cw|ccw" }, + { SkType_Style, "fill|stroke|strokeAndFill" }, + { SkType_TextBoxAlign, "start|center|end" }, + { SkType_TextBoxMode, "oneLine|lineBreak" }, + { SkType_TileMode, "clamp|repeat|mirror" }, + { SkType_Xfermode, "clear|src|dst|srcOver|dstOver|srcIn|dstIn|srcOut|dstOut|" + "srcATop|dstATop|xor|darken|lighten" }, +}; + +static int gEnumMapCount = SK_ARRAY_COUNT(gEnumMaps); + + +class SkAnimatorScript_Box : public SkScriptCallBackConvert { +public: + SkAnimatorScript_Box() {} + + ~SkAnimatorScript_Box() { + for (SkDisplayable** dispPtr = fTrackDisplayable.begin(); dispPtr < fTrackDisplayable.end(); dispPtr++) + delete *dispPtr; + } + + virtual bool convert(SkOperand2::OpType type, SkOperand2* operand) { + SkDisplayable* displayable; + switch (type) { + case SkOperand2::kArray: { + SkDisplayArray* boxedValue = new SkDisplayArray(*operand->fArray); + displayable = boxedValue; + } break; + case SkOperand2::kS32: { + SkDisplayInt* boxedValue = new SkDisplayInt; + displayable = boxedValue; + boxedValue->value = operand->fS32; + } break; + case SkOperand2::kScalar: { + SkDisplayFloat* boxedValue = new SkDisplayFloat; + displayable = boxedValue; + boxedValue->value = operand->fScalar; + } break; + case SkOperand2::kString: { + SkDisplayString* boxedValue = new SkDisplayString(*operand->fString); + displayable = boxedValue; + } break; + case SkOperand2::kObject: + return true; + default: + SkASSERT(0); + return false; + } + track(displayable); + operand->fObject = (void*) displayable; + return true; + } + + virtual SkOperand2::OpType getReturnType(int index) { + return SkOperand2::kObject; + } + + virtual Type getType() const { + return kBox; + } + + void track(SkDisplayable* displayable) { + SkASSERT(fTrackDisplayable.find(displayable) < 0); + *fTrackDisplayable.append() = displayable; + } + + SkTDDisplayableArray fTrackDisplayable; +}; + + +class SkAnimatorScript_Enum : public SkScriptCallBackProperty { +public: + SkAnimatorScript_Enum(const char* tokens) : fTokens(tokens) {} + + virtual bool getConstValue(const char* name, int len, SkOperand2* value) { + return SkAnimatorScript2::MapEnums(fTokens, name, len, &value->fS32); + } + +private: + const char* fTokens; +}; + + // !!! if type is string, call invoke + // if any other type, return original value + // distinction is undone: could do this by returning index == 0 only if param is string + // still, caller of getParamTypes will attempt to convert param to string (I guess) +class SkAnimatorScript_Eval : public SkScriptCallBackFunction { +public: + SkAnimatorScript_Eval(SkAnimatorScript2* engine) : fEngine(engine) {} + + virtual bool getIndex(const char* name, int len, size_t* result) { + if (SK_LITERAL_STR_EQUAL("eval", name, len) != 0) + return false; + *result = 0; + return true; + } + + virtual void getParamTypes(SkIntArray(SkOperand2::OpType)* types) { + types->setCount(1); + SkOperand2::OpType* type = types->begin(); + type[0] = SkOperand2::kString; + } + + virtual bool invoke(size_t index, SkOpArray* params, SkOperand2* answer) { + SkAnimatorScript2 engine(fEngine->getMaker(), fEngine->getWorking(), + SkAnimatorScript2::ToDisplayType(fEngine->getReturnType())); + SkOperand2* op = params->begin(); + const char* script = op->fString->c_str(); + SkScriptValue2 value; + return engine.evaluateScript(&script, &value); + SkASSERT(value.fType == fEngine->getReturnType()); + *answer = value.fOperand; + // !!! incomplete ? + return true; + } + +private: + SkAnimatorScript2* fEngine; +}; + +class SkAnimatorScript_ID : public SkScriptCallBackProperty { +public: + SkAnimatorScript_ID(SkAnimatorScript2* engine) : fEngine(engine) {} + + virtual bool getIndex(const char* token, int len, size_t* result) { + SkDisplayable* displayable; + bool success = fEngine->getMaker().find(token, len, &displayable); + if (success == false) { + *result = 0; + } else { + *result = (size_t) displayable; + SkDisplayable* working = fEngine->getWorking(); + if (displayable->canContainDependents() && working && working->isAnimate()) { + SkAnimateBase* animator = (SkAnimateBase*) working; + if (animator->isDynamic()) { + SkDisplayDepend* depend = (SkDisplayDepend* ) displayable; + depend->addDependent(working); + } + } + } + return true; + } + + virtual bool getResult(size_t ref, SkOperand2* answer) { + answer->fObject = (void*) ref; + return true; + } + + virtual SkOperand2::OpType getReturnType(size_t index) { + return index == 0 ? SkOperand2::kString : SkOperand2::kObject; + } + +private: + SkAnimatorScript2* fEngine; +}; + + +class SkAnimatorScript_Member : public SkScriptCallBackMember { +public: + + SkAnimatorScript_Member(SkAnimatorScript2* engine) : fEngine(engine) {} + + bool getMemberReference(const char* member, size_t len, void* object, SkScriptValue2* ref) { + SkDisplayable* displayable = (SkDisplayable*) object; + SkString name(member, len); + SkDisplayable* named = displayable->contains(name); + if (named) { + ref->fType = SkOperand2::kObject; + ref->fOperand.fObject = named; + return true; + } + const SkMemberInfo* info = displayable->getMember(name.c_str()); + if (info == nil) + return false; // !!! add additional error info? + ref->fType = SkAnimatorScript2::ToOpType(info->getType()); + ref->fOperand.fObject = (void*) info; + return true; + } + + bool invoke(size_t ref, void* object, SkOperand2* value) { + const SkMemberInfo* info = (const SkMemberInfo* ) ref; + SkDisplayable* displayable = (SkDisplayable*) object; + if (info->fType == SkType_MemberProperty) { + if (displayable->getProperty2(info->propertyIndex(), value) == false) { + return false; + } + } + return fEngine->evalMemberCommon(info, displayable, value); + } + + SkAnimatorScript2* fEngine; +}; + + +class SkAnimatorScript_MemberFunction : public SkScriptCallBackMemberFunction { +public: + SkAnimatorScript_MemberFunction(SkAnimatorScript2* engine) : fEngine(engine) {} + + bool getMemberReference(const char* member, size_t len, void* object, SkScriptValue2* ref) { + SkDisplayable* displayable = (SkDisplayable*) object; + SkString name(member, len); + const SkMemberInfo* info = displayable->getMember(name.c_str()); + if (info == nil || info->fType != SkType_MemberFunction) + return false; // !!! add additional error info? + ref->fType = SkAnimatorScript2::ToOpType(info->getType()); + ref->fOperand.fObject = (void*) info; + return true; + } + + virtual void getParamTypes(SkIntArray(SkOperand2::OpType)* types) { + types->setCount(3); + SkOperand2::OpType* type = types->begin(); + type[0] = type[1] = type[2] = SkOperand2::kS32; + } + + bool invoke(size_t ref, void* object, SkOpArray* params, SkOperand2* value) + { + const SkMemberInfo* info = (const SkMemberInfo* ) ref; + SkDisplayable* displayable = (SkDisplayable*) object; + displayable->executeFunction2(displayable, info->functionIndex(), params, info->getType(), + value); + return fEngine->evalMemberCommon(info, displayable, value); + } + + SkAnimatorScript2* fEngine; +}; + + +class SkAnimatorScript_NamedColor : public SkScriptCallBackProperty { +public: + virtual bool getConstValue(const char* name, int len, SkOperand2* value) { + return SkParse::FindNamedColor(name, len, (SkColor*) &value->fS32) != nil; + } +}; + + +class SkAnimatorScript_RGB : public SkScriptCallBackFunction { +public: + virtual bool getIndex(const char* name, int len, size_t* result) { + if (SK_LITERAL_STR_EQUAL("rgb", name, len) != 0) + return false; + *result = 0; + return true; + } + + virtual void getParamTypes(SkIntArray(SkOperand2::OpType)* types) { + types->setCount(3); + SkOperand2::OpType* type = types->begin(); + type[0] = type[1] = type[2] = SkOperand2::kS32; + } + + virtual bool invoke(size_t index, SkOpArray* params, SkOperand2* answer) { + SkASSERT(index == 0); + unsigned result = 0xFF000000; + int shift = 16; + for (int index = 0; index < 3; index++) { + result |= SkClampMax(params->begin()[index].fS32, 255) << shift; + shift -= 8; + } + answer->fS32 = result; + return true; + } + +}; + + +class SkAnimatorScript_Unbox : public SkScriptCallBackConvert { +public: + SkAnimatorScript_Unbox(SkAnimatorScript2* engine) : fEngine(engine) {} + + virtual bool convert(SkOperand2::OpType type, SkOperand2* operand) { + SkASSERT(type == SkOperand2::kObject); + SkDisplayable* displayable = (SkDisplayable*) operand->fObject; + switch (displayable->getType()) { + case SkType_Array: { + SkDisplayArray* boxedValue = (SkDisplayArray*) displayable; + operand->fArray = new SkOpArray(SkAnimatorScript2::ToOpType(boxedValue->values.getType())); + int count = boxedValue->values.count(); + operand->fArray->setCount(count); + memcpy(operand->fArray->begin(), boxedValue->values.begin(), count * sizeof(SkOperand2)); + fEngine->track(operand->fArray); + } break; + case SkType_Boolean: { + SkDisplayBoolean* boxedValue = (SkDisplayBoolean*) displayable; + operand->fS32 = boxedValue->value; + } break; + case SkType_Int: { + SkDisplayInt* boxedValue = (SkDisplayInt*) displayable; + operand->fS32 = boxedValue->value; + } break; + case SkType_Float: { + SkDisplayFloat* boxedValue = (SkDisplayFloat*) displayable; + operand->fScalar = boxedValue->value; + } break; + case SkType_String: { + SkDisplayString* boxedValue = (SkDisplayString*) displayable; + operand->fString = SkNEW_ARGS(SkString, (boxedValue->value)); + } break; + default: { + const char* id; + bool success = fEngine->getMaker().findKey(displayable, &id); + SkASSERT(success); + operand->fString = SkNEW_ARGS(SkString, (id)); + } + } + return true; + } + + virtual SkOperand2::OpType getReturnType(int /*index*/, SkOperand2* operand) { + SkDisplayable* displayable = (SkDisplayable*) operand->fObject; + switch (displayable->getType()) { + case SkType_Array: + return SkOperand2::kArray; + case SkType_Int: + return SkOperand2::kS32; + case SkType_Float: + return SkOperand2::kScalar; + case SkType_String: + default: + return SkOperand2::kString; + } + } + + virtual Type getType() const { + return kUnbox; + } + + SkAnimatorScript2* fEngine; +}; + +SkAnimatorScript2::SkAnimatorScript2(SkAnimateMaker& maker, SkDisplayable* working, SkDisplayTypes type) : + SkScriptEngine2(ToOpType(type)), fMaker(maker), fWorking(working) { + *fCallBackArray.append() = new SkAnimatorScript_Member(this); + *fCallBackArray.append() = new SkAnimatorScript_MemberFunction(this); + *fCallBackArray.append() = new SkAnimatorScript_Box(); + *fCallBackArray.append() = new SkAnimatorScript_Unbox(this); + *fCallBackArray.append() = new SkAnimatorScript_ID(this); + if (type == SkType_ARGB) { + *fCallBackArray.append() = new SkAnimatorScript_RGB(); + *fCallBackArray.append() = new SkAnimatorScript_NamedColor(); + } + if (SkDisplayType::IsEnum(&maker, type)) { + // !!! for SpiderMonkey, iterate through the enum values, and map them to globals + const SkDisplayEnumMap& map = GetEnumValues(type); + *fCallBackArray.append() = new SkAnimatorScript_Enum(map.fValues); + } + *fCallBackArray.append() = new SkAnimatorScript_Eval(this); +#if 0 // !!! no extra support for now + for (SkExtras** extraPtr = maker.fExtras.begin(); extraPtr < maker.fExtras.end(); extraPtr++) { + SkExtras* extra = *extraPtr; + if (extra->fExtraCallBack) + *fCallBackArray.append() = new propertyCallBack(extra->fExtraCallBack, extra->fExtraStorage); + } +#endif +} + +SkAnimatorScript2::~SkAnimatorScript2() { + SkScriptCallBack** end = fCallBackArray.end(); + for (SkScriptCallBack** ptr = fCallBackArray.begin(); ptr < end; ptr++) + delete *ptr; +} + +bool SkAnimatorScript2::evalMemberCommon(const SkMemberInfo* info, + SkDisplayable* displayable, SkOperand2* value) { + SkDisplayTypes original; + SkDisplayTypes type = original = (SkDisplayTypes) info->getType(); + if (info->fType == SkType_Array) + type = SkType_Array; + switch (type) { + case SkType_ARGB: + type = SkType_Int; + case SkType_Boolean: + case SkType_Int: + case SkType_MSec: + case SkType_Float: + SkASSERT(info->getCount() == 1); + if (info->fType != SkType_MemberProperty && info->fType != SkType_MemberFunction) + value->fS32 = *(int32_t*) info->memberData(displayable); // OK for SkScalar too + if (type == SkType_MSec) { + value->fScalar = SkScalarDiv((SkScalar) value->fS32, 1000); // dividing two ints is the same as dividing two scalars + type = SkType_Float; + } + break; + case SkType_String: { + SkString* displayableString; + if (info->fType != SkType_MemberProperty && info->fType != SkType_MemberFunction) { + info->getString(displayable, &displayableString); + value->fString = new SkString(*displayableString); + } + } break; + case SkType_Array: { + SkASSERT(info->fType != SkType_MemberProperty); // !!! incomplete + SkTDOperandArray* displayableArray = (SkTDOperandArray*) info->memberData(displayable); + if (displayable->getType() == SkType_Array) { + SkDisplayArray* typedArray = (SkDisplayArray*) displayable; + original = typedArray->values.getType(); + } + SkASSERT(original != SkType_Unknown); + SkOpArray* array = value->fArray = new SkOpArray(ToOpType(original)); + track(array); + int count = displayableArray->count(); + if (count > 0) { + array->setCount(count); + memcpy(array->begin(), displayableArray->begin(), count * sizeof(SkOperand2)); + } + } break; + default: + SkASSERT(0); // unimplemented + } + return true; +} + +const SkDisplayEnumMap& SkAnimatorScript2::GetEnumValues(SkDisplayTypes type) { + int index = SkTSearch(&gEnumMaps[0].fType, gEnumMapCount, type, + sizeof(SkDisplayEnumMap)); + SkASSERT(index >= 0); + return gEnumMaps[index]; +} + +SkDisplayTypes SkAnimatorScript2::ToDisplayType(SkOperand2::OpType type) { + int val = type; + switch (val) { + case SkOperand2::kNoType: + return SkType_Unknown; + case SkOperand2::kS32: + return SkType_Int; + case SkOperand2::kScalar: + return SkType_Float; + case SkOperand2::kString: + return SkType_String; + case SkOperand2::kArray: + return SkType_Array; + case SkOperand2::kObject: + return SkType_Displayable; + default: + SkASSERT(0); + return SkType_Unknown; + } +} + +SkOperand2::OpType SkAnimatorScript2::ToOpType(SkDisplayTypes type) { + if (SkDisplayType::IsDisplayable(nil /* fMaker */, type)) + return SkOperand2::kObject; + if (SkDisplayType::IsEnum(nil /* fMaker */, type)) + return SkOperand2::kS32; + switch (type) { + case SkType_ARGB: + case SkType_MSec: + case SkType_Int: + return SkOperand2::kS32; + case SkType_Float: + case SkType_Point: + case SkType_3D_Point: + return SkOperand2::kScalar; + case SkType_Base64: + case SkType_DynamicString: + case SkType_String: + return SkOperand2::kString; + case SkType_Array: + return SkOperand2::kArray; + case SkType_Unknown: + return SkOperand2::kNoType; + default: + SkASSERT(0); + return SkOperand2::kNoType; + } +} + +bool SkAnimatorScript2::MapEnums(const char* ptr, const char* match, size_t len, int* value) { + int index = 0; + bool more = true; + do { + const char* last = strchr(ptr, '|'); + if (last == nil) { + last = &ptr[strlen(ptr)]; + more = false; + } + size_t length = last - ptr; + if (len == length && strncmp(ptr, match, length) == 0) { + *value = index; + return true; + } + index++; + ptr = last + 1; + } while (more); + return false; +} + +#if defined SK_DEBUG + +#include "SkAnimator.h" + +static const char scriptTestSetup[] = +"" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" +""; + +#if !defined(SK_BUILD_FOR_BREW) +static const SkScriptNAnswer scriptTests[] = { + { "alpha+alpha", SkType_String, 0, 0, "abcabc" }, + { "0 ? Math.sin(0) : 1", SkType_Int, 1 }, + { "intArray[4]", SkType_Unknown }, + { "emptyArray[4]", SkType_Unknown }, + { "idx", SkType_Int, 2 }, + { "intArray.length", SkType_Int, 3 }, + { "intArray.values[0]", SkType_Int, 1 }, + { "intArray[0]", SkType_Int, 1 }, + { "idx.value", SkType_Int, 2 }, + { "alpha.value", SkType_String, 0, 0, "abc" }, + { "alpha", SkType_String, 0, 0, "abc" }, + { "alpha.value+alpha.value", SkType_String, 0, 0, "abcabc" }, + { "alpha+idx", SkType_String, 0, 0, "abc2" }, + { "idx+alpha", SkType_String, 0, 0, "2abc" }, + { "intArray[idx]", SkType_Int, 6 }, + { "alpha.slice(1,2)", SkType_String, 0, 0, "b" }, + { "alpha.value.slice(1,2)", SkType_String, 0, 0, "b" }, + { "Math.sin(0)", SkType_Float, 0, SkIntToScalar(0) }, + { "testRect.left+2", SkType_Float, 0, SkIntToScalar(3) }, + { "0 ? intArray[0] : 1", SkType_Int, 1 }, + { "0 ? intArray.values[0] : 1", SkType_Int, 1 }, + { "0 ? idx : 1", SkType_Int, 1 }, + { "0 ? idx.value : 1", SkType_Int, 1 }, + { "0 ? alpha.slice(1,2) : 1", SkType_Int, 1 }, + { "0 ? alpha.value.slice(1,2) : 1", SkType_Int, 1 }, + { "idy", SkType_Int, 3 } +}; +#endif + +#define SkScriptNAnswer_testCount SK_ARRAY_COUNT(scriptTests) + +void SkAnimatorScript2::UnitTest() { +#if !defined(SK_BUILD_FOR_BREW) && defined(SK_SUPPORT_UNITTEST) + SkAnimator animator; + SkASSERT(animator.decodeMemory(scriptTestSetup, sizeof(scriptTestSetup)-1)); + SkEvent evt; + evt.setString("id", "evt"); + evt.setS32("x", 3); + animator.doUserEvent(evt); + // set up animator with memory script above, then run value tests + for (int index = 0; index < SkScriptNAnswer_testCount; index++) { + SkAnimatorScript2 engine(*animator.fMaker, nil, scriptTests[index].fType); + SkScriptValue2 value; + const char* script = scriptTests[index].fScript; + bool success = engine.evaluateScript(&script, &value); + if (success == false) { + SkASSERT(scriptTests[index].fType == SkType_Unknown); + continue; + } + SkASSERT(value.fType == ToOpType(scriptTests[index].fType)); + SkScalar error; + switch (value.fType) { + case SkOperand2::kS32: + SkASSERT(value.fOperand.fS32 == scriptTests[index].fIntAnswer); + break; + case SkOperand2::kScalar: + error = SkScalarAbs(value.fOperand.fScalar - scriptTests[index].fScalarAnswer); + SkASSERT(error < SK_Scalar1 / 10000); + break; + case SkOperand2::kString: + SkASSERT(value.fOperand.fString->equals(scriptTests[index].fStringAnswer)); + break; + default: + SkASSERT(0); + } + } +#endif +} + +#endif + diff --git a/libs/graphics/animator/SkAnimatorScript2.h b/libs/graphics/animator/SkAnimatorScript2.h new file mode 100755 index 000000000..61261e91e --- /dev/null +++ b/libs/graphics/animator/SkAnimatorScript2.h @@ -0,0 +1,43 @@ +#ifndef SkAnimatorScript2_DEFINED +#define SkAnimatorScript2_DEFINED + +#include "SkDisplayable.h" +#include "SkScript2.h" +#include "SkTypedArray.h" + +class SkAnimateMaker; +struct SkMemberInfo; + +#ifndef SkAnimatorScript_DEFINED +struct SkDisplayEnumMap { + SkDisplayTypes fType; + const char* fValues; +}; +#endif + +class SkAnimatorScript2 : public SkScriptEngine2 { +public: + SkAnimatorScript2(SkAnimateMaker& , SkDisplayable* working, SkDisplayTypes type); + ~SkAnimatorScript2(); + bool evalMemberCommon(const SkMemberInfo* info, + SkDisplayable* displayable, SkOperand2* value); + SkAnimateMaker& getMaker() { return fMaker; } + SkDisplayable* getWorking() { return fWorking; } + static bool MapEnums(const char* ptr, const char* match, size_t len, int* value); + static const SkDisplayEnumMap& GetEnumValues(SkDisplayTypes type); + static SkDisplayTypes ToDisplayType(SkOperand2::OpType type); + static SkOperand2::OpType ToOpType(SkDisplayTypes type); +private: + SkAnimateMaker& fMaker; + SkDisplayable* fWorking; + friend class SkDump; + friend struct SkScriptNAnswer; + // illegal + SkAnimatorScript2& operator=(const SkAnimatorScript2&); +#ifdef SK_DEBUG +public: + static void UnitTest(); +#endif +}; + +#endif // SkAnimatorScript2_DEFINED diff --git a/libs/graphics/animator/SkBase64.cpp b/libs/graphics/animator/SkBase64.cpp new file mode 100644 index 000000000..664841ab1 --- /dev/null +++ b/libs/graphics/animator/SkBase64.cpp @@ -0,0 +1,171 @@ +#include "SkBase64.h" + +#define DecodePad -2 +#define EncodePad 64 + +static const char encode[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/="; + +static const signed char decodeData[] = { + 62, -1, -1, -1, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, DecodePad, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 +}; + +SkBase64::SkBase64() : fLength((size_t) -1), fData(nil) { +} + +#if defined _WIN32 && _MSC_VER >= 1300 // disable 'two', etc. may be used without having been initialized +#pragma warning ( push ) +#pragma warning ( disable : 4701 ) +#endif + +SkBase64::Error SkBase64::decode(const void* srcPtr, size_t size, bool writeDestination) { + unsigned char* dst = (unsigned char*) fData; + const unsigned char* dstStart = (const unsigned char*) fData; + const unsigned char* src = (const unsigned char*) srcPtr; + bool padTwo = false; + bool padThree = false; + const unsigned char* end = src + size; + while (src < end) { + unsigned char bytes[4]; + int byte = 0; + do { + unsigned char srcByte = *src++; + if (srcByte == 0) + goto goHome; + if (srcByte <= ' ') + continue; // treat as white space + if (srcByte < '+' || srcByte > 'z') + return kBadCharError; + signed char decoded = decodeData[srcByte - '+']; + bytes[byte] = decoded; + if (decoded < 0) { + if (decoded == DecodePad) + goto handlePad; + return kBadCharError; + } else + byte++; + if (*src) + continue; + if (byte == 0) + goto goHome; + if (byte == 4) + break; +handlePad: + if (byte < 2) + return kPadError; + padThree = true; + if (byte == 2) + padTwo = true; + break; + } while (byte < 4); + int two, three; + if (writeDestination) { + int one = (U8) (bytes[0] << 2); + two = bytes[1]; + one |= two >> 4; + two = (U8) (two << 4); + three = bytes[2]; + two |= three >> 2; + three = (U8) (three << 6); + three |= bytes[3]; + SkASSERT(one < 256 && two < 256 && three < 256); + *dst = (unsigned char) one; + } + dst++; + if (padTwo) + break; + if (writeDestination) + *dst = (unsigned char) two; + dst++; + if (padThree) + break; + if (writeDestination) + *dst = (unsigned char) three; + dst++; + } +goHome: + fLength = dst - dstStart; + return kNoError; +} + +#if defined _WIN32 && _MSC_VER >= 1300 +#pragma warning ( pop ) +#endif + +size_t SkBase64::Encode(const void* srcPtr, size_t length, void* dstPtr) { + const unsigned char* src = (const unsigned char*) srcPtr; + unsigned char* dst = (unsigned char*) dstPtr; + if (dst) { + size_t remainder = length % 3; + const unsigned char* end = &src[length - remainder]; + while (src < end) { + unsigned a = *src++; + unsigned b = *src++; + unsigned c = *src++; + int d = c & 0x3F; + c = (c >> 6 | b << 2) & 0x3F; + b = (b >> 4 | a << 4) & 0x3F; + a = a >> 2; + *dst++ = encode[a]; + *dst++ = encode[b]; + *dst++ = encode[c]; + *dst++ = encode[d]; + } + if (remainder > 0) { + int k1 = 0; + int k2 = EncodePad; + int a = (U8) *src++; + if (remainder == 2) + { + int b = *src++; + k1 = b >> 4; + k2 = (b << 2) & 0x3F; + } + *dst++ = encode[a >> 2]; + *dst++ = encode[(k1 | a << 4) & 0x3F]; + *dst++ = encode[k2]; + *dst++ = encode[EncodePad]; + } + } + return (length + 2) / 3 * 4; +} + +SkBase64::Error SkBase64::decode(const char* src, size_t len) { + Error err = decode(src, len, false); + SkASSERT(err == kNoError); + if (err != kNoError) + return err; + fData = new char[fLength]; // should use sk_malloc/sk_free + decode(src, len, true); + return kNoError; +} + +#ifdef SK_SUPPORT_UNITTEST +void SkBase64::UnitTest() { + signed char all[256]; + for (int index = 0; index < 256; index++) + all[index] = (signed char) (index + 1); + for (int offset = 0; offset < 6; offset++) { + size_t length = 256 - offset; + size_t encodeLength = Encode(all + offset, length, nil); + char* src = (char*)sk_malloc_throw(encodeLength + 1); + Encode(all + offset, length, src); + src[encodeLength] = '\0'; + SkBase64 tryMe; + tryMe.decode(src, encodeLength); + SkASSERT(length == tryMe.fLength); + SkASSERT(strcmp((const char*) (all + offset), tryMe.fData) == 0); + sk_free(src); + delete[] tryMe.fData; + } +} +#endif + + diff --git a/libs/graphics/animator/SkBase64.h b/libs/graphics/animator/SkBase64.h new file mode 100644 index 000000000..4132dd3d2 --- /dev/null +++ b/libs/graphics/animator/SkBase64.h @@ -0,0 +1,30 @@ +#ifndef SkBase64_DEFINED +#define SkBase64_DEFINED + +#include "SkTypes.h" + +struct SkBase64 { +public: + enum Error { + kNoError, + kPadError, + kBadCharError + }; + + SkBase64(); + Error decode(const char* src, size_t length); + char* getData() { return fData; } + static size_t Encode(const void* src, size_t length, void* dest); + +#ifdef SK_SUPPORT_UNITTEST + static void UnitTest(); +#endif +private: + Error decode(const void* srcPtr, size_t length, bool writeDestination); + + size_t fLength; + char* fData; + friend class SkImage; +}; + +#endif // SkBase64_DEFINED diff --git a/libs/graphics/animator/SkBoundable.cpp b/libs/graphics/animator/SkBoundable.cpp new file mode 100644 index 000000000..92c8fd00b --- /dev/null +++ b/libs/graphics/animator/SkBoundable.cpp @@ -0,0 +1,47 @@ +#include "SkBoundable.h" +#include "SkAnimateMaker.h" +#include "SkCanvas.h" + +SkBoundable::SkBoundable() { + clearBounds(); + fBounds.fTop = 0; + fBounds.fRight = 0; + fBounds.fBottom = 0; +} + +void SkBoundable::clearBounder() { + fBounds.fLeft = 0x7fff; +} + +void SkBoundable::getBounds(SkRect* rect) { + SkASSERT(rect); + if (fBounds.fLeft == (S16)0x8000U) { + INHERITED::getBounds(rect); + return; + } + rect->fLeft = SkIntToScalar(fBounds.fLeft); + rect->fTop = SkIntToScalar(fBounds.fTop); + rect->fRight = SkIntToScalar(fBounds.fRight); + rect->fBottom = SkIntToScalar(fBounds.fBottom); +} + +void SkBoundable::enableBounder() { + fBounds.fLeft = 0; +} + + +SkBoundableAuto::SkBoundableAuto(SkBoundable* boundable, + SkAnimateMaker& maker) : fBoundable(boundable), fMaker(maker) { + if (fBoundable->hasBounds()) { + fMaker.fCanvas->setBounder(&maker.fDisplayList); + fMaker.fDisplayList.fBounds.setEmpty(); + } +} + +SkBoundableAuto::~SkBoundableAuto() { + if (fBoundable->hasBounds() == false) + return; + fMaker.fCanvas->setBounder(nil); + fBoundable->setBounds(fMaker.fDisplayList.fBounds); +} + diff --git a/libs/graphics/animator/SkBoundable.h b/libs/graphics/animator/SkBoundable.h new file mode 100644 index 000000000..d3e358652 --- /dev/null +++ b/libs/graphics/animator/SkBoundable.h @@ -0,0 +1,33 @@ +#ifndef SkBoundable_DEFINED +#define SkBoundable_DEFINED + +#include "SkDrawable.h" +#include "SkRect.h" + +class SkBoundable : public SkDrawable { +public: + SkBoundable(); + virtual void clearBounder(); + virtual void enableBounder(); + virtual void getBounds(SkRect* ); + bool hasBounds() { return fBounds.fLeft != (S16)0x8000U; } + void setBounds(SkRect16& bounds) { fBounds = bounds; } +protected: + void clearBounds() { fBounds.fLeft = (S16) SkToU16(0x8000); }; // mark bounds as unset + SkRect16 fBounds; +private: + typedef SkDrawable INHERITED; +}; + +class SkBoundableAuto { +public: + SkBoundableAuto(SkBoundable* boundable, SkAnimateMaker& maker); + ~SkBoundableAuto(); +private: + SkBoundable* fBoundable; + SkAnimateMaker& fMaker; + SkBoundableAuto& operator= (const SkBoundableAuto& ); +}; + +#endif // SkBoundable_DEFINED + diff --git a/libs/graphics/animator/SkBuildCondensedInfo.cpp b/libs/graphics/animator/SkBuildCondensedInfo.cpp new file mode 100644 index 000000000..6c2949930 --- /dev/null +++ b/libs/graphics/animator/SkBuildCondensedInfo.cpp @@ -0,0 +1,275 @@ +#include "SkTypes.h" +#if defined SK_BUILD_CONDENSED +#include "SkMemberInfo.h" +#if SK_USE_CONDENSED_INFO == 1 +#error "SK_USE_CONDENSED_INFO must be zero to build condensed info" +#endif +#if !defined SK_BUILD_FOR_WIN32 +#error "SK_BUILD_FOR_WIN32 must be defined to build condensed info" +#endif +#include "SkDisplayType.h" +#include "SkIntArray.h" +#include + +SkTDMemberInfoArray gInfos; +SkTDIntArray gInfosCounts; +SkTDDisplayTypesArray gInfosTypeIDs; +SkTDMemberInfoArray gUnknowns; +SkTDIntArray gUnknownsCounts; + +static void AddInfo(SkDisplayTypes type, const SkMemberInfo* info, int infoCount) { + SkASSERT(gInfos[type] == nil); + gInfos[type] = info; + gInfosCounts[type] = infoCount; + *gInfosTypeIDs.append() = type; + size_t allStrs = 0; + for (int inner = 0; inner < infoCount; inner++) { + SkASSERT(info[inner].fCount < 256); + int offset = (int) info[inner].fOffset; + SkASSERT(offset < 128 && offset > -129); + SkASSERT(allStrs < 256); + if (info[inner].fType == SkType_BaseClassInfo) { + const SkMemberInfo* innerInfo = (const SkMemberInfo*) info[inner].fName; + if (gUnknowns.find(innerInfo) == -1) { + *gUnknowns.append() = innerInfo; + *gUnknownsCounts.append() = info[inner].fCount; + } + } + if (info[inner].fType != SkType_BaseClassInfo && info[inner].fName) + allStrs += strlen(info[inner].fName); + allStrs += 1; + SkASSERT(info[inner].fType < 256); + } +} + +static void WriteInfo(FILE* condensed, const SkMemberInfo* info, int infoCount, + const char* typeName, bool draw, bool display) { + fprintf(condensed, "static const char g%sStrings[] = \n", typeName); + int inner; + // write strings + for (inner = 0; inner < infoCount; inner++) { + const char* name = (info[inner].fType != SkType_BaseClassInfo && info[inner].fName) ? + info[inner].fName : ""; + const char* zero = inner < infoCount - 1 ? "\\0" : ""; + fprintf(condensed, "\t\"%s%s\"\n", name, zero); + } + fprintf(condensed, ";\n\nstatic const SkMemberInfo g%s", draw ? "Draw" : display ? "Display" : ""); + fprintf(condensed, "%sInfo[] = {", typeName); + size_t nameOffset = 0; + // write info tables + for (inner = 0; inner < infoCount; inner++) { + size_t offset = info[inner].fOffset; + if (info[inner].fType == SkType_BaseClassInfo) { + offset = (size_t) gInfos.find((const SkMemberInfo* ) info[inner].fName); + SkASSERT((int) offset >= 0); + offset = gInfosTypeIDs.find((SkDisplayTypes) offset); + SkASSERT((int) offset >= 0); + } + fprintf(condensed, "\n\t{%d, %d, %d, %d}", nameOffset, offset, + info[inner].fType, info[inner].fCount); + if (inner < infoCount - 1) + putc(',', condensed); + if (info[inner].fType != SkType_BaseClassInfo && info[inner].fName) + nameOffset += strlen(info[inner].fName); + nameOffset += 1; + } + fprintf(condensed, "\n};\n\n"); +} + +static void Get3DName(char* scratch, const char* name) { + if (strncmp("skia3d:", name, sizeof("skia3d:") - 1) == 0) { + strcpy(scratch, "3D_"); + scratch[3]= name[7] & ~0x20; + strcpy(&scratch[4], &name[8]); + } else { + scratch[0] = name[0] & ~0x20; + strcpy(&scratch[1], &name[1]); + } +} + +int type_compare(const void* a, const void* b) { + SkDisplayTypes first = *(SkDisplayTypes*) a; + SkDisplayTypes second = *(SkDisplayTypes*) b; + return first < second ? -1 : first == second ? 0 : 1; +} + +void SkDisplayType::BuildCondensedInfo(SkAnimateMaker* maker) { + gInfos.setCount(kNumberOfTypes); + memset(gInfos.begin(), 0, sizeof(gInfos[0]) * kNumberOfTypes); + gInfosCounts.setCount(kNumberOfTypes); + memset(gInfosCounts.begin(), -1, sizeof(gInfosCounts[0]) * kNumberOfTypes); + // check to see if it is condensable + int index, infoCount; + for (index = 0; index < kTypeNamesSize; index++) { + const SkMemberInfo* info = GetMembers(maker, gTypeNames[index].fType, &infoCount); + if (info == nil) + continue; + AddInfo(gTypeNames[index].fType, info, infoCount); + } + const SkMemberInfo* extraInfo = + SkDisplayType::GetMembers(maker, SkType_3D_Point, &infoCount); + AddInfo(SkType_Point, extraInfo, infoCount); + AddInfo(SkType_3D_Point, extraInfo, infoCount); +// int baseInfos = gInfos.count(); + do { + SkTDMemberInfoArray oldRefs = gUnknowns; + SkTDIntArray oldRefCounts = gUnknownsCounts; + gUnknowns.reset(); + gUnknownsCounts.reset(); + for (index = 0; index < oldRefs.count(); index++) { + const SkMemberInfo* info = oldRefs[index]; + if (gInfos.find(info) == -1) { + int typeIndex = 0; + for (; typeIndex < kNumberOfTypes; typeIndex++) { + const SkMemberInfo* temp = SkDisplayType::GetMembers( + maker, (SkDisplayTypes) typeIndex, nil); + if (temp == info) + break; + } + SkASSERT(typeIndex < kNumberOfTypes); + AddInfo((SkDisplayTypes) typeIndex, info, oldRefCounts[index]); + } + } + } while (gUnknowns.count() > 0); + qsort(gInfosTypeIDs.begin(), gInfosTypeIDs.count(), sizeof(gInfosTypeIDs[0]), &type_compare); +#ifdef SK_DEBUG + FILE* condensed = fopen("../../src/animator/SkCondensedDebug.cpp", "w+"); + fprintf(condensed, "#include \"SkTypes.h\"\n"); + fprintf(condensed, "#ifdef SK_DEBUG\n"); +#else + FILE* condensed = fopen("../../src/animator/SkCondensedRelease.cpp", "w+"); + fprintf(condensed, "#include \"SkTypes.h\"\n"); + fprintf(condensed, "#ifdef SK_RELEASE\n"); +#endif + // write header + fprintf(condensed, "// This file was automatically generated.\n"); + fprintf(condensed, "// To change it, edit the file with the matching debug info.\n"); + fprintf(condensed, "// Then execute SkDisplayType::BuildCondensedInfo() to " + "regenerate this file.\n\n"); + // write name of memberInfo + int typeNameIndex = 0; + int unknown = 1; + for (index = 0; index < gInfos.count(); index++) { + const SkMemberInfo* info = gInfos[index]; + if (info == nil) + continue; + char scratch[64]; + bool drawPrefix, displayPrefix; + while (gTypeNames[typeNameIndex].fType < index) + typeNameIndex++; + if (gTypeNames[typeNameIndex].fType == index) { + Get3DName(scratch, gTypeNames[typeNameIndex].fName); + drawPrefix = gTypeNames[typeNameIndex].fDrawPrefix; + displayPrefix = gTypeNames[typeNameIndex].fDisplayPrefix; + } else { + sprintf(scratch, "Unknown%d", unknown++); + drawPrefix = displayPrefix = false; + } + WriteInfo(condensed, info, gInfosCounts[index], scratch, drawPrefix, displayPrefix); + } + // write array of table pointers +// start here; + fprintf(condensed, "static const SkMemberInfo* const gInfoTables[] = {"); + typeNameIndex = 0; + unknown = 1; + for (index = 0; index < gInfos.count(); index++) { + const SkMemberInfo* info = gInfos[index]; + if (info == nil) + continue; + char scratch[64]; + bool drawPrefix, displayPrefix; + while (gTypeNames[typeNameIndex].fType < index) + typeNameIndex++; + if (gTypeNames[typeNameIndex].fType == index) { + Get3DName(scratch, gTypeNames[typeNameIndex].fName); + drawPrefix = gTypeNames[typeNameIndex].fDrawPrefix; + displayPrefix = gTypeNames[typeNameIndex].fDisplayPrefix; + } else { + sprintf(scratch, "Unknown%d", unknown++); + drawPrefix = displayPrefix = false; + } + fprintf(condensed, "\n\tg"); + if (drawPrefix) + fprintf(condensed, "Draw"); + if (displayPrefix) + fprintf(condensed, "Display"); + fprintf(condensed, "%sInfo", scratch); + if (index < gInfos.count() - 1) + putc(',', condensed); + } + fprintf(condensed, "\n};\n\n"); + // write the array of number of entries in the info table + fprintf(condensed, "static const unsigned char gInfoCounts[] = {\n\t"); + int written = 0; + for (index = 0; index < gInfosCounts.count(); index++) { + int count = gInfosCounts[index]; + if (count < 0) + continue; + if (written > 0) + putc(',', condensed); + if (written % 20 == 19) + fprintf(condensed, "\n\t"); + fprintf(condensed, "%d",count); + written++; + } + fprintf(condensed, "\n};\n\n"); + // write array of type ids table entries correspond to + fprintf(condensed, "static const unsigned char gTypeIDs[] = {\n\t"); + int typeIDCount = 0; + typeNameIndex = 0; + unknown = 1; + for (index = 0; index < gInfosCounts.count(); index++) { + const SkMemberInfo* info = gInfos[index]; + if (info == nil) + continue; + typeIDCount++; + char scratch[64]; + while (gTypeNames[typeNameIndex].fType < index) + typeNameIndex++; + if (gTypeNames[typeNameIndex].fType == index) { + Get3DName(scratch, gTypeNames[typeNameIndex].fName); + } else + sprintf(scratch, "Unknown%d", unknown++); + fprintf(condensed, "%d%c // %s\n\t", index, + index < gInfosCounts.count() ? ',' : ' ', scratch); + } + fprintf(condensed, "\n};\n\n"); + fprintf(condensed, "static const int kTypeIDs = %d;\n\n", typeIDCount); + // write the array of string pointers + fprintf(condensed, "static const char* const gInfoNames[] = {"); + typeNameIndex = 0; + unknown = 1; + written = 0; + for (index = 0; index < gInfosCounts.count(); index++) { + const SkMemberInfo* info = gInfos[index]; + if (info == nil) + continue; + if (written > 0) + putc(',', condensed); + written++; + fprintf(condensed, "\n\tg"); + char scratch[64]; + while (gTypeNames[typeNameIndex].fType < index) + typeNameIndex++; + if (gTypeNames[typeNameIndex].fType == index) { + Get3DName(scratch, gTypeNames[typeNameIndex].fName); + } else + sprintf(scratch, "Unknown%d", unknown++); + fprintf(condensed, "%sStrings", scratch); + } + fprintf(condensed, "\n};\n\n"); + fprintf(condensed, "#endif\n"); + fclose(condensed); + gInfos.reset(); + gInfosCounts.reset(); + gInfosTypeIDs.reset(); + gUnknowns.reset(); + gUnknownsCounts.reset(); +} + +#elif defined SK_DEBUG +#include "SkDisplayType.h" +void SkDisplayType::BuildCondensedInfo(SkAnimateMaker* ) {} +#endif + + diff --git a/libs/graphics/animator/SkCondensedDebug.cpp b/libs/graphics/animator/SkCondensedDebug.cpp new file mode 100644 index 000000000..f60487ba8 --- /dev/null +++ b/libs/graphics/animator/SkCondensedDebug.cpp @@ -0,0 +1,1380 @@ +#include "SkTypes.h" +#ifndef SK_BUILD_FOR_UNIX +#ifdef SK_DEBUG +// This file was automatically generated. +// To change it, edit the file with the matching debug info. +// Then execute SkDisplayType::BuildCondensedInfo() to regenerate this file. + +static const char gMathStrings[] = + "E\0" + "LN10\0" + "LN2\0" + "LOG10E\0" + "LOG2E\0" + "PI\0" + "SQRT1_2\0" + "SQRT2\0" + "abs\0" + "acos\0" + "asin\0" + "atan\0" + "atan2\0" + "ceil\0" + "cos\0" + "exp\0" + "floor\0" + "log\0" + "max\0" + "min\0" + "pow\0" + "random\0" + "round\0" + "sin\0" + "sqrt\0" + "tan" +; + +static const SkMemberInfo gMathInfo[] = { + {0, -1, 67, 98}, + {2, -2, 67, 98}, + {7, -3, 67, 98}, + {11, -4, 67, 98}, + {18, -5, 67, 98}, + {24, -6, 67, 98}, + {27, -7, 67, 98}, + {35, -8, 67, 98}, + {41, -1, 66, 98}, + {45, -2, 66, 98}, + {50, -3, 66, 98}, + {55, -4, 66, 98}, + {60, -5, 66, 98}, + {66, -6, 66, 98}, + {71, -7, 66, 98}, + {75, -8, 66, 98}, + {79, -9, 66, 98}, + {85, -10, 66, 98}, + {89, -11, 66, 98}, + {93, -12, 66, 98}, + {97, -13, 66, 98}, + {101, -14, 66, 98}, + {108, -15, 66, 98}, + {114, -16, 66, 98}, + {118, -17, 66, 98}, + {123, -18, 66, 98} +}; + +static const char gAddStrings[] = + "inPlace\0" + "offset\0" + "use\0" + "where" +; + +static const SkMemberInfo gAddInfo[] = { + {0, 16, 26, 1}, + {8, 20, 96, 1}, + {15, 24, 37, 1}, + {19, 28, 37, 1} +}; + +static const char gAddCircleStrings[] = + "\0" + "radius\0" + "x\0" + "y" +; + +static const SkMemberInfo gAddCircleInfo[] = { + {0, 3, 18, 1}, + {1, 24, 98, 1}, + {8, 28, 98, 1}, + {10, 32, 98, 1} +}; + +static const char gUnknown1Strings[] = + "direction" +; + +static const SkMemberInfo gUnknown1Info[] = { + {0, 20, 75, 1} +}; + +static const char gAddOvalStrings[] = + "" +; + +static const SkMemberInfo gAddOvalInfo[] = { + {0, 6, 18, 5} +}; + +static const char gAddPathStrings[] = + "matrix\0" + "path" +; + +static const SkMemberInfo gAddPathInfo[] = { + {0, 20, 65, 1}, + {7, 24, 74, 1} +}; + +static const char gAddRectangleStrings[] = + "\0" + "bottom\0" + "left\0" + "right\0" + "top" +; + +static const SkMemberInfo gAddRectangleInfo[] = { + {0, 3, 18, 1}, + {1, 36, 98, 1}, + {8, 24, 98, 1}, + {13, 32, 98, 1}, + {19, 28, 98, 1} +}; + +static const char gAddRoundRectStrings[] = + "\0" + "rx\0" + "ry" +; + +static const SkMemberInfo gAddRoundRectInfo[] = { + {0, 6, 18, 5}, + {1, 40, 98, 1}, + {4, 44, 98, 1} +}; + +static const char gUnknown2Strings[] = + "begin\0" + "blend\0" + "dur\0" + "dynamic\0" + "field\0" + "formula\0" + "from\0" + "mirror\0" + "repeat\0" + "reset\0" + "target\0" + "to\0" + "values" +; + +static const SkMemberInfo gUnknown2Info[] = { + {0, 16, 71, 1}, + {6, 20, 119, 98}, + {12, 36, 71, 1}, + {16, -1, 67, 26}, + {24, 40, 108, 2}, + {30, 48, 40, 2}, + {38, 56, 40, 2}, + {43, -2, 67, 26}, + {50, 64, 98, 1}, + {57, -3, 67, 26}, + {63, 68, 40, 2}, + {70, 76, 40, 2}, + {73, -4, 67, 40} +}; + +static const char gAnimateFieldStrings[] = + "" +; + +static const SkMemberInfo gAnimateFieldInfo[] = { + {0, 8, 18, 13} +}; + +static const char gApplyStrings[] = + "animator\0" + "begin\0" + "dontDraw\0" + "dynamicScope\0" + "interval\0" + "mode\0" + "pickup\0" + "restore\0" + "scope\0" + "step\0" + "steps\0" + "time\0" + "transition" +; + +static const SkMemberInfo gApplyInfo[] = { + {0, -1, 67, 10}, + {9, 16, 71, 1}, + {15, 20, 26, 1}, + {24, 24, 108, 2}, + {37, 32, 71, 1}, + {46, 36, 13, 1}, + {51, 40, 26, 1}, + {58, 44, 26, 1}, + {66, 48, 37, 1}, + {72, -2, 67, 96}, + {77, 52, 96, 1}, + {83, -3, 67, 71}, + {88, 56, 14, 1} +}; + +static const char gUnknown3Strings[] = + "x\0" + "y" +; + +static const SkMemberInfo gUnknown3Info[] = { + {0, 48, 98, 1}, + {2, 52, 98, 1} +}; + +static const char gBitmapStrings[] = + "\0" + "erase\0" + "format\0" + "height\0" + "rowBytes\0" + "width" +; + +static const SkMemberInfo gDrawBitmapInfo[] = { + {0, 11, 18, 2}, + {1, -1, 67, 15}, + {7, 56, 21, 1}, + {14, 60, 96, 1}, + {21, 64, 96, 1}, + {30, 68, 96, 1} +}; + +static const char gBitmapShaderStrings[] = + "\0" + "filterType\0" + "image" +; + +static const SkMemberInfo gDrawBitmapShaderInfo[] = { + {0, 67, 18, 2}, + {1, 28, 47, 1}, + {12, 32, 17, 1} +}; + +static const char gBlurStrings[] = + "blurStyle\0" + "radius" +; + +static const SkMemberInfo gDrawBlurInfo[] = { + {0, 24, 63, 1}, + {10, 20, 98, 1} +}; + +static const char gBoundsStrings[] = + "\0" + "inval" +; + +static const SkMemberInfo gDisplayBoundsInfo[] = { + {0, 58, 18, 7}, + {1, 44, 26, 1} +}; + +static const char gClipStrings[] = + "path\0" + "rectangle" +; + +static const SkMemberInfo gDrawClipInfo[] = { + {0, 20, 74, 1}, + {5, 16, 91, 1} +}; + +static const char gColorStrings[] = + "alpha\0" + "blue\0" + "color\0" + "green\0" + "hue\0" + "red\0" + "saturation\0" + "value" +; + +static const SkMemberInfo gDrawColorInfo[] = { + {0, -1, 67, 98}, + {6, -2, 67, 98}, + {11, 20, 15, 1}, + {17, -3, 67, 98}, + {23, -4, 67, 98}, + {27, -5, 67, 98}, + {31, -6, 67, 98}, + {42, -7, 67, 98} +}; + +static const char gCubicToStrings[] = + "x1\0" + "x2\0" + "x3\0" + "y1\0" + "y2\0" + "y3" +; + +static const SkMemberInfo gCubicToInfo[] = { + {0, 20, 98, 1}, + {3, 28, 98, 1}, + {6, 36, 98, 1}, + {9, 24, 98, 1}, + {12, 32, 98, 1}, + {15, 40, 98, 1} +}; + +static const char gDashStrings[] = + "intervals\0" + "phase" +; + +static const SkMemberInfo gDashInfo[] = { + {0, 20, 119, 98}, + {10, 36, 98, 1} +}; + +static const char gDataStrings[] = + "\0" + "name" +; + +static const SkMemberInfo gDataInfo[] = { + {0, 33, 18, 3}, + {1, 32, 108, 2} +}; + +static const char gDiscreteStrings[] = + "deviation\0" + "segLength" +; + +static const SkMemberInfo gDiscreteInfo[] = { + {0, 20, 98, 1}, + {10, 24, 98, 1} +}; + +static const char gDrawToStrings[] = + "drawOnce\0" + "use" +; + +static const SkMemberInfo gDrawToInfo[] = { + {0, 72, 26, 1}, + {9, 76, 19, 1} +}; + +static const char gDumpStrings[] = + "displayList\0" + "eventList\0" + "events\0" + "groups\0" + "name\0" + "posts" +; + +static const SkMemberInfo gDumpInfo[] = { + {0, 16, 26, 1}, + {12, 20, 26, 1}, + {22, 24, 26, 1}, + {29, 36, 26, 1}, + {36, 28, 108, 2}, + {41, 40, 26, 1} +}; + +static const char gEmbossStrings[] = + "ambient\0" + "direction\0" + "radius\0" + "specular" +; + +static const SkMemberInfo gDrawEmbossInfo[] = { + {0, -1, 67, 98}, + {8, 20, 119, 98}, + {18, 36, 98, 1}, + {25, -2, 67, 98} +}; + +static const char gEventStrings[] = + "code\0" + "disable\0" + "key\0" + "keys\0" + "kind\0" + "target\0" + "x\0" + "y" +; + +static const SkMemberInfo gDisplayEventInfo[] = { + {0, 16, 43, 1}, + {5, 20, 26, 1}, + {13, -1, 67, 108}, + {17, -2, 67, 108}, + {22, 24, 44, 1}, + {27, 28, 108, 2}, + {34, 36, 98, 1}, + {36, 40, 98, 1} +}; + +static const char gFromPathStrings[] = + "mode\0" + "offset\0" + "path" +; + +static const SkMemberInfo gFromPathInfo[] = { + {0, 20, 49, 1}, + {5, 24, 98, 1}, + {12, 28, 74, 1} +}; + +static const char gUnknown4Strings[] = + "\0" + "offsets\0" + "unitMapper" +; + +static const SkMemberInfo gUnknown4Info[] = { + {0, 67, 18, 2}, + {1, 28, 119, 98}, + {9, 44, 108, 2} +}; + +static const char gGStrings[] = + "condition\0" + "enableCondition" +; + +static const SkMemberInfo gGInfo[] = { + {0, 16, 40, 2}, + {10, 24, 40, 2} +}; + +static const char gHitClearStrings[] = + "targets" +; + +static const SkMemberInfo gHitClearInfo[] = { + {0, 16, 119, 36} +}; + +static const char gHitTestStrings[] = + "bullets\0" + "hits\0" + "targets\0" + "value" +; + +static const SkMemberInfo gHitTestInfo[] = { + {0, 16, 119, 36}, + {8, 32, 119, 96}, + {13, 48, 119, 36}, + {21, 64, 26, 1} +}; + +static const char gImageStrings[] = + "\0" + "base64\0" + "src" +; + +static const SkMemberInfo gImageInfo[] = { + {0, 11, 18, 2}, + {1, 56, 16, 2}, + {8, 64, 108, 2} +}; + +static const char gIncludeStrings[] = + "src" +; + +static const SkMemberInfo gIncludeInfo[] = { + {0, 16, 108, 2} +}; + +static const char gInputStrings[] = + "s32\0" + "scalar\0" + "string" +; + +static const SkMemberInfo gInputInfo[] = { + {0, 16, 96, 1}, + {4, 20, 98, 1}, + {11, 24, 108, 2} +}; + +static const char gLineStrings[] = + "x1\0" + "x2\0" + "y1\0" + "y2" +; + +static const SkMemberInfo gLineInfo[] = { + {0, 24, 98, 1}, + {3, 28, 98, 1}, + {6, 32, 98, 1}, + {9, 36, 98, 1} +}; + +static const char gLineToStrings[] = + "x\0" + "y" +; + +static const SkMemberInfo gLineToInfo[] = { + {0, 20, 98, 1}, + {2, 24, 98, 1} +}; + +static const char gLinearGradientStrings[] = + "\0" + "points" +; + +static const SkMemberInfo gLinearGradientInfo[] = { + {0, 27, 18, 3}, + {1, 88, 77, 4} +}; + +static const char gMatrixStrings[] = + "matrix\0" + "perspectX\0" + "perspectY\0" + "rotate\0" + "scale\0" + "scaleX\0" + "scaleY\0" + "skewX\0" + "skewY\0" + "translate\0" + "translateX\0" + "translateY" +; + +static const SkMemberInfo gDrawMatrixInfo[] = { + {0, 16, 119, 98}, + {7, -1, 67, 98}, + {17, -2, 67, 98}, + {27, -3, 67, 98}, + {34, -4, 67, 98}, + {40, -5, 67, 98}, + {47, -6, 67, 98}, + {54, -7, 67, 98}, + {60, -8, 67, 98}, + {66, -9, 67, 77}, + {76, -10, 67, 98}, + {87, -11, 67, 98} +}; + +static const char gMoveStrings[] = + "" +; + +static const SkMemberInfo gMoveInfo[] = { + {0, 1, 18, 4} +}; + +static const char gMoveToStrings[] = + "x\0" + "y" +; + +static const SkMemberInfo gMoveToInfo[] = { + {0, 20, 98, 1}, + {2, 24, 98, 1} +}; + +static const char gMovieStrings[] = + "src" +; + +static const SkMemberInfo gMovieInfo[] = { + {0, 16, 108, 2} +}; + +static const char gOvalStrings[] = + "" +; + +static const SkMemberInfo gOvalInfo[] = { + {0, 58, 18, 7} +}; + +static const char gPaintStrings[] = + "antiAlias\0" + "ascent\0" + "color\0" + "descent\0" + "filterType\0" + "linearText\0" + "maskFilter\0" + "measureText\0" + "pathEffect\0" + "shader\0" + "strikeThru\0" + "stroke\0" + "strokeCap\0" + "strokeJoin\0" + "strokeMiter\0" + "strokeWidth\0" + "style\0" + "textAlign\0" + "textScaleX\0" + "textSize\0" + "textSkewX\0" + "textTracking\0" + "typeface\0" + "underline\0" + "xfermode" +; + +static const SkMemberInfo gDrawPaintInfo[] = { + {0, 16, 26, 1}, + {10, -1, 67, 98}, + {17, 20, 31, 1}, + {23, -2, 67, 98}, + {31, 24, 47, 1}, + {42, 28, 26, 1}, + {53, 32, 62, 1}, + {64, -1, 66, 98}, + {76, 36, 76, 1}, + {87, 40, 102, 1}, + {94, 44, 26, 1}, + {105, 48, 26, 1}, + {112, 52, 27, 1}, + {122, 56, 58, 1}, + {133, 60, 98, 1}, + {145, 64, 98, 1}, + {157, 68, 109, 1}, + {163, 72, 9, 1}, + {173, 76, 98, 1}, + {184, 80, 98, 1}, + {193, 84, 98, 1}, + {203, 88, 98, 1}, + {216, 92, 120, 1}, + {225, 96, 26, 1}, + {235, 100, 121, 1} +}; + +static const char gPathStrings[] = + "d\0" + "fillType\0" + "length" +; + +static const SkMemberInfo gDrawPathInfo[] = { + {0, 52, 108, 2}, + {2, -1, 67, 46}, + {11, -2, 67, 98} +}; + +static const char gUnknown5Strings[] = + "x\0" + "y\0" + "z" +; + +static const SkMemberInfo gUnknown5Info[] = { + {0, 0, 98, 1}, + {2, 4, 98, 1}, + {4, 8, 98, 1} +}; + +static const char gPointStrings[] = + "x\0" + "y" +; + +static const SkMemberInfo gDrawPointInfo[] = { + {0, 16, 98, 1}, + {2, 20, 98, 1} +}; + +static const char gPolyToPolyStrings[] = + "destination\0" + "source" +; + +static const SkMemberInfo gPolyToPolyInfo[] = { + {0, 24, 80, 1}, + {12, 20, 80, 1} +}; + +static const char gPolygonStrings[] = + "" +; + +static const SkMemberInfo gPolygonInfo[] = { + {0, 48, 18, 1} +}; + +static const char gPolylineStrings[] = + "points" +; + +static const SkMemberInfo gPolylineInfo[] = { + {0, 88, 119, 98} +}; + +static const char gPostStrings[] = + "delay\0" + "initialized\0" + "mode\0" + "sink\0" + "target\0" + "type" +; + +static const SkMemberInfo gPostInfo[] = { + {0, 16, 71, 1}, + {6, 20, 26, 1}, + {18, 24, 45, 1}, + {23, -1, 67, 108}, + {28, -2, 67, 108}, + {35, -3, 67, 108} +}; + +static const char gQuadToStrings[] = + "x1\0" + "x2\0" + "y1\0" + "y2" +; + +static const SkMemberInfo gQuadToInfo[] = { + {0, 20, 98, 1}, + {3, 28, 98, 1}, + {6, 24, 98, 1}, + {9, 32, 98, 1} +}; + +static const char gRCubicToStrings[] = + "" +; + +static const SkMemberInfo gRCubicToInfo[] = { + {0, 18, 18, 6} +}; + +static const char gRLineToStrings[] = + "" +; + +static const SkMemberInfo gRLineToInfo[] = { + {0, 35, 18, 2} +}; + +static const char gRMoveToStrings[] = + "" +; + +static const SkMemberInfo gRMoveToInfo[] = { + {0, 39, 18, 2} +}; + +static const char gRQuadToStrings[] = + "" +; + +static const SkMemberInfo gRQuadToInfo[] = { + {0, 50, 18, 4} +}; + +static const char gRadialGradientStrings[] = + "\0" + "center\0" + "radius" +; + +static const SkMemberInfo gRadialGradientInfo[] = { + {0, 27, 18, 3}, + {1, 88, 77, 2}, + {8, 96, 98, 1} +}; + +static const char gRandomStrings[] = + "blend\0" + "max\0" + "min\0" + "random\0" + "seed" +; + +static const SkMemberInfo gDisplayRandomInfo[] = { + {0, 16, 98, 1}, + {6, 24, 98, 1}, + {10, 20, 98, 1}, + {14, 1, 67, 98}, + {21, -2, 67, 96} +}; + +static const char gRectToRectStrings[] = + "destination\0" + "source" +; + +static const SkMemberInfo gRectToRectInfo[] = { + {0, 24, 91, 1}, + {12, 20, 91, 1} +}; + +static const char gRectangleStrings[] = + "bottom\0" + "height\0" + "left\0" + "needsRedraw\0" + "right\0" + "top\0" + "width" +; + +static const SkMemberInfo gRectangleInfo[] = { + {0, 36, 98, 1}, + {7, -1, 67, 98}, + {14, 24, 98, 1}, + {19, -2, 67, 26}, + {31, 32, 98, 1}, + {37, 28, 98, 1}, + {41, -3, 67, 98} +}; + +static const char gRemoveStrings[] = + "offset\0" + "where" +; + +static const SkMemberInfo gRemoveInfo[] = { + {0, 20, 96, 1}, + {7, 28, 37, 1} +}; + +static const char gReplaceStrings[] = + "" +; + +static const SkMemberInfo gReplaceInfo[] = { + {0, 1, 18, 4} +}; + +static const char gRotateStrings[] = + "center\0" + "degrees" +; + +static const SkMemberInfo gRotateInfo[] = { + {0, 24, 77, 2}, + {7, 20, 98, 1} +}; + +static const char gRoundRectStrings[] = + "\0" + "rx\0" + "ry" +; + +static const SkMemberInfo gRoundRectInfo[] = { + {0, 58, 18, 7}, + {1, 44, 98, 1}, + {4, 48, 98, 1} +}; + +static const char gS32Strings[] = + "value" +; + +static const SkMemberInfo gS32Info[] = { + {0, 16, 96, 1} +}; + +static const char gScalarStrings[] = + "value" +; + +static const SkMemberInfo gScalarInfo[] = { + {0, 16, 98, 1} +}; + +static const char gScaleStrings[] = + "center\0" + "x\0" + "y" +; + +static const SkMemberInfo gScaleInfo[] = { + {0, 28, 77, 2}, + {7, 20, 98, 1}, + {9, 24, 98, 1} +}; + +static const char gSetStrings[] = + "begin\0" + "dur\0" + "dynamic\0" + "field\0" + "formula\0" + "reset\0" + "target\0" + "to" +; + +static const SkMemberInfo gSetInfo[] = { + {0, 16, 71, 1}, + {6, 36, 71, 1}, + {10, -1, 67, 26}, + {18, 40, 108, 2}, + {24, 48, 40, 2}, + {32, -3, 67, 26}, + {38, 68, 40, 2}, + {45, 76, 40, 2} +}; + +static const char gShaderStrings[] = + "matrix\0" + "tileMode" +; + +static const SkMemberInfo gShaderInfo[] = { + {0, 20, 65, 1}, + {7, 24, 116, 1} +}; + +static const char gSkewStrings[] = + "center\0" + "x\0" + "y" +; + +static const SkMemberInfo gSkewInfo[] = { + {0, 28, 77, 2}, + {7, 20, 98, 1}, + {9, 24, 98, 1} +}; + +static const char g3D_CameraStrings[] = + "axis\0" + "hackHeight\0" + "hackWidth\0" + "location\0" + "observer\0" + "patch\0" + "zenith" +; + +static const SkMemberInfo g3D_CameraInfo[] = { + {0, 36, 106, 3}, + {5, 20, 98, 1}, + {16, 16, 98, 1}, + {26, 24, 106, 3}, + {35, 60, 106, 3}, + {44, 108, 105, 1}, + {50, 48, 106, 3} +}; + +static const char g3D_PatchStrings[] = + "origin\0" + "rotateDegrees\0" + "u\0" + "v" +; + +static const SkMemberInfo g3D_PatchInfo[] = { + {0, 40, 106, 3}, + {7, -1, 66, 98}, + {21, 16, 106, 3}, + {23, 28, 106, 3} +}; + +static const char gUnknown6Strings[] = + "x\0" + "y\0" + "z" +; + +static const SkMemberInfo gUnknown6Info[] = { + {0, 0, 98, 1}, + {2, 4, 98, 1}, + {4, 8, 98, 1} +}; + +static const char gSnapshotStrings[] = + "filename\0" + "quality\0" + "sequence\0" + "type" +; + +static const SkMemberInfo gSnapshotInfo[] = { + {0, 16, 108, 2}, + {9, 24, 98, 1}, + {17, 28, 26, 1}, + {26, 32, 20, 1} +}; + +static const char gStringStrings[] = + "length\0" + "slice\0" + "value" +; + +static const SkMemberInfo gStringInfo[] = { + {0, -1, 67, 96}, + {7, -1, 66, 108}, + {13, 16, 108, 2} +}; + +static const char gTextStrings[] = + "length\0" + "text\0" + "x\0" + "y" +; + +static const SkMemberInfo gTextInfo[] = { + {0, -1, 67, 96}, + {7, 24, 108, 2}, + {12, 32, 98, 1}, + {14, 36, 98, 1} +}; + +static const char gTextBoxStrings[] = + "\0" + "mode\0" + "spacingAdd\0" + "spacingAlign\0" + "spacingMul\0" + "text" +; + +static const SkMemberInfo gTextBoxInfo[] = { + {0, 58, 18, 7}, + {1, 60, 113, 1}, + {6, 56, 98, 1}, + {17, 64, 112, 1}, + {30, 52, 98, 1}, + {41, 44, 108, 2} +}; + +static const char gTextOnPathStrings[] = + "offset\0" + "path\0" + "text" +; + +static const SkMemberInfo gTextOnPathInfo[] = { + {0, 24, 98, 1}, + {7, 28, 74, 1}, + {12, 32, 110, 1} +}; + +static const char gTextToPathStrings[] = + "path\0" + "text" +; + +static const SkMemberInfo gTextToPathInfo[] = { + {0, 16, 74, 1}, + {5, 20, 110, 1} +}; + +static const char gTranslateStrings[] = + "x\0" + "y" +; + +static const SkMemberInfo gTranslateInfo[] = { + {0, 20, 98, 1}, + {2, 24, 98, 1} +}; + +static const char gTypedArrayStrings[] = + "length\0" + "values" +; + +static const SkMemberInfo gTypedArrayInfo[] = { + {0, -1, 67, 96}, + {7, 16, 119, 0} +}; + +static const char gTypefaceStrings[] = + "fontName" +; + +static const SkMemberInfo gTypefaceInfo[] = { + {0, 20, 108, 2} +}; + +static const SkMemberInfo* const gInfoTables[] = { + gMathInfo, + gAddInfo, + gAddCircleInfo, + gUnknown1Info, + gAddOvalInfo, + gAddPathInfo, + gAddRectangleInfo, + gAddRoundRectInfo, + gUnknown2Info, + gAnimateFieldInfo, + gApplyInfo, + gUnknown3Info, + gDrawBitmapInfo, + gDrawBitmapShaderInfo, + gDrawBlurInfo, + gDisplayBoundsInfo, + gDrawClipInfo, + gDrawColorInfo, + gCubicToInfo, + gDashInfo, + gDataInfo, + gDiscreteInfo, + gDrawToInfo, + gDumpInfo, + gDrawEmbossInfo, + gDisplayEventInfo, + gFromPathInfo, + gUnknown4Info, + gGInfo, + gHitClearInfo, + gHitTestInfo, + gImageInfo, + gIncludeInfo, + gInputInfo, + gLineInfo, + gLineToInfo, + gLinearGradientInfo, + gDrawMatrixInfo, + gMoveInfo, + gMoveToInfo, + gMovieInfo, + gOvalInfo, + gDrawPaintInfo, + gDrawPathInfo, + gUnknown5Info, + gDrawPointInfo, + gPolyToPolyInfo, + gPolygonInfo, + gPolylineInfo, + gPostInfo, + gQuadToInfo, + gRCubicToInfo, + gRLineToInfo, + gRMoveToInfo, + gRQuadToInfo, + gRadialGradientInfo, + gDisplayRandomInfo, + gRectToRectInfo, + gRectangleInfo, + gRemoveInfo, + gReplaceInfo, + gRotateInfo, + gRoundRectInfo, + gS32Info, + gScalarInfo, + gScaleInfo, + gSetInfo, + gShaderInfo, + gSkewInfo, + g3D_CameraInfo, + g3D_PatchInfo, + gUnknown6Info, + gSnapshotInfo, + gStringInfo, + gTextInfo, + gTextBoxInfo, + gTextOnPathInfo, + gTextToPathInfo, + gTranslateInfo, + gTypedArrayInfo, + gTypefaceInfo, +}; + +static const unsigned char gInfoCounts[] = { + 26,4,4,1,1,2,5,3,13,1,13,2,6,3,2,2,2,8,6, + 2,2,2,2,6,4,8,3,3,2,1,4,3,1,3,4,2,2,12,1, + 2,1,1,25,3,3,2,2,1,1,6,4,1,1,1,1,3,5,2,7, + 2,1,2,3,1,1,3,8,2,3,7,4,3,4,3,4,6,3,2,2, + 2,1 +}; + +static const unsigned char gTypeIDs[] = { + 1, // Math + 2, // Add + 3, // AddCircle + 4, // Unknown1 + 5, // AddOval + 6, // AddPath + 7, // AddRectangle + 8, // AddRoundRect + 10, // Unknown2 + 11, // AnimateField + 12, // Apply + 17, // Unknown3 + 19, // Bitmap + 22, // BitmapShader + 23, // Blur + 25, // Bounds + 29, // Clip + 31, // Color + 32, // CubicTo + 33, // Dash + 34, // Data + 35, // Discrete + 38, // DrawTo + 39, // Dump + 41, // Emboss + 42, // Event + 48, // FromPath + 51, // Unknown4 + 52, // G + 53, // HitClear + 54, // HitTest + 55, // Image + 56, // Include + 57, // Input + 59, // Line + 60, // LineTo + 61, // LinearGradient + 65, // Matrix + 68, // Move + 69, // MoveTo + 70, // Movie + 72, // Oval + 73, // Paint + 74, // Path + 77, // Unknown5 + 78, // Point + 79, // PolyToPoly + 80, // Polygon + 81, // Polyline + 82, // Post + 83, // QuadTo + 84, // RCubicTo + 85, // RLineTo + 86, // RMoveTo + 87, // RQuadTo + 88, // RadialGradient + 89, // Random + 90, // RectToRect + 91, // Rectangle + 92, // Remove + 93, // Replace + 94, // Rotate + 95, // RoundRect + 96, // S32 + 98, // Scalar + 99, // Scale + 101, // Set + 102, // Shader + 103, // Skew + 104, // 3D_Camera + 105, // 3D_Patch + 106, // Unknown6 + 107, // Snapshot + 108, // String + 110, // Text + 111, // TextBox + 114, // TextOnPath + 115, // TextToPath + 117, // Translate + 119, // TypedArray + 120, // Typeface + +}; + +static const int kTypeIDs = 81; + +static const char* const gInfoNames[] = { + gMathStrings, + gAddStrings, + gAddCircleStrings, + gUnknown1Strings, + gAddOvalStrings, + gAddPathStrings, + gAddRectangleStrings, + gAddRoundRectStrings, + gUnknown2Strings, + gAnimateFieldStrings, + gApplyStrings, + gUnknown3Strings, + gBitmapStrings, + gBitmapShaderStrings, + gBlurStrings, + gBoundsStrings, + gClipStrings, + gColorStrings, + gCubicToStrings, + gDashStrings, + gDataStrings, + gDiscreteStrings, + gDrawToStrings, + gDumpStrings, + gEmbossStrings, + gEventStrings, + gFromPathStrings, + gUnknown4Strings, + gGStrings, + gHitClearStrings, + gHitTestStrings, + gImageStrings, + gIncludeStrings, + gInputStrings, + gLineStrings, + gLineToStrings, + gLinearGradientStrings, + gMatrixStrings, + gMoveStrings, + gMoveToStrings, + gMovieStrings, + gOvalStrings, + gPaintStrings, + gPathStrings, + gUnknown5Strings, + gPointStrings, + gPolyToPolyStrings, + gPolygonStrings, + gPolylineStrings, + gPostStrings, + gQuadToStrings, + gRCubicToStrings, + gRLineToStrings, + gRMoveToStrings, + gRQuadToStrings, + gRadialGradientStrings, + gRandomStrings, + gRectToRectStrings, + gRectangleStrings, + gRemoveStrings, + gReplaceStrings, + gRotateStrings, + gRoundRectStrings, + gS32Strings, + gScalarStrings, + gScaleStrings, + gSetStrings, + gShaderStrings, + gSkewStrings, + g3D_CameraStrings, + g3D_PatchStrings, + gUnknown6Strings, + gSnapshotStrings, + gStringStrings, + gTextStrings, + gTextBoxStrings, + gTextOnPathStrings, + gTextToPathStrings, + gTranslateStrings, + gTypedArrayStrings, + gTypefaceStrings +}; + +#endif +#endif + + diff --git a/libs/graphics/animator/SkCondensedRelease.cpp b/libs/graphics/animator/SkCondensedRelease.cpp new file mode 100644 index 000000000..70bb1b4e1 --- /dev/null +++ b/libs/graphics/animator/SkCondensedRelease.cpp @@ -0,0 +1,1357 @@ +#include "SkTypes.h" +#ifndef SK_BUILD_FOR_UNIX +#ifdef SK_RELEASE +// This file was automatically generated. +// To change it, edit the file with the matching debug info. +// Then execute SkDisplayType::BuildCondensedInfo() to regenerate this file. + +static const char gMathStrings[] = + "E\0" + "LN10\0" + "LN2\0" + "LOG10E\0" + "LOG2E\0" + "PI\0" + "SQRT1_2\0" + "SQRT2\0" + "abs\0" + "acos\0" + "asin\0" + "atan\0" + "atan2\0" + "ceil\0" + "cos\0" + "exp\0" + "floor\0" + "log\0" + "max\0" + "min\0" + "pow\0" + "random\0" + "round\0" + "sin\0" + "sqrt\0" + "tan" +; + +static const SkMemberInfo gMathInfo[] = { + {0, -1, 67, 98}, + {2, -2, 67, 98}, + {7, -3, 67, 98}, + {11, -4, 67, 98}, + {18, -5, 67, 98}, + {24, -6, 67, 98}, + {27, -7, 67, 98}, + {35, -8, 67, 98}, + {41, -1, 66, 98}, + {45, -2, 66, 98}, + {50, -3, 66, 98}, + {55, -4, 66, 98}, + {60, -5, 66, 98}, + {66, -6, 66, 98}, + {71, -7, 66, 98}, + {75, -8, 66, 98}, + {79, -9, 66, 98}, + {85, -10, 66, 98}, + {89, -11, 66, 98}, + {93, -12, 66, 98}, + {97, -13, 66, 98}, + {101, -14, 66, 98}, + {108, -15, 66, 98}, + {114, -16, 66, 98}, + {118, -17, 66, 98}, + {123, -18, 66, 98} +}; + +static const char gAddStrings[] = + "inPlace\0" + "offset\0" + "use\0" + "where" +; + +static const SkMemberInfo gAddInfo[] = { + {0, 4, 26, 1}, + {8, 8, 96, 1}, + {15, 12, 37, 1}, + {19, 16, 37, 1} +}; + +static const char gAddCircleStrings[] = + "\0" + "radius\0" + "x\0" + "y" +; + +static const SkMemberInfo gAddCircleInfo[] = { + {0, 3, 18, 1}, + {1, 12, 98, 1}, + {8, 16, 98, 1}, + {10, 20, 98, 1} +}; + +static const char gUnknown1Strings[] = + "direction" +; + +static const SkMemberInfo gUnknown1Info[] = { + {0, 8, 75, 1} +}; + +static const char gAddOvalStrings[] = + "" +; + +static const SkMemberInfo gAddOvalInfo[] = { + {0, 6, 18, 5} +}; + +static const char gAddPathStrings[] = + "matrix\0" + "path" +; + +static const SkMemberInfo gAddPathInfo[] = { + {0, 8, 65, 1}, + {7, 12, 74, 1} +}; + +static const char gAddRectangleStrings[] = + "\0" + "bottom\0" + "left\0" + "right\0" + "top" +; + +static const SkMemberInfo gAddRectangleInfo[] = { + {0, 3, 18, 1}, + {1, 24, 98, 1}, + {8, 12, 98, 1}, + {13, 20, 98, 1}, + {19, 16, 98, 1} +}; + +static const char gAddRoundRectStrings[] = + "\0" + "rx\0" + "ry" +; + +static const SkMemberInfo gAddRoundRectInfo[] = { + {0, 6, 18, 5}, + {1, 28, 98, 1}, + {4, 32, 98, 1} +}; + +static const char gUnknown2Strings[] = + "begin\0" + "blend\0" + "dur\0" + "dynamic\0" + "field\0" + "formula\0" + "from\0" + "mirror\0" + "repeat\0" + "reset\0" + "target\0" + "to\0" + "values" +; + +static const SkMemberInfo gUnknown2Info[] = { + {0, 4, 71, 1}, + {6, 8, 119, 98}, + {12, 16, 71, 1}, + {16, -1, 67, 26}, + {24, 20, 108, 1}, + {30, 24, 40, 1}, + {38, 28, 40, 1}, + {43, -2, 67, 26}, + {50, 32, 98, 1}, + {57, -3, 67, 26}, + {63, 36, 40, 1}, + {70, 40, 40, 1}, + {73, -4, 67, 40} +}; + +static const char gAnimateFieldStrings[] = + "" +; + +static const SkMemberInfo gAnimateFieldInfo[] = { + {0, 8, 18, 13} +}; + +static const char gApplyStrings[] = + "animator\0" + "begin\0" + "dontDraw\0" + "dynamicScope\0" + "interval\0" + "mode\0" + "pickup\0" + "restore\0" + "scope\0" + "step\0" + "steps\0" + "time\0" + "transition" +; + +static const SkMemberInfo gApplyInfo[] = { + {0, -1, 67, 10}, + {9, 4, 71, 1}, + {15, 8, 26, 1}, + {24, 12, 108, 1}, + {37, 16, 71, 1}, + {46, 20, 13, 1}, + {51, 24, 26, 1}, + {58, 28, 26, 1}, + {66, 32, 37, 1}, + {72, -2, 67, 96}, + {77, 36, 96, 1}, + {83, -3, 67, 71}, + {88, 40, 14, 1} +}; + +static const char gUnknown3Strings[] = + "x\0" + "y" +; + +static const SkMemberInfo gUnknown3Info[] = { + {0, 36, 98, 1}, + {2, 40, 98, 1} +}; + +static const char gBitmapStrings[] = + "\0" + "erase\0" + "format\0" + "height\0" + "rowBytes\0" + "width" +; + +static const SkMemberInfo gDrawBitmapInfo[] = { + {0, 11, 18, 2}, + {1, -1, 67, 15}, + {7, 44, 21, 1}, + {14, 48, 96, 1}, + {21, 52, 96, 1}, + {30, 56, 96, 1} +}; + +static const char gBitmapShaderStrings[] = + "\0" + "filterType\0" + "image" +; + +static const SkMemberInfo gDrawBitmapShaderInfo[] = { + {0, 66, 18, 2}, + {1, 16, 47, 1}, + {12, 20, 17, 1} +}; + +static const char gBlurStrings[] = + "blurStyle\0" + "radius" +; + +static const SkMemberInfo gDrawBlurInfo[] = { + {0, 12, 63, 1}, + {10, 8, 98, 1} +}; + +static const char gBoundsStrings[] = + "\0" + "inval" +; + +static const SkMemberInfo gDisplayBoundsInfo[] = { + {0, 57, 18, 7}, + {1, 32, 26, 1} +}; + +static const char gClipStrings[] = + "path\0" + "rectangle" +; + +static const SkMemberInfo gDrawClipInfo[] = { + {0, 8, 74, 1}, + {5, 4, 91, 1} +}; + +static const char gColorStrings[] = + "alpha\0" + "blue\0" + "color\0" + "green\0" + "hue\0" + "red\0" + "saturation\0" + "value" +; + +static const SkMemberInfo gDrawColorInfo[] = { + {0, -1, 67, 98}, + {6, -2, 67, 98}, + {11, 8, 15, 1}, + {17, -3, 67, 98}, + {23, -4, 67, 98}, + {27, -5, 67, 98}, + {31, -6, 67, 98}, + {42, -7, 67, 98} +}; + +static const char gCubicToStrings[] = + "x1\0" + "x2\0" + "x3\0" + "y1\0" + "y2\0" + "y3" +; + +static const SkMemberInfo gCubicToInfo[] = { + {0, 8, 98, 1}, + {3, 16, 98, 1}, + {6, 24, 98, 1}, + {9, 12, 98, 1}, + {12, 20, 98, 1}, + {15, 28, 98, 1} +}; + +static const char gDashStrings[] = + "intervals\0" + "phase" +; + +static const SkMemberInfo gDashInfo[] = { + {0, 8, 119, 98}, + {10, 16, 98, 1} +}; + +static const char gDataStrings[] = + "\0" + "name" +; + +static const SkMemberInfo gDataInfo[] = { + {0, 32, 18, 3}, + {1, 16, 108, 1} +}; + +static const char gDiscreteStrings[] = + "deviation\0" + "segLength" +; + +static const SkMemberInfo gDiscreteInfo[] = { + {0, 8, 98, 1}, + {10, 12, 98, 1} +}; + +static const char gDrawToStrings[] = + "drawOnce\0" + "use" +; + +static const SkMemberInfo gDrawToInfo[] = { + {0, 36, 26, 1}, + {9, 40, 19, 1} +}; + +static const char gEmbossStrings[] = + "ambient\0" + "direction\0" + "radius\0" + "specular" +; + +static const SkMemberInfo gDrawEmbossInfo[] = { + {0, -1, 67, 98}, + {8, 8, 119, 98}, + {18, 16, 98, 1}, + {25, -2, 67, 98} +}; + +static const char gEventStrings[] = + "code\0" + "disable\0" + "key\0" + "keys\0" + "kind\0" + "target\0" + "x\0" + "y" +; + +static const SkMemberInfo gDisplayEventInfo[] = { + {0, 4, 43, 1}, + {5, 8, 26, 1}, + {13, -1, 67, 108}, + {17, -2, 67, 108}, + {22, 12, 44, 1}, + {27, 16, 108, 1}, + {34, 20, 98, 1}, + {36, 24, 98, 1} +}; + +static const char gFromPathStrings[] = + "mode\0" + "offset\0" + "path" +; + +static const SkMemberInfo gFromPathInfo[] = { + {0, 8, 49, 1}, + {5, 12, 98, 1}, + {12, 16, 74, 1} +}; + +static const char gUnknown4Strings[] = + "\0" + "offsets\0" + "unitMapper" +; + +static const SkMemberInfo gUnknown4Info[] = { + {0, 66, 18, 2}, + {1, 16, 119, 98}, + {9, 24, 108, 1} +}; + +static const char gGStrings[] = + "condition\0" + "enableCondition" +; + +static const SkMemberInfo gGInfo[] = { + {0, 4, 40, 1}, + {10, 8, 40, 1} +}; + +static const char gHitClearStrings[] = + "targets" +; + +static const SkMemberInfo gHitClearInfo[] = { + {0, 4, 119, 36} +}; + +static const char gHitTestStrings[] = + "bullets\0" + "hits\0" + "targets\0" + "value" +; + +static const SkMemberInfo gHitTestInfo[] = { + {0, 4, 119, 36}, + {8, 12, 119, 96}, + {13, 20, 119, 36}, + {21, 28, 26, 1} +}; + +static const char gImageStrings[] = + "\0" + "base64\0" + "src" +; + +static const SkMemberInfo gImageInfo[] = { + {0, 11, 18, 2}, + {1, 44, 16, 2}, + {8, 52, 108, 1} +}; + +static const char gIncludeStrings[] = + "src" +; + +static const SkMemberInfo gIncludeInfo[] = { + {0, 4, 108, 1} +}; + +static const char gInputStrings[] = + "s32\0" + "scalar\0" + "string" +; + +static const SkMemberInfo gInputInfo[] = { + {0, 4, 96, 1}, + {4, 8, 98, 1}, + {11, 12, 108, 1} +}; + +static const char gLineStrings[] = + "x1\0" + "x2\0" + "y1\0" + "y2" +; + +static const SkMemberInfo gLineInfo[] = { + {0, 12, 98, 1}, + {3, 16, 98, 1}, + {6, 20, 98, 1}, + {9, 24, 98, 1} +}; + +static const char gLineToStrings[] = + "x\0" + "y" +; + +static const SkMemberInfo gLineToInfo[] = { + {0, 8, 98, 1}, + {2, 12, 98, 1} +}; + +static const char gLinearGradientStrings[] = + "\0" + "points" +; + +static const SkMemberInfo gLinearGradientInfo[] = { + {0, 26, 18, 3}, + {1, 48, 77, 4} +}; + +static const char gMatrixStrings[] = + "matrix\0" + "perspectX\0" + "perspectY\0" + "rotate\0" + "scale\0" + "scaleX\0" + "scaleY\0" + "skewX\0" + "skewY\0" + "translate\0" + "translateX\0" + "translateY" +; + +static const SkMemberInfo gDrawMatrixInfo[] = { + {0, 4, 119, 98}, + {7, -1, 67, 98}, + {17, -2, 67, 98}, + {27, -3, 67, 98}, + {34, -4, 67, 98}, + {40, -5, 67, 98}, + {47, -6, 67, 98}, + {54, -7, 67, 98}, + {60, -8, 67, 98}, + {66, -9, 67, 77}, + {76, -10, 67, 98}, + {87, -11, 67, 98} +}; + +static const char gMoveStrings[] = + "" +; + +static const SkMemberInfo gMoveInfo[] = { + {0, 1, 18, 4} +}; + +static const char gMoveToStrings[] = + "x\0" + "y" +; + +static const SkMemberInfo gMoveToInfo[] = { + {0, 8, 98, 1}, + {2, 12, 98, 1} +}; + +static const char gMovieStrings[] = + "src" +; + +static const SkMemberInfo gMovieInfo[] = { + {0, 4, 108, 1} +}; + +static const char gOvalStrings[] = + "" +; + +static const SkMemberInfo gOvalInfo[] = { + {0, 57, 18, 7} +}; + +static const char gPaintStrings[] = + "antiAlias\0" + "ascent\0" + "color\0" + "descent\0" + "filterType\0" + "linearText\0" + "maskFilter\0" + "measureText\0" + "pathEffect\0" + "shader\0" + "strikeThru\0" + "stroke\0" + "strokeCap\0" + "strokeJoin\0" + "strokeMiter\0" + "strokeWidth\0" + "style\0" + "textAlign\0" + "textScaleX\0" + "textSize\0" + "textSkewX\0" + "textTracking\0" + "typeface\0" + "underline\0" + "xfermode" +; + +static const SkMemberInfo gDrawPaintInfo[] = { + {0, 4, 26, 1}, + {10, -1, 67, 98}, + {17, 8, 31, 1}, + {23, -2, 67, 98}, + {31, 12, 47, 1}, + {42, 16, 26, 1}, + {53, 20, 62, 1}, + {64, -1, 66, 98}, + {76, 24, 76, 1}, + {87, 28, 102, 1}, + {94, 32, 26, 1}, + {105, 36, 26, 1}, + {112, 40, 27, 1}, + {122, 44, 58, 1}, + {133, 48, 98, 1}, + {145, 52, 98, 1}, + {157, 56, 109, 1}, + {163, 60, 9, 1}, + {173, 64, 98, 1}, + {184, 68, 98, 1}, + {193, 72, 98, 1}, + {203, 76, 98, 1}, + {216, 80, 120, 1}, + {225, 84, 26, 1}, + {235, 88, 121, 1} +}; + +static const char gPathStrings[] = + "d\0" + "fillType\0" + "length" +; + +static const SkMemberInfo gDrawPathInfo[] = { + {0, 32, 108, 1}, + {2, -1, 67, 46}, + {11, -2, 67, 98} +}; + +static const char gUnknown5Strings[] = + "x\0" + "y\0" + "z" +; + +static const SkMemberInfo gUnknown5Info[] = { + {0, 0, 98, 1}, + {2, 4, 98, 1}, + {4, 8, 98, 1} +}; + +static const char gPointStrings[] = + "x\0" + "y" +; + +static const SkMemberInfo gDrawPointInfo[] = { + {0, 4, 98, 1}, + {2, 8, 98, 1} +}; + +static const char gPolyToPolyStrings[] = + "destination\0" + "source" +; + +static const SkMemberInfo gPolyToPolyInfo[] = { + {0, 12, 80, 1}, + {12, 8, 80, 1} +}; + +static const char gPolygonStrings[] = + "" +; + +static const SkMemberInfo gPolygonInfo[] = { + {0, 47, 18, 1} +}; + +static const char gPolylineStrings[] = + "points" +; + +static const SkMemberInfo gPolylineInfo[] = { + {0, 56, 119, 98} +}; + +static const char gPostStrings[] = + "delay\0" + "initialized\0" + "mode\0" + "sink\0" + "target\0" + "type" +; + +static const SkMemberInfo gPostInfo[] = { + {0, 4, 71, 1}, + {6, 8, 26, 1}, + {18, 12, 45, 1}, + {23, -1, 67, 108}, + {28, -2, 67, 108}, + {35, -3, 67, 108} +}; + +static const char gQuadToStrings[] = + "x1\0" + "x2\0" + "y1\0" + "y2" +; + +static const SkMemberInfo gQuadToInfo[] = { + {0, 8, 98, 1}, + {3, 16, 98, 1}, + {6, 12, 98, 1}, + {9, 20, 98, 1} +}; + +static const char gRCubicToStrings[] = + "" +; + +static const SkMemberInfo gRCubicToInfo[] = { + {0, 18, 18, 6} +}; + +static const char gRLineToStrings[] = + "" +; + +static const SkMemberInfo gRLineToInfo[] = { + {0, 34, 18, 2} +}; + +static const char gRMoveToStrings[] = + "" +; + +static const SkMemberInfo gRMoveToInfo[] = { + {0, 38, 18, 2} +}; + +static const char gRQuadToStrings[] = + "" +; + +static const SkMemberInfo gRQuadToInfo[] = { + {0, 49, 18, 4} +}; + +static const char gRadialGradientStrings[] = + "\0" + "center\0" + "radius" +; + +static const SkMemberInfo gRadialGradientInfo[] = { + {0, 26, 18, 3}, + {1, 48, 77, 2}, + {8, 56, 98, 1} +}; + +static const char gRandomStrings[] = + "blend\0" + "max\0" + "min\0" + "random\0" + "seed" +; + +static const SkMemberInfo gDisplayRandomInfo[] = { + {0, 4, 98, 1}, + {6, 12, 98, 1}, + {10, 8, 98, 1}, + {14, 1, 67, 98}, + {21, -2, 67, 96} +}; + +static const char gRectToRectStrings[] = + "destination\0" + "source" +; + +static const SkMemberInfo gRectToRectInfo[] = { + {0, 12, 91, 1}, + {12, 8, 91, 1} +}; + +static const char gRectangleStrings[] = + "bottom\0" + "height\0" + "left\0" + "needsRedraw\0" + "right\0" + "top\0" + "width" +; + +static const SkMemberInfo gRectangleInfo[] = { + {0, 24, 98, 1}, + {7, -1, 67, 98}, + {14, 12, 98, 1}, + {19, -2, 67, 26}, + {31, 20, 98, 1}, + {37, 16, 98, 1}, + {41, -3, 67, 98} +}; + +static const char gRemoveStrings[] = + "offset\0" + "where" +; + +static const SkMemberInfo gRemoveInfo[] = { + {0, 8, 96, 1}, + {7, 16, 37, 1} +}; + +static const char gReplaceStrings[] = + "" +; + +static const SkMemberInfo gReplaceInfo[] = { + {0, 1, 18, 4} +}; + +static const char gRotateStrings[] = + "center\0" + "degrees" +; + +static const SkMemberInfo gRotateInfo[] = { + {0, 12, 77, 2}, + {7, 8, 98, 1} +}; + +static const char gRoundRectStrings[] = + "\0" + "rx\0" + "ry" +; + +static const SkMemberInfo gRoundRectInfo[] = { + {0, 57, 18, 7}, + {1, 32, 98, 1}, + {4, 36, 98, 1} +}; + +static const char gS32Strings[] = + "value" +; + +static const SkMemberInfo gS32Info[] = { + {0, 4, 96, 1} +}; + +static const char gScalarStrings[] = + "value" +; + +static const SkMemberInfo gScalarInfo[] = { + {0, 4, 98, 1} +}; + +static const char gScaleStrings[] = + "center\0" + "x\0" + "y" +; + +static const SkMemberInfo gScaleInfo[] = { + {0, 16, 77, 2}, + {7, 8, 98, 1}, + {9, 12, 98, 1} +}; + +static const char gSetStrings[] = + "begin\0" + "dur\0" + "dynamic\0" + "field\0" + "formula\0" + "reset\0" + "target\0" + "to" +; + +static const SkMemberInfo gSetInfo[] = { + {0, 4, 71, 1}, + {6, 16, 71, 1}, + {10, -1, 67, 26}, + {18, 20, 108, 1}, + {24, 24, 40, 1}, + {32, -3, 67, 26}, + {38, 36, 40, 1}, + {45, 40, 40, 1} +}; + +static const char gShaderStrings[] = + "matrix\0" + "tileMode" +; + +static const SkMemberInfo gShaderInfo[] = { + {0, 8, 65, 1}, + {7, 12, 116, 1} +}; + +static const char gSkewStrings[] = + "center\0" + "x\0" + "y" +; + +static const SkMemberInfo gSkewInfo[] = { + {0, 16, 77, 2}, + {7, 8, 98, 1}, + {9, 12, 98, 1} +}; + +static const char g3D_CameraStrings[] = + "axis\0" + "hackHeight\0" + "hackWidth\0" + "location\0" + "observer\0" + "patch\0" + "zenith" +; + +static const SkMemberInfo g3D_CameraInfo[] = { + {0, 24, 106, 3}, + {5, 8, 98, 1}, + {16, 4, 98, 1}, + {26, 12, 106, 3}, + {35, 48, 106, 3}, + {44, 96, 105, 1}, + {50, 36, 106, 3} +}; + +static const char g3D_PatchStrings[] = + "origin\0" + "rotateDegrees\0" + "u\0" + "v" +; + +static const SkMemberInfo g3D_PatchInfo[] = { + {0, 28, 106, 3}, + {7, -1, 66, 98}, + {21, 4, 106, 3}, + {23, 16, 106, 3} +}; + +static const char gUnknown6Strings[] = + "x\0" + "y\0" + "z" +; + +static const SkMemberInfo gUnknown6Info[] = { + {0, 0, 98, 1}, + {2, 4, 98, 1}, + {4, 8, 98, 1} +}; + +static const char gSnapshotStrings[] = + "filename\0" + "quality\0" + "sequence\0" + "type" +; + +static const SkMemberInfo gSnapshotInfo[] = { + {0, 4, 108, 1}, + {9, 8, 98, 1}, + {17, 12, 26, 1}, + {26, 16, 20, 1} +}; + +static const char gStringStrings[] = + "length\0" + "slice\0" + "value" +; + +static const SkMemberInfo gStringInfo[] = { + {0, -1, 67, 96}, + {7, -1, 66, 108}, + {13, 4, 108, 1} +}; + +static const char gTextStrings[] = + "length\0" + "text\0" + "x\0" + "y" +; + +static const SkMemberInfo gTextInfo[] = { + {0, -1, 67, 96}, + {7, 12, 108, 1}, + {12, 16, 98, 1}, + {14, 20, 98, 1} +}; + +static const char gTextBoxStrings[] = + "\0" + "mode\0" + "spacingAdd\0" + "spacingAlign\0" + "spacingMul\0" + "text" +; + +static const SkMemberInfo gTextBoxInfo[] = { + {0, 57, 18, 7}, + {1, 44, 113, 1}, + {6, 40, 98, 1}, + {17, 48, 112, 1}, + {30, 36, 98, 1}, + {41, 32, 108, 1} +}; + +static const char gTextOnPathStrings[] = + "offset\0" + "path\0" + "text" +; + +static const SkMemberInfo gTextOnPathInfo[] = { + {0, 12, 98, 1}, + {7, 16, 74, 1}, + {12, 20, 110, 1} +}; + +static const char gTextToPathStrings[] = + "path\0" + "text" +; + +static const SkMemberInfo gTextToPathInfo[] = { + {0, 4, 74, 1}, + {5, 8, 110, 1} +}; + +static const char gTranslateStrings[] = + "x\0" + "y" +; + +static const SkMemberInfo gTranslateInfo[] = { + {0, 8, 98, 1}, + {2, 12, 98, 1} +}; + +static const char gTypedArrayStrings[] = + "length\0" + "values" +; + +static const SkMemberInfo gTypedArrayInfo[] = { + {0, -1, 67, 96}, + {7, 4, 119, 0} +}; + +static const char gTypefaceStrings[] = + "fontName" +; + +static const SkMemberInfo gTypefaceInfo[] = { + {0, 8, 108, 1} +}; + +static const SkMemberInfo* const gInfoTables[] = { + gMathInfo, + gAddInfo, + gAddCircleInfo, + gUnknown1Info, + gAddOvalInfo, + gAddPathInfo, + gAddRectangleInfo, + gAddRoundRectInfo, + gUnknown2Info, + gAnimateFieldInfo, + gApplyInfo, + gUnknown3Info, + gDrawBitmapInfo, + gDrawBitmapShaderInfo, + gDrawBlurInfo, + gDisplayBoundsInfo, + gDrawClipInfo, + gDrawColorInfo, + gCubicToInfo, + gDashInfo, + gDataInfo, + gDiscreteInfo, + gDrawToInfo, + gDrawEmbossInfo, + gDisplayEventInfo, + gFromPathInfo, + gUnknown4Info, + gGInfo, + gHitClearInfo, + gHitTestInfo, + gImageInfo, + gIncludeInfo, + gInputInfo, + gLineInfo, + gLineToInfo, + gLinearGradientInfo, + gDrawMatrixInfo, + gMoveInfo, + gMoveToInfo, + gMovieInfo, + gOvalInfo, + gDrawPaintInfo, + gDrawPathInfo, + gUnknown5Info, + gDrawPointInfo, + gPolyToPolyInfo, + gPolygonInfo, + gPolylineInfo, + gPostInfo, + gQuadToInfo, + gRCubicToInfo, + gRLineToInfo, + gRMoveToInfo, + gRQuadToInfo, + gRadialGradientInfo, + gDisplayRandomInfo, + gRectToRectInfo, + gRectangleInfo, + gRemoveInfo, + gReplaceInfo, + gRotateInfo, + gRoundRectInfo, + gS32Info, + gScalarInfo, + gScaleInfo, + gSetInfo, + gShaderInfo, + gSkewInfo, + g3D_CameraInfo, + g3D_PatchInfo, + gUnknown6Info, + gSnapshotInfo, + gStringInfo, + gTextInfo, + gTextBoxInfo, + gTextOnPathInfo, + gTextToPathInfo, + gTranslateInfo, + gTypedArrayInfo, + gTypefaceInfo, +}; + +static const unsigned char gInfoCounts[] = { + 26,4,4,1,1,2,5,3,13,1,13,2,6,3,2,2,2,8,6, + 2,2,2,2,4,8,3,3,2,1,4,3,1,3,4,2,2,12,1,2, + 1,1,25,3,3,2,2,1,1,6,4,1,1,1,1,3,5,2,7,2, + 1,2,3,1,1,3,8,2,3,7,4,3,4,3,4,6,3,2,2,2, + 1 +}; + +static const unsigned char gTypeIDs[] = { + 1, // Math + 2, // Add + 3, // AddCircle + 4, // Unknown1 + 5, // AddOval + 6, // AddPath + 7, // AddRectangle + 8, // AddRoundRect + 10, // Unknown2 + 11, // AnimateField + 12, // Apply + 17, // Unknown3 + 19, // Bitmap + 22, // BitmapShader + 23, // Blur + 25, // Bounds + 29, // Clip + 31, // Color + 32, // CubicTo + 33, // Dash + 34, // Data + 35, // Discrete + 38, // DrawTo + 41, // Emboss + 42, // Event + 48, // FromPath + 51, // Unknown4 + 52, // G + 53, // HitClear + 54, // HitTest + 55, // Image + 56, // Include + 57, // Input + 59, // Line + 60, // LineTo + 61, // LinearGradient + 65, // Matrix + 68, // Move + 69, // MoveTo + 70, // Movie + 72, // Oval + 73, // Paint + 74, // Path + 77, // Unknown5 + 78, // Point + 79, // PolyToPoly + 80, // Polygon + 81, // Polyline + 82, // Post + 83, // QuadTo + 84, // RCubicTo + 85, // RLineTo + 86, // RMoveTo + 87, // RQuadTo + 88, // RadialGradient + 89, // Random + 90, // RectToRect + 91, // Rectangle + 92, // Remove + 93, // Replace + 94, // Rotate + 95, // RoundRect + 96, // S32 + 98, // Scalar + 99, // Scale + 101, // Set + 102, // Shader + 103, // Skew + 104, // 3D_Camera + 105, // 3D_Patch + 106, // Unknown6 + 107, // Snapshot + 108, // String + 110, // Text + 111, // TextBox + 114, // TextOnPath + 115, // TextToPath + 117, // Translate + 119, // TypedArray + 120, // Typeface + +}; + +static const int kTypeIDs = 80; + +static const char* const gInfoNames[] = { + gMathStrings, + gAddStrings, + gAddCircleStrings, + gUnknown1Strings, + gAddOvalStrings, + gAddPathStrings, + gAddRectangleStrings, + gAddRoundRectStrings, + gUnknown2Strings, + gAnimateFieldStrings, + gApplyStrings, + gUnknown3Strings, + gBitmapStrings, + gBitmapShaderStrings, + gBlurStrings, + gBoundsStrings, + gClipStrings, + gColorStrings, + gCubicToStrings, + gDashStrings, + gDataStrings, + gDiscreteStrings, + gDrawToStrings, + gEmbossStrings, + gEventStrings, + gFromPathStrings, + gUnknown4Strings, + gGStrings, + gHitClearStrings, + gHitTestStrings, + gImageStrings, + gIncludeStrings, + gInputStrings, + gLineStrings, + gLineToStrings, + gLinearGradientStrings, + gMatrixStrings, + gMoveStrings, + gMoveToStrings, + gMovieStrings, + gOvalStrings, + gPaintStrings, + gPathStrings, + gUnknown5Strings, + gPointStrings, + gPolyToPolyStrings, + gPolygonStrings, + gPolylineStrings, + gPostStrings, + gQuadToStrings, + gRCubicToStrings, + gRLineToStrings, + gRMoveToStrings, + gRQuadToStrings, + gRadialGradientStrings, + gRandomStrings, + gRectToRectStrings, + gRectangleStrings, + gRemoveStrings, + gReplaceStrings, + gRotateStrings, + gRoundRectStrings, + gS32Strings, + gScalarStrings, + gScaleStrings, + gSetStrings, + gShaderStrings, + gSkewStrings, + g3D_CameraStrings, + g3D_PatchStrings, + gUnknown6Strings, + gSnapshotStrings, + gStringStrings, + gTextStrings, + gTextBoxStrings, + gTextOnPathStrings, + gTextToPathStrings, + gTranslateStrings, + gTypedArrayStrings, + gTypefaceStrings +}; +#endif +#endif + diff --git a/libs/graphics/animator/SkDisplayAdd.cpp b/libs/graphics/animator/SkDisplayAdd.cpp new file mode 100644 index 000000000..0264a5f9d --- /dev/null +++ b/libs/graphics/animator/SkDisplayAdd.cpp @@ -0,0 +1,237 @@ +#include "SkDisplayAdd.h" +#include "SkAnimateMaker.h" +#include "SkDisplayApply.h" +#include "SkDisplayList.h" +#include "SkDrawable.h" +#include "SkDrawGroup.h" + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkAdd::fInfo[] = { + SK_MEMBER(mode, AddMode), + SK_MEMBER(offset, Int), + SK_MEMBER(use, Drawable), + SK_MEMBER(where, Drawable) +}; + +#endif + +// start here; +// add onEndElement to turn where string into f_Where +// probably need new SkAnimateMaker::resolve flavor that takes +// where="id", where="event-target" or not-specified +// offset="#" (implements before, after, and index if no 'where') + +DEFINE_GET_MEMBER(SkAdd); + +SkAdd::SkAdd() : mode(kMode_indirect), + offset(SK_MaxS32), use(nil), where(nil) { +} + +SkDisplayable* SkAdd::deepCopy(SkAnimateMaker* maker) { + SkDrawable* saveUse = use; + SkDrawable* saveWhere = where; + use = nil; + where = nil; + SkAdd* copy = (SkAdd*) INHERITED::deepCopy(maker); + copy->use = use = saveUse; + copy->where = where = saveWhere; + return copy; +} + +bool SkAdd::draw(SkAnimateMaker& maker) { + SkASSERT(use); + SkASSERT(use->isDrawable()); + if (mode == kMode_indirect) + use->draw(maker); + return false; +} + +#ifdef SK_DUMP_ENABLED +void SkAdd::dump(SkAnimateMaker* maker) { + dumpBase(maker); + dumpAttrs(maker); + if (where) + SkDebugf("where=\"%s\" ", where->id); + if (mode == kMode_immediate) + SkDebugf("mode=\"immediate\" "); + SkDebugf(">\n"); + SkDisplayList::fIndent += 4; + int save = SkDisplayList::fDumpIndex; + if (use) //just in case + use->dump(maker); + SkDisplayList::fIndent -= 4; + SkDisplayList::fDumpIndex = save; + dumpEnd(maker); +} +#endif + +bool SkAdd::enable(SkAnimateMaker& maker ) { + SkDisplayTypes type = getType(); + SkDisplayList& displayList = maker.fDisplayList; + SkTDDrawableArray* parentList = displayList.getDrawList(); + if (type == SkType_Add) { + if (use == nil) // not set in apply yet + return true; + } + bool skipAddToParent = true; + SkASSERT(type != SkType_Replace || where); + SkTDDrawableArray* grandList SK_INIT_TO_AVOID_WARNING; + SkGroup* parentGroup = nil; + SkGroup* thisGroup = nil; + int index = where ? displayList.findGroup(where, &parentList, &parentGroup, + &thisGroup, &grandList) : 0; + if (index < 0) + return true; + int max = parentList->count(); + if (where == nil && type == SkType_Move) + index = max; + if (offset != SK_MaxS32) { + index += offset; + if (index > max) { + maker.setErrorCode(SkDisplayXMLParserError::kIndexOutOfRange); + return true; // caller should not add + } + } + if (offset < 0 && where == nil) + index += max + 1; + switch (type) { + case SkType_Add: + if (offset == SK_MaxS32 && where == nil) { + if (use->isDrawable()) { + skipAddToParent = mode == kMode_immediate; + if (skipAddToParent) { + if (where == nil) { + SkTDDrawableArray* useParentList; + index = displayList.findGroup(this, &useParentList, &parentGroup, + &thisGroup, &grandList); + if (index >= 0) { + parentGroup->markCopySize(index); + parentGroup->markCopySet(index); + useParentList->begin()[index] = use; + break; + } + } + *parentList->append() = use; + } + } + break; + } else { + if (thisGroup) + thisGroup->markCopySize(index); + *parentList->insert(index) = use; + if (thisGroup) + thisGroup->markCopySet(index); + if (use->isApply()) + ((SkApply*) use)->setEmbedded(); + } + break; + case SkType_Move: { + int priorLocation = parentList->find(use); + if (priorLocation < 0) + break; + *parentList->insert(index) = use; + if (index < priorLocation) + priorLocation++; + parentList->remove(priorLocation); + } break; + case SkType_Remove: { + SkDisplayable* old = (*parentList)[index]; + if (((SkRemove*)(this))->fDelete) { + delete old; + goto noHelperNeeded; + } + for (int inner = 0; inner < maker.fChildren.count(); inner++) { + SkDisplayable* child = maker.fChildren[inner]; + if (child == old || child->contains(old)) + goto noHelperNeeded; + } + if (maker.fHelpers.find(old) < 0) + maker.helperAdd(old); +noHelperNeeded: + parentList->remove(index); + } break; + case SkType_Replace: + if (thisGroup) { + thisGroup->markCopySize(index); + if (thisGroup->markedForDelete(index)) { + SkDisplayable* old = (*parentList)[index]; + if (maker.fHelpers.find(old) < 0) + maker.helperAdd(old); + } + } + (*parentList)[index] = use; + if (thisGroup) + thisGroup->markCopySet(index); + break; + default: + SkASSERT(0); + } + if (type == SkType_Remove) + return true; + if (use->hasEnable()) + use->enable(maker); + return skipAddToParent; // append if indirect: *parentList->append() = this; +} + +bool SkAdd::hasEnable() const { + return true; +} + +void SkAdd::initialize() { + if (use) + use->initialize(); +} + +bool SkAdd::isDrawable() const { + return getType() == SkType_Add && mode == kMode_indirect && offset == SK_MaxS32 && + where == nil && use != nil && use->isDrawable(); +} + +//SkDisplayable* SkAdd::resolveTarget(SkAnimateMaker& maker) { +// return use; +//} + + +bool SkClear::enable(SkAnimateMaker& maker ) { + SkDisplayList& displayList = maker.fDisplayList; + displayList.clear(); + return true; +} + + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkMove::fInfo[] = { + SK_MEMBER_INHERITED +}; + +#endif + +DEFINE_GET_MEMBER(SkMove); + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkRemove::fInfo[] = { + SK_MEMBER_ALIAS(delete, fDelete, Boolean), // !!! experimental + SK_MEMBER(offset, Int), + SK_MEMBER(where, Drawable) +}; + +#endif + +DEFINE_GET_MEMBER(SkRemove); + +SkRemove::SkRemove() : fDelete(false) { +} + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkReplace::fInfo[] = { + SK_MEMBER_INHERITED +}; + +#endif + +DEFINE_GET_MEMBER(SkReplace); + diff --git a/libs/graphics/animator/SkDisplayAdd.h b/libs/graphics/animator/SkDisplayAdd.h new file mode 100644 index 000000000..ed727307f --- /dev/null +++ b/libs/graphics/animator/SkDisplayAdd.h @@ -0,0 +1,64 @@ +#ifndef SkDisplayAdd_DEFINED +#define SkDisplayAdd_DEFINED + +#include "SkDrawable.h" +#include "SkMemberInfo.h" + +class SkAdd : public SkDrawable { + DECLARE_MEMBER_INFO(Add); + SkAdd(); + + enum Mode { + kMode_indirect, + kMode_immediate + }; + + virtual SkDisplayable* deepCopy(SkAnimateMaker* ); + virtual bool draw(SkAnimateMaker& ); +#ifdef SK_DUMP_ENABLED + virtual void dump(SkAnimateMaker* ); +#endif + virtual bool enable(SkAnimateMaker& ); + virtual bool hasEnable() const; + virtual void initialize(); + virtual bool isDrawable() const; +protected: +// struct _A { + Mode mode; + S32 offset; + SkDrawable* use; + SkDrawable* where; // if nil, offset becomes index +// } A; +private: + typedef SkDrawable INHERITED; +}; + +class SkClear : public SkDisplayable { + virtual bool enable(SkAnimateMaker& ); +}; + +class SkMove : public SkAdd { + DECLARE_MEMBER_INFO(Move); +private: + typedef SkAdd INHERITED; +}; + +class SkRemove : public SkAdd { + DECLARE_MEMBER_INFO(Remove); + SkRemove(); +protected: + SkBool fDelete; +private: + friend class SkAdd; + typedef SkAdd INHERITED; +}; + +class SkReplace : public SkAdd { + DECLARE_MEMBER_INFO(Replace); +private: + typedef SkAdd INHERITED; +}; + +#endif // SkDisplayAdd_DEFINED + + diff --git a/libs/graphics/animator/SkDisplayApply.cpp b/libs/graphics/animator/SkDisplayApply.cpp new file mode 100644 index 000000000..af886312f --- /dev/null +++ b/libs/graphics/animator/SkDisplayApply.cpp @@ -0,0 +1,797 @@ +#include "SkDisplayApply.h" +#include "SkAnimateActive.h" +#include "SkAnimateMaker.h" +#include "SkAnimateSet.h" +#include "SkAnimatorScript.h" +#include "SkDisplayType.h" +#include "SkDrawGroup.h" +#include "SkParse.h" +#include "SkScript.h" +#include "SkSystemEventTypes.h" +#ifdef SK_DEBUG +#include "SkTime.h" +#endif +#include + +enum SkApply_Properties { + SK_PROPERTY(animator), + SK_PROPERTY(step), + SK_PROPERTY(steps), + SK_PROPERTY(time) +}; + +#if SK_USE_CONDENSED_INFO == 0 + +// if no attibutes, enclosed displayable is both scope & target +// only if both scope & target are specified, or if target and enclosed displayable, are scope and target different +const SkMemberInfo SkApply::fInfo[] = { + SK_MEMBER_PROPERTY(animator, Animate), + SK_MEMBER(begin, MSec), + SK_MEMBER(dontDraw, Boolean), + SK_MEMBER(dynamicScope, String), + SK_MEMBER(interval, MSec), // recommended redraw interval + SK_MEMBER(mode, ApplyMode), +#if 0 + SK_MEMBER(pickup, Boolean), +#endif + SK_MEMBER(restore, Boolean), + SK_MEMBER(scope, Drawable), // thing that scopes animation (unnamed enclosed displayable goes here) + SK_MEMBER_PROPERTY(step, Int), + SK_MEMBER_PROPERTY(steps, Int), + SK_MEMBER_PROPERTY(time, MSec), + SK_MEMBER(transition, ApplyTransition) +}; + +#endif + +DEFINE_GET_MEMBER(SkApply); + +SkApply::SkApply() : begin(0), dontDraw(false), interval((SkMSec) -1), mode((Mode) -1), /*pickup(false), */ + restore(false), scope(nil), steps(-1), transition((Transition) -1), fActive(nil), /*fCurrentScope(nil),*/ + fLastTime(0), fAppended(false), fContainsScope(false), fDeleteScope(false), fEmbedded(false), + fEnabled(false), fEnabling(false) { +} + +SkApply::~SkApply() { + for (SkDrawable** curPtr = fScopes.begin(); curPtr < fScopes.end(); curPtr++) + delete *curPtr; + if (fDeleteScope) + delete scope; + // !!! caller must call maker.removeActive(fActive) + delete fActive; +} + +void SkApply::activate(SkAnimateMaker& maker) { + if (fActive != nil) { + if (fActive->fDrawIndex == 0 && fActive->fDrawMax == 0) + return; // if only one use, nothing more to do + if (restore == false) + return; // all share same state, regardless of instance number + bool save = fActive->initializeSave(); + fActive->fixInterpolator(save); + } else { + fActive = new SkActive(*this, maker); + fActive->init(); + maker.appendActive(fActive); + if (restore) { + fActive->initializeSave(); + int animators = fAnimators.count(); + for (int index = 0; index < animators; index++) + fActive->saveInterpolatorValues(index); + } + } +} + +void SkApply::append(SkApply* apply) { + if (fActive == nil) + return; + int oldCount = fActive->fAnimators.count(); + fActive->append(apply); + if (restore) { + fActive->appendSave(oldCount); + int newCount = fActive->fAnimators.count(); + for (int index = oldCount; index < newCount; index++) + fActive->saveInterpolatorValues(index); + } +} + +void SkApply::applyValues(int animatorIndex, SkOperand* values, int count, + SkDisplayTypes valuesType, SkMSec time) +{ + SkAnimateBase* animator = fActive->fAnimators[animatorIndex]; + const SkMemberInfo * info = animator->fFieldInfo; + SkASSERT(animator); + SkASSERT(info != nil); + SkDisplayTypes type = (SkDisplayTypes) info->fType; + SkDisplayable* target = getTarget(animator); + if (animator->hasExecute() || type == SkType_MemberFunction || type == SkType_MemberProperty) { + SkDisplayable* executor = animator->hasExecute() ? animator : target; + if (type != SkType_MemberProperty) { + SkTDArray typedValues; + for (int index = 0; index < count; index++) { + SkScriptValue temp; + temp.fType = valuesType; + temp.fOperand = values[index]; + *typedValues.append() = temp; + } + executor->executeFunction(target, info->functionIndex(), typedValues, info->getType(), nil); + } else { + SkScriptValue scriptValue; + scriptValue.fOperand = values[0]; + scriptValue.fType = info->getType(); + target->setProperty(info->propertyIndex(), scriptValue); + } + } else { + SkTypedArray converted; + if (type == SkType_ARGB) { + if (count == 4) { + // !!! assert that it is SkType_Float ? + animator->packARGB(&values->fScalar, count, &converted); + values = converted.begin(); + count = converted.count(); + } else + SkASSERT(count == 1); + } +// SkASSERT(type == SkType_ARGB || type == SkType_String ||info->isSettable()); + if (type == SkType_String || type == SkType_DynamicString) + info->setString(target, values->fString); + else if (type == SkType_Drawable || type == SkType_Displayable) + target->setReference(info, values->fDisplayable); + else + info->setValue(target, values, count); + } +} + +bool SkApply::contains(SkDisplayable* child) { + for (SkDrawable** curPtr = fScopes.begin(); curPtr < fScopes.end(); curPtr++) { + if (*curPtr == child || (*curPtr)->contains(child)) + return true; + } + return fDeleteScope && scope == child; +} + +SkDisplayable* SkApply::deepCopy(SkAnimateMaker* maker) { + SkDrawable* saveScope = scope; + scope = nil; + SkApply* result = (SkApply*) INHERITED::deepCopy(maker); + result->scope = scope = saveScope; + SkAnimateBase** end = fAnimators.end(); + for (SkAnimateBase** animPtr = fAnimators.begin(); animPtr < end; animPtr++) { + SkAnimateBase* anim = (SkAnimateBase*) (*animPtr)->deepCopy(maker); + *result->fAnimators.append() = anim; + maker->helperAdd(anim); + } + return result; +} + +void SkApply::disable() { + //!!! this is the right thing to do, but has bad side effects because of other problems + // currently, if an apply is in a g and scopes a statement in another g, it ends up as members + // of both containers. The disabling here incorrectly disables both instances + // maybe the fEnabled flag needs to be moved to the fActive data so that both + // instances are not affected. +// fEnabled = false; +} + +bool SkApply::draw(SkAnimateMaker& maker) { + if (scope ==nil) + return false; + if (scope->isApply() || scope->isDrawable() == false) + return false; + if (fEnabled == false) + enable(maker); + SkASSERT(scope); + activate(maker); + if (mode == kMode_immediate) + return fActive->draw(); + bool result = interpolate(maker, maker.getInTime()); + if (dontDraw == false) { +// if (scope->isDrawable()) + result |= scope->draw(maker); + } + if (restore) { + for (int index = 0; index < fActive->fAnimators.count(); index++) + endSave(index); + fActive->advance(); + } + return result; +} + +#ifdef SK_DUMP_ENABLED +void SkApply::dump(SkAnimateMaker* maker) { + dumpBase(maker); + if (dynamicScope.isEmpty() == false) + SkDebugf("dynamicScope=\"%s\" ", dynamicScope.c_str()); + if (dontDraw) + SkDebugf("dontDraw=\"true\" "); + if (begin != 0) //perhaps we want this no matter what? + SkDebugf("begin=\"%g\" ", (float) begin/1000.0f); //is this correct? + if (interval != (SkMSec) -1) + SkDebugf("interval=\"%g\" ", (float) interval/1000.0f); + if (steps != -1) + SkDebugf("steps=\"%d\" ", steps); + if (restore) + SkDebugf("restore=\"true\" "); + if (transition == kTransition_reverse) + SkDebugf("transition=\"reverse\" "); + if (mode == kMode_immediate) { + SkDebugf("mode=\"immediate\" "); + } + else if (mode == kMode_create) { + SkDebugf("mode=\"create\" "); + } + bool closedYet = false; + SkDisplayList::fIndent += 4; + int save = SkDisplayList::fDumpIndex; + if (scope) { + if (closedYet == false) { + SkDebugf(">\n"); + closedYet = true; + } + scope->dump(maker); + } + int index; +// if (fActive) { + for (index = 0; index < fAnimators.count(); index++) { + if (closedYet == false) { + SkDebugf(">\n"); + closedYet = true; + } + SkAnimateBase* animator = fAnimators[index]; + animator->dump(maker); +// } + } + SkDisplayList::fIndent -= 4; + SkDisplayList::fDumpIndex = save; + if (closedYet) + dumpEnd(maker); + else + SkDebugf("/>\n"); +} +#endif + +bool SkApply::enable(SkAnimateMaker& maker) { + fEnabled = true; + bool initialized = fActive != nil; + if (dynamicScope.size() > 0) + enableDynamic(maker); + if (maker.fError.hasError()) + return false; + int animators = fAnimators.count(); + int index; + for (index = 0; index < animators; index++) { + SkAnimateBase* animator = fAnimators[index]; + animator->fStart = maker.fEnableTime; + animator->fResetPending = animator->fReset; + } + if (scope && scope->isApply()) + ((SkApply*) scope)->setEmbedded(); +/* if (mode == kMode_once) { + if (scope) { + activate(maker); + interpolate(maker, maker.fEnableTime); + inactivate(maker); + } + return true; + }*/ + if ((mode == kMode_immediate || mode == kMode_create) && scope == nil) + return false; // !!! error? + bool enableMe = scope && (scope->hasEnable() || scope->isApply() || scope->isDrawable() == false); + if (mode == kMode_immediate && enableMe || mode == kMode_create) + activate(maker); // for non-drawables like post, prime them here + if (mode == kMode_immediate && enableMe) + fActive->enable(); + if (mode == kMode_create && scope != nil) { + enableCreate(maker); + return true; + } + if (mode == kMode_immediate) { + return scope->isApply() || scope->isDrawable() == false; + } + refresh(maker); + SkDisplayList& displayList = maker.fDisplayList; + SkDrawable* drawable; +#if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING + SkString debugOut; + SkMSec time = maker.getAppTime(); + debugOut.appendS32(time - maker.fDebugTimeBase); + debugOut.append(" apply enable id="); + debugOut.append(_id); + debugOut.append("; start="); + debugOut.appendS32(maker.fEnableTime - maker.fDebugTimeBase); + SkDebugf("%s\n", debugOut.c_str()); +#endif + if (scope == nil || scope->isApply() || scope->getType() == SkType_Movie || scope->isDrawable() == false) { + activate(maker); // for non-drawables like post, prime them here + if (initialized) { + append(this); + } + fEnabling = true; + interpolate(maker, maker.fEnableTime); + fEnabling = false; + if (scope != nil && dontDraw == false) + scope->enable(maker); + return true; + } else if (initialized && restore == false) + append(this); +#if 0 + bool wasActive = inactivate(maker); // start fresh + if (wasActive) { + activate(maker); + interpolate(maker, maker.fEnableTime); + return true; + } +#endif +// start here; + // now that one apply might embed another, only the parent apply should replace the scope + // or get appended to the display list + // similarly, an apply added by an add immediate has already been located in the display list + // and should not get moved or added again here + if (fEmbedded) { + return false; // already added to display list by embedder + } + drawable = (SkDrawable*) scope; + SkTDDrawableArray* parentList; + SkTDDrawableArray* grandList; + SkGroup* parentGroup; + SkGroup* thisGroup; + int old = displayList.findGroup(drawable, &parentList, &parentGroup, &thisGroup, &grandList); + if (old < 0) + goto append; + else if (fContainsScope) { + if ((*parentList)[old] != this || restore == true) { +append: + if (parentGroup) + parentGroup->markCopySize(old); + if (parentList->count() < 10000) { + fAppended = true; + *parentList->append() = this; + } else + maker.setErrorCode(SkDisplayXMLParserError::kDisplayTreeTooDeep); + old = -1; + } else + reset(); + } else { + SkASSERT(old < parentList->count()); + if ((*parentList)[old]->isApply()) { + SkApply* apply = (SkApply*) (*parentList)[old]; + if (apply != this && apply->fActive == nil) + apply->activate(maker); + apply->append(this); + parentGroup = nil; + } else { + if (parentGroup) + parentGroup->markCopySize(old); + SkDrawable** newApplyLocation = &(*parentList)[old]; + SkGroup* pGroup; + int oldApply = displayList.findGroup(this, &parentList, &pGroup, &thisGroup, &grandList); + if (oldApply >= 0) { + (*parentList)[oldApply] = (SkDrawable*) SkDisplayType::CreateInstance(&maker, SkType_Apply); + parentGroup = nil; + fDeleteScope = true; + } + *newApplyLocation = this; + } + } + if (parentGroup) { + parentGroup->markCopySet(old); + fDeleteScope = dynamicScope.size() == 0; + } + return true; +} + +void SkApply::enableCreate(SkAnimateMaker& maker) { + SkString newID; + for (int step = 0; step <= steps; step++) { + fLastTime = step * SK_MSec1; + bool success = maker.computeID(scope, this, &newID); + if (success == false) + return; + if (maker.find(newID.c_str(), nil)) + continue; + SkApply* copy = (SkApply*) deepCopy(&maker); // work on copy of animator state + if (mode == kMode_create) + copy->mode = (Mode) -1; + SkDrawable* copyScope = copy->scope = (SkDrawable*) scope->deepCopy(&maker); + *fScopes.append() = copyScope; + if (copyScope->resolveIDs(maker, scope, this)) { + step = steps; // quit + goto next; // resolveIDs failed + } + if (newID.size() > 0) + maker.setID(copyScope, newID); + if (copy->resolveIDs(maker, this, this)) { // fix up all fields, including target + step = steps; // quit + goto next; // resolveIDs failed + } + copy->activate(maker); + copy->interpolate(maker, step * SK_MSec1); + maker.removeActive(copy->fActive); + next: + delete copy; + } +} + +void SkApply::enableDynamic(SkAnimateMaker& maker) { + SkASSERT(mode != kMode_create); // create + dynamic are not currently compatible + SkDisplayable* newScope; + bool success = SkAnimatorScript::EvaluateDisplayable(maker, this, dynamicScope.c_str(), + &newScope); + if (success && scope != newScope) { + SkTDDrawableArray* pList, * gList; + SkGroup* pGroup = nil, * found = nil; + int old = maker.fDisplayList.findGroup(scope, &pList, &pGroup, &found, &gList); + if (pList && old >= 0 && (*pList)[old]->isApply() && (*pList)[old] != this) { + if (fAppended == false) { + if (found != nil) { + SkDisplayable* oldChild = (*pList)[old]; + if (oldChild->isApply() && found->copySet(old)) { + found->markCopyClear(old); + // delete oldChild; + } + } + (*pList)[old] = scope; + } else + pList->remove(old); + } + scope = (SkDrawable*) newScope; + onEndElement(maker); + } + maker.removeActive(fActive); + delete fActive; + fActive = nil; +} + +void SkApply::endSave(int index) { + SkAnimateBase* animate = fActive->fAnimators[index]; + const SkMemberInfo* info = animate->fFieldInfo; + SkDisplayTypes type = (SkDisplayTypes) info->fType; + if (type == SkType_MemberFunction) + return; + SkDisplayable* target = getTarget(animate); + size_t size = info->getSize(target); + int count = (int) (size / sizeof(SkScalar)); + int activeIndex = fActive->fDrawIndex + index; + SkOperand* last = new SkOperand[count]; + SkAutoTDelete autoLast(last); + if (type != SkType_MemberProperty) { + info->getValue(target, last, count); + SkOperand* saveOperand = fActive->fSaveRestore[activeIndex]; + if (saveOperand) + info->setValue(target, fActive->fSaveRestore[activeIndex], count); + } else { + SkScriptValue scriptValue; + bool success = target->getProperty(info->propertyIndex(), &scriptValue); + SkASSERT(success = true); + last[0] = scriptValue.fOperand; + scriptValue.fOperand = fActive->fSaveRestore[activeIndex][0]; + target->setProperty(info->propertyIndex(), scriptValue); + } + SkOperand* save = fActive->fSaveRestore[activeIndex]; + if (save) + memcpy(save, last, count * sizeof(SkOperand)); +} + +bool SkApply::getProperty(int index, SkScriptValue* value) const { + switch (index) { + case SK_PROPERTY(step): + value->fType = SkType_Int; + value->fOperand.fS32 = fLastTime / SK_MSec1; + break; + case SK_PROPERTY(steps): + value->fType = SkType_Int; + value->fOperand.fS32 = steps; + break; + case SK_PROPERTY(time): + value->fType = SkType_MSec; + value->fOperand.fS32 = fLastTime; + break; + default: + // SkASSERT(0); + return false; + } + return true; +} + +void SkApply::getStep(SkScriptValue* value) { + getProperty(SK_PROPERTY(step), value); +} + +SkDrawable* SkApply::getTarget(SkAnimateBase* animate) { + if (animate->fTargetIsScope == false || mode != kMode_create) + return animate->fTarget; + return scope; +} + +bool SkApply::hasDelayedAnimator() const { + SkAnimateBase** animEnd = fAnimators.end(); + for (SkAnimateBase** animPtr = fAnimators.begin(); animPtr < animEnd; animPtr++) { + SkAnimateBase* animator = *animPtr; + if (animator->fDelayed) + return true; + } + return false; +} + +bool SkApply::hasEnable() const { + return true; +} + +bool SkApply::inactivate(SkAnimateMaker& maker) { + if (fActive == nil) + return false; + maker.removeActive(fActive); + delete fActive; + fActive = nil; + return true; +} + +#ifdef SK_DEBUG +SkMSec lastTime = (SkMSec) -1; +#endif + +bool SkApply::interpolate(SkAnimateMaker& maker, SkMSec rawTime) { + if (fActive == nil) + return false; + bool result = false; +#if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING + SkMSec time = maker.getAppTime(); + if (lastTime == (SkMSec) -1) + lastTime = rawTime - 1; + if (fActive != nil && + strcmp(id, "a3") == 0 && rawTime > lastTime) { + lastTime += 1000; + SkString debugOut; + debugOut.appendS32(time - maker.fDebugTimeBase); + debugOut.append(" apply id="); + debugOut.append(_id); + debugOut.append("; "); + debugOut.append(fActive->fAnimators[0]->_id); + debugOut.append("="); + debugOut.appendS32(rawTime - fActive->fState[0].fStartTime); + debugOut.append(")"); + SkDebugf("%s\n", debugOut.c_str()); + } +#endif + fActive->start(); + if (restore) + fActive->initializeSave(); + int animators = fActive->fAnimators.count(); + for (int inner = 0; inner < animators; inner++) { + SkAnimateBase* animate = fActive->fAnimators[inner]; + if (animate->fChanged) { + animate->fChanged = false; + animate->fStart = rawTime; + // SkTypedArray values; + // int count = animate->fValues.count(); + // values.setCount(count); + // memcpy(values.begin(), animate->fValues.begin(), sizeof(SkOperand) * count); + animate->onEndElement(maker); + // if (memcmp(values.begin(), animate->fValues.begin(), sizeof(SkOperand) * count) != 0) { + fActive->append(this); + fActive->start(); + // } + } + SkMSec time = fActive->getTime(rawTime, inner); + SkActive::SkState& state = fActive->fState[inner]; + if (SkMSec_LT(rawTime, state.fStartTime)) { + if (fEnabling) { + animate->fDelayed = true; + maker.delayEnable(this, state.fStartTime); + } + continue; + } else + animate->fDelayed = false; + SkMSec innerTime = fLastTime = state.getRelativeTime(time); + if (restore) + fActive->restoreInterpolatorValues(inner); + if (animate->fReset) { + if (transition != SkApply::kTransition_reverse) { + if (SkMSec_LT(state.fBegin + state.fDuration, innerTime)) { + if (animate->fResetPending) { + innerTime = 0; + animate->fResetPending = false; + } else + continue; + } + } else if (innerTime == 0) { + if (animate->fResetPending) { + innerTime = state.fBegin + state.fDuration; + animate->fResetPending = false; + } else + continue; + } + } + int count = animate->components(); + SkAutoSTMalloc<16, SkOperand> values(count); + SkInterpolatorBase::Result interpResult = fActive->fInterpolators[inner]->timeToValues( + innerTime, values.get()); + result |= (interpResult != SkInterpolatorBase::kFreezeEnd_Result); + if ((transition != SkApply::kTransition_reverse && interpResult == SkInterpolatorBase::kFreezeEnd_Result || + transition == SkApply::kTransition_reverse && fLastTime == 0) && state.fUnpostedEndEvent) { +// SkDEBUGF(("interpolate: post on end\n")); + state.fUnpostedEndEvent = false; + maker.postOnEnd(animate, state.fBegin + state.fDuration); + maker.fAdjustedStart = 0; // !!! left over from synchronizing animation days, undoubtably out of date (and broken) + } + if (animate->formula.size() > 0) { + if (fLastTime > animate->dur) + fLastTime = animate->dur; + SkTypedArray formulaValues; + formulaValues.setCount(count); + bool success = animate->fFieldInfo->setValue(maker, &formulaValues, 0, 0, nil, + animate->getValuesType(), animate->formula); + SkASSERT(success); + if (restore) + save(inner); // save existing value + applyValues(inner, formulaValues.begin(), count, animate->getValuesType(), innerTime); + } else { + if (restore) + save(inner); // save existing value + applyValues(inner, values.get(), count, animate->getValuesType(), innerTime); + } + } + return result; +} + +void SkApply::initialize() { + if (scope == nil) + return; + if (scope->isApply() || scope->isDrawable() == false) + return; + scope->initialize(); +} + +void SkApply::onEndElement(SkAnimateMaker& maker) +{ + SkDrawable* scopePtr = scope; + while (scopePtr && scopePtr->isApply()) { + SkApply* scopedApply = (SkApply*) scopePtr; + if (scopedApply->scope == this) { + maker.setErrorCode(SkDisplayXMLParserError::kApplyScopesItself); + return; + } + scopePtr = scopedApply->scope; + } + if (mode == kMode_create) + return; + if (scope != nil && steps >= 0 && scope->isApply() == false && scope->isDrawable()) + scope->setSteps(steps); + for (SkAnimateBase** animPtr = fAnimators.begin(); animPtr < fAnimators.end(); animPtr++) { + SkAnimateBase* anim = *animPtr; + //for reusing apply statements with dynamic scope + if (anim->fTarget == nil || anim->fTargetIsScope) { + anim->fTargetIsScope = true; + if (scope) + anim->fTarget = scope; + else + anim->setTarget(maker); + anim->onEndElement(maker); // allows animate->fFieldInfo to be set + } + if (scope != nil && steps >= 0 && anim->fTarget != scope && anim->fTarget->isDrawable()) + anim->fTarget->setSteps(steps); + } +} + +const SkMemberInfo* SkApply::preferredChild(SkDisplayTypes type) { + SkASSERT(SkDisplayType::IsAnimate(type) == false); + fContainsScope = true; + return getMember("scope"); // !!! cwap! need to refer to member through enum like kScope instead +} + +void SkApply::refresh(SkAnimateMaker& maker) { + for (SkAnimateBase** animPtr = fAnimators.begin(); animPtr < fAnimators.end(); animPtr++) { + SkAnimateBase* animate = *animPtr; + animate->onEndElement(maker); + } + if (fActive) + fActive->resetInterpolators(); +} + +void SkApply::reset() { + if (fActive) + fActive->resetState(); +} + +bool SkApply::resolveIDs(SkAnimateMaker& maker, SkDisplayable* original, SkApply* apply) { // replace to/formula strings in animators of the form xxx.step with the step value, if xxx.step is in scope + if (resolveField(maker, apply, &dynamicScope) == false) + return true; // failed + SkAnimateBase** endPtr = fAnimators.end(); + SkAnimateBase** origPtr = ((SkApply*) original)->fAnimators.begin(); + for (SkAnimateBase** animPtr = fAnimators.begin(); animPtr < endPtr; ) { + SkAnimateBase* animator = *animPtr++; + maker.resolveID(animator, *origPtr++); + if (resolveField(maker, this, &animator->target) == false) + return true; + if (resolveField(maker, this, &animator->from) == false) + return true; + if (resolveField(maker, this, &animator->to) == false) + return true; + if (resolveField(maker, this, &animator->formula) == false) + return true; + } +// setEmbedded(); + onEndElement(maker); + return false; // succeeded +} + +bool SkApply::resolveField(SkAnimateMaker& maker, SkDisplayable* parent, SkString* str) { + const char* script = str->c_str(); + if (str->startsWith("#string:") == false) + return true; + script += sizeof("#string:") - 1; + return SkAnimatorScript::EvaluateString(maker, this, parent, script, str); +} + +void SkApply::save(int index) { + SkAnimateBase* animate = fActive->fAnimators[index]; + const SkMemberInfo * info = animate->fFieldInfo; + SkDisplayable* target = getTarget(animate); +// if (animate->hasExecute()) +// info = animate->getResolvedInfo(); + SkDisplayTypes type = (SkDisplayTypes) info->fType; + if (type == SkType_MemberFunction) + return; // nothing to save + size_t size = info->getSize(target); + int count = (int) (size / sizeof(SkScalar)); + bool useLast = true; +// !!! this all may be unneeded, at least in the dynamic case ?? + int activeIndex = fActive->fDrawIndex + index; + SkTDOperandArray last; + if (fActive->fSaveRestore[activeIndex] == nil) { + fActive->fSaveRestore[activeIndex] = new SkOperand[count]; + useLast = false; + } else { + last.setCount(count); + memcpy(last.begin(), fActive->fSaveRestore[activeIndex], count * sizeof(SkOperand)); + } + if (type != SkType_MemberProperty) { + info->getValue(target, fActive->fSaveRestore[activeIndex], count); + if (useLast) + info->setValue(target, last.begin(), count); + } else { + SkScriptValue scriptValue; + bool success = target->getProperty(info->propertyIndex(), &scriptValue); + SkASSERT(success == true); + SkASSERT(scriptValue.fType == SkType_Float); + fActive->fSaveRestore[activeIndex][0] = scriptValue.fOperand; + if (useLast) { + SkScriptValue scriptValue; + scriptValue.fType = type; + scriptValue.fOperand = last[0]; + target->setProperty(info->propertyIndex(), scriptValue); + } + } +// !!! end of unneeded +} + +bool SkApply::setProperty(int index, SkScriptValue& scriptValue) { + switch (index) { + case SK_PROPERTY(animator): { + SkAnimateBase* animate = (SkAnimateBase*) scriptValue.fOperand.fDisplayable; + SkASSERT(animate->isAnimate()); + *fAnimators.append() = animate; + return true; + } + case SK_PROPERTY(steps): + steps = scriptValue.fOperand.fS32; + if (fActive) + fActive->setSteps(steps); + return true; + } + return false; +} + +void SkApply::setSteps(int _steps) { + steps = _steps; +} + +#ifdef SK_DEBUG +void SkApply::validate() { + if (fActive) + fActive->validate(); +} +#endif + + + diff --git a/libs/graphics/animator/SkDisplayApply.h b/libs/graphics/animator/SkDisplayApply.h new file mode 100644 index 000000000..883323af8 --- /dev/null +++ b/libs/graphics/animator/SkDisplayApply.h @@ -0,0 +1,99 @@ +#ifndef SkDisplayApply_DEFINED +#define SkDisplayApply_DEFINED + +#include "SkAnimateBase.h" +#include "SkDrawable.h" +#include "SkIntArray.h" + +class SkActive; + +class SkApply : public SkDrawable { + DECLARE_MEMBER_INFO(Apply); +public: + + SkApply(); + virtual ~SkApply(); + + enum Transition { + kTransition_normal, + kTransition_reverse + }; + + enum Mode { + kMode_create, + kMode_immediate, + //kMode_once + }; + void activate(SkAnimateMaker& ); + void append(SkApply* apply); + void appendActive(SkActive* ); + void applyValues(int animatorIndex, SkOperand* values, int count, + SkDisplayTypes , SkMSec time); + virtual bool contains(SkDisplayable*); +// void createActive(SkAnimateMaker& ); + virtual SkDisplayable* deepCopy(SkAnimateMaker* ); + void disable(); + virtual bool draw(SkAnimateMaker& ); +#ifdef SK_DUMP_ENABLED + virtual void dump(SkAnimateMaker* ); +#endif + virtual bool enable(SkAnimateMaker& ); + void enableCreate(SkAnimateMaker& ); + void enableDynamic(SkAnimateMaker& ); + void endSave(int index); + Mode getMode() { return mode; } + virtual bool getProperty(int index, SkScriptValue* value) const; + SkDrawable* getScope() { return scope; } + void getStep(SkScriptValue* ); + SkDrawable* getTarget(SkAnimateBase* ); + bool hasDelayedAnimator() const; + virtual bool hasEnable() const; + bool inactivate(SkAnimateMaker& maker); + virtual void initialize(); + bool interpolate(SkAnimateMaker& , SkMSec time); + virtual void onEndElement(SkAnimateMaker& ); + virtual const SkMemberInfo* preferredChild(SkDisplayTypes type); + void refresh(SkAnimateMaker& ); + void reset(); + virtual bool resolveIDs(SkAnimateMaker& maker, SkDisplayable* original, SkApply* ); + bool resolveField(SkAnimateMaker& , SkDisplayable* parent, SkString* str); + void save(int index); + void setEmbedded() { fEmbedded = true; } + virtual bool setProperty(int index, SkScriptValue& ); + virtual void setSteps(int _steps); +// virtual void setTime(SkMSec time); +#ifdef SK_DEBUG + virtual void validate(); +#endif +private: + SkMSec begin; + SkBool dontDraw; + SkString dynamicScope; + SkMSec interval; + Mode mode; +#if 0 + SkBool pickup; +#endif + SkBool restore; + SkDrawable* scope; + S32 steps; + Transition transition; + SkActive* fActive; + SkTDAnimateArray fAnimators; +// SkDrawable* fCurrentScope; + SkMSec fLastTime; // used only to return script property time + SkTDDrawableArray fScopes; + SkBool fAppended : 1; + SkBool fContainsScope : 1; + SkBool fDeleteScope : 1; + SkBool fEmbedded : 1; + SkBool fEnabled : 1; + SkBool fEnabling : 1; // set if calling interpolate from enable + friend class SkActive; + friend class SkDisplayList; + typedef SkDrawable INHERITED; +}; + +#endif // SkDisplayApply_DEFINED + + diff --git a/libs/graphics/animator/SkDisplayBounds.cpp b/libs/graphics/animator/SkDisplayBounds.cpp new file mode 100644 index 000000000..e6abcc31c --- /dev/null +++ b/libs/graphics/animator/SkDisplayBounds.cpp @@ -0,0 +1,37 @@ +#include "SkDisplayBounds.h" +#include "SkAnimateMaker.h" + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDisplayBounds::fInfo[] = { + SK_MEMBER_INHERITED, + SK_MEMBER(inval, Boolean) +}; + +#endif + +DEFINE_GET_MEMBER(SkDisplayBounds); + +SkDisplayBounds::SkDisplayBounds() : inval(false) { +} + +bool SkDisplayBounds::draw(SkAnimateMaker& maker) { + maker.fDisplayList.fUnionBounds = SkToBool(inval); + maker.fDisplayList.fDrawBounds = false; + fBounds.setEmpty(); + bool result = INHERITED::draw(maker); + maker.fDisplayList.fUnionBounds = false; + maker.fDisplayList.fDrawBounds = true; + if (inval && fBounds.isEmpty() == false) { + SkRect16& rect = maker.fDisplayList.fInvalBounds; + maker.fDisplayList.fHasUnion = true; + if (rect.isEmpty()) + rect = fBounds; + else + rect.join(fBounds); + } + return result; +} + + + diff --git a/libs/graphics/animator/SkDisplayBounds.h b/libs/graphics/animator/SkDisplayBounds.h new file mode 100644 index 000000000..077d4cc8f --- /dev/null +++ b/libs/graphics/animator/SkDisplayBounds.h @@ -0,0 +1,16 @@ +#ifndef SkDisplayBounds_DEFINED +#define SkDisplayBounds_DEFINED + +#include "SkDrawRectangle.h" + +class SkDisplayBounds : public SkDrawRect { + DECLARE_DISPLAY_MEMBER_INFO(Bounds); + SkDisplayBounds(); + virtual bool draw(SkAnimateMaker& ); +private: + SkBool inval; + typedef SkDrawRect INHERITED; +}; + +#endif // SkDisplayBounds_DEFINED + diff --git a/libs/graphics/animator/SkDisplayEvent.cpp b/libs/graphics/animator/SkDisplayEvent.cpp new file mode 100644 index 000000000..46af81cff --- /dev/null +++ b/libs/graphics/animator/SkDisplayEvent.cpp @@ -0,0 +1,248 @@ +#include "SkDisplayEvent.h" +#include "SkAnimateMaker.h" +#include "SkDisplayApply.h" +#include "SkDisplayInput.h" +#include "SkDisplayList.h" +#ifdef SK_DEBUG +#include "SkDump.h" +#endif +#include "SkEvent.h" +#include "SkDisplayInput.h" +#include "SkKey.h" +#include "SkMetaData.h" +#include "SkScript.h" +#include "SkUtils.h" + +enum SkDisplayEvent_Properties { + SK_PROPERTY(key), + SK_PROPERTY(keys) +}; + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDisplayEvent::fInfo[] = { + SK_MEMBER(code, EventCode), + SK_MEMBER(disable, Boolean), + SK_MEMBER_PROPERTY(key, String), // a single key (also last key pressed) + SK_MEMBER_PROPERTY(keys, String), // a single key or dash-delimited range of keys + SK_MEMBER(kind, EventKind), + SK_MEMBER(target, String), + SK_MEMBER(x, Float), + SK_MEMBER(y, Float) +}; + +#endif + +DEFINE_GET_MEMBER(SkDisplayEvent); + +SkDisplayEvent::SkDisplayEvent() : code((SkKey) -1), disable(false), + kind(kUser), x(0), y(0), fLastCode((SkKey) -1), fMax((SkKey) -1), fTarget(nil) { +} + +SkDisplayEvent::~SkDisplayEvent() { + deleteMembers(); +} + +bool SkDisplayEvent::add(SkAnimateMaker& , SkDisplayable* child) { + *fChildren.append() = child; + return true; +} + +bool SkDisplayEvent::contains(SkDisplayable* match) { + for (int index = 0; index < fChildren.count(); index++) { + if (fChildren[index] == match || fChildren[index]->contains(match)) + return true; + } + return false; +} + +SkDisplayable* SkDisplayEvent::contains(const SkString& match) { + for (int index = 0; index < fChildren.count(); index++) { + SkDisplayable* child = fChildren[index]; + if (child->contains(match)) + return child; + } + return nil; +} + +void SkDisplayEvent::deleteMembers() { + for (int index = 0; index < fChildren.count(); index++) { + SkDisplayable* evt = fChildren[index]; + delete evt; + } +} + +#ifdef SK_DUMP_ENABLED +void SkDisplayEvent::dumpEvent(SkAnimateMaker* maker) { + dumpBase(maker); + SkString str; + SkDump::GetEnumString(SkType_EventKind, kind, &str); + SkDebugf("kind=\"%s\" ", str.c_str()); + if (kind == SkDisplayEvent::kKeyPress || kind == SkDisplayEvent::kKeyPressUp) { + if (code >= 0) + SkDump::GetEnumString(SkType_EventCode, code, &str); + else + str.set("none"); + SkDebugf("code=\"%s\" ", str.c_str()); + } + if (kind == SkDisplayEvent::kKeyChar) { + if (fMax != (SkKey) -1 && fMax != code) + SkDebugf("keys=\"%c - %c\" ", code, fMax); + else + SkDebugf("key=\"%c\" ", code); + } + if (fTarget != nil) { + SkDebugf("target=\"%s\" ", fTarget->id); + } + if (kind >= SkDisplayEvent::kMouseDown && kind <= SkDisplayEvent::kMouseUp) { +#ifdef SK_CAN_USE_FLOAT + SkDebugf("x=\"%g\" y=\"%g\" ", SkScalarToFloat(x), SkScalarToFloat(y)); +#else + SkDebugf("x=\"%x\" y=\"%x\" ", x, y); +#endif + } + if (disable) + SkDebugf("disable=\"true\" "); + SkDebugf("/>\n"); +} +#endif + +bool SkDisplayEvent::enableEvent(SkAnimateMaker& maker) +{ + maker.fActiveEvent = this; + if (fChildren.count() == 0) + return false; + if (disable) + return false; +#ifdef SK_DUMP_ENABLED + if (maker.fDumpEvents) { + SkDebugf("enable: "); + dumpEvent(&maker); + } +#endif + SkDisplayList& displayList = maker.fDisplayList; + for (int index = 0; index < fChildren.count(); index++) { + SkDisplayable* displayable = fChildren[index]; + if (displayable->isGroup()) { + SkTDDrawableArray* parentList = displayList.getDrawList(); + *parentList->append() = (SkDrawable*) displayable; // make it findable before children are enabled + } + if (displayable->enable(maker)) + continue; + if (maker.hasError()) + return true; + if (displayable->isDrawable() == false) + return true; // error + SkDrawable* drawable = (SkDrawable*) displayable; + SkTDDrawableArray* parentList = displayList.getDrawList(); + *parentList->append() = drawable; + } + return false; +} + +bool SkDisplayEvent::getProperty(int index, SkScriptValue* value) const { + switch (index) { + case SK_PROPERTY(key): + case SK_PROPERTY(keys): { + value->fType = SkType_String; + char scratch[8]; + SkKey convert = index == SK_PROPERTY(keys) ? code : fLastCode; + size_t size = convert > 0 ? SkUTF8_FromUnichar(convert, scratch) : 0; + fKeyString.set(scratch, size); + value->fOperand.fString = &fKeyString; + if (index != SK_PROPERTY(keys) || fMax == (SkKey) -1 || fMax == code) + break; + value->fOperand.fString->append("-"); + size = SkUTF8_FromUnichar(fMax, scratch); + value->fOperand.fString->append(scratch, size); + } break; + default: + SkASSERT(0); + return false; + } + return true; +} + +void SkDisplayEvent::onEndElement(SkAnimateMaker& maker) +{ + if (kind == kUser) + return; + maker.fEvents.addEvent(this); + if (kind == kOnEnd) { + bool found = maker.find(target.c_str(), &fTarget); + SkASSERT(found); + SkASSERT(fTarget && fTarget->isAnimate()); + SkAnimateBase* animate = (SkAnimateBase*) fTarget; + animate->setHasEndEvent(); + } +} + +void SkDisplayEvent::populateInput(SkAnimateMaker& maker, const SkEvent& fEvent) { + const SkMetaData& meta = fEvent.getMetaData(); + SkMetaData::Iter iter(meta); + SkMetaData::Type type; + int number; + const char* name; + while ((name = iter.next(&type, &number)) != nil) { + if (name[0] == '\0') + continue; + SkDisplayable* displayable; + SkInput* input; + for (int index = 0; index < fChildren.count(); index++) { + displayable = fChildren[index]; + if (displayable->getType() != SkType_Input) + continue; + input = (SkInput*) displayable; + if (input->name.equals(name)) + goto found; + } + if (!maker.find(name, &displayable) || displayable->getType() != SkType_Input) + continue; + input = (SkInput*) displayable; + found: + switch (type) { + case SkMetaData::kS32_Type: + meta.findS32(name, &input->fInt); + break; + case SkMetaData::kScalar_Type: + meta.findScalar(name, &input->fFloat); + break; + case SkMetaData::kPtr_Type: + SkASSERT(0); + break; // !!! not handled for now + case SkMetaData::kString_Type: + input->string.set(meta.findString(name)); + break; + default: + SkASSERT(0); + } + } + // re-evaluate all animators that may have built their values from input strings + for (SkDisplayable** childPtr = fChildren.begin(); childPtr < fChildren.end(); childPtr++) { + SkDisplayable* displayable = *childPtr; + if (displayable->isApply() == false) + continue; + SkApply* apply = (SkApply*) displayable; + apply->refresh(maker); + } +} + +bool SkDisplayEvent::setProperty(int index, SkScriptValue& value) { + SkASSERT(index == SK_PROPERTY(key) || index == SK_PROPERTY(keys)); + SkASSERT(value.fType == SkType_String); + SkString* string = value.fOperand.fString; + const char* chars = string->c_str(); + int count = SkUTF8_CountUnichars(chars); + SkASSERT(count >= 1); + code = (SkKey) SkUTF8_NextUnichar(&chars); + fMax = code; + SkASSERT(count == 1 || index == SK_PROPERTY(keys)); + if (--count > 0) { + SkASSERT(*chars == '-'); + chars++; + fMax = (SkKey) SkUTF8_NextUnichar(&chars); + SkASSERT(fMax >= code); + } + return true; +} + diff --git a/libs/graphics/animator/SkDisplayEvent.h b/libs/graphics/animator/SkDisplayEvent.h new file mode 100644 index 000000000..4d5be0236 --- /dev/null +++ b/libs/graphics/animator/SkDisplayEvent.h @@ -0,0 +1,58 @@ +#ifndef SkDisplayEvent_DEFINED +#define SkDisplayEvent_DEFINED + +#include "SkDisplayable.h" +#include "SkMemberInfo.h" +#include "SkIntArray.h" +#include "SkKey.h" + +class SkEvent; + +class SkDisplayEvent : public SkDisplayable { + DECLARE_DISPLAY_MEMBER_INFO(Event); + enum Kind { + kNo_kind, + kKeyChar, + kKeyPress, + kKeyPressUp, //i assume the order here is intended to match with skanimatorscript.cpp + kMouseDown, + kMouseDrag, + kMouseMove, + kMouseUp, + kOnEnd, + kOnload, + kUser + }; + SkDisplayEvent(); + virtual ~SkDisplayEvent(); + virtual bool add(SkAnimateMaker& , SkDisplayable* child); + virtual bool contains(SkDisplayable*); + virtual SkDisplayable* contains(const SkString& ); +#ifdef SK_DEBUG + void dumpEvent(SkAnimateMaker* ); +#endif + bool enableEvent(SkAnimateMaker& ); + virtual bool getProperty(int index, SkScriptValue* ) const; + virtual void onEndElement(SkAnimateMaker& maker); + void populateInput(SkAnimateMaker& , const SkEvent& fEvent); + virtual bool setProperty(int index, SkScriptValue& ); +protected: + SkKey code; + SkBool disable; + Kind kind; + SkString target; + SkScalar x; + SkScalar y; + SkTDDisplayableArray fChildren; + mutable SkString fKeyString; + SkKey fLastCode; // last key to trigger this event + SkKey fMax; // if the code expresses a range + SkDisplayable* fTarget; // used by onEnd +private: + void deleteMembers(); + friend class SkEvents; + typedef SkDisplayable INHERITED; +}; + +#endif // SkDisplayEvent_DEFINED + diff --git a/libs/graphics/animator/SkDisplayEvents.cpp b/libs/graphics/animator/SkDisplayEvents.cpp new file mode 100644 index 000000000..405e1341b --- /dev/null +++ b/libs/graphics/animator/SkDisplayEvents.cpp @@ -0,0 +1,104 @@ +#include "SkDisplayEvents.h" +#include "SkAnimateMaker.h" +#include "SkAnimator.h" +#include "SkDisplayEvent.h" +#include "SkDisplayMovie.h" +#include "SkDrawable.h" +#ifdef SK_DEBUG +#include "SkDump.h" +#endif + +SkEventState::SkEventState() : fCode(0), fDisable(false), fDisplayable(0), fX(0), fY(0) { +} + +SkEvents::SkEvents() { +} + +SkEvents::~SkEvents() { +} + +bool SkEvents::doEvent(SkAnimateMaker& maker, SkDisplayEvent::Kind kind, SkEventState* state) { +/*#ifdef SK_DUMP_ENABLED + if (maker.fDumpEvents) { + SkDebugf("doEvent: "); + SkString str; + SkDump::GetEnumString(SkType_EventKind, kind, &str); + SkDebugf("kind=%s ", str.c_str()); + if (state && state->fDisplayable) + state->fDisplayable->SkDisplayable::dump(&maker); + else + SkDebugf("\n"); + } +#endif*/ + bool handled = false; + SkDisplayable** firstMovie = maker.fMovies.begin(); + SkDisplayable** endMovie = maker.fMovies.end(); + for (SkDisplayable** ptr = firstMovie; ptr < endMovie; ptr++) { + SkDisplayMovie* movie = (SkDisplayMovie*) *ptr; + if (kind != SkDisplayEvent::kOnload) + movie->doEvent(kind, state); + } + SkDisplayable* displayable = state ? state->fDisplayable : nil; + int keyCode = state ? state->fCode : 0; + int count = fEvents.count(); + for (int index = 0; index < count; index++) { + SkDisplayEvent* evt = fEvents[index]; + if (evt->disable) + continue; + if (evt->kind != kind) + continue; + if (evt->code != (SkKey) -1) { + if ((int) evt->code > keyCode || (int) (evt->fMax != (SkKey) -1 ? evt->fMax : evt->code) < keyCode) + continue; + evt->fLastCode = (SkKey) keyCode; + } + if (evt->fTarget != nil && evt->fTarget != displayable) + continue; + if (state == nil || state->fDisable == 0) { + if (kind >= SkDisplayEvent::kMouseDown && kind <= SkDisplayEvent::kMouseUp) { + evt->x = state->fX; + evt->y = state->fY; + } + if (evt->enableEvent(maker)) + fError = true; + } + handled = true; + } + return handled; +} + +#ifdef SK_DUMP_ENABLED +void SkEvents::dump(SkAnimateMaker& maker) { + int index; + SkTDDrawableArray& drawArray = maker.fDisplayList.fDrawList; + int count = drawArray.count(); + for (index = 0; index < count; index++) { + SkDrawable* drawable = drawArray[index]; + drawable->dumpEvents(); + } + count = fEvents.count(); + for (index = 0; index < count; index++) { + SkDisplayEvent* evt = fEvents[index]; + evt->dumpEvent(&maker); + } +} +#endif + +// currently this only removes onLoad events +void SkEvents::removeEvent(SkDisplayEvent::Kind kind, SkEventState* state) { + int keyCode = state ? state->fCode : 0; + SkDisplayable* displayable = state ? state->fDisplayable : nil; + for (SkDisplayEvent** evtPtr = fEvents.begin(); evtPtr < fEvents.end(); evtPtr++) { + SkDisplayEvent* evt = *evtPtr; + if (evt->kind != kind) + continue; + if (evt->code != (SkKey) -1) { + if ((int) evt->code > keyCode || (int) (evt->fMax != (SkKey) -1 ? evt->fMax : evt->code) < keyCode) + continue; + } + if (evt->fTarget != nil && evt->fTarget != displayable) + continue; + int index = fEvents.find(evt); + fEvents.remove(index); + } +} diff --git a/libs/graphics/animator/SkDisplayEvents.h b/libs/graphics/animator/SkDisplayEvents.h new file mode 100644 index 000000000..7000b672f --- /dev/null +++ b/libs/graphics/animator/SkDisplayEvents.h @@ -0,0 +1,34 @@ +#ifndef SkDisplayEvents_DEFINED +#define SkDisplayEvents_DEFINED + +#include "SkEvent.h" +#include "SkDisplayEvent.h" + +struct SkEventState { + SkEventState(); + int fCode; + SkBool fDisable; + SkDisplayable* fDisplayable; + SkScalar fX; + SkScalar fY; +}; + +class SkEvents { +public: + SkEvents(); + ~SkEvents(); + void addEvent(SkDisplayEvent* evt) { *fEvents.append() = evt; } + bool doEvent(SkAnimateMaker& , SkDisplayEvent::Kind , SkEventState* ); +#ifdef SK_DUMP_ENABLED + void dump(SkAnimateMaker& ); +#endif + void reset() { fEvents.reset(); } + void removeEvent(SkDisplayEvent::Kind kind, SkEventState* ); +private: + SkTDDisplayEventArray fEvents; + SkBool fError; + friend class SkDisplayXMLParser; +}; + +#endif // SkDisplayEvents_DEFINED + diff --git a/libs/graphics/animator/SkDisplayInclude.cpp b/libs/graphics/animator/SkDisplayInclude.cpp new file mode 100644 index 000000000..eee5f9667 --- /dev/null +++ b/libs/graphics/animator/SkDisplayInclude.cpp @@ -0,0 +1,50 @@ +#include "SkDisplayInclude.h" +#include "SkAnimateMaker.h" +#include "SkAnimator.h" + +#if 0 +#undef SK_MEMBER +#define SK_MEMBER(_member, _type) \ + { #_member, SK_OFFSETOF(BASE_CLASS::_A, _member), SkType_##_type, \ + sizeof(((BASE_CLASS::_A*) 0)->_member) / sizeof(SkScalar) } +#endif + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkInclude::fInfo[] = { + SK_MEMBER(src, String) +}; + +#endif + +DEFINE_GET_MEMBER(SkInclude); + +//SkInclude::SkInclude() { +// src.init(); +//} + +//SkInclude::~SkInclude() { +// src.unref(); +//} + +bool SkInclude::enable(SkAnimateMaker & ) { + return true; +} + +bool SkInclude::hasEnable() const { + return true; +} + +void SkInclude::onEndElement(SkAnimateMaker& maker) { + maker.fInInclude = true; + if (src.size() == 0 || maker.decodeURI(src.c_str()) == false) { + if (maker.getErrorCode() != SkXMLParserError::kNoError || maker.getNativeCode() != -1) { + maker.setInnerError(&maker, src); + maker.setErrorCode(SkDisplayXMLParserError::kInInclude); + } else { + maker.setErrorNoun(src); + maker.setErrorCode(SkDisplayXMLParserError::kIncludeNameUnknownOrMissing); + } + } + maker.fInInclude = false; +} diff --git a/libs/graphics/animator/SkDisplayInclude.h b/libs/graphics/animator/SkDisplayInclude.h new file mode 100644 index 000000000..b842c69d2 --- /dev/null +++ b/libs/graphics/animator/SkDisplayInclude.h @@ -0,0 +1,17 @@ +#ifndef SkDisplayInclude_DEFINED +#define SkDisplayInclude_DEFINED + +#include "SkDisplayable.h" +#include "SkMemberInfo.h" + +class SkInclude : public SkDisplayable { + DECLARE_MEMBER_INFO(Include); + virtual void onEndElement(SkAnimateMaker & ); + virtual bool enable(SkAnimateMaker & ); + virtual bool hasEnable() const; +protected: + SkString src; +}; + +#endif // SkDisplayInclude_DEFINED + diff --git a/libs/graphics/animator/SkDisplayInput.cpp b/libs/graphics/animator/SkDisplayInput.cpp new file mode 100644 index 000000000..7eec8d3bf --- /dev/null +++ b/libs/graphics/animator/SkDisplayInput.cpp @@ -0,0 +1,46 @@ +#include "SkDisplayInput.h" + +enum SkInput_Properties { + SK_PROPERTY(initialized) +}; + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkInput::fInfo[] = { + SK_MEMBER_ALIAS(float, fFloat, Float), + SK_MEMBER_PROPERTY(initialized, Boolean), + SK_MEMBER_ALIAS(int, fInt, Int), + SK_MEMBER(name, String), + SK_MEMBER(string, String) +}; + +#endif + +DEFINE_GET_MEMBER(SkInput); + +SkInput::SkInput() : fInt((int) SK_NaN32), fFloat(SK_ScalarNaN) {} + +SkDisplayable* SkInput::contains(const SkString& string) { + return string.equals(name) ? this : nil; +} + +bool SkInput::enable(SkAnimateMaker & ) { + return true; +} + +bool SkInput::getProperty(int index, SkScriptValue* value) const { + switch (index) { + case SK_PROPERTY(initialized): + value->fType = SkType_Boolean; + value->fOperand.fS32 = fInt != (int) SK_NaN32 || + SkScalarIsNaN(fFloat) == false || string.size() > 0; + break; + default: + return false; + } + return true; +} + +bool SkInput::hasEnable() const { + return true; +} diff --git a/libs/graphics/animator/SkDisplayInput.h b/libs/graphics/animator/SkDisplayInput.h new file mode 100644 index 000000000..b118b220f --- /dev/null +++ b/libs/graphics/animator/SkDisplayInput.h @@ -0,0 +1,25 @@ +#ifndef SkDisplayInput_DEFINED +#define SkDisplayInput_DEFINED + +#include "SkDisplayable.h" +#include "SkMemberInfo.h" + +class SkInput : public SkDisplayable { + DECLARE_MEMBER_INFO(Input); + SkInput(); + virtual SkDisplayable* contains(const SkString& ); + virtual bool getProperty(int index, SkScriptValue* value) const; + virtual bool enable(SkAnimateMaker & ); + virtual bool hasEnable() const; +protected: + SkString name; + int32_t fInt; + SkScalar fFloat; + SkString string; +private: + friend class SkDisplayEvent; + friend class SkPost; +}; + +#endif // SkDisplayInput_DEFINED + diff --git a/libs/graphics/animator/SkDisplayList.cpp b/libs/graphics/animator/SkDisplayList.cpp new file mode 100644 index 000000000..2e4d92841 --- /dev/null +++ b/libs/graphics/animator/SkDisplayList.cpp @@ -0,0 +1,151 @@ +#include "SkDisplayList.h" +#include "SkAnimateActive.h" +#include "SkAnimateBase.h" +#include "SkAnimateMaker.h" +#include "SkDisplayApply.h" +#include "SkDrawable.h" +#include "SkDrawGroup.h" +#include "SkDrawMatrix.h" +#include "SkInterpolator.h" +#include "SkTime.h" + +SkDisplayList::SkDisplayList() : fDrawBounds(true), fUnionBounds(false), fInTime(0) { +} + +SkDisplayList::~SkDisplayList() { +} + +void SkDisplayList::append(SkActive* active) { + *fActiveList.append() = active; +} + +bool SkDisplayList::draw(SkAnimateMaker& maker, SkMSec inTime) { + validate(); + fInTime = inTime; + bool result = false; + fInvalBounds.setEmpty(); + if (fDrawList.count()) { + for (SkActive** activePtr = fActiveList.begin(); activePtr < fActiveList.end(); activePtr++) { + SkActive* active = *activePtr; + active->reset(); + } + for (int index = 0; index < fDrawList.count(); index++) { + SkDrawable* draw = fDrawList[index]; + draw->initialize(); // allow matrices to reset themselves + SkASSERT(draw->isDrawable()); + validate(); + result |= draw->draw(maker); + } + } + validate(); + return result; +} + +int SkDisplayList::findGroup(SkDrawable* match, SkTDDrawableArray** list, + SkGroup** parent, SkGroup** found, SkTDDrawableArray**grandList) { + *parent = nil; + *list = &fDrawList; + *grandList = &fDrawList; + return SearchForMatch(match, list, parent, found, grandList); +} + +void SkDisplayList::hardReset() { + fDrawList.reset(); + fActiveList.reset(); +} + +bool SkDisplayList::onIRect(const SkRect16& r) { + fBounds = r; + return fDrawBounds; +} + +int SkDisplayList::SearchForMatch(SkDrawable* match, SkTDDrawableArray** list, + SkGroup** parent, SkGroup** found, SkTDDrawableArray**grandList) { + *found = nil; + for (int index = 0; index < (*list)->count(); index++) { + SkDrawable* draw = (**list)[index]; + if (draw == match) + return index; + if (draw->isApply()) { + SkApply* apply = (SkApply*) draw; + if (apply->scope == match) + return index; + if (apply->scope->isGroup() && SearchGroupForMatch(apply->scope, match, list, parent, found, grandList, index)) + return index; + if (apply->mode == SkApply::kMode_create) { + for (SkDrawable** ptr = apply->fScopes.begin(); ptr < apply->fScopes.end(); ptr++) { + SkDrawable* scope = *ptr; + if (scope == match) + return index; + //perhaps should call SearchGroupForMatch here as well (on scope) + } + } + } + if (draw->isGroup() && SearchGroupForMatch(draw, match, list, parent, found, grandList, index)) + return index; + + } + return -1; +} + +bool SkDisplayList::SearchGroupForMatch(SkDrawable* draw, SkDrawable* match, SkTDDrawableArray** list, + SkGroup** parent, SkGroup** found, SkTDDrawableArray** grandList, int &index) { + SkGroup* group = (SkGroup*) draw; + if (group->getOriginal() == match) + return true; + SkTDDrawableArray* saveList = *list; + int groupIndex = group->findGroup(match, list, parent, found, grandList); + if (groupIndex >= 0) { + *found = group; + index = groupIndex; + return true; + } + *list = saveList; + return false; + } + +void SkDisplayList::reset() { + for (int index = 0; index < fDrawList.count(); index++) { + SkDrawable* draw = fDrawList[index]; + if (draw->isApply() == false) + continue; + SkApply* apply = (SkApply*) draw; + apply->reset(); + } +} + +void SkDisplayList::remove(SkActive* active) { + int index = fActiveList.find(active); + SkASSERT(index >= 0); + fActiveList.remove(index); // !!! could use shuffle instead + SkASSERT(fActiveList.find(active) < 0); +} + +#ifdef SK_DUMP_ENABLED +int SkDisplayList::fDumpIndex; +int SkDisplayList::fIndent; + +void SkDisplayList::dump(SkAnimateMaker* maker) { + fIndent = 0; + dumpInner(maker); +} + +void SkDisplayList::dumpInner(SkAnimateMaker* maker) { + for (int index = 0; index < fDrawList.count(); index++) { + fDumpIndex = index; + fDrawList[fDumpIndex]->dump(maker); + } +} + +#endif + +#ifdef SK_DEBUG +void SkDisplayList::validate() { + for (int index = 0; index < fDrawList.count(); index++) { + SkDrawable* draw = fDrawList[index]; + draw->validate(); + } +} +#endif + + diff --git a/libs/graphics/animator/SkDisplayList.h b/libs/graphics/animator/SkDisplayList.h new file mode 100644 index 000000000..30c21a646 --- /dev/null +++ b/libs/graphics/animator/SkDisplayList.h @@ -0,0 +1,62 @@ +#ifndef SkDisplayList_DEFINED +#define SkDisplayList_DEFINED + +#include "SkOperand.h" +#include "SkIntArray.h" +#include "SkBounder.h" +#include "SkRect.h" + +class SkAnimateMaker; +class SkActive; +class SkApply; +class SkDrawable; +class SkGroup; + +class SkDisplayList : public SkBounder { +public: + SkDisplayList(); + virtual ~SkDisplayList(); + void append(SkActive* ); + void clear() { fDrawList.reset(); } + int count() { return fDrawList.count(); } + bool draw(SkAnimateMaker& , SkMSec time); +#ifdef SK_DUMP_ENABLED + void dump(SkAnimateMaker* maker); + void dumpInner(SkAnimateMaker* maker); + static int fIndent; + static int fDumpIndex; +#endif + int findGroup(SkDrawable* match, SkTDDrawableArray** list, + SkGroup** parent, SkGroup** found, SkTDDrawableArray** grandList); + SkDrawable* get(int index) { return fDrawList[index]; } + SkMSec getTime() { return fInTime; } + SkTDDrawableArray* getDrawList() { return &fDrawList; } + void hardReset(); + virtual bool onIRect(const SkRect16& r); + void reset(); + void remove(SkActive* ); +#ifdef SK_DEBUG + void validate(); +#else + void validate() {} +#endif + static int SearchForMatch(SkDrawable* match, SkTDDrawableArray** list, + SkGroup** parent, SkGroup** found, SkTDDrawableArray**grandList); + static bool SearchGroupForMatch(SkDrawable* draw, SkDrawable* match, + SkTDDrawableArray** list, SkGroup** parent, SkGroup** found, SkTDDrawableArray** grandList, + int &index); +public: + SkRect16 fBounds; + SkRect16 fInvalBounds; + bool fDrawBounds; + bool fHasUnion; + bool fUnionBounds; +private: + SkTDDrawableArray fDrawList; + SkTDActiveArray fActiveList; + SkMSec fInTime; + friend class SkEvents; +}; + +#endif // SkDisplayList_DEFINED + diff --git a/libs/graphics/animator/SkDisplayMath.cpp b/libs/graphics/animator/SkDisplayMath.cpp new file mode 100644 index 000000000..da757a35c --- /dev/null +++ b/libs/graphics/animator/SkDisplayMath.cpp @@ -0,0 +1,231 @@ +#include "SkDisplayMath.h" + +enum SkDisplayMath_Properties { + SK_PROPERTY(E), + SK_PROPERTY(LN10), + SK_PROPERTY(LN2), + SK_PROPERTY(LOG10E), + SK_PROPERTY(LOG2E), + SK_PROPERTY(PI), + SK_PROPERTY(SQRT1_2), + SK_PROPERTY(SQRT2) +}; + +const SkScalar SkDisplayMath::gConstants[] = { +#ifdef SK_SCALAR_IS_FLOAT + 2.718281828f, // E + 2.302585093f, // LN10 + 0.693147181f, // LN2 + 0.434294482f, // LOG10E + 1.442695041f, // LOG2E + 3.141592654f, // PI + 0.707106781f, // SQRT1_2 + 1.414213562f // SQRT2 +#else + 0x2B7E1, // E + 0x24D76, // LN10 + 0xB172, // LN2 + 0x6F2E, // LOG10E + 0x17154, // LOG2E + 0x3243F, // PI + 0xB505, // SQRT1_2 + 0x16A0A // SQRT2 +#endif +}; + +enum SkDisplayMath_Functions { + SK_FUNCTION(abs), + SK_FUNCTION(acos), + SK_FUNCTION(asin), + SK_FUNCTION(atan), + SK_FUNCTION(atan2), + SK_FUNCTION(ceil), + SK_FUNCTION(cos), + SK_FUNCTION(exp), + SK_FUNCTION(floor), + SK_FUNCTION(log), + SK_FUNCTION(max), + SK_FUNCTION(min), + SK_FUNCTION(pow), + SK_FUNCTION(random), + SK_FUNCTION(round), + SK_FUNCTION(sin), + SK_FUNCTION(sqrt), + SK_FUNCTION(tan) +}; + +const SkFunctionParamType SkDisplayMath::fFunctionParameters[] = { + (SkFunctionParamType) SkType_Float, // abs + (SkFunctionParamType) 0, + (SkFunctionParamType) SkType_Float, // acos + (SkFunctionParamType) 0, + (SkFunctionParamType) SkType_Float, // asin + (SkFunctionParamType) 0, + (SkFunctionParamType) SkType_Float, // atan + (SkFunctionParamType) 0, + (SkFunctionParamType) SkType_Float, // atan2 + (SkFunctionParamType) SkType_Float, + (SkFunctionParamType) 0, + (SkFunctionParamType) SkType_Float, // ceil + (SkFunctionParamType) 0, + (SkFunctionParamType) SkType_Float, // cos + (SkFunctionParamType) 0, + (SkFunctionParamType) SkType_Float, // exp + (SkFunctionParamType) 0, + (SkFunctionParamType) SkType_Float, // floor + (SkFunctionParamType) 0, + (SkFunctionParamType) SkType_Float, // log + (SkFunctionParamType) 0, + (SkFunctionParamType) SkType_Array, // max + (SkFunctionParamType) 0, + (SkFunctionParamType) SkType_Array, // min + (SkFunctionParamType) 0, + (SkFunctionParamType) SkType_Float, // pow + (SkFunctionParamType) SkType_Float, + (SkFunctionParamType) 0, + (SkFunctionParamType) SkType_Float, // random + (SkFunctionParamType) 0, + (SkFunctionParamType) SkType_Float, // round + (SkFunctionParamType) 0, + (SkFunctionParamType) SkType_Float, // sin + (SkFunctionParamType) 0, + (SkFunctionParamType) SkType_Float, // sqrt + (SkFunctionParamType) 0, + (SkFunctionParamType) SkType_Float, // tan + (SkFunctionParamType) 0 +}; + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDisplayMath::fInfo[] = { + SK_MEMBER_PROPERTY(E, Float), + SK_MEMBER_PROPERTY(LN10, Float), + SK_MEMBER_PROPERTY(LN2, Float), + SK_MEMBER_PROPERTY(LOG10E, Float), + SK_MEMBER_PROPERTY(LOG2E, Float), + SK_MEMBER_PROPERTY(PI, Float), + SK_MEMBER_PROPERTY(SQRT1_2, Float), + SK_MEMBER_PROPERTY(SQRT2, Float), + SK_MEMBER_FUNCTION(abs, Float), + SK_MEMBER_FUNCTION(acos, Float), + SK_MEMBER_FUNCTION(asin, Float), + SK_MEMBER_FUNCTION(atan, Float), + SK_MEMBER_FUNCTION(atan2, Float), + SK_MEMBER_FUNCTION(ceil, Float), + SK_MEMBER_FUNCTION(cos, Float), + SK_MEMBER_FUNCTION(exp, Float), + SK_MEMBER_FUNCTION(floor, Float), + SK_MEMBER_FUNCTION(log, Float), + SK_MEMBER_FUNCTION(max, Float), + SK_MEMBER_FUNCTION(min, Float), + SK_MEMBER_FUNCTION(pow, Float), + SK_MEMBER_FUNCTION(random, Float), + SK_MEMBER_FUNCTION(round, Float), + SK_MEMBER_FUNCTION(sin, Float), + SK_MEMBER_FUNCTION(sqrt, Float), + SK_MEMBER_FUNCTION(tan, Float) +}; + +#endif + +DEFINE_GET_MEMBER(SkDisplayMath); + +void SkDisplayMath::executeFunction(SkDisplayable* target, int index, + SkTDArray& parameters, SkDisplayTypes type, + SkScriptValue* scriptValue) { + if (scriptValue == nil) + return; + SkASSERT(target == this); + SkScriptValue* array = parameters.begin(); + SkScriptValue* end = parameters.end(); + SkScalar input = parameters[0].fOperand.fScalar; + SkScalar scalarResult; + switch (index) { + case SK_FUNCTION(abs): + scalarResult = SkScalarAbs(input); + break; + case SK_FUNCTION(acos): + scalarResult = SkScalarACos(input); + break; + case SK_FUNCTION(asin): + scalarResult = SkScalarASin(input); + break; + case SK_FUNCTION(atan): + scalarResult = SkScalarATan2(input, SK_Scalar1); + break; + case SK_FUNCTION(atan2): + scalarResult = SkScalarATan2(input, parameters[1].fOperand.fScalar); + break; + case SK_FUNCTION(ceil): + scalarResult = SkIntToScalar(SkScalarCeil(input)); + break; + case SK_FUNCTION(cos): + scalarResult = SkScalarCos(input); + break; + case SK_FUNCTION(exp): + scalarResult = SkScalarExp(input); + break; + case SK_FUNCTION(floor): + scalarResult = SkIntToScalar(SkScalarFloor(input)); + break; + case SK_FUNCTION(log): + scalarResult = SkScalarLog(input); + break; + case SK_FUNCTION(max): + scalarResult = -SK_ScalarMax; + while (array < end) { + scalarResult = SkMaxScalar(scalarResult, array->fOperand.fScalar); + array++; + } + break; + case SK_FUNCTION(min): + scalarResult = SK_ScalarMax; + while (array < end) { + scalarResult = SkMinScalar(scalarResult, array->fOperand.fScalar); + array++; + } + break; + case SK_FUNCTION(pow): + // not the greatest -- but use x^y = e^(y * ln(x)) + scalarResult = SkScalarLog(input); + scalarResult = SkScalarMul(parameters[1].fOperand.fScalar, scalarResult); + scalarResult = SkScalarExp(scalarResult); + break; + case SK_FUNCTION(random): + scalarResult = fRandom.nextUScalar1(); + break; + case SK_FUNCTION(round): + scalarResult = SkIntToScalar(SkScalarRound(input)); + break; + case SK_FUNCTION(sin): + scalarResult = SkScalarSin(input); + break; + case SK_FUNCTION(sqrt): { + SkASSERT(parameters.count() == 1); + SkASSERT(type == SkType_Float); + scalarResult = SkScalarSqrt(input); + } break; + case SK_FUNCTION(tan): + scalarResult = SkScalarTan(input); + break; + default: + SkASSERT(0); + scalarResult = SK_ScalarNaN; + } + scriptValue->fOperand.fScalar = scalarResult; + scriptValue->fType = SkType_Float; +} + +const SkFunctionParamType* SkDisplayMath::getFunctionsParameters() { + return fFunctionParameters; +} + +bool SkDisplayMath::getProperty(int index, SkScriptValue* value) const { + if ((unsigned)index < SK_ARRAY_COUNT(gConstants)) { + value->fOperand.fScalar = gConstants[index]; + value->fType = SkType_Float; + return true; + } + SkASSERT(0); + return false; +} diff --git a/libs/graphics/animator/SkDisplayMath.h b/libs/graphics/animator/SkDisplayMath.h new file mode 100644 index 000000000..ced6e42d7 --- /dev/null +++ b/libs/graphics/animator/SkDisplayMath.h @@ -0,0 +1,23 @@ +#ifndef SkDisplayMath_DEFINED +#define SkDisplayMath_DEFINED + +#include "SkDisplayable.h" +#include "SkMemberInfo.h" +#include "SkRandom.h" + +class SkDisplayMath : public SkDisplayable { + DECLARE_DISPLAY_MEMBER_INFO(Math); + virtual void executeFunction(SkDisplayable* , int index, + SkTDArray& parameters, SkDisplayTypes type, + SkScriptValue* ); + virtual const SkFunctionParamType* getFunctionsParameters(); + virtual bool getProperty(int index, SkScriptValue* value) const; +private: + mutable SkRandom fRandom; + static const SkScalar gConstants[]; + static const SkFunctionParamType fFunctionParameters[]; + +}; + +#endif // SkDisplayMath_DEFINED + diff --git a/libs/graphics/animator/SkDisplayMovie.cpp b/libs/graphics/animator/SkDisplayMovie.cpp new file mode 100644 index 000000000..3727efec4 --- /dev/null +++ b/libs/graphics/animator/SkDisplayMovie.cpp @@ -0,0 +1,121 @@ +#include "SkDisplayMovie.h" +#include "SkAnimateMaker.h" +#include "SkCanvas.h" +#include "SkPaint.h" + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDisplayMovie::fInfo[] = { + SK_MEMBER(src, String) +}; + +#endif + +DEFINE_GET_MEMBER(SkDisplayMovie); + +SkDisplayMovie::SkDisplayMovie() : fDecodedSuccessfully(false), fLoaded(false), fMovieBuilt(false) { + fMovie.fMaker->fInMovie = true; +} + +SkDisplayMovie::~SkDisplayMovie() { +} + +void SkDisplayMovie::buildMovie() { + if (fMovieBuilt) + return; + SkAnimateMaker* movieMaker = fMovie.fMaker; + SkAnimateMaker* parentMaker = movieMaker->fParentMaker; + if (src.size() == 0 || parentMaker == nil) + return; + movieMaker->fPrefix.set(parentMaker->fPrefix); + fDecodedSuccessfully = fMovie.fMaker->decodeURI(src.c_str()); + if (fDecodedSuccessfully == false) { + + if (movieMaker->getErrorCode() != SkXMLParserError::kNoError || movieMaker->getNativeCode() != -1) { + movieMaker->setInnerError(parentMaker, src); + parentMaker->setErrorCode(SkDisplayXMLParserError::kInMovie); + } else { + parentMaker->setErrorNoun(src); + parentMaker->setErrorCode(SkDisplayXMLParserError::kMovieNameUnknownOrMissing); + } + } + fMovieBuilt = true; +} + +SkDisplayable* SkDisplayMovie::deepCopy(SkAnimateMaker* maker) { + SkDisplayMovie* copy = (SkDisplayMovie*) INHERITED::deepCopy(maker); + copy->fMovie.fMaker->fParentMaker = fMovie.fMaker->fParentMaker; + copy->fMovie.fMaker->fHostEventSinkID = fMovie.fMaker->fHostEventSinkID; + copy->fMovieBuilt = false; + *fMovie.fMaker->fParentMaker->fMovies.append() = copy; + return copy; +} + +void SkDisplayMovie::dirty() { + buildMovie(); +} + +bool SkDisplayMovie::doEvent(SkDisplayEvent::Kind kind, SkEventState* state) { + if (fLoaded == false) + return false; + fMovie.fMaker->fEnableTime = fMovie.fMaker->fParentMaker->fEnableTime; + return fMovie.fMaker->fEvents.doEvent(*fMovie.fMaker, kind, state); +} + +bool SkDisplayMovie::draw(SkAnimateMaker& maker) { + if (fDecodedSuccessfully == false) + return false; + if (fLoaded == false) + enable(maker); + maker.fCanvas->save(); + SkPaint local = SkPaint(*maker.fPaint); + bool result = fMovie.draw(maker.fCanvas, &local, + maker.fDisplayList.getTime()) != SkAnimator::kNotDifferent; + maker.fDisplayList.fInvalBounds.join(fMovie.fMaker->fDisplayList.fInvalBounds); + maker.fCanvas->restore(); + return result; +} + +#ifdef SK_DUMP_ENABLED +void SkDisplayMovie::dump(SkAnimateMaker* maker) { + dumpBase(maker); + SkDebugf("src=\"%s\"/>\n", src.c_str()); + SkAnimateMaker* movieMaker = fMovie.fMaker; + SkDisplayList::fIndent += 4; + movieMaker->fDisplayList.dumpInner(movieMaker); + SkDisplayList::fIndent -= 4; + dumpEnd(maker); +} + +void SkDisplayMovie::dumpEvents() { + fMovie.fMaker->fEvents.dump(*fMovie.fMaker); +} +#endif + +bool SkDisplayMovie::enable(SkAnimateMaker& maker) { + if (fDecodedSuccessfully == false) + return false; + SkAnimateMaker* movieMaker = fMovie.fMaker; + movieMaker->fEvents.doEvent(*movieMaker, SkDisplayEvent::kOnload, nil); + movieMaker->fEvents.removeEvent(SkDisplayEvent::kOnload, nil); + fLoaded = true; + movieMaker->fLoaded = true; + return false; +} + +bool SkDisplayMovie::hasEnable() const { + return true; +} + +void SkDisplayMovie::onEndElement(SkAnimateMaker& maker) { +#if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING + fMovie.fMaker->fDebugTimeBase = maker.fDebugTimeBase; +#endif + fMovie.fMaker->fPrefix.set(maker.fPrefix); + fMovie.fMaker->fHostEventSinkID = maker.fHostEventSinkID; + fMovie.fMaker->fParentMaker = &maker; + buildMovie(); + *maker.fMovies.append() = this; +} + + diff --git a/libs/graphics/animator/SkDisplayMovie.h b/libs/graphics/animator/SkDisplayMovie.h new file mode 100644 index 000000000..f81a74007 --- /dev/null +++ b/libs/graphics/animator/SkDisplayMovie.h @@ -0,0 +1,43 @@ +#ifndef SkDisplayMovie_DEFINED +#define SkDisplayMovie_DEFINED + +#include "SkAnimator.h" +#include "SkDrawable.h" +#include "SkMemberInfo.h" + +struct SkEventState; + +class SkDisplayMovie : public SkDrawable { + DECLARE_DISPLAY_MEMBER_INFO(Movie); + SkDisplayMovie(); + virtual ~SkDisplayMovie(); + void buildMovie(); + virtual SkDisplayable* deepCopy(SkAnimateMaker* ); + virtual void dirty(); + bool doEvent(const SkEvent& evt) { + return fLoaded && fMovie.doEvent(evt); + } + virtual bool doEvent(SkDisplayEvent::Kind , SkEventState* state ); + virtual bool draw(SkAnimateMaker& ); +#ifdef SK_DUMP_ENABLED + virtual void dump(SkAnimateMaker* ); + virtual void dumpEvents(); +#endif + virtual bool enable(SkAnimateMaker& ); + const SkAnimator* getAnimator() const { return &fMovie; } + virtual bool hasEnable() const; + virtual void onEndElement(SkAnimateMaker& ); +protected: + SkString src; + SkAnimator fMovie; + SkBool8 fDecodedSuccessfully; + SkBool8 fLoaded; + SkBool8 fMovieBuilt; + friend class SkAnimateMaker; + friend class SkPost; +private: + typedef SkDrawable INHERITED; +}; + +#endif // SkDisplayMovie_DEFINED + diff --git a/libs/graphics/animator/SkDisplayNumber.cpp b/libs/graphics/animator/SkDisplayNumber.cpp new file mode 100644 index 000000000..03de65cfb --- /dev/null +++ b/libs/graphics/animator/SkDisplayNumber.cpp @@ -0,0 +1,50 @@ +#include "SkDisplayNumber.h" + +enum SkDisplayNumber_Properties { + SK_PROPERTY(MAX_VALUE), + SK_PROPERTY(MIN_VALUE), + SK_PROPERTY(NEGATIVE_INFINITY), + SK_PROPERTY(NaN), + SK_PROPERTY(POSITIVE_INFINITY) +}; + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDisplayNumber::fInfo[] = { + SK_MEMBER_PROPERTY(MAX_VALUE, Float), + SK_MEMBER_PROPERTY(MIN_VALUE, Float), + SK_MEMBER_PROPERTY(NEGATIVE_INFINITY, Float), + SK_MEMBER_PROPERTY(NaN, Float), + SK_MEMBER_PROPERTY(POSITIVE_INFINITY, Float) +}; + +#endif + +DEFINE_GET_MEMBER(SkDisplayNumber); + +bool SkDisplayNumber::getProperty(int index, SkScriptValue* value) const { + SkScalar constant; + switch (index) { + case SK_PROPERTY(MAX_VALUE): + constant = SK_ScalarMax; + break; + case SK_PROPERTY(MIN_VALUE): + constant = SK_ScalarMin; + break; + case SK_PROPERTY(NEGATIVE_INFINITY): + constant = -SK_ScalarInfinity; + break; + case SK_PROPERTY(NaN): + constant = SK_ScalarNaN; + break; + case SK_PROPERTY(POSITIVE_INFINITY): + constant = SK_ScalarInfinity; + break; + default: + SkASSERT(0); + return false; + } + value->fOperand.fScalar = constant; + value->fType = SkType_Float; + return true; +} diff --git a/libs/graphics/animator/SkDisplayNumber.h b/libs/graphics/animator/SkDisplayNumber.h new file mode 100644 index 000000000..7b2ea5855 --- /dev/null +++ b/libs/graphics/animator/SkDisplayNumber.h @@ -0,0 +1,13 @@ +#ifndef SkDisplayNumber_DEFINED +#define SkDisplayNumber_DEFINED + +#include "SkDisplayable.h" +#include "SkMemberInfo.h" + +class SkDisplayNumber : public SkDisplayable { + DECLARE_DISPLAY_MEMBER_INFO(Number); + virtual bool getProperty(int index, SkScriptValue* value) const; +private: +}; + +#endif // SkDisplayNumber_DEFINED diff --git a/libs/graphics/animator/SkDisplayPost.cpp b/libs/graphics/animator/SkDisplayPost.cpp new file mode 100644 index 000000000..fad3aee52 --- /dev/null +++ b/libs/graphics/animator/SkDisplayPost.cpp @@ -0,0 +1,298 @@ +#include "SkDisplayPost.h" +#include "SkAnimateMaker.h" +#include "SkAnimator.h" +#include "SkDisplayMovie.h" +#include "SkPostParts.h" +#include "SkScript.h" +#ifdef SK_DEBUG +#include "SkDump.h" +#include "SkTime.h" +#endif + +enum SkPost_Properties { + SK_PROPERTY(target), + SK_PROPERTY(type) +}; + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkPost::fInfo[] = { + SK_MEMBER(delay, MSec), +// SK_MEMBER(initialized, Boolean), + SK_MEMBER(mode, EventMode), + SK_MEMBER(sink, String), + SK_MEMBER_PROPERTY(target, String), + SK_MEMBER_PROPERTY(type, String) +}; + +#endif + +DEFINE_GET_MEMBER(SkPost); + +SkPost::SkPost() : delay(0), /*initialized(SkBool(-1)), */ mode(kImmediate), fMaker(nil), + fSinkID(0), fTargetMaker(nil), fChildHasID(false), fDirty(false) { +} + +SkPost::~SkPost() { + for (SkData** part = fParts.begin(); part < fParts.end(); part++) + delete *part; +} + +bool SkPost::add(SkAnimateMaker& , SkDisplayable* child) { + SkASSERT(child && child->isData()); + SkData* part = (SkData*) child; + *fParts.append() = part; + return true; +} + +bool SkPost::childrenNeedDisposing() const { + return false; +} + +void SkPost::dirty() { + fDirty = true; +} + +#ifdef SK_DUMP_ENABLED +void SkPost::dump(SkAnimateMaker* maker) { + dumpBase(maker); + SkString* eventType = new SkString(); + fEvent.getType(eventType); + if (eventType->equals("user")) { + const char* target = fEvent.findString("id"); + SkDebugf("target=\"%s\" ", target); + } + else + SkDebugf("type=\"%s\" ", eventType->c_str()); + delete eventType; + + if (delay > 0) { +#ifdef SK_CAN_USE_FLOAT + SkDebugf("delay=\"%g\" ", SkScalarToFloat(SkScalarDiv(delay, 1000))); +#else + SkDebugf("delay=\"%x\" ", SkScalarDiv(delay, 1000)); +#endif + } +// if (initialized == false) +// SkDebugf("(uninitialized) "); + SkString string; + SkDump::GetEnumString(SkType_EventMode, mode, &string); + if (!string.equals("immediate")) + SkDebugf("mode=\"%s\" ", string.c_str()); + // !!! could enhance this to search through make hierarchy to show name of sink + if (sink.size() > 0) { + SkDebugf("sink=\"%s\" sinkID=\"%d\" ", sink.c_str(), fSinkID); + } else if (fSinkID != maker->getAnimator()->getSinkID() && fSinkID != 0) { + SkDebugf("sinkID=\"%d\" ", fSinkID); + } + const SkMetaData& meta = fEvent.getMetaData(); + SkMetaData::Iter iter(meta); + SkMetaData::Type type; + int number; + const char* name; + bool closedYet = false; + SkDisplayList::fIndent += 4; + //this seems to work, but kinda hacky + //for some reason the last part is id, which i don't want + //and the parts seem to be in the reverse order from the one in which we find the + //data itself + //SkData** ptr = fParts.end(); + //SkData* data; + //const char* ID; + while ((name = iter.next(&type, &number)) != nil) { + //ptr--; + if (strcmp(name, "id") == 0) + continue; + if (closedYet == false) { + SkDebugf(">\n"); + closedYet = true; + } + //data = *ptr; + //if (data->id) + // ID = data->id; + //else + // ID = ""; + SkDebugf("%*s\n"); + //ptr++; +/* perhaps this should only be done in the case of a pointer? + SkDisplayable* displayable; + if (maker->find(name, &displayable)) + displayable->dump(maker); + else + SkDebugf("\n");*/ + } + SkDisplayList::fIndent -= 4; + if (closedYet) + dumpEnd(maker); + else + SkDebugf("/>\n"); + +} +#endif + +bool SkPost::enable(SkAnimateMaker& maker ) { + if (maker.hasError()) + return true; + if (fDirty) { + if (sink.size() > 0) + findSinkID(); + if (fChildHasID) { + SkString preserveID(fEvent.findString("id")); + fEvent.getMetaData().reset(); + if (preserveID.size() > 0) + fEvent.setString("id", preserveID); + for (SkData** part = fParts.begin(); part < fParts.end(); part++) { + if ((*part)->add()) + maker.setErrorCode(SkDisplayXMLParserError::kErrorAddingDataToPost); + } + } + fDirty = false; + } +#ifdef SK_DUMP_ENABLED + if (maker.fDumpPosts) { + SkDebugf("post enable: "); + dump(&maker); + } +#if defined SK_DEBUG_ANIMATION_TIMING + SkString debugOut; + SkMSec time = maker.getAppTime(); + debugOut.appendS32(time - maker.fDebugTimeBase); + debugOut.append(" post id="); + debugOut.append(_id); + debugOut.append(" enable="); + debugOut.appendS32(maker.fEnableTime - maker.fDebugTimeBase); + debugOut.append(" delay="); + debugOut.appendS32(delay); +#endif +#endif +// SkMSec adjustedDelay = maker.adjustDelay(maker.fEnableTime, delay); + SkMSec futureTime = maker.fEnableTime + delay; + fEvent.setFast32(futureTime); +#if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING + debugOut.append(" future="); + debugOut.appendS32(futureTime - maker.fDebugTimeBase); + SkDebugf("%s\n", debugOut.c_str()); +#endif + SkEventSinkID targetID = fSinkID; + bool isAnimatorEvent = true; + SkAnimator* anim = maker.getAnimator(); + if (targetID == 0) { + isAnimatorEvent = fEvent.findString("id") != nil; + if (isAnimatorEvent) + targetID = anim->getSinkID(); + else if (maker.fHostEventSinkID) + targetID = maker.fHostEventSinkID; + else + return true; + } else + anim = fTargetMaker->getAnimator(); + if (delay == 0) { + if (isAnimatorEvent && mode == kImmediate) + fTargetMaker->doEvent(fEvent); + else + anim->onEventPost(new SkEvent(fEvent), targetID); + } else + anim->onEventPostTime(new SkEvent(fEvent), targetID, futureTime); + return true; +} + +void SkPost::findSinkID() { + // get the next delimiter '.' if any + fTargetMaker = fMaker; + const char* ch = sink.c_str(); + do { + const char* end = strchr(ch, '.'); + size_t len = end ? end - ch : strlen(ch); + SkDisplayable* displayable = nil; + if (SK_LITERAL_STR_EQUAL("parent", ch, len)) { + if (fTargetMaker->fParentMaker) + fTargetMaker = fTargetMaker->fParentMaker; + else { + fTargetMaker->setErrorCode(SkDisplayXMLParserError::kNoParentAvailable); + return; + } + } else { + fTargetMaker->find(ch, len, &displayable); + if (displayable == nil || displayable->getType() != SkType_Movie) { + fTargetMaker->setErrorCode(SkDisplayXMLParserError::kExpectedMovie); + return; + } + SkDisplayMovie* movie = (SkDisplayMovie*) displayable; + fTargetMaker = movie->fMovie.fMaker; + } + if (end == nil) + break; + ch = ++end; + } while (true); + SkAnimator* anim = fTargetMaker->getAnimator(); + fSinkID = anim->getSinkID(); +} + +bool SkPost::hasEnable() const { + return true; +} + +void SkPost::onEndElement(SkAnimateMaker& maker) { + fTargetMaker = fMaker = &maker; + if (fChildHasID == false) { + for (SkData** part = fParts.begin(); part < fParts.end(); part++) + delete *part; + fParts.reset(); + } +} + +void SkPost::setChildHasID() { + fChildHasID = true; +} + +bool SkPost::setProperty(int index, SkScriptValue& value) { + SkASSERT(value.fType == SkType_String); + SkString* string = value.fOperand.fString; + switch(index) { + case SK_PROPERTY(target): { + fEvent.setType("user"); + fEvent.setString("id", *string); + mode = kImmediate; + } break; + case SK_PROPERTY(type): + fEvent.setType(*string); + break; + default: + SkASSERT(0); + return false; + } + return true; +} + diff --git a/libs/graphics/animator/SkDisplayPost.h b/libs/graphics/animator/SkDisplayPost.h new file mode 100644 index 000000000..cfc2fabb6 --- /dev/null +++ b/libs/graphics/animator/SkDisplayPost.h @@ -0,0 +1,50 @@ +#ifndef SkDisplayPost_DEFINED +#define SkDisplayPost_DEFINED + +#include "SkDisplayable.h" +#include "SkEvent.h" +#include "SkEventSink.h" +#include "SkMemberInfo.h" +#include "SkIntArray.h" + +class SkData; +class SkAnimateMaker; + +class SkPost : public SkDisplayable { + DECLARE_MEMBER_INFO(Post); + enum Mode { + kDeferred, + kImmediate + }; + SkPost(); + virtual ~SkPost(); + virtual bool add(SkAnimateMaker& , SkDisplayable* child); + virtual bool childrenNeedDisposing() const; + virtual void dirty(); +#ifdef SK_DUMP_ENABLED + virtual void dump(SkAnimateMaker* ); +#endif + virtual bool enable(SkAnimateMaker& ); + virtual bool hasEnable() const; + virtual void onEndElement(SkAnimateMaker& ); + virtual void setChildHasID(); + virtual bool setProperty(int index, SkScriptValue& ); +protected: + SkMSec delay; + SkString sink; +// SkBool initialized; + Mode mode; + SkEvent fEvent; + SkAnimateMaker* fMaker; + SkTDDataArray fParts; + SkEventSinkID fSinkID; + SkAnimateMaker* fTargetMaker; + SkBool8 fChildHasID; + SkBool8 fDirty; +private: + void findSinkID(); + friend class SkData; + typedef SkDisplayable INHERITED; +}; + +#endif //SkDisplayPost_DEFINED diff --git a/libs/graphics/animator/SkDisplayRandom.cpp b/libs/graphics/animator/SkDisplayRandom.cpp new file mode 100644 index 000000000..53775d30d --- /dev/null +++ b/libs/graphics/animator/SkDisplayRandom.cpp @@ -0,0 +1,63 @@ +#include "SkDisplayRandom.h" +#include "SkInterpolator.h" + +enum SkDisplayRandom_Properties { + SK_PROPERTY(random), + SK_PROPERTY(seed) +}; + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDisplayRandom::fInfo[] = { + SK_MEMBER(blend, Float), + SK_MEMBER(max, Float), + SK_MEMBER(min, Float), + SK_MEMBER_DYNAMIC_PROPERTY(random, Float), + SK_MEMBER_PROPERTY(seed, Int) +}; + +#endif + +DEFINE_GET_MEMBER(SkDisplayRandom); + +SkDisplayRandom::SkDisplayRandom() : blend(0), min(0), max(SK_Scalar1) { +} + +#ifdef SK_DUMP_ENABLED +void SkDisplayRandom::dump(SkAnimateMaker* maker) { + dumpBase(maker); +#ifdef SK_CAN_USE_FLOAT + SkDebugf("min=\"%g\" ", SkScalarToFloat(min)); + SkDebugf("max=\"%g\" ", SkScalarToFloat(max)); + SkDebugf("blend=\"%g\" ", SkScalarToFloat(blend)); +#else + SkDebugf("min=\"%x\" ", min); + SkDebugf("max=\"%x\" ", max); + SkDebugf("blend=\"%x\" ", blend); +#endif + SkDebugf("/>\n"); +} +#endif + +bool SkDisplayRandom::getProperty(int index, SkScriptValue* value) const { + switch(index) { + case SK_PROPERTY(random): { + SkScalar random = fRandom.nextUScalar1(); + SkScalar relativeT = SkInterpolatorBase::Blend(random, blend); + value->fOperand.fScalar = min + SkScalarMul(max - min, relativeT); + value->fType = SkType_Float; + return true; + } + default: + SkASSERT(0); + } + return false; +} + +bool SkDisplayRandom::setProperty(int index, SkScriptValue& value) { + SkASSERT(index == SK_PROPERTY(seed)); + SkASSERT(value.fType == SkType_Int); + fRandom.setSeed(value.fOperand.fS32); + return true; +} + diff --git a/libs/graphics/animator/SkDisplayRandom.h b/libs/graphics/animator/SkDisplayRandom.h new file mode 100644 index 000000000..bcfc945cc --- /dev/null +++ b/libs/graphics/animator/SkDisplayRandom.h @@ -0,0 +1,32 @@ +#ifndef SkDisplayRandom_DEFINED +#define SkDisplayRandom_DEFINED + +#include "SkDisplayable.h" +#include "SkMemberInfo.h" +#include "SkRandom.h" + +#ifdef min +#undef min +#endif + +#ifdef max +#undef max +#endif + +class SkDisplayRandom : public SkDisplayable { + DECLARE_DISPLAY_MEMBER_INFO(Random); + SkDisplayRandom(); +#ifdef SK_DUMP_ENABLED + virtual void dump(SkAnimateMaker* ); +#endif + virtual bool getProperty(int index, SkScriptValue* value) const; + virtual bool setProperty(int index, SkScriptValue& ); +private: + SkScalar blend; + SkScalar min; + SkScalar max; + mutable SkRandom fRandom; +}; + +#endif // SkDisplayRandom_DEFINED + diff --git a/libs/graphics/animator/SkDisplayScreenplay.cpp b/libs/graphics/animator/SkDisplayScreenplay.cpp new file mode 100644 index 000000000..44c7a8954 --- /dev/null +++ b/libs/graphics/animator/SkDisplayScreenplay.cpp @@ -0,0 +1,13 @@ +#include "SkDisplayScreenplay.h" + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDisplayScreenplay::fInfo[] = { + SK_MEMBER(time, MSec) +}; + +#endif + +DEFINE_GET_MEMBER(SkDisplayScreenplay); + + diff --git a/libs/graphics/animator/SkDisplayScreenplay.h b/libs/graphics/animator/SkDisplayScreenplay.h new file mode 100644 index 000000000..6d11f7ace --- /dev/null +++ b/libs/graphics/animator/SkDisplayScreenplay.h @@ -0,0 +1,12 @@ +#ifndef SkDisplayScreenplay_DEFINED +#define SkDisplayScreenplay_DEFINED + +#include "SkDisplayable.h" +#include "SkMemberInfo.h" + +class SkDisplayScreenplay : public SkDisplayable { + DECLARE_DISPLAY_MEMBER_INFO(Screenplay); + SkMSec time; +}; + +#endif // SkDisplayScreenplay_DEFINED diff --git a/libs/graphics/animator/SkDisplayType.cpp b/libs/graphics/animator/SkDisplayType.cpp new file mode 100644 index 000000000..dfb536ff4 --- /dev/null +++ b/libs/graphics/animator/SkDisplayType.cpp @@ -0,0 +1,757 @@ +#include "SkDisplayType.h" +#include "SkAnimateMaker.h" +#include "SkAnimateSet.h" +#include "SkDisplayAdd.h" +#include "SkDisplayApply.h" +#include "SkDisplayBounds.h" +#include "SkDisplayEvent.h" +#include "SkDisplayInclude.h" +#ifdef SK_DEBUG +#include "SkDisplayList.h" +#endif +#include "SkDisplayMath.h" +#include "SkDisplayMovie.h" +#include "SkDisplayNumber.h" +#include "SkDisplayPost.h" +#include "SkDisplayRandom.h" +#include "SkDisplayTypes.h" +#include "SkDraw3D.h" +#include "SkDrawBitmap.h" +#include "SkDrawClip.h" +#include "SkDrawDash.h" +#include "SkDrawDiscrete.h" +#include "SkDrawEmboss.h" +#include "SkDrawFull.h" +#include "SkDrawGradient.h" +#include "SkDrawLine.h" +#include "SkDrawMatrix.h" +#include "SkDrawOval.h" +#include "SkDrawPaint.h" +#include "SkDrawPath.h" +#include "SkDrawPoint.h" +#include "SkDrawSaveLayer.h" +#include "SkDrawText.h" +#include "SkDrawTextBox.h" +#include "SkDrawTo.h" +#include "SkDrawTransparentShader.h" +#include "SkDump.h" +#include "SkExtras.h" +#include "SkHitClear.h" +#include "SkHitTest.h" +#include "SkMatrixParts.h" +#include "SkPathParts.h" +#include "SkPostParts.h" +#include "SkSnapshot.h" +#include "SkTextOnPath.h" +#include "SkTextToPath.h" +#include "SkTSearch.h" + +#define CASE_NEW(_class) \ + case SkType_##_class: result = new Sk##_class(); break +#define CASE_DRAW_NEW(_class) \ + case SkType_##_class: result = new SkDraw##_class(); break +#define CASE_DISPLAY_NEW(_class) \ + case SkType_##_class: result = new SkDisplay##_class(); break +#ifdef SK_DEBUG + #define CASE_DEBUG_RETURN_NIL(_class) \ + case SkType_##_class: return NULL +#else + #define CASE_DEBUG_RETURN_NIL(_class) +#endif + + +SkDisplayTypes SkDisplayType::gNewTypes = kNumberOfTypes; + +SkDisplayable* SkDisplayType::CreateInstance(SkAnimateMaker* maker, SkDisplayTypes type) { + SkDisplayable* result = NULL; + switch (type) { + // unknown + CASE_DISPLAY_NEW(Math); + CASE_DISPLAY_NEW(Number); + CASE_NEW(Add); + CASE_NEW(AddCircle); + // addgeom + CASE_DEBUG_RETURN_NIL(AddMode); + CASE_NEW(AddOval); + CASE_NEW(AddPath); + CASE_NEW(AddRect); + CASE_NEW(AddRoundRect); + CASE_DEBUG_RETURN_NIL(Align); + CASE_NEW(Animate); + // animatebase + CASE_NEW(Apply); + CASE_DEBUG_RETURN_NIL(ApplyMode); + CASE_DEBUG_RETURN_NIL(ApplyTransition); + CASE_DISPLAY_NEW(Array); + // argb + // base64 + // basebitmap + // baseclassinfo + CASE_DRAW_NEW(Bitmap); + // bitmapencoding + // bitmapformat + CASE_DRAW_NEW(BitmapShader); + CASE_DRAW_NEW(Blur); + CASE_DISPLAY_NEW(Boolean); + // boundable + CASE_DISPLAY_NEW(Bounds); + CASE_DEBUG_RETURN_NIL(Cap); + CASE_NEW(Clear); + CASE_DRAW_NEW(Clip); + CASE_NEW(Close); + CASE_DRAW_NEW(Color); + CASE_NEW(CubicTo); + CASE_NEW(Dash); + CASE_NEW(Data); + CASE_NEW(Discrete); + // displayable + // drawable + CASE_NEW(DrawTo); + CASE_NEW(Dump); + // dynamicstring + CASE_DRAW_NEW(Emboss); + CASE_DISPLAY_NEW(Event); + CASE_DEBUG_RETURN_NIL(EventCode); + CASE_DEBUG_RETURN_NIL(EventKind); + CASE_DEBUG_RETURN_NIL(EventMode); + // filltype + // filtertype + CASE_DISPLAY_NEW(Float); + CASE_NEW(FromPath); + CASE_DEBUG_RETURN_NIL(FromPathMode); + CASE_NEW(Full); + // gradient + CASE_NEW(Group); + CASE_NEW(HitClear); + CASE_NEW(HitTest); + CASE_NEW(Image); + CASE_NEW(Include); + CASE_NEW(Input); + CASE_DISPLAY_NEW(Int); + CASE_DEBUG_RETURN_NIL(Join); + CASE_NEW(Line); + CASE_NEW(LineTo); + CASE_NEW(LinearGradient); + CASE_DRAW_NEW(MaskFilter); + CASE_DEBUG_RETURN_NIL(MaskFilterBlurStyle); + // maskfilterlight + CASE_DRAW_NEW(Matrix); + // memberfunction + // memberproperty + CASE_NEW(Move); + CASE_NEW(MoveTo); + CASE_DISPLAY_NEW(Movie); + // msec + CASE_NEW(Oval); + CASE_DRAW_NEW(Paint); + CASE_DRAW_NEW(Path); + // pathdirection + CASE_DRAW_NEW(PathEffect); + // point + CASE_NEW(DrawPoint); + CASE_NEW(PolyToPoly); + CASE_NEW(Polygon); + CASE_NEW(Polyline); + CASE_NEW(Post); + CASE_NEW(QuadTo); + CASE_NEW(RCubicTo); + CASE_NEW(RLineTo); + CASE_NEW(RMoveTo); + CASE_NEW(RQuadTo); + CASE_NEW(RadialGradient); + CASE_DISPLAY_NEW(Random); + CASE_DRAW_NEW(Rect); + CASE_NEW(RectToRect); + CASE_NEW(Remove); + CASE_NEW(Replace); + CASE_NEW(Rotate); + CASE_NEW(RoundRect); + CASE_NEW(Save); + CASE_NEW(SaveLayer); + CASE_NEW(Scale); + // screenplay + CASE_NEW(Set); + CASE_DRAW_NEW(Shader); + CASE_NEW(Skew); + CASE_NEW(3D_Camera); + CASE_NEW(3D_Patch); + // 3dpoint + CASE_NEW(Snapshot); + CASE_DISPLAY_NEW(String); + // style + CASE_NEW(Text); + CASE_DRAW_NEW(TextBox); + // textboxalign + // textboxmode + CASE_NEW(TextOnPath); + CASE_NEW(TextToPath); + CASE_DEBUG_RETURN_NIL(TileMode); + CASE_NEW(Translate); + CASE_DRAW_NEW(TransparentShader); + CASE_DRAW_NEW(Typeface); + CASE_DEBUG_RETURN_NIL(Xfermode); + default: + SkExtras** end = maker->fExtras.end(); + for (SkExtras** extraPtr = maker->fExtras.begin(); extraPtr < end; extraPtr++) { + if ((result = (*extraPtr)->createInstance(type)) != NULL) + return result; + } + SkASSERT(0); + } + return result; +} + +#undef CASE_NEW +#undef CASE_DRAW_NEW +#undef CASE_DISPLAY_NEW + +#if SK_USE_CONDENSED_INFO == 0 + +#define CASE_GET_INFO(_class) case SkType_##_class: \ + info = Sk##_class::fInfo; infoCount = Sk##_class::fInfoCount; break +#define CASE_GET_DRAW_INFO(_class) case SkType_##_class: \ + info = SkDraw##_class::fInfo; infoCount = SkDraw##_class::fInfoCount; break +#define CASE_GET_DISPLAY_INFO(_class) case SkType_##_class: \ + info = SkDisplay##_class::fInfo; infoCount = SkDisplay##_class::fInfoCount; \ + break + +const SkMemberInfo* SkDisplayType::GetMembers(SkAnimateMaker* maker, + SkDisplayTypes type, int* infoCountPtr) { + const SkMemberInfo* info = NULL; + int infoCount = 0; + switch (type) { + // unknown + CASE_GET_DISPLAY_INFO(Math); + CASE_GET_DISPLAY_INFO(Number); + CASE_GET_INFO(Add); + CASE_GET_INFO(AddCircle); + CASE_GET_INFO(AddGeom); + // addmode + CASE_GET_INFO(AddOval); + CASE_GET_INFO(AddPath); + CASE_GET_INFO(AddRect); + CASE_GET_INFO(AddRoundRect); + // align + CASE_GET_INFO(Animate); + CASE_GET_INFO(AnimateBase); + CASE_GET_INFO(Apply); + // applymode + // applytransition + CASE_GET_DISPLAY_INFO(Array); + // argb + // base64 + CASE_GET_INFO(BaseBitmap); + // baseclassinfo + CASE_GET_DRAW_INFO(Bitmap); + // bitmapencoding + // bitmapformat + CASE_GET_DRAW_INFO(BitmapShader); + CASE_GET_DRAW_INFO(Blur); + CASE_GET_DISPLAY_INFO(Boolean); + // boundable + CASE_GET_DISPLAY_INFO(Bounds); + // cap + // clear + CASE_GET_DRAW_INFO(Clip); + // close + CASE_GET_DRAW_INFO(Color); + CASE_GET_INFO(CubicTo); + CASE_GET_INFO(Dash); + CASE_GET_INFO(Data); + CASE_GET_INFO(Discrete); + // displayable + // drawable + CASE_GET_INFO(DrawTo); + CASE_GET_INFO(Dump); + // dynamicstring + CASE_GET_DRAW_INFO(Emboss); + CASE_GET_DISPLAY_INFO(Event); + // eventcode + // eventkind + // eventmode + // filltype + // filtertype + CASE_GET_DISPLAY_INFO(Float); + CASE_GET_INFO(FromPath); + // frompathmode + // full + CASE_GET_INFO(Gradient); + CASE_GET_INFO(Group); + CASE_GET_INFO(HitClear); + CASE_GET_INFO(HitTest); + CASE_GET_INFO(Image); + CASE_GET_INFO(Include); + CASE_GET_INFO(Input); + CASE_GET_DISPLAY_INFO(Int); + // join + CASE_GET_INFO(Line); + CASE_GET_INFO(LineTo); + CASE_GET_INFO(LinearGradient); + // maskfilter + // maskfilterblurstyle + // maskfilterlight + CASE_GET_DRAW_INFO(Matrix); + // memberfunction + // memberproperty + CASE_GET_INFO(Move); + CASE_GET_INFO(MoveTo); + CASE_GET_DISPLAY_INFO(Movie); + // msec + CASE_GET_INFO(Oval); + CASE_GET_DRAW_INFO(Path); + CASE_GET_DRAW_INFO(Paint); + // pathdirection + // patheffect + case SkType_Point: info = Sk_Point::fInfo; infoCount = Sk_Point::fInfoCount; break; // no virtual flavor + CASE_GET_INFO(DrawPoint); // virtual flavor + CASE_GET_INFO(PolyToPoly); + CASE_GET_INFO(Polygon); + CASE_GET_INFO(Polyline); + CASE_GET_INFO(Post); + CASE_GET_INFO(QuadTo); + CASE_GET_INFO(RCubicTo); + CASE_GET_INFO(RLineTo); + CASE_GET_INFO(RMoveTo); + CASE_GET_INFO(RQuadTo); + CASE_GET_INFO(RadialGradient); + CASE_GET_DISPLAY_INFO(Random); + CASE_GET_DRAW_INFO(Rect); + CASE_GET_INFO(RectToRect); + CASE_GET_INFO(Remove); + CASE_GET_INFO(Replace); + CASE_GET_INFO(Rotate); + CASE_GET_INFO(RoundRect); + CASE_GET_INFO(Save); + CASE_GET_INFO(SaveLayer); + CASE_GET_INFO(Scale); + // screenplay + CASE_GET_INFO(Set); + CASE_GET_DRAW_INFO(Shader); + CASE_GET_INFO(Skew); + CASE_GET_INFO(3D_Camera); + CASE_GET_INFO(3D_Patch); + CASE_GET_INFO(3D_Point); + CASE_GET_INFO(Snapshot); + CASE_GET_DISPLAY_INFO(String); + // style + CASE_GET_INFO(Text); + CASE_GET_DRAW_INFO(TextBox); + // textboxalign + // textboxmode + CASE_GET_INFO(TextOnPath); + CASE_GET_INFO(TextToPath); + // tilemode + CASE_GET_INFO(Translate); + // transparentshader + CASE_GET_DRAW_INFO(Typeface); + // xfermode + // knumberoftypes + default: + if (maker) { + SkExtras** end = maker->fExtras.end(); + for (SkExtras** extraPtr = maker->fExtras.begin(); extraPtr < end; extraPtr++) { + if ((info = (*extraPtr)->getMembers(type, infoCountPtr)) != NULL) + return info; + } + } + return NULL; + } + if (infoCountPtr) + *infoCountPtr = infoCount; + return info; +} + +const SkMemberInfo* SkDisplayType::GetMember(SkAnimateMaker* maker, + SkDisplayTypes type, const char** matchPtr ) { + int infoCount; + const SkMemberInfo* info = GetMembers(maker, type, &infoCount); + info = SkMemberInfo::Find(info, infoCount, matchPtr); +// SkASSERT(info); + return info; +} + +#undef CASE_GET_INFO +#undef CASE_GET_DRAW_INFO +#undef CASE_GET_DISPLAY_INFO + +#endif // SK_USE_CONDENSED_INFO == 0 + +#if defined SK_DEBUG || defined SK_BUILD_CONDENSED + #define DRAW_NAME(_name, _type) {_name, _type, true, false } + #define DISPLAY_NAME(_name, _type) {_name, _type, false, true } + #define INIT_BOOL_FIELDS , false, false +#else + #define DRAW_NAME(_name, _type) {_name, _type } + #define DISPLAY_NAME(_name, _type) {_name, _type } + #define INIT_BOOL_FIELDS +#endif + +const TypeNames gTypeNames[] = { + // unknown + { "Math", SkType_Math INIT_BOOL_FIELDS }, + { "Number", SkType_Number INIT_BOOL_FIELDS }, + { "add", SkType_Add INIT_BOOL_FIELDS }, + { "addCircle", SkType_AddCircle INIT_BOOL_FIELDS }, + // addgeom + // addmode + { "addOval", SkType_AddOval INIT_BOOL_FIELDS }, + { "addPath", SkType_AddPath INIT_BOOL_FIELDS }, + { "addRect", SkType_AddRect INIT_BOOL_FIELDS }, + { "addRoundRect", SkType_AddRoundRect INIT_BOOL_FIELDS }, + // align + { "animate", SkType_Animate INIT_BOOL_FIELDS }, + // animateBase + { "apply", SkType_Apply INIT_BOOL_FIELDS }, + // applymode + // applytransition + { "array", SkType_Array INIT_BOOL_FIELDS }, + // argb + // base64 + // basebitmap + // baseclassinfo + DRAW_NAME("bitmap", SkType_Bitmap), + // bitmapencoding + // bitmapformat + DRAW_NAME("bitmapShader", SkType_BitmapShader), + DRAW_NAME("blur", SkType_Blur), + { "boolean", SkType_Boolean INIT_BOOL_FIELDS }, + // boundable + DISPLAY_NAME("bounds", SkType_Bounds), + // cap + { "clear", SkType_Clear INIT_BOOL_FIELDS }, + DRAW_NAME("clip", SkType_Clip), + { "close", SkType_Close INIT_BOOL_FIELDS }, + DRAW_NAME("color", SkType_Color), + { "cubicTo", SkType_CubicTo INIT_BOOL_FIELDS }, + { "dash", SkType_Dash INIT_BOOL_FIELDS }, + { "data", SkType_Data INIT_BOOL_FIELDS }, + { "discrete", SkType_Discrete INIT_BOOL_FIELDS }, + // displayable + // drawable + { "drawTo", SkType_DrawTo INIT_BOOL_FIELDS }, + { "dump", SkType_Dump INIT_BOOL_FIELDS }, + // dynamicstring + DRAW_NAME("emboss", SkType_Emboss), + DISPLAY_NAME("event", SkType_Event), + // eventcode + // eventkind + // eventmode + // filltype + // filtertype + { "float", SkType_Float INIT_BOOL_FIELDS }, + { "fromPath", SkType_FromPath INIT_BOOL_FIELDS }, + // frompathmode + { "full", SkType_Full INIT_BOOL_FIELDS }, + // gradient + { "group", SkType_Group INIT_BOOL_FIELDS }, + { "hitClear", SkType_HitClear INIT_BOOL_FIELDS }, + { "hitTest", SkType_HitTest INIT_BOOL_FIELDS }, + { "image", SkType_Image INIT_BOOL_FIELDS }, + { "include", SkType_Include INIT_BOOL_FIELDS }, + { "input", SkType_Input INIT_BOOL_FIELDS }, + { "int", SkType_Int INIT_BOOL_FIELDS }, + // join + { "line", SkType_Line INIT_BOOL_FIELDS }, + { "lineTo", SkType_LineTo INIT_BOOL_FIELDS }, + { "linearGradient", SkType_LinearGradient INIT_BOOL_FIELDS }, + { "maskFilter", SkType_MaskFilter INIT_BOOL_FIELDS }, + // maskfilterblurstyle + // maskfilterlight + DRAW_NAME("matrix", SkType_Matrix), + // memberfunction + // memberproperty + { "move", SkType_Move INIT_BOOL_FIELDS }, + { "moveTo", SkType_MoveTo INIT_BOOL_FIELDS }, + { "movie", SkType_Movie INIT_BOOL_FIELDS }, + // msec + { "oval", SkType_Oval INIT_BOOL_FIELDS }, + DRAW_NAME("paint", SkType_Paint), + DRAW_NAME("path", SkType_Path), + // pathdirection + { "pathEffect", SkType_PathEffect INIT_BOOL_FIELDS }, + // point + DRAW_NAME("point", SkType_DrawPoint), + { "polyToPoly", SkType_PolyToPoly INIT_BOOL_FIELDS }, + { "polygon", SkType_Polygon INIT_BOOL_FIELDS }, + { "polyline", SkType_Polyline INIT_BOOL_FIELDS }, + { "post", SkType_Post INIT_BOOL_FIELDS }, + { "quadTo", SkType_QuadTo INIT_BOOL_FIELDS }, + { "rCubicTo", SkType_RCubicTo INIT_BOOL_FIELDS }, + { "rLineTo", SkType_RLineTo INIT_BOOL_FIELDS }, + { "rMoveTo", SkType_RMoveTo INIT_BOOL_FIELDS }, + { "rQuadTo", SkType_RQuadTo INIT_BOOL_FIELDS }, + { "radialGradient", SkType_RadialGradient INIT_BOOL_FIELDS }, + DISPLAY_NAME("random", SkType_Random), + { "rect", SkType_Rect INIT_BOOL_FIELDS }, + { "rectToRect", SkType_RectToRect INIT_BOOL_FIELDS }, + { "remove", SkType_Remove INIT_BOOL_FIELDS }, + { "replace", SkType_Replace INIT_BOOL_FIELDS }, + { "rotate", SkType_Rotate INIT_BOOL_FIELDS }, + { "roundRect", SkType_RoundRect INIT_BOOL_FIELDS }, + { "save", SkType_Save INIT_BOOL_FIELDS }, + { "saveLayer", SkType_SaveLayer INIT_BOOL_FIELDS }, + { "scale", SkType_Scale INIT_BOOL_FIELDS }, + // screenplay + { "set", SkType_Set INIT_BOOL_FIELDS }, + { "shader", SkType_Shader INIT_BOOL_FIELDS }, + { "skew", SkType_Skew INIT_BOOL_FIELDS }, + { "skia3d:camera", SkType_3D_Camera INIT_BOOL_FIELDS }, + { "skia3d:patch", SkType_3D_Patch INIT_BOOL_FIELDS }, + // point + { "snapshot", SkType_Snapshot INIT_BOOL_FIELDS }, + { "string", SkType_String INIT_BOOL_FIELDS }, + // style + { "text", SkType_Text INIT_BOOL_FIELDS }, + { "textBox", SkType_TextBox INIT_BOOL_FIELDS }, + // textboxalign + // textboxmode + { "textOnPath", SkType_TextOnPath INIT_BOOL_FIELDS }, + { "textToPath", SkType_TextToPath INIT_BOOL_FIELDS }, + // tilemode + { "translate", SkType_Translate INIT_BOOL_FIELDS }, + DRAW_NAME("transparentShader", SkType_TransparentShader), + { "typeface", SkType_Typeface INIT_BOOL_FIELDS } + // xfermode + // knumberoftypes +}; + +const int kTypeNamesSize = SK_ARRAY_COUNT(gTypeNames); + +SkDisplayTypes SkDisplayType::Find(SkAnimateMaker* maker, const SkMemberInfo* match) { + for (int index = 0; index < kTypeNamesSize; index++) { + SkDisplayTypes type = gTypeNames[index].fType; + const SkMemberInfo* info = SkDisplayType::GetMembers(maker, type, NULL); + if (info == match) + return type; + } + return (SkDisplayTypes) -1; +} + +// !!! optimize this by replacing function with a byte-sized lookup table +SkDisplayTypes SkDisplayType::GetParent(SkAnimateMaker* maker, SkDisplayTypes base) { + if (base == SkType_Group || base == SkType_Save || base == SkType_SaveLayer) //!!! cheat a little until we have a lookup table + return SkType_Displayable; + if (base == SkType_Set) + return SkType_Animate; // another cheat until we have a lookup table + const SkMemberInfo* info = GetMembers(maker, base, NULL); // get info for this type + SkASSERT(info); + if (info->fType != SkType_BaseClassInfo) + return SkType_Unknown; // if no base, done + // !!! could change SK_MEMBER_INHERITED macro to take type, stuff in offset, so that + // this (and table builder) could know type without the following steps: + const SkMemberInfo* inherited = info->getInherited(); + SkDisplayTypes result = (SkDisplayTypes) (SkType_Unknown + 1); + for (; result <= SkType_Xfermode; result = (SkDisplayTypes) (result + 1)) { + const SkMemberInfo* match = GetMembers(maker, result, NULL); + if (match == inherited) + break; + } + SkASSERT(result <= SkType_Xfermode); + return result; +} + +SkDisplayTypes SkDisplayType::GetType(SkAnimateMaker* maker, const char match[], size_t len ) { + int index = SkStrSearch(&gTypeNames[0].fName, kTypeNamesSize, match, + len, sizeof(gTypeNames[0])); + if (index >= 0 && index < kTypeNamesSize) + return gTypeNames[index].fType; + SkExtras** end = maker->fExtras.end(); + for (SkExtras** extraPtr = maker->fExtras.begin(); extraPtr < end; extraPtr++) { + SkDisplayTypes result = (*extraPtr)->getType(match, len); + if (result != SkType_Unknown) + return result; + } + return (SkDisplayTypes) -1; +} + +bool SkDisplayType::IsEnum(SkAnimateMaker* , SkDisplayTypes type) { + switch (type) { + case SkType_AddMode: + case SkType_Align: + case SkType_ApplyMode: + case SkType_ApplyTransition: + case SkType_BitmapEncoding: + case SkType_BitmapFormat: + case SkType_Boolean: + case SkType_Cap: + case SkType_EventCode: + case SkType_EventKind: + case SkType_EventMode: + case SkType_FillType: + case SkType_FilterType: + case SkType_FontStyle: + case SkType_FromPathMode: + case SkType_Join: + case SkType_MaskFilterBlurStyle: + case SkType_PathDirection: + case SkType_Style: + case SkType_TextBoxAlign: + case SkType_TextBoxMode: + case SkType_TileMode: + case SkType_Xfermode: + return true; + default: // to avoid warnings + break; + } + return false; +} + +bool SkDisplayType::IsDisplayable(SkAnimateMaker* , SkDisplayTypes type) { + switch (type) { + case SkType_Add: + case SkType_AddCircle: + case SkType_AddOval: + case SkType_AddPath: + case SkType_AddRect: + case SkType_AddRoundRect: + case SkType_Animate: + case SkType_AnimateBase: + case SkType_Apply: + case SkType_BaseBitmap: + case SkType_Bitmap: + case SkType_BitmapShader: + case SkType_Blur: + case SkType_Clear: + case SkType_Clip: + case SkType_Close: + case SkType_Color: + case SkType_CubicTo: + case SkType_Dash: + case SkType_Data: + case SkType_Discrete: + case SkType_Displayable: + case SkType_Drawable: + case SkType_DrawTo: + case SkType_Emboss: + case SkType_Event: + case SkType_FromPath: + case SkType_Full: + case SkType_Group: + case SkType_Image: + case SkType_Input: + case SkType_Line: + case SkType_LineTo: + case SkType_LinearGradient: + case SkType_Matrix: + case SkType_Move: + case SkType_MoveTo: + case SkType_Movie: + case SkType_Oval: + case SkType_Paint: + case SkType_Path: + case SkType_PolyToPoly: + case SkType_Polygon: + case SkType_Polyline: + case SkType_Post: + case SkType_QuadTo: + case SkType_RCubicTo: + case SkType_RLineTo: + case SkType_RMoveTo: + case SkType_RQuadTo: + case SkType_RadialGradient: + case SkType_Random: + case SkType_Rect: + case SkType_RectToRect: + case SkType_Remove: + case SkType_Replace: + case SkType_Rotate: + case SkType_RoundRect: + case SkType_Save: + case SkType_SaveLayer: + case SkType_Scale: + case SkType_Set: + case SkType_Shader: + case SkType_Skew: + case SkType_3D_Camera: + case SkType_3D_Patch: + case SkType_Snapshot: + case SkType_Text: + case SkType_TextBox: + case SkType_TextOnPath: + case SkType_TextToPath: + case SkType_Translate: + case SkType_TransparentShader: + return true; + default: // to avoid warnings + break; + } + return false; +} + +bool SkDisplayType::IsStruct(SkAnimateMaker* , SkDisplayTypes type) { + switch (type) { + case SkType_Point: + case SkType_3D_Point: + return true; + default: // to avoid warnings + break; + } + return false; +} + + +SkDisplayTypes SkDisplayType::RegisterNewType() { + gNewTypes = (SkDisplayTypes) (gNewTypes + 1); + return gNewTypes; +} + + + +#ifdef SK_DEBUG +const char* SkDisplayType::GetName(SkAnimateMaker* maker, SkDisplayTypes type) { + for (int index = 0; index < kTypeNamesSize - 1; index++) { + if (gTypeNames[index].fType == type) + return gTypeNames[index].fName; + } + SkExtras** end = maker->fExtras.end(); + for (SkExtras** extraPtr = maker->fExtras.begin(); extraPtr < end; extraPtr++) { + const char* result = (*extraPtr)->getName(type); + if (result != NULL) + return result; + } + return NULL; +} +#endif + +#ifdef SK_SUPPORT_UNITTEST +void SkDisplayType::UnitTest() { + SkAnimator animator; + SkAnimateMaker* maker = animator.fMaker; + int index; + for (index = 0; index < kTypeNamesSize - 1; index++) { + SkASSERT(strcmp(gTypeNames[index].fName, gTypeNames[index + 1].fName) < 0); + SkASSERT(gTypeNames[index].fType < gTypeNames[index + 1].fType); + } + for (index = 0; index < kTypeNamesSize; index++) { + SkDisplayable* test = CreateInstance(maker, gTypeNames[index].fType); + if (test == NULL) + continue; +#if defined _WIN32 && _MSC_VER >= 1300 && defined _INC_CRTDBG // only on windows, only if using "crtdbg.h" + // we know that crtdbg puts 0xfdfdfdfd at the end of the block + // look for unitialized memory, signature 0xcdcdcdcd prior to that + int* start = (int*) test; + while (*start != 0xfdfdfdfd) { + SkASSERT(*start != 0xcdcdcdcd); + start++; + } +#endif + delete test; + } + for (index = 0; index < kTypeNamesSize; index++) { + int infoCount; + const SkMemberInfo* info = GetMembers(maker, gTypeNames[index].fType, &infoCount); + if (info == NULL) + continue; +#if SK_USE_CONDENSED_INFO == 0 + for (int inner = 0; inner < infoCount - 1; inner++) { + if (info[inner].fType == SkType_BaseClassInfo) + continue; + SkASSERT(strcmp(info[inner].fName, info[inner + 1].fName) < 0); + } +#endif + } +#if defined SK_DEBUG || defined SK_BUILD_CONDENSED + BuildCondensedInfo(maker); +#endif +} +#endif diff --git a/libs/graphics/animator/SkDisplayType.h b/libs/graphics/animator/SkDisplayType.h new file mode 100644 index 000000000..d6c4a931e --- /dev/null +++ b/libs/graphics/animator/SkDisplayType.h @@ -0,0 +1,198 @@ +#ifndef SkDisplayType_DEFINED +#define SkDisplayType_DEFINED + +#include "SkMath.h" + +#ifdef SK_DEBUG + #ifdef SK_CAN_USE_FLOAT + #define SK_DUMP_ENABLED + #endif + #ifdef SK_BUILD_FOR_MAC + #define SK_FIND_LEAKS + #endif +#endif + +#define SK_LITERAL_STR_EQUAL(str, token, len) (sizeof(str) - 1 == len \ + && strncmp(str, token, sizeof(str) - 1) == 0) + +class SkAnimateMaker; +class SkDisplayable; +struct SkMemberInfo; + +enum SkDisplayTypes { + SkType_Unknown, + SkType_Math, // for ecmascript compatible Math functions and constants + SkType_Number, // for for ecmascript compatible Number functions and constants + SkType_Add, + SkType_AddCircle, + SkType_AddGeom, + SkType_AddMode, + SkType_AddOval, + SkType_AddPath, + SkType_AddRect, // path part + SkType_AddRoundRect, + SkType_Align, + SkType_Animate, + SkType_AnimateBase, // base type for animate, set + SkType_Apply, + SkType_ApplyMode, + SkType_ApplyTransition, + SkType_Array, + SkType_ARGB, + SkType_Base64, + SkType_BaseBitmap, + SkType_BaseClassInfo, + SkType_Bitmap, + SkType_BitmapEncoding, + SkType_BitmapFormat, + SkType_BitmapShader, + SkType_Blur, + SkType_Boolean, // can have values -1 (uninitialized), 0, 1 + SkType_Boundable, + SkType_Bounds, + SkType_Cap, + SkType_Clear, + SkType_Clip, + SkType_Close, + SkType_Color, + SkType_CubicTo, + SkType_Dash, + SkType_Data, + SkType_Discrete, + SkType_Displayable, + SkType_Drawable, + SkType_DrawTo, + SkType_Dump, + SkType_DynamicString, // evaluate at draw time + SkType_Emboss, + SkType_Event, + SkType_EventCode, + SkType_EventKind, + SkType_EventMode, + SkType_FillType, + SkType_FilterType, + SkType_Float, + SkType_FontStyle, + SkType_FromPath, + SkType_FromPathMode, + SkType_Full, + SkType_Gradient, + SkType_Group, + SkType_HitClear, + SkType_HitTest, + SkType_Image, + SkType_Include, + SkType_Input, + SkType_Int, + SkType_Join, + SkType_Line, // simple line primitive + SkType_LineTo, // used as part of path construction + SkType_LinearGradient, + SkType_MaskFilter, + SkType_MaskFilterBlurStyle, + SkType_MaskFilterLight, + SkType_Matrix, + SkType_MemberFunction, + SkType_MemberProperty, + SkType_Move, + SkType_MoveTo, + SkType_Movie, + SkType_MSec, + SkType_Oval, + SkType_Paint, + SkType_Path, + SkType_PathDirection, + SkType_PathEffect, + SkType_Point, // used inside other structures, no vtable + SkType_DrawPoint, // used to draw points, has a vtable + SkType_PolyToPoly, + SkType_Polygon, + SkType_Polyline, + SkType_Post, + SkType_QuadTo, + SkType_RCubicTo, + SkType_RLineTo, + SkType_RMoveTo, + SkType_RQuadTo, + SkType_RadialGradient, + SkType_Random, + SkType_Rect, + SkType_RectToRect, + SkType_Remove, + SkType_Replace, + SkType_Rotate, + SkType_RoundRect, + SkType_Save, + SkType_SaveLayer, + SkType_Scale, + SkType_Screenplay, + SkType_Set, + SkType_Shader, + SkType_Skew, + SkType_3D_Camera, + SkType_3D_Patch, + SkType_3D_Point, + SkType_Snapshot, + SkType_String, // pointer to SkString + SkType_Style, + SkType_Text, + SkType_TextBox, + SkType_TextBoxAlign, + SkType_TextBoxMode, + SkType_TextOnPath, + SkType_TextToPath, + SkType_TileMode, + SkType_Translate, + SkType_TransparentShader, + SkType_Typeface, + SkType_Xfermode, + kNumberOfTypes +}; + +struct TypeNames { + const char* fName; + SkDisplayTypes fType; +#if defined SK_DEBUG || defined SK_BUILD_CONDENSED + bool fDrawPrefix; + bool fDisplayPrefix; +#endif +}; + +#ifdef SK_DEBUG +typedef SkDisplayTypes SkFunctionParamType; +#else +typedef unsigned char SkFunctionParamType; +#endif + +extern const TypeNames gTypeNames[]; +extern const int kTypeNamesSize; + +class SkDisplayType { +public: + static SkDisplayTypes Find(SkAnimateMaker* , const SkMemberInfo* ); + static const SkMemberInfo* GetMember(SkAnimateMaker* , SkDisplayTypes , const char** ); + static const SkMemberInfo* GetMembers(SkAnimateMaker* , SkDisplayTypes , int* infoCountPtr); + static SkDisplayTypes GetParent(SkAnimateMaker* , SkDisplayTypes ); + static bool IsDisplayable(SkAnimateMaker* , SkDisplayTypes ); + static bool IsEnum(SkAnimateMaker* , SkDisplayTypes ); + static bool IsStruct(SkAnimateMaker* , SkDisplayTypes ); + static SkDisplayTypes RegisterNewType(); + static SkDisplayTypes Resolve(const char[] , const SkMemberInfo** ); +#ifdef SK_DEBUG + static bool IsAnimate(SkDisplayTypes type ) { return type == SkType_Animate || + type == SkType_Set; } + static const char* GetName(SkAnimateMaker* , SkDisplayTypes ); +#endif +#ifdef SK_SUPPORT_UNITTEST + static void UnitTest(); +#endif +#if defined SK_DEBUG || defined SK_BUILD_CONDENSED + static void BuildCondensedInfo(SkAnimateMaker* ); +#endif + static SkDisplayTypes GetType(SkAnimateMaker* , const char[] , size_t len); + static SkDisplayable* CreateInstance(SkAnimateMaker* , SkDisplayTypes ); +private: + static SkDisplayTypes gNewTypes; +}; + +#endif // SkDisplayType_DEFINED diff --git a/libs/graphics/animator/SkDisplayTypes.cpp b/libs/graphics/animator/SkDisplayTypes.cpp new file mode 100644 index 000000000..b38a04cc2 --- /dev/null +++ b/libs/graphics/animator/SkDisplayTypes.cpp @@ -0,0 +1,212 @@ +#include "SkDisplayTypes.h" +#include "SkAnimateBase.h" + +bool SkDisplayDepend::canContainDependents() const { + return true; +} + +void SkDisplayDepend::dirty() { + SkDisplayable** last = fDependents.end(); + for (SkDisplayable** depPtr = fDependents.begin(); depPtr < last; depPtr++) { + SkAnimateBase* animate = (SkAnimateBase* ) *depPtr; + animate->setChanged(true); + } +} + +// Boolean +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDisplayBoolean::fInfo[] = { + SK_MEMBER(value, Boolean) +}; + +#endif + +DEFINE_GET_MEMBER(SkDisplayBoolean); + +SkDisplayBoolean::SkDisplayBoolean() : value(false) { +} + +#ifdef SK_DUMP_ENABLED +void SkDisplayBoolean::dump(SkAnimateMaker* maker){ + dumpBase(maker); + SkDebugf("value=\"%s\" />\n", value ? "true" : "false"); +} +#endif + +// S32 +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDisplayInt::fInfo[] = { + SK_MEMBER(value, Int) +}; + +#endif + +DEFINE_GET_MEMBER(SkDisplayInt); + +SkDisplayInt::SkDisplayInt() : value(0) { +} + +#ifdef SK_DUMP_ENABLED +void SkDisplayInt::dump(SkAnimateMaker* maker){ + dumpBase(maker); + SkDebugf("value=\"%d\" />\n", value); +} +#endif + +// SkScalar +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDisplayFloat::fInfo[] = { + SK_MEMBER(value, Float) +}; + +#endif + +DEFINE_GET_MEMBER(SkDisplayFloat); + +SkDisplayFloat::SkDisplayFloat() : value(0) { +} + +#ifdef SK_DUMP_ENABLED +void SkDisplayFloat::dump(SkAnimateMaker* maker) { + dumpBase(maker); +#ifdef SK_CAN_USE_FLOAT + SkDebugf("value=\"%g\" />\n", SkScalarToFloat(value)); +#else + SkDebugf("value=\"%x\" />\n", value); +#endif +} +#endif + +// SkString +enum SkDisplayString_Functions { + SK_FUNCTION(slice) +}; + +enum SkDisplayString_Properties { + SK_PROPERTY(length) +}; + +const SkFunctionParamType SkDisplayString::fFunctionParameters[] = { + (SkFunctionParamType) SkType_Int, // slice + (SkFunctionParamType) SkType_Int, + (SkFunctionParamType) 0 +}; + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDisplayString::fInfo[] = { + SK_MEMBER_PROPERTY(length, Int), + SK_MEMBER_FUNCTION(slice, String), + SK_MEMBER(value, String) +}; + +#endif + +DEFINE_GET_MEMBER(SkDisplayString); + +SkDisplayString::SkDisplayString() { +} + +SkDisplayString::SkDisplayString(SkString& copyFrom) : value(copyFrom) { +} + +void SkDisplayString::executeFunction(SkDisplayable* target, int index, + SkTDArray& parameters, SkDisplayTypes type, + SkScriptValue* scriptValue) { + if (scriptValue == nil) + return; + SkASSERT(target == this); + switch (index) { + case SK_FUNCTION(slice): + scriptValue->fType = SkType_String; + SkASSERT(parameters[0].fType == SkType_Int); + int start = parameters[0].fOperand.fS32; + if (start < 0) + start = (int) (value.size() - start); + int end = (int) value.size(); + if (parameters.count() > 1) { + SkASSERT(parameters[1].fType == SkType_Int); + end = parameters[1].fOperand.fS32; + } + //if (end >= 0 && end < (int) value.size()) + if (end >= 0 && end <= (int) value.size()) + scriptValue->fOperand.fString = new SkString(&value.c_str()[start], end - start); + else + scriptValue->fOperand.fString = new SkString(value); + break; + } +} + +const SkFunctionParamType* SkDisplayString::getFunctionsParameters() { + return fFunctionParameters; +} + +bool SkDisplayString::getProperty(int index, SkScriptValue* scriptValue) const { + switch (index) { + case SK_PROPERTY(length): + scriptValue->fType = SkType_Int; + scriptValue->fOperand.fS32 = (S32) value.size(); + break; + default: + SkASSERT(0); + return false; + } + return true; +} + + +// SkArray +#if 0 // !!! reason enough to qualify enum with class name or move typedArray into its own file +enum SkDisplayArray_Properties { + SK_PROPERTY(length) +}; +#endif + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDisplayArray::fInfo[] = { + SK_MEMBER_PROPERTY(length, Int), + SK_MEMBER_ARRAY(values, Unknown) +}; + +#endif + +DEFINE_GET_MEMBER(SkDisplayArray); + +SkDisplayArray::SkDisplayArray() { +} + +SkDisplayArray::SkDisplayArray(SkTypedArray& copyFrom) : values(copyFrom) { + +} + +SkDisplayArray::~SkDisplayArray() { + if (values.getType() == SkType_String) { + for (int index = 0; index < values.count(); index++) + delete values[index].fString; + return; + } + if (values.getType() == SkType_Array) { + for (int index = 0; index < values.count(); index++) + delete values[index].fArray; + } +} + +bool SkDisplayArray::getProperty(int index, SkScriptValue* value) const { + switch (index) { + case SK_PROPERTY(length): + value->fType = SkType_Int; + value->fOperand.fS32 = values.count(); + break; + default: + SkASSERT(0); + return false; + } + return true; +} + + + diff --git a/libs/graphics/animator/SkDisplayTypes.h b/libs/graphics/animator/SkDisplayTypes.h new file mode 100644 index 000000000..ce654ab08 --- /dev/null +++ b/libs/graphics/animator/SkDisplayTypes.h @@ -0,0 +1,98 @@ +#ifndef SkDisplayTypes_DEFINED +#define SkDisplayTypes_DEFINED + +#include "SkDisplayable.h" +#include "SkMemberInfo.h" +#include "SkTypedArray.h" + +class SkOpArray; // compiled script experiment + + +class SkDisplayDepend : public SkDisplayable { +public: + virtual bool canContainDependents() const; + void addDependent(SkDisplayable* displayable) { + if (fDependents.find(displayable) < 0) + *fDependents.append() = displayable; + } + virtual void dirty(); +private: + SkTDDisplayableArray fDependents; + typedef SkDisplayable INHERITED; +}; + +class SkDisplayBoolean : public SkDisplayDepend { + DECLARE_DISPLAY_MEMBER_INFO(Boolean); + SkDisplayBoolean(); +#ifdef SK_DUMP_ENABLED + virtual void dump(SkAnimateMaker* ); +#endif + SkBool value; + friend class SkAnimatorScript; + friend class SkAnimatorScript_Box; + friend class SkAnimatorScript_Unbox; + typedef SkDisplayDepend INHERITED; +}; + +class SkDisplayInt : public SkDisplayDepend { + DECLARE_DISPLAY_MEMBER_INFO(Int); + SkDisplayInt(); +#ifdef SK_DUMP_ENABLED + virtual void dump(SkAnimateMaker* ); +#endif +private: + S32 value; + friend class SkAnimatorScript; + friend class SkAnimatorScript_Box; + friend class SkAnimatorScript_Unbox; + typedef SkDisplayDepend INHERITED; +}; + +class SkDisplayFloat : public SkDisplayDepend { + DECLARE_DISPLAY_MEMBER_INFO(Float); + SkDisplayFloat(); +#ifdef SK_DUMP_ENABLED + virtual void dump(SkAnimateMaker* ); +#endif +private: + SkScalar value; + friend class SkAnimatorScript; + friend class SkAnimatorScript_Box; + friend class SkAnimatorScript_Unbox; + typedef SkDisplayDepend INHERITED; +}; + +class SkDisplayString : public SkDisplayDepend { + DECLARE_DISPLAY_MEMBER_INFO(String); + SkDisplayString(); + SkDisplayString(SkString& ); + virtual void executeFunction(SkDisplayable* , int index, + SkTDArray& parameters, SkDisplayTypes type, + SkScriptValue* ); + virtual const SkFunctionParamType* getFunctionsParameters(); + virtual bool getProperty(int index, SkScriptValue* ) const; + SkString value; +private: + static const SkFunctionParamType fFunctionParameters[]; +}; + +class SkDisplayArray : public SkDisplayDepend { + DECLARE_DISPLAY_MEMBER_INFO(Array); + SkDisplayArray(); + SkDisplayArray(SkTypedArray& ); + SkDisplayArray(SkOpArray& ); // compiled script experiment + virtual ~SkDisplayArray(); + virtual bool getProperty(int index, SkScriptValue* ) const; +private: + SkTypedArray values; + friend class SkAnimator; + friend class SkAnimatorScript; + friend class SkAnimatorScript2; + friend class SkAnimatorScript_Unbox; + friend class SkDisplayable; + friend struct SkMemberInfo; + friend class SkScriptEngine; +}; + +#endif // SkDisplayTypes_DEFINED + diff --git a/libs/graphics/animator/SkDisplayXMLParser.cpp b/libs/graphics/animator/SkDisplayXMLParser.cpp new file mode 100644 index 000000000..fd4840a08 --- /dev/null +++ b/libs/graphics/animator/SkDisplayXMLParser.cpp @@ -0,0 +1,301 @@ +#include "SkDisplayXMLParser.h" +#include "SkAnimateMaker.h" +#include "SkDisplayApply.h" +#include "SkUtils.h" +#ifdef SK_DEBUG +#include "SkTime.h" +#endif + +static char const* const gErrorStrings[] = { + "unknown error ", + "apply scopes itself", + "display tree too deep (circular reference?) ", + "element missing parent ", + "element type not allowed in parent ", + "error adding to ", + "error adding to ", + "error adding to ", + "error adding to ", + "error in attribute value ", + "error in script ", + "expected movie in sink attribute ", + "field not in target ", + "number of offsets in gradient must match number of colors", + "no offset in gradient may be greater than one", + "last offset in gradient must be one", + "offsets in gradient must be increasing", + "first offset in gradient must be zero", + "gradient attribute \"points\" must have length of four", + "in include ", + "in movie ", + "include name unknown or missing ", + "index out of range ", + "movie name unknown or missing ", + "no parent available to resolve sink attribute ", + "parent element can't contain ", + "saveLayer must specify a bounds", + "target id not found ", + "unexpected type " +}; + +SkDisplayXMLParserError::~SkDisplayXMLParserError() { +} + +void SkDisplayXMLParserError::getErrorString(SkString* str) const { + if (fCode > kUnknownError) + str->set(gErrorStrings[fCode - kUnknownError]); + else + str->reset(); + INHERITED::getErrorString(str); +} + +void SkDisplayXMLParserError::setInnerError(SkAnimateMaker* parent, const SkString& src) { + SkString inner; + getErrorString(&inner); + inner.prepend(": "); + inner.prependS32(getLineNumber()); + inner.prepend(", line "); + inner.prepend(src); + parent->setErrorNoun(inner); +} + + +SkDisplayXMLParser::SkDisplayXMLParser(SkAnimateMaker& maker) + : INHERITED(&maker.fError), fMaker(maker), fInInclude(maker.fInInclude), + fInSkia(maker.fInInclude), fCurrDisplayable(nil) +{ +} + +SkDisplayXMLParser::~SkDisplayXMLParser() { + if (fCurrDisplayable && fMaker.fChildren.find(fCurrDisplayable) < 0) + delete fCurrDisplayable; + for (Parent* parPtr = fParents.begin() + 1; parPtr < fParents.end(); parPtr++) { + SkDisplayable* displayable = parPtr->fDisplayable; + if (displayable == fCurrDisplayable) + continue; + SkASSERT(fMaker.fChildren.find(displayable) < 0); + if (fMaker.fHelpers.find(displayable) < 0) + delete displayable; + } +} + + + +bool SkDisplayXMLParser::onAddAttribute(const char name[], const char value[]) { + return onAddAttributeLen(name, value, strlen(value)); +} + +bool SkDisplayXMLParser::onAddAttributeLen(const char attrName[], const char attrValue[], + size_t attrValueLen) +{ + if (fCurrDisplayable == nil) // this signals we should ignore attributes for this element + return strncmp(attrName, "xmlns", sizeof("xmlns") - 1) != 0; + SkDisplayable* displayable = fCurrDisplayable; + SkDisplayTypes type = fCurrType; + + if (strcmp(attrName, "id") == 0) { + if (fMaker.find(attrValue, attrValueLen, nil)) { + fError->setNoun(attrValue, attrValueLen); + fError->setCode(SkXMLParserError::kDuplicateIDs); + return true; + } +#ifdef SK_DEBUG + displayable->_id.set(attrValue, attrValueLen); + displayable->id = displayable->_id.c_str(); +#endif + fMaker.idsSet(attrValue, attrValueLen, displayable); + int parentIndex = fParents.count() - 1; + if (parentIndex > 0) { + SkDisplayable* parent = fParents[parentIndex - 1].fDisplayable; + parent->setChildHasID(); + } + return false; + } + const char* name = attrName; + const SkMemberInfo* info = SkDisplayType::GetMember(&fMaker, type, &name); + if (info == nil) { + fError->setNoun(name); + fError->setCode(SkXMLParserError::kUnknownAttributeName); + return true; + } + if (info->setValue(fMaker, nil, 0, info->getCount(), displayable, info->getType(), attrValue, + attrValueLen)) + return false; + if (fMaker.fError.hasError()) { + fError->setNoun(attrValue, attrValueLen); + return true; + } + SkDisplayable* ref = nil; + if (fMaker.find(attrValue, attrValueLen, &ref) == false) { + ref = fMaker.createInstance(attrValue, attrValueLen); + if (ref == nil) { + fError->setNoun(attrValue, attrValueLen); + fError->setCode(SkXMLParserError::kErrorInAttributeValue); + return true; + } else + fMaker.helperAdd(ref); + } + if (info->fType != SkType_MemberProperty) { + fError->setNoun(name); + fError->setCode(SkXMLParserError::kUnknownAttributeName); + return true; + } + SkScriptValue scriptValue; + scriptValue.fOperand.fDisplayable = ref; + scriptValue.fType = ref->getType(); + displayable->setProperty(info->propertyIndex(), scriptValue); + return false; +} + +bool SkDisplayXMLParser::onEndElement(const char elem[]) +{ + int parentIndex = fParents.count() - 1; + if (parentIndex >= 0) { + Parent& container = fParents[parentIndex]; + SkDisplayable* displayable = container.fDisplayable; + fMaker.fEndDepth = parentIndex; + displayable->onEndElement(fMaker); + if (fMaker.fError.hasError()) + return true; + if (parentIndex > 0) { + SkDisplayable* parent = fParents[parentIndex - 1].fDisplayable; + bool result = parent->add(fMaker, displayable); + if (fMaker.hasError()) + return true; + if (result == false) { + int infoCount; + const SkMemberInfo* info = + SkDisplayType::GetMembers(&fMaker, fParents[parentIndex - 1].fType, &infoCount); + const SkMemberInfo* foundInfo; + if ((foundInfo = searchContainer(info, infoCount)) != nil) { + parent->setReference(foundInfo, displayable); + // if (displayable->isHelper() == false) + fMaker.helperAdd(displayable); + } else { + fMaker.setErrorCode(SkDisplayXMLParserError::kElementTypeNotAllowedInParent); + return true; + } + } + if (parent->childrenNeedDisposing()) + delete displayable; + } + fParents.remove(parentIndex); + } + fCurrDisplayable = nil; + if (fInInclude == false && strcasecmp(elem, "screenplay") == 0) { + if (fMaker.fInMovie == false) { + fMaker.fEnableTime = fMaker.getAppTime(); +#if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING + if (fMaker.fDebugTimeBase == (SkMSec) -1) + fMaker.fDebugTimeBase = fMaker.fEnableTime; + SkString debugOut; + SkMSec time = fMaker.getAppTime(); + debugOut.appendS32(time - fMaker.fDebugTimeBase); + debugOut.append(" onLoad enable="); + debugOut.appendS32(fMaker.fEnableTime - fMaker.fDebugTimeBase); + SkDebugf("%s\n", debugOut.c_str()); +#endif + fMaker.fEvents.doEvent(fMaker, SkDisplayEvent::kOnload, nil); + if (fMaker.fError.hasError()) + return true; + fMaker.fEvents.removeEvent(SkDisplayEvent::kOnload, nil); + + } + fInSkia = false; + } + return false; +} + +bool SkDisplayXMLParser::onStartElement(const char name[]) +{ + return onStartElementLen(name, strlen(name)); +} + +bool SkDisplayXMLParser::onStartElementLen(const char name[], size_t len) { + fCurrDisplayable = nil; // init so we'll ignore attributes if we exit early + + if (strncasecmp(name, "screenplay", len) == 0) { + fInSkia = true; + if (fInInclude == false) + fMaker.idsSet(name, len, &fMaker.fScreenplay); + return false; + } + if (fInSkia == false) + return false; + + SkDisplayable* displayable = fMaker.createInstance(name, len); + if (displayable == nil) { + fError->setNoun(name, len); + fError->setCode(SkXMLParserError::kUnknownElement); + return true; + } + SkDisplayTypes type = displayable->getType(); + Parent record = { displayable, type }; + *fParents.append() = record; + if (fParents.count() == 1) + fMaker.childrenAdd(displayable); + else { + Parent* parent = fParents.end() - 2; + if (displayable->setParent(parent->fDisplayable)) { + fError->setNoun(name, len); + getError()->setCode(SkDisplayXMLParserError::kParentElementCantContain); + return true; + } + } + + // set these for subsequent calls to addAttribute() + fCurrDisplayable = displayable; + fCurrType = type; + return false; +} + +const SkMemberInfo* SkDisplayXMLParser::searchContainer(const SkMemberInfo* infoBase, + int infoCount) { + const SkMemberInfo* bestDisplayable = nil; + const SkMemberInfo* lastResort = nil; + for (int index = 0; index < infoCount; index++) { + const SkMemberInfo* info = &infoBase[index]; + if (info->fType == SkType_BaseClassInfo) { + const SkMemberInfo* inherited = info->getInherited(); + const SkMemberInfo* result = searchContainer(inherited, info->fCount); + if (result != nil) + return result; + continue; + } + Parent* container = fParents.end() - 1; + SkDisplayTypes type = (SkDisplayTypes) info->fType; + if (type == SkType_MemberProperty) + type = info->propertyType(); + SkDisplayTypes containerType = container->fType; + if (type == containerType && (type == SkType_Rect || type == SkType_Polygon || + type == SkType_Array || type == SkType_Int || type == SkType_Bitmap)) + goto rectNext; + while (type != containerType) { + if (containerType == SkType_Displayable) + goto next; + containerType = SkDisplayType::GetParent(&fMaker, containerType); + if (containerType == SkType_Unknown) + goto next; + } + return info; +next: + if (type == SkType_Drawable || type == SkType_Displayable && + container->fDisplayable->isDrawable()) { +rectNext: + if (fParents.count() > 1) { + Parent* parent = fParents.end() - 2; + if (info == parent->fDisplayable->preferredChild(type)) + bestDisplayable = info; + else + lastResort = info; + } + } + } + if (bestDisplayable) + return bestDisplayable; + if (lastResort) + return lastResort; + return nil; +} + + diff --git a/libs/graphics/animator/SkDisplayXMLParser.h b/libs/graphics/animator/SkDisplayXMLParser.h new file mode 100644 index 000000000..3aa42cfc5 --- /dev/null +++ b/libs/graphics/animator/SkDisplayXMLParser.h @@ -0,0 +1,84 @@ +#ifndef SkDisplayXMLParser_DEFINED +#define SkDisplayXMLParser_DEFINED + +#include "SkIntArray.h" +#include "SkTDict.h" +#include "SkDisplayType.h" +#include "SkXMLParser.h" + +class SkAnimateMaker; +class SkDisplayable; + +class SkDisplayXMLParserError : public SkXMLParserError { +public: + enum ErrorCode { + kApplyScopesItself = kUnknownError + 1, + kDisplayTreeTooDeep, + kElementMissingParent, + kElementTypeNotAllowedInParent, + kErrorAddingDataToPost, + kErrorAddingToMatrix, + kErrorAddingToPaint, + kErrorAddingToPath, + kErrorInAttributeValue, + kErrorInScript, + kExpectedMovie, + kFieldNotInTarget, + kGradientOffsetsDontMatchColors, + kGradientOffsetsMustBeNoMoreThanOne, + kGradientOffsetsMustEndWithOne, + kGradientOffsetsMustIncrease, + kGradientOffsetsMustStartWithZero, + kGradientPointsLengthMustBeFour, + kInInclude, + kInMovie, + kIncludeNameUnknownOrMissing, + kIndexOutOfRange, + kMovieNameUnknownOrMissing, + kNoParentAvailable, + kParentElementCantContain, + kSaveLayerNeedsBounds, + kTargetIDNotFound, + kUnexpectedType + }; + virtual ~SkDisplayXMLParserError(); + virtual void getErrorString(SkString* str) const; + void setCode(ErrorCode code) { INHERITED::setCode((INHERITED::ErrorCode) code); } + void setInnerError(SkAnimateMaker* maker, const SkString& str); + typedef SkXMLParserError INHERITED; + friend class SkDisplayXMLParser; +}; + +class SkDisplayXMLParser : public SkXMLParser { +public: + SkDisplayXMLParser(SkAnimateMaker& maker); + virtual ~SkDisplayXMLParser(); +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); +private: + struct Parent { + SkDisplayable* fDisplayable; + SkDisplayTypes fType; + }; + SkTDArray fParents; + SkDisplayXMLParser& operator= (const SkDisplayXMLParser& ); + SkDisplayXMLParserError* getError() { return (SkDisplayXMLParserError*) fError; } + const SkMemberInfo* searchContainer(const SkMemberInfo* , + int infoCount); + SkAnimateMaker& fMaker; + SkBool fInInclude; + SkBool fInSkia; + // local state between onStartElement and onAddAttribute + SkDisplayable* fCurrDisplayable; + SkDisplayTypes fCurrType; + friend class SkXMLAnimatorWriter; + typedef SkXMLParser INHERITED; +}; + +#endif // SkDisplayXMLParser_DEFINED + + diff --git a/libs/graphics/animator/SkDisplayable.cpp b/libs/graphics/animator/SkDisplayable.cpp new file mode 100644 index 000000000..41c4b4793 --- /dev/null +++ b/libs/graphics/animator/SkDisplayable.cpp @@ -0,0 +1,549 @@ +#include "SkDisplayable.h" +#include "SkDisplayApply.h" +#include "SkParse.h" +#ifdef SK_DEBUG +#include "SkDisplayList.h" +#endif +#include "SkDisplayTypes.h" + +#ifdef SK_FIND_LEAKS +// int SkDisplayable::fAllocationCount; +SkTDDisplayableArray SkDisplayable::fAllocations; +#endif + +#ifdef SK_DEBUG +SkDisplayable::SkDisplayable() { + id = _id.c_str(); +#ifdef SK_FIND_LEAKS + // fAllocationCount++; + *fAllocations.append() = this; +#endif +} +#endif + +SkDisplayable::~SkDisplayable() { +#ifdef SK_FIND_LEAKS + // fAllocationCount--; + int index = fAllocations.find(this); + SkASSERT(index >= 0); + fAllocations.remove(index); +#endif +} + +bool SkDisplayable::add(SkAnimateMaker& , SkDisplayable* child) { + return false; +} + +//void SkDisplayable::apply(SkAnimateMaker& , const SkMemberInfo* , +// SkDisplayable* , SkScalar [], int count) { +// SkASSERT(0); +//} + +bool SkDisplayable::canContainDependents() const { + return false; +} + +bool SkDisplayable::childrenNeedDisposing() const { + return false; +} + +void SkDisplayable::clearBounder() { +} + +bool SkDisplayable::contains(SkDisplayable* ) { + return false; +} + +SkDisplayable* SkDisplayable::contains(const SkString& ) { + return nil; +} + +SkDisplayable* SkDisplayable::deepCopy(SkAnimateMaker* maker) { + SkDisplayTypes type = getType(); + if (type == SkType_Unknown) { + SkASSERT(0); + return nil; + } + SkDisplayable* copy = SkDisplayType::CreateInstance(maker, type); + int index = -1; + int propIndex = 0; + const SkMemberInfo* info; + do { + info = copy->getMember(++index); + if (info == nil) + break; + if (info->fType == SkType_MemberProperty) { + SkScriptValue value; + if (getProperty(propIndex, &value)) + copy->setProperty(propIndex, value); + propIndex++; + continue; + } + if (info->fType == SkType_MemberFunction) + continue; + if (info->fType == SkType_Array) { + SkTDOperandArray* array = (SkTDOperandArray*) info->memberData(this); + int arrayCount; + if (array == nil || (arrayCount = array->count()) == 0) + continue; + SkTDOperandArray* copyArray = (SkTDOperandArray*) info->memberData(copy); + copyArray->setCount(arrayCount); + SkDisplayTypes elementType; + if (type == SkType_Array) { + SkDisplayArray* dispArray = (SkDisplayArray*) this; + elementType = dispArray->values.getType(); + } else + elementType = info->arrayType(); + size_t elementSize = SkMemberInfo::GetSize(elementType); + size_t byteSize = elementSize * arrayCount; + memcpy(copyArray->begin(), array->begin(), byteSize); + continue; + } + if (SkDisplayType::IsDisplayable(maker, info->fType)) { + SkDisplayable** displayable = (SkDisplayable**) info->memberData(this); + if (*displayable == nil || *displayable == (SkDisplayable*) -1) + continue; + SkDisplayable* deeper = (*displayable)->deepCopy(maker); + info->setMemberData(copy, deeper, sizeof(deeper)); + continue; + } + if (info->fType == SkType_String || info->fType == SkType_DynamicString) { + SkString* string; + info->getString(this, &string); + info->setString(copy, string); + continue; + } + void* data = info->memberData(this); + size_t size = SkMemberInfo::GetSize(info->fType); + info->setMemberData(copy, data, size); + } while (true); + copy->dirty(); + return copy; +} + +void SkDisplayable::dirty() { +} + +#ifdef SK_DUMP_ENABLED +void SkDisplayable::dump(SkAnimateMaker* maker) { + dumpBase(maker); +#if SK_USE_CONDENSED_INFO == 0 + this->dumpAttrs(maker); + this->dumpChildren(maker); +#endif +} + +void SkDisplayable::dumpAttrs(SkAnimateMaker* maker) { + SkDisplayTypes type = getType(); + if (type == SkType_Unknown) { + //SkDebugf("/>\n"); + return; + } + SkDisplayable* blankCopy = SkDisplayType::CreateInstance(maker, type); + + int index = -1; + int propIndex = 0; + const SkMemberInfo* info; + const SkMemberInfo* blankInfo; + SkScriptValue value; + SkScriptValue blankValue; + SkOperand values[2]; + SkOperand blankValues[2]; + do { + info = this->getMember(++index); + if (nil == info) { + //SkDebugf("\n"); + break; + } + if (SkType_MemberProperty == info->fType) { + if (getProperty(propIndex, &value)) { + blankCopy->getProperty(propIndex, &blankValue); + //last two are dummies + dumpValues(info, value.fType, value.fOperand, blankValue.fOperand, value.fOperand, blankValue.fOperand); + } + + propIndex++; + continue; + } + if (SkDisplayType::IsDisplayable(maker, info->fType)) { + continue; + } + + if (info->fType == SkType_MemberFunction) + continue; + + + if (info->fType == SkType_Array) { + SkTDOperandArray* array = (SkTDOperandArray*) info->memberData(this); + int arrayCount; + if (array == nil || (arrayCount = array->count()) == 0) + continue; + SkDisplayTypes elementType; + if (type == SkType_Array) { + SkDisplayArray* dispArray = (SkDisplayArray*) this; + elementType = dispArray->values.getType(); + } else + elementType = info->arrayType(); + bool firstElem = true; + SkDebugf("%s=\"[", info->fName); + for (SkOperand* op = array->begin(); op < array->end(); op++) { + if (!firstElem) SkDebugf(","); + switch (elementType) { + case SkType_Displayable: + SkDebugf("%s", op->fDisplayable->id); + break; + case SkType_Int: + SkDebugf("%d", op->fS32); + break; + case SkType_Float: +#ifdef SK_CAN_USE_FLOAT + SkDebugf("%g", SkScalarToFloat(op->fScalar)); +#else + SkDebugf("%x", op->fScalar); +#endif + break; + case SkType_String: + case SkType_DynamicString: + SkDebugf("%s", op->fString->c_str()); + break; + default: + break; + } + firstElem = false; + } + SkDebugf("]\" "); + continue; + } + + if (info->fType == SkType_String || info->fType == SkType_DynamicString) { + SkString* string; + info->getString(this, &string); + if (string->isEmpty() == false) + SkDebugf("%s=\"%s\"\t", info->fName, string->c_str()); + continue; + } + + + blankInfo = blankCopy->getMember(index); + int i = info->fCount; + info->getValue(this, values, i); + blankInfo->getValue(blankCopy, blankValues, i); + dumpValues(info, info->fType, values[0], blankValues[0], values[1], blankValues[1]); + } while (true); + delete blankCopy; +} + +void SkDisplayable::dumpBase(SkAnimateMaker* maker) { + SkDisplayTypes type = getType(); + const char* elementName = "(unknown)"; + if (type != SkType_Unknown && type != SkType_Screenplay) + elementName = SkDisplayType::GetName(maker, type); + SkDebugf("%*s", SkDisplayList::fIndent, ""); + if (SkDisplayList::fDumpIndex != 0 && SkDisplayList::fIndent == 0) + SkDebugf("%d: ", SkDisplayList::fDumpIndex); + SkDebugf("<%s ", elementName); + if (strcmp(id,"") != 0) + SkDebugf("id=\"%s\" ", id); +} + +void SkDisplayable::dumpChildren(SkAnimateMaker* maker, bool closedAngle) { + + int index = -1; + const SkMemberInfo* info; + index = -1; + SkDisplayList::fIndent += 4; + do { + info = this->getMember(++index); + if (nil == info) { + break; + } + if (SkDisplayType::IsDisplayable(maker, info->fType)) { + SkDisplayable** displayable = (SkDisplayable**) info->memberData(this); + if (*displayable == nil || *displayable == (SkDisplayable*) -1) + continue; + if (closedAngle == false) { + SkDebugf(">\n"); + closedAngle = true; + } + (*displayable)->dump(maker); + } + } while (true); + SkDisplayList::fIndent -= 4; + if (closedAngle) + dumpEnd(maker); + else + SkDebugf("/>\n"); +} + +void SkDisplayable::dumpEnd(SkAnimateMaker* maker) { + SkDisplayTypes type = getType(); + const char* elementName = "(unknown)"; + if (type != SkType_Unknown && type != SkType_Screenplay) + elementName = SkDisplayType::GetName(maker, type); + SkDebugf("%*s", SkDisplayList::fIndent, ""); + SkDebugf("\n", elementName); +} + +void SkDisplayable::dumpEvents() { +} + +void SkDisplayable::dumpValues(const SkMemberInfo* info, SkDisplayTypes type, SkOperand op, SkOperand blankOp, + SkOperand op2, SkOperand blankOp2) { + switch (type) { + case SkType_BitmapEncoding: + switch (op.fS32) { + case 0 : SkDebugf("type=\"jpeg\" "); + break; + case 1 : SkDebugf("type=\"png\" "); + break; + default: SkDebugf("type=\"UNDEFINED\" "); + } + break; + //should make this a separate case in dump attrs, rather than make dump values have a larger signature + case SkType_Point: + if (op.fScalar != blankOp.fScalar || op2.fScalar != blankOp.fScalar) { +#ifdef SK_CAN_USE_FLOAT + SkDebugf("%s=\"[%g,%g]\" ", info->fName, SkScalarToFloat(op.fScalar), SkScalarToFloat(op2.fScalar)); +#else + SkDebugf("%s=\"[%x,%x]\" ", info->fName, op.fScalar, op2.fScalar); +#endif + } + break; + case SkType_FromPathMode: + switch (op.fS32) { + case 0: + //don't want to print anything for 0, just adding it to remove it from default: + break; + case 1: + SkDebugf("%s=\"%s\" ", info->fName, "angle"); + break; + case 2: + SkDebugf("%s=\"%s\" ", info->fName, "position"); + break; + default: + SkDebugf("%s=\"INVALID\" ", info->fName); + } + break; + case SkType_MaskFilterBlurStyle: + switch (op.fS32) { + case 0: + break; + case 1: + SkDebugf("%s=\"%s\" ", info->fName, "solid"); + break; + case 2: + SkDebugf("%s=\"%s\" ", info->fName, "outer"); + break; + case 3: + SkDebugf("%s=\"%s\" ", info->fName, "inner"); + break; + default: + SkDebugf("%s=\"INVALID\" ", info->fName); + } + break; + case SkType_FilterType: + if (op.fS32 == 1) + SkDebugf("%s=\"%s\" ", info->fName, "bilinear"); + break; + case SkType_PathDirection: + SkDebugf("%s=\"%s\" ", info->fName, op.fS32 == 0 ? "cw" : "ccw"); + break; + case SkType_FillType: + SkDebugf("%s=\"%s\" ", info->fName, op.fS32 == 0 ? "winding" : "evenOdd"); + break; + case SkType_TileMode: + //correct to look at the S32? + if (op.fS32 != blankOp.fS32) + SkDebugf("%s=\"%s\" ", info->fName, op.fS32 == 0 ? "clamp" : op.fS32 == 1 ? "repeat" : "mirror"); + break; + case SkType_Boolean: + if (op.fS32 != blankOp.fS32) + SkDebugf("%s=\"%s\" ", info->fName, op.fS32 == 0 ? "false" : "true"); + break; + case SkType_Int: + if (op.fS32 != blankOp.fS32) + SkDebugf(" %s=\"%d\" ", info->fName, op.fS32); + break; + case SkType_Float: + if (op.fScalar != blankOp.fScalar) { //or /65536? +#ifdef SK_CAN_USE_FLOAT + SkDebugf("%s=\"%g\" ", info->fName, SkScalarToFloat(op.fScalar)); +#else + SkDebugf("%s=\"%x\" ", info->fName, op.fScalar); +#endif + } + break; + case SkType_String: + case SkType_DynamicString: + if (op.fString->size() > 0) + SkDebugf("%s=\"%s\" ", info->fName, op.fString->c_str()); + break; + case SkType_MSec: + if (op.fS32 != blankOp.fS32) { +#ifdef SK_CAN_USE_FLOAT + SkDebugf(" %s=\"%g\" ", info->fName, SkScalarToFloat(SkScalarDiv(op.fS32, 1000))); +#else + SkDebugf(" %s=\"%x\" ", info->fName, SkScalarDiv(op.fS32, 1000)); +#endif + } + default: + SkDebugf(""); + } +} + +#endif + +bool SkDisplayable::enable( SkAnimateMaker& ) { + return false; +} + +void SkDisplayable::enableBounder() { +} + +void SkDisplayable::executeFunction(SkDisplayable* , int index, + SkTDArray& , SkDisplayTypes, SkScriptValue* ) { + SkASSERT(0); +} + +void SkDisplayable::executeFunction(SkDisplayable* target, + const SkMemberInfo* info, SkTypedArray* values, SkScriptValue* value) { + SkTDArray typedValues; + for (SkOperand* op = values->begin(); op < values->end(); op++) { + SkScriptValue temp; + temp.fType = values->getType(); + temp.fOperand = *op; + *typedValues.append() = temp; + } + executeFunction(target, info->functionIndex(), typedValues, info->getType(), value); +} + +void SkDisplayable::executeFunction2(SkDisplayable* , int index, + SkOpArray* params, SkDisplayTypes, SkOperand2* ) { + SkASSERT(0); +} + +void SkDisplayable::getBounds(SkRect* rect) { + SkASSERT(rect); + rect->fLeft = rect->fTop = SK_ScalarMax; + rect->fRight= rect->fBottom = -SK_ScalarMax; +} + +const SkFunctionParamType* SkDisplayable::getFunctionsParameters() { + return nil; +} + +const SkMemberInfo* SkDisplayable::getMember(int index) { + return nil; +} + +const SkMemberInfo* SkDisplayable::getMember(const char name[]) { + return nil; +} + +const SkFunctionParamType* SkDisplayable::getParameters(const SkMemberInfo* info, + int* paramCount) { + const SkFunctionParamType* params = getFunctionsParameters(); + SkASSERT(params != nil); + int funcIndex = info->functionIndex(); + // !!! eventually break traversing params into an external function (maybe this whole function) + int index = funcIndex; + int offset = 0; + while (--index >= 0) { + while (params[offset] != 0) + offset++; + offset++; + } + int count = 0; + while (params[offset] != 0) { + count++; + offset++; + } + *paramCount = count; + return ¶ms[offset - count]; +} + +SkDisplayable* SkDisplayable::getParent() const { + return nil; +} + +bool SkDisplayable::getProperty(int index, SkScriptValue* ) const { +// SkASSERT(0); + return false; +} + +bool SkDisplayable::getProperty2(int index, SkOperand2* value) const { + SkASSERT(0); + return false; +} + +SkDisplayTypes SkDisplayable::getType() const { + return SkType_Unknown; +} + +bool SkDisplayable::hasEnable() const { + return false; +} + +bool SkDisplayable::isDrawable() const { + return false; +} + +void SkDisplayable::onEndElement(SkAnimateMaker& ) {} + +const SkMemberInfo* SkDisplayable::preferredChild(SkDisplayTypes type) { + return nil; +} + +bool SkDisplayable::resolveIDs(SkAnimateMaker& maker, SkDisplayable* original, SkApply* apply) { + return false; +} + +//SkDisplayable* SkDisplayable::resolveTarget(SkAnimateMaker& ) { +// return this; +//} + +void SkDisplayable::setChildHasID() { +} + +bool SkDisplayable::setParent(SkDisplayable* ) { + return false; +} + +bool SkDisplayable::setProperty(int index, SkScriptValue& ) { + //SkASSERT(0); + return false; +} + +void SkDisplayable::setReference(const SkMemberInfo* info, SkDisplayable* displayable) { + if (info->fType == SkType_MemberProperty) { + SkScriptValue scriptValue; + scriptValue.fOperand.fDisplayable = displayable; + scriptValue.fType = displayable->getType(); + setProperty(info->propertyIndex(), scriptValue); + } else if (info->fType == SkType_Array) { + SkASSERT(displayable->getType() == SkType_Array); + SkDisplayArray* dispArray = (SkDisplayArray*) displayable; + SkTDScalarArray* array = (SkTDScalarArray* ) info->memberData(this); + array->setCount(dispArray->values.count()); + memcpy(array->begin(), dispArray->values.begin(), dispArray->values.count() * sizeof(int)); + // + + // !!! need a way for interpreter engine to own array + // !!! probably need to replace all scriptable arrays with single bigger array + // that has operand and type on every element -- or + // when array is dirtied, need to get parent to reparse to local array + } else { + void* storage = info->memberData(this); + memcpy(storage, &displayable, sizeof(SkDisplayable*)); + } +// !!! unclear why displayable is dirtied here +// if this is called, this breaks fromPath.xml +// displayable->dirty(); +} + +#ifdef SK_DEBUG +void SkDisplayable::validate() { +} +#endif + + diff --git a/libs/graphics/animator/SkDisplayable.h b/libs/graphics/animator/SkDisplayable.h new file mode 100644 index 000000000..aea64b516 --- /dev/null +++ b/libs/graphics/animator/SkDisplayable.h @@ -0,0 +1,103 @@ +#ifndef SkDisplayable_DEFINED +#define SkDisplayable_DEFINED + +#include "SkOperand.h" +#ifdef SK_DEBUG +#include "SkString.h" +#endif +#include "SkIntArray.h" +#include "SkRect.h" +#include "SkTDArray.h" + +class SkAnimateMaker; +class SkApply; +class SkEvents; +struct SkMemberInfo; +struct SkScriptValue; +class SkOpArray; // compiled scripting experiment +union SkOperand2; // compiled scripting experiment + +class SkDisplayable { +public: +#ifdef SK_DEBUG + SkDisplayable(); +#endif + virtual ~SkDisplayable(); + virtual bool add(SkAnimateMaker& , SkDisplayable* child); + virtual bool canContainDependents() const; + virtual bool childrenNeedDisposing() const; + virtual void clearBounder(); + virtual bool contains(SkDisplayable* ); + virtual SkDisplayable* contains(const SkString& ); + virtual SkDisplayable* deepCopy(SkAnimateMaker* ); + virtual void dirty(); +#ifdef SK_DUMP_ENABLED + virtual void dump(SkAnimateMaker* ); + void dumpAttrs(SkAnimateMaker* ); + void dumpBase(SkAnimateMaker* ); + void dumpChildren(SkAnimateMaker* maker, bool closedAngle = false ); + void dumpEnd(SkAnimateMaker* ); + virtual void dumpEvents(); +#endif + virtual bool enable( SkAnimateMaker& ); + virtual void enableBounder(); + virtual void executeFunction(SkDisplayable* , int functionIndex, + SkTDArray& , SkDisplayTypes , SkScriptValue* ); + void executeFunction(SkDisplayable* , const SkMemberInfo* , + SkTypedArray* , SkScriptValue* ); + virtual void executeFunction2(SkDisplayable* , int functionIndex, + SkOpArray* params , SkDisplayTypes , SkOperand2* ); // compiled scripting experiment + virtual void getBounds(SkRect* ); + virtual const SkFunctionParamType* getFunctionsParameters(); + virtual const SkMemberInfo* getMember(int index); + virtual const SkMemberInfo* getMember(const char name[]); + const SkFunctionParamType* getParameters(const SkMemberInfo* info, + int* paramCount); + virtual SkDisplayable* getParent() const; + virtual bool getProperty(int index, SkScriptValue* value) const; + virtual bool getProperty2(int index, SkOperand2* value) const; // compiled scripting experiment + virtual SkDisplayTypes getType() const; + virtual bool hasEnable() const; + bool isAnimate() const { + SkDisplayTypes type = getType(); + return type == SkType_Animate || type == SkType_Set; } + bool isApply() const { return getType() == SkType_Apply; } + bool isColor() const { return getType() == SkType_Color; } + virtual bool isDrawable() const; + bool isGroup() const { return getType() == SkType_Group || + getType() == SkType_Save || getType() == SkType_DrawTo || + getType() == SkType_SaveLayer; } + bool isMatrix() const { return getType() == SkType_Matrix; } + virtual bool isPaint() const { return getType() == SkType_Paint; } + virtual bool isPath() const { return false; } + bool isPost() const { return getType() == SkType_Post; } + virtual void onEndElement(SkAnimateMaker& ); + virtual const SkMemberInfo* preferredChild(SkDisplayTypes type); + virtual bool resolveIDs(SkAnimateMaker& maker, SkDisplayable* original, SkApply* ); + virtual void setChildHasID(); + virtual bool setParent(SkDisplayable* ); + virtual bool setProperty(int index, SkScriptValue& ); + void setReference(const SkMemberInfo* info, SkDisplayable* ref); +#ifdef SK_DEBUG + bool isData() const { return getType() == SkType_Data; }; + bool isEvent() const { return getType() == SkType_Event; } + virtual bool isMatrixPart() const { return false; } + bool isPatch() const { return getType() == SkType_3D_Patch; } + virtual bool isPaintPart() const { return false; } + virtual bool isPathPart() const { return false; } + virtual void validate(); + SkString _id; + const char* id; +// static int fAllocationCount; + static SkTDDisplayableArray fAllocations; +#else + void validate() {} +#endif +#ifdef SK_DUMP_ENABLED +private: + void dumpValues(const SkMemberInfo* info, SkDisplayTypes type, SkOperand op, SkOperand blankOp, + SkOperand op2, SkOperand blankOp2); +#endif +}; + +#endif // SkDisplayable_DEFINED diff --git a/libs/graphics/animator/SkDraw3D.cpp b/libs/graphics/animator/SkDraw3D.cpp new file mode 100644 index 000000000..8a6944521 --- /dev/null +++ b/libs/graphics/animator/SkDraw3D.cpp @@ -0,0 +1,100 @@ +#include "SkDraw3D.h" +#include "SkAnimateMaker.h" +#include "SkCanvas.h" +#include "SkTypedArray.h" + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo Sk3D_Point::fInfo[] = { + SK_MEMBER_ALIAS(x, fPoint.fX, Float), + SK_MEMBER_ALIAS(y, fPoint.fY, Float), + SK_MEMBER_ALIAS(z, fPoint.fZ, Float) +}; + +#endif + +DEFINE_NO_VIRTUALS_GET_MEMBER(Sk3D_Point); + +Sk3D_Point::Sk3D_Point() { + fPoint.set(0, 0, 0); +} + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo Sk3D_Camera::fInfo[] = { + SK_MEMBER_ALIAS(axis, fCamera.fAxis, 3D_Point), + SK_MEMBER(hackHeight, Float), + SK_MEMBER(hackWidth, Float), + SK_MEMBER_ALIAS(location, fCamera.fLocation, 3D_Point), + SK_MEMBER_ALIAS(observer, fCamera.fObserver, 3D_Point), + SK_MEMBER(patch, 3D_Patch), + SK_MEMBER_ALIAS(zenith, fCamera.fZenith, 3D_Point), +}; + +#endif + +DEFINE_GET_MEMBER(Sk3D_Camera); + +Sk3D_Camera::Sk3D_Camera() : hackWidth(0), hackHeight(0), patch(nil) { +} + +Sk3D_Camera::~Sk3D_Camera() { +} + +bool Sk3D_Camera::draw(SkAnimateMaker& maker) { + fCamera.update(); + SkMatrix matrix; + fCamera.computeMatrix(patch->fPatch, &matrix); + matrix.preTranslate(hackWidth / 2, -hackHeight / 2); + matrix.postTranslate(hackWidth / 2, hackHeight / 2); + maker.fCanvas->concat(matrix); + return false; +} + + +enum Sk3D_Patch_Functions { + SK_FUNCTION(rotateDegrees) +}; + +const SkFunctionParamType Sk3D_Patch::fFunctionParameters[] = { + (SkFunctionParamType) SkType_Float, + (SkFunctionParamType) SkType_Float, + (SkFunctionParamType) SkType_Float, + (SkFunctionParamType) 0 // terminator for parameter list (there may be multiple parameter lists) +}; + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo Sk3D_Patch::fInfo[] = { + SK_MEMBER_ALIAS(origin, fPatch.fOrigin, 3D_Point), + SK_MEMBER_FUNCTION(rotateDegrees, Float), + SK_MEMBER_ALIAS(u, fPatch.fU, 3D_Point), + SK_MEMBER_ALIAS(v, fPatch.fV, 3D_Point) +}; + +#endif + +DEFINE_GET_MEMBER(Sk3D_Patch); + +void Sk3D_Patch::executeFunction(SkDisplayable* target, int index, + SkTDArray& parameters, SkDisplayTypes type, + SkScriptValue* ) { + SkASSERT(target == this); + switch (index) { + case SK_FUNCTION(rotateDegrees): + SkASSERT(parameters.count() == 3); + SkASSERT(type == SkType_Float); + fPatch.rotateDegrees(parameters[0].fOperand.fScalar, + parameters[1].fOperand.fScalar, parameters[2].fOperand.fScalar); + break; + default: + SkASSERT(0); + } +} + +const SkFunctionParamType* Sk3D_Patch::getFunctionsParameters() { + return fFunctionParameters; +} + + + diff --git a/libs/graphics/animator/SkDraw3D.h b/libs/graphics/animator/SkDraw3D.h new file mode 100644 index 000000000..55f76645e --- /dev/null +++ b/libs/graphics/animator/SkDraw3D.h @@ -0,0 +1,42 @@ +#ifndef SkDraw3D_DEFINED +#define SkDraw3D_DEFINED + +#include "SkCamera.h" +#include "SkDrawable.h" +#include "SkMemberInfo.h" + +class Sk3D_Patch; + +struct Sk3D_Point { + DECLARE_NO_VIRTUALS_MEMBER_INFO(3D_Point); + Sk3D_Point(); +private: + SkPoint3D fPoint; +}; + +class Sk3D_Camera : public SkDrawable { + DECLARE_MEMBER_INFO(3D_Camera); + Sk3D_Camera(); + virtual ~Sk3D_Camera(); + virtual bool draw(SkAnimateMaker& ); +private: + SkScalar hackWidth; + SkScalar hackHeight; + SkCamera3D fCamera; + Sk3D_Patch* patch; +}; + +class Sk3D_Patch : public SkDisplayable { + DECLARE_MEMBER_INFO(3D_Patch); +private: + virtual void executeFunction(SkDisplayable* , int index, + SkTDArray& parameters, SkDisplayTypes type, + SkScriptValue* ); + virtual const SkFunctionParamType* getFunctionsParameters(); + SkPatch3D fPatch; + static const SkFunctionParamType fFunctionParameters[]; + friend class Sk3D_Camera; +}; + +#endif // SkDraw3D_DEFINED + diff --git a/libs/graphics/animator/SkDrawBitmap.cpp b/libs/graphics/animator/SkDrawBitmap.cpp new file mode 100644 index 000000000..3ad4e007d --- /dev/null +++ b/libs/graphics/animator/SkDrawBitmap.cpp @@ -0,0 +1,186 @@ +#include "SkDrawBitmap.h" +#include "SkAnimateMaker.h" +#include "SkCanvas.h" +#include "SkImageDecoder.h" +#include "SkPaint.h" +#include "SkStream.h" + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkBaseBitmap::fInfo[] = { + SK_MEMBER(x, Float), + SK_MEMBER(y, Float) +}; + +#endif + +DEFINE_GET_MEMBER(SkBaseBitmap); + +SkBaseBitmap::SkBaseBitmap() : x(0), y(0) { +} + +SkBaseBitmap::~SkBaseBitmap() { +} + +bool SkBaseBitmap::draw(SkAnimateMaker& maker) { + SkBoundableAuto boundable(this, maker); + maker.fCanvas->drawBitmap(fBitmap, x, y, *maker.fPaint); + return false; +} + +enum SkDrawBitmap_Properties { + SK_PROPERTY(erase) +}; + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDrawBitmap::fInfo[] = { + SK_MEMBER_INHERITED, + SK_MEMBER_PROPERTY(erase, ARGB), + SK_MEMBER(format, BitmapFormat), + SK_MEMBER(height, Int), + SK_MEMBER(rowBytes, Int), + SK_MEMBER(width, Int), +}; + +#endif + +DEFINE_GET_MEMBER(SkDrawBitmap); + +SkDrawBitmap::SkDrawBitmap() : format((SkBitmap::Config) -1), height(-1), + rowBytes(0), width(-1), fColor(0), fColorSet(false) { +} + +SkDrawBitmap::~SkDrawBitmap() { +} + +#ifdef SK_DUMP_ENABLED +void SkDrawBitmap::dump(SkAnimateMaker* maker) { + dumpBase(maker); + dumpAttrs(maker); + if (fColorSet) + SkDebugf("erase=\"argb(%d,%d,%d,%d)\" ", SkColorGetA(fColor)/255, SkColorGetR(fColor), + SkColorGetG(fColor), SkColorGetB(fColor)); + if (rowBytes > 0) + SkDebugf("rowBytes=\"%d\" ", rowBytes); + const char* formatName; + switch (format) { + case 0: formatName = "none"; break; + case 1: formatName = "A1"; break; + case 2: formatName = "A8"; break; + case 3: formatName = "Index8"; break; + case 4: formatName = "RGB16"; break; + case 5: formatName = "RGB32"; break; + } + SkDebugf("format=\"%s\" />\n", formatName); +} +#endif + +void SkDrawBitmap::onEndElement(SkAnimateMaker& maker) { + SkASSERT(format != (SkBitmap::Config) -1); + SkASSERT(width != -1); + SkASSERT(height != -1); + SkASSERT(rowBytes >= 0); + fBitmap.setConfig((SkBitmap::Config) format, width, height, rowBytes); + fBitmap.allocPixels(); + if (fColorSet) + fBitmap.eraseColor(fColor); +} + +bool SkDrawBitmap::setProperty(int index, SkScriptValue& value) +{ + switch (index) { + case SK_PROPERTY(erase): + SkASSERT(value.fType == SkType_ARGB); + fColor = value.fOperand.fS32; + fColorSet = true; + break; + default: + SkASSERT(0); + return false; + } + return true; +} + + +enum SkImage_Properties { + SK_PROPERTY(height), + SK_PROPERTY(width) +}; + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkImage::fInfo[] = { + SK_MEMBER_INHERITED, + SK_MEMBER(base64, Base64), + SK_MEMBER_PROPERTY(height, Int), + SK_MEMBER(src, String), + SK_MEMBER_PROPERTY(width, Int) +}; + +#endif + +DEFINE_GET_MEMBER(SkImage); + +SkImage::SkImage() : fDirty(true), fUriBase(nil) { + base64.fData = nil; + base64.fLength = 0; +} + +SkImage::~SkImage() { + delete[] base64.fData; +} + +SkDisplayable* SkImage::deepCopy(SkAnimateMaker* maker) { + SkDisplayable* copy = INHERITED::deepCopy(maker); + ((SkImage*) copy)->fUriBase = ((SkImage*) this)->fUriBase; + return copy; +} + +void SkImage::dirty() { + fDirty = true; +} + +bool SkImage::draw(SkAnimateMaker& maker) { + if (fDirty) + resolve(); + return INHERITED::draw(maker); +} + +bool SkImage::getProperty(int index, SkScriptValue* value) const { + if (fDirty) + resolve(); + switch (index) { + case SK_PROPERTY(height): + value->fOperand.fS32 = fBitmap.height(); + break; + case SK_PROPERTY(width): + value->fOperand.fS32 = fBitmap.width(); + break; + default: + SkASSERT(0); + return false; + } + value->fType = SkType_Int; + return true; +} + +void SkImage::onEndElement(SkAnimateMaker& maker) { + fUriBase = maker.fPrefix.c_str(); +} + +void SkImage::resolve() { + fDirty = false; + if (base64.fData) { + fBitmap.reset(); + SkImageDecoder::DecodeMemory(base64.fData, base64.fLength, &fBitmap); + } else if (src.size()) { + if (fLast.equals(src)) + return; + fLast.set(src); + fBitmap.reset(); + SkStream* stream = SkStream::GetURIStream(fUriBase, src.c_str()); + SkAutoTDelete autoDel(stream); + SkImageDecoder::DecodeStream(stream, &fBitmap); + } +} diff --git a/libs/graphics/animator/SkDrawBitmap.h b/libs/graphics/animator/SkDrawBitmap.h new file mode 100644 index 000000000..f5ef3303c --- /dev/null +++ b/libs/graphics/animator/SkDrawBitmap.h @@ -0,0 +1,65 @@ +#ifndef SkDrawBitmap_DEFINED +#define SkDrawBitmap_DEFINED + +#include "SkBoundable.h" +#include "SkBase64.h" +#include "SkBitmap.h" +// #include "SkImageDecoder.h" +#include "SkMemberInfo.h" + +class SkBaseBitmap : public SkBoundable { + DECLARE_MEMBER_INFO(BaseBitmap); + SkBaseBitmap(); + virtual ~SkBaseBitmap(); + virtual bool draw(SkAnimateMaker& ); +protected: + SkBitmap fBitmap; + SkScalar x; + SkScalar y; +private: + friend class SkDrawTo; + friend class SkDrawBitmapShader; + typedef SkBoundable INHERITED; +}; + +class SkDrawBitmap : public SkBaseBitmap { + DECLARE_DRAW_MEMBER_INFO(Bitmap); + SkDrawBitmap(); + virtual ~SkDrawBitmap(); +#ifdef SK_DUMP_ENABLED + virtual void dump(SkAnimateMaker* ); +#endif + virtual void onEndElement(SkAnimateMaker& ); + virtual bool setProperty(int index, SkScriptValue& value); +protected: + int /*SkBitmap::Config*/ format; + S32 height; + S32 rowBytes; + S32 width; + SkColor fColor; + SkBool fColorSet; + typedef SkBaseBitmap INHERITED; +}; + +class SkImage : public SkBaseBitmap { + DECLARE_MEMBER_INFO(Image); + SkImage(); + virtual ~SkImage(); + virtual SkDisplayable* deepCopy(SkAnimateMaker* ); + virtual void dirty(); + virtual bool draw(SkAnimateMaker& ); + virtual bool getProperty(int index, SkScriptValue* value) const; + virtual void onEndElement(SkAnimateMaker& maker); +private: + void resolve() const { (const_cast(this))->resolve(); } + void resolve(); +protected: + SkBase64 base64; + SkString src; + SkString fLast; // cache of src so that stream isn't unnecessarily decoded + SkBool fDirty; + const char* fUriBase; + typedef SkBaseBitmap INHERITED; +}; + +#endif // SkDrawBitmap_DEFINED diff --git a/libs/graphics/animator/SkDrawBlur.cpp b/libs/graphics/animator/SkDrawBlur.cpp new file mode 100644 index 000000000..170a770ba --- /dev/null +++ b/libs/graphics/animator/SkDrawBlur.cpp @@ -0,0 +1,23 @@ +#include "SkDrawBlur.h" + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDrawBlur::fInfo[] = { + SK_MEMBER(blurStyle, MaskFilterBlurStyle), + SK_MEMBER(radius, Float) +}; + +#endif + +DEFINE_GET_MEMBER(SkDrawBlur); + +SkDrawBlur::SkDrawBlur() : radius(-1), + blurStyle(SkBlurMaskFilter::kNormal_BlurStyle) { +} + +SkMaskFilter* SkDrawBlur::getMaskFilter() { + if (radius < 0) + return nil; + return SkBlurMaskFilter::Create(radius, (SkBlurMaskFilter::BlurStyle) blurStyle); +} + diff --git a/libs/graphics/animator/SkDrawBlur.h b/libs/graphics/animator/SkDrawBlur.h new file mode 100644 index 000000000..4bfb2689d --- /dev/null +++ b/libs/graphics/animator/SkDrawBlur.h @@ -0,0 +1,17 @@ +#ifndef SkDrawBlur_DEFINED +#define SkDrawBlur_DEFINED + +#include "SkPaintParts.h" +#include "SkBlurMaskFilter.h" + +class SkDrawBlur : public SkDrawMaskFilter { + DECLARE_DRAW_MEMBER_INFO(Blur); + SkDrawBlur(); + virtual SkMaskFilter* getMaskFilter(); +protected: + SkScalar radius; + int /*SkBlurMaskFilter::BlurStyle*/ blurStyle; +}; + +#endif // SkDrawBlur_DEFINED + diff --git a/libs/graphics/animator/SkDrawClip.cpp b/libs/graphics/animator/SkDrawClip.cpp new file mode 100644 index 000000000..471750101 --- /dev/null +++ b/libs/graphics/animator/SkDrawClip.cpp @@ -0,0 +1,31 @@ +#include "SkDrawClip.h" +#include "SkAnimateMaker.h" +#include "SkCanvas.h" +#include "SkDrawRectangle.h" +#include "SkDrawPath.h" + + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDrawClip::fInfo[] = { + SK_MEMBER(path, Path), + SK_MEMBER(rect, Rect) +}; + +#endif + +DEFINE_GET_MEMBER(SkDrawClip); + +SkDrawClip::SkDrawClip() : rect(nil), path(nil) { +} + +bool SkDrawClip::draw(SkAnimateMaker& maker ) { + if (rect != nil) + maker.fCanvas->clipRect(rect->fRect); + else { + SkASSERT(path != nil); + maker.fCanvas->clipPath(path->fPath); + } + return false; +} + diff --git a/libs/graphics/animator/SkDrawClip.h b/libs/graphics/animator/SkDrawClip.h new file mode 100644 index 000000000..6c896660a --- /dev/null +++ b/libs/graphics/animator/SkDrawClip.h @@ -0,0 +1,20 @@ +#ifndef SkDrawClip_DEFINED +#define SkDrawClip_DEFINED + +#include "SkDrawable.h" +#include "SkMemberInfo.h" +#include "SkRegion.h" + +class SkDrawPath; +class SkDrawRect; + +class SkDrawClip : public SkDrawable { + DECLARE_DRAW_MEMBER_INFO(Clip); + SkDrawClip(); + virtual bool draw(SkAnimateMaker& ); +private: + SkDrawRect* rect; + SkDrawPath* path; +}; + +#endif // SkDrawClip_DEFINED diff --git a/libs/graphics/animator/SkDrawColor.cpp b/libs/graphics/animator/SkDrawColor.cpp new file mode 100644 index 000000000..a21bde4e7 --- /dev/null +++ b/libs/graphics/animator/SkDrawColor.cpp @@ -0,0 +1,261 @@ +#include "SkDrawColor.h" +#ifdef SK_DEBUG +#include "SkDisplayList.h" +#endif +#include "SkDrawPaint.h" +#include "SkParse.h" +#include "SkScript.h" + +enum HSV_Choice { + kGetHue, + kGetSaturation, + kGetValue +}; + +static SkScalar RGB_to_HSV(SkColor color, HSV_Choice choice) { + SkScalar red = SkIntToScalar(SkColorGetR(color)); + SkScalar green = SkIntToScalar(SkColorGetG(color)); + SkScalar blue = SkIntToScalar(SkColorGetB(color)); + SkScalar min = SkMinScalar(SkMinScalar(red, green), blue); + SkScalar value = SkMaxScalar(SkMaxScalar(red, green), blue); + if (choice == kGetValue) + return value/255; + SkScalar delta = value - min; + SkScalar saturation = value == 0 ? 0 : SkScalarDiv(delta, value); + if (choice == kGetSaturation) + return saturation; + SkScalar hue; + if (saturation == 0) + hue = 0; + else { + SkScalar part60 = SkScalarDiv(60 * SK_Scalar1, delta); + if (red == value) { + hue = SkScalarMul(green - blue, part60); + if (hue < 0) + hue += 360 * SK_Scalar1; + } + else if (green == value) + hue = 120 * SK_Scalar1 + SkScalarMul(blue - red, part60); + else // blue == value + hue = 240 * SK_Scalar1 + SkScalarMul(red - green, part60); + } + SkASSERT(choice == kGetHue); + return hue; +} + +#if defined _WIN32 && _MSC_VER >= 1300 // disable 'red', etc. may be used without having been initialized +#pragma warning ( push ) +#pragma warning ( disable : 4701 ) +#endif + +static SkColor HSV_to_RGB(SkColor color, HSV_Choice choice, SkScalar hsv) { + SkScalar hue = choice == kGetHue ? hsv : RGB_to_HSV(color, kGetHue); + SkScalar saturation = choice == kGetSaturation ? hsv : RGB_to_HSV(color, kGetSaturation); + SkScalar value = choice == kGetValue ? hsv : RGB_to_HSV(color, kGetValue); + value *= 255; + SkScalar red SK_INIT_TO_AVOID_WARNING; + SkScalar green SK_INIT_TO_AVOID_WARNING; + SkScalar blue SK_INIT_TO_AVOID_WARNING; + if (saturation == 0) // color is on black-and-white center line + red = green = blue = value; + else { + //SkScalar fraction = SkScalarMod(hue, 60 * SK_Scalar1); + int sextant = SkScalarFloor(hue / 60); + SkScalar fraction = hue / 60 - SkIntToScalar(sextant); + SkScalar p = SkScalarMul(value , SK_Scalar1 - saturation); + SkScalar q = SkScalarMul(value, SK_Scalar1 - SkScalarMul(saturation, fraction)); + SkScalar t = SkScalarMul(value, SK_Scalar1 - + SkScalarMul(saturation, SK_Scalar1 - fraction)); + switch (sextant % 6) { + case 0: red = value; green = t; blue = p; break; + case 1: red = q; green = value; blue = p; break; + case 2: red = p; green = value; blue = t; break; + case 3: red = p; green = q; blue = value; break; + case 4: red = t; green = p; blue = value; break; + case 5: red = value; green = p; blue = q; break; + } + } + //used to say SkToU8((U8CPU) red) etc + return SkColorSetARGB(SkColorGetA(color), SkScalarRound(red), + SkScalarRound(green), SkScalarRound(blue)); +} + +#if defined _WIN32 && _MSC_VER >= 1300 +#pragma warning ( pop ) +#endif + +enum SkDrawColor_Properties { + SK_PROPERTY(alpha), + SK_PROPERTY(blue), + SK_PROPERTY(green), + SK_PROPERTY(hue), + SK_PROPERTY(red), + SK_PROPERTY(saturation), + SK_PROPERTY(value) +}; + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDrawColor::fInfo[] = { + SK_MEMBER_PROPERTY(alpha, Float), + SK_MEMBER_PROPERTY(blue, Float), + SK_MEMBER(color, ARGB), + SK_MEMBER_PROPERTY(green, Float), + SK_MEMBER_PROPERTY(hue, Float), + SK_MEMBER_PROPERTY(red, Float), + SK_MEMBER_PROPERTY(saturation, Float), + SK_MEMBER_PROPERTY(value, Float), +}; + +#endif + +DEFINE_GET_MEMBER(SkDrawColor); + +SkDrawColor::SkDrawColor() : fDirty(false) { + color = SK_ColorBLACK; + fHue = fSaturation = fValue = SK_ScalarNaN; +} + +bool SkDrawColor::add() { + if (fPaint->color != nil) + return true; // error (probably color in paint as attribute as well) + fPaint->color = this; + fPaint->fOwnsColor = true; + return false; +} + +SkDisplayable* SkDrawColor::deepCopy(SkAnimateMaker* maker) { + SkDrawColor* copy = new SkDrawColor(); + copy->color = color; + copy->fHue = fHue; + copy->fSaturation = fSaturation; + copy->fValue = fValue; + copy->fDirty = fDirty; + return copy; +} + +void SkDrawColor::dirty(){ + fDirty = true; +} + +#ifdef SK_DUMP_ENABLED +void SkDrawColor::dump(SkAnimateMaker* maker) { + dumpBase(maker); + SkDebugf("alpha=\"%d\" red=\"%d\" green=\"%d\" blue=\"%d\" />\n", + SkColorGetA(color)/255, SkColorGetR(color), + SkColorGetG(color), SkColorGetB(color)); +} +#endif + +SkColor SkDrawColor::getColor() { + if (fDirty) { + if (SkScalarIsNaN(fValue) == false) + color = HSV_to_RGB(color, kGetValue, fValue); + if (SkScalarIsNaN(fSaturation) == false) + color = HSV_to_RGB(color, kGetSaturation, fSaturation); + if (SkScalarIsNaN(fHue) == false) + color = HSV_to_RGB(color, kGetHue, fHue); + fDirty = false; + } + return color; +} + +SkDisplayable* SkDrawColor::getParent() const { + return fPaint; +} + +bool SkDrawColor::getProperty(int index, SkScriptValue* value) const { + value->fType = SkType_Float; + SkScalar result; + switch(index) { + case SK_PROPERTY(alpha): + result = SkIntToScalar(SkColorGetA(color)) / 255; + break; + case SK_PROPERTY(blue): + result = SkIntToScalar(SkColorGetB(color)); + break; + case SK_PROPERTY(green): + result = SkIntToScalar(SkColorGetG(color)); + break; + case SK_PROPERTY(hue): + result = RGB_to_HSV(color, kGetHue); + break; + case SK_PROPERTY(red): + result = SkIntToScalar(SkColorGetR(color)); + break; + case SK_PROPERTY(saturation): + result = RGB_to_HSV(color, kGetSaturation); + break; + case SK_PROPERTY(value): + result = RGB_to_HSV(color, kGetValue); + break; + default: + SkASSERT(0); + return false; + } + value->fOperand.fScalar = result; + return true; +} + +void SkDrawColor::onEndElement(SkAnimateMaker& maker){ + fDirty = true; +} + +bool SkDrawColor::setParent(SkDisplayable* parent) { + SkASSERT(parent != nil); + if (parent->getType() == SkType_LinearGradient || parent->getType() == SkType_RadialGradient) + return false; + if (parent->isPaint() == false) + return true; + fPaint = (SkDrawPaint*) parent; + return false; +} + +bool SkDrawColor::setProperty(int index, SkScriptValue& value) { + SkASSERT(value.fType == SkType_Float); + SkScalar scalar = value.fOperand.fScalar; + switch (index) { + case SK_PROPERTY(alpha): + U8 alpha; + #ifdef SK_SCALAR_IS_FLOAT + alpha = scalar == SK_Scalar1 ? 255 : SkToU8((U8CPU) (scalar * 256)); + #else + alpha = SkToU8((scalar - (scalar >= SK_ScalarHalf)) >> 8); + #endif + color = SkColorSetARGB(alpha, SkColorGetR(color), + SkColorGetG(color), SkColorGetB(color)); + break; + case SK_PROPERTY(blue): + scalar = SkScalarClampMax(scalar, 255 * SK_Scalar1); + color = SkColorSetARGB(SkColorGetA(color), SkColorGetR(color), + SkColorGetG(color), SkToU8((U8CPU) scalar)); + break; + case SK_PROPERTY(green): + scalar = SkScalarClampMax(scalar, 255 * SK_Scalar1); + color = SkColorSetARGB(SkColorGetA(color), SkColorGetR(color), + SkToU8((U8CPU) scalar), SkColorGetB(color)); + break; + case SK_PROPERTY(hue): + fHue = scalar;//RGB_to_HSV(color, kGetHue); + fDirty = true; + break; + case SK_PROPERTY(red): + scalar = SkScalarClampMax(scalar, 255 * SK_Scalar1); + color = SkColorSetARGB(SkColorGetA(color), SkToU8((U8CPU) scalar), + SkColorGetG(color), SkColorGetB(color)); + break; + case SK_PROPERTY(saturation): + fSaturation = scalar;//RGB_to_HSV(color, kGetSaturation); + fDirty = true; + break; + case SK_PROPERTY(value): + fValue = scalar;//RGB_to_HSV(color, kGetValue); + fDirty = true; + break; + default: + SkASSERT(0); + return false; + } + return true; +} + diff --git a/libs/graphics/animator/SkDrawColor.h b/libs/graphics/animator/SkDrawColor.h new file mode 100644 index 000000000..ad7c3f8c2 --- /dev/null +++ b/libs/graphics/animator/SkDrawColor.h @@ -0,0 +1,33 @@ +#ifndef SkDrawColor_DEFINED +#define SkDrawColor_DEFINED + +#include "SkPaintParts.h" +#include "SkColor.h" + +class SkDrawColor : public SkPaintPart { + DECLARE_DRAW_MEMBER_INFO(Color); + SkDrawColor(); + virtual bool add(); + virtual void dirty(); +#ifdef SK_DUMP_ENABLED + virtual void dump(SkAnimateMaker* ); +#endif + SkColor getColor(); + virtual SkDisplayable* deepCopy(SkAnimateMaker* ); + virtual SkDisplayable* getParent() const; + virtual bool getProperty(int index, SkScriptValue* value) const; + virtual void onEndElement(SkAnimateMaker& ); + virtual bool setParent(SkDisplayable* parent); + virtual bool setProperty(int index, SkScriptValue&); +protected: + SkColor color; + SkScalar fHue; + SkScalar fSaturation; + SkScalar fValue; + SkBool fDirty; +private: + friend class SkGradient; + typedef SkPaintPart INHERITED; +}; + +#endif // SkDrawColor_DEFINED diff --git a/libs/graphics/animator/SkDrawDash.cpp b/libs/graphics/animator/SkDrawDash.cpp new file mode 100644 index 000000000..78e2d66db --- /dev/null +++ b/libs/graphics/animator/SkDrawDash.cpp @@ -0,0 +1,27 @@ +#include "SkDrawDash.h" +#include "SkDashPathEffect.h" + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDash::fInfo[] = { + SK_MEMBER_ARRAY(intervals, Float), + SK_MEMBER(phase, Float) +}; + +#endif + +DEFINE_GET_MEMBER(SkDash); + +SkDash::SkDash() : phase(0) { +} + +SkDash::~SkDash() { +} + +SkPathEffect* SkDash::getPathEffect() { + int count = intervals.count(); + if (count == 0) + return nil; + return new SkDashPathEffect(intervals.begin(), count, phase); +} + diff --git a/libs/graphics/animator/SkDrawDash.h b/libs/graphics/animator/SkDrawDash.h new file mode 100644 index 000000000..ff89f50c2 --- /dev/null +++ b/libs/graphics/animator/SkDrawDash.h @@ -0,0 +1,18 @@ +#ifndef SkDrawDash_DEFINED +#define SkDrawDash_DEFINED + +#include "SkPaintParts.h" +#include "SkIntArray.h" + +class SkDash : public SkDrawPathEffect { + DECLARE_MEMBER_INFO(Dash); + SkDash(); + virtual ~SkDash(); + virtual SkPathEffect* getPathEffect(); +private: + SkTDScalarArray intervals; + SkScalar phase; +}; + +#endif // SkDrawDash_DEFINED + diff --git a/libs/graphics/animator/SkDrawDiscrete.cpp b/libs/graphics/animator/SkDrawDiscrete.cpp new file mode 100644 index 000000000..9e32772e3 --- /dev/null +++ b/libs/graphics/animator/SkDrawDiscrete.cpp @@ -0,0 +1,26 @@ +#include "SkDrawDiscrete.h" +#include "SkAnimateMaker.h" +#include "SkPaint.h" +#include "SkDiscretePathEffect.h" + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDiscrete::fInfo[] = { + SK_MEMBER(deviation, Float), + SK_MEMBER(segLength, Float) +}; + +#endif + +DEFINE_GET_MEMBER(SkDiscrete); + +SkDiscrete::SkDiscrete() : deviation(0), segLength(0) { +} + +SkPathEffect* SkDiscrete::getPathEffect() { + if (deviation <= 0 || segLength <= 0) + return nil; + else + return new SkDiscretePathEffect(segLength, deviation); +} + diff --git a/libs/graphics/animator/SkDrawDiscrete.h b/libs/graphics/animator/SkDrawDiscrete.h new file mode 100644 index 000000000..61aeac039 --- /dev/null +++ b/libs/graphics/animator/SkDrawDiscrete.h @@ -0,0 +1,15 @@ +#ifndef SkDrawDiscrete_DEFINED +#define SkDrawDiscrete_DEFINED + +#include "SkPaintParts.h" + +class SkDiscrete : public SkDrawPathEffect { + DECLARE_MEMBER_INFO(Discrete); + SkDiscrete(); + virtual SkPathEffect* getPathEffect(); +private: + SkScalar deviation; + SkScalar segLength; +}; + +#endif //SkDrawDiscrete_DEFINED diff --git a/libs/graphics/animator/SkDrawEmboss.cpp b/libs/graphics/animator/SkDrawEmboss.cpp new file mode 100644 index 000000000..f0aee8762 --- /dev/null +++ b/libs/graphics/animator/SkDrawEmboss.cpp @@ -0,0 +1,25 @@ +#include "SkDrawEmboss.h" + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDrawEmboss::fInfo[] = { + SK_MEMBER(ambient, Float), + SK_MEMBER_ARRAY(direction, Float), + SK_MEMBER(radius, Float), + SK_MEMBER(specular, Float) +}; + +#endif + +DEFINE_GET_MEMBER(SkDrawEmboss); + +SkDrawEmboss::SkDrawEmboss() : radius(-1) { + direction.setCount(3); +} + +SkMaskFilter* SkDrawEmboss::getMaskFilter() { + if (radius < 0 || direction.count() !=3) + return nil; + return SkBlurMaskFilter::CreateEmboss(direction.begin(), ambient, specular, radius); +} + diff --git a/libs/graphics/animator/SkDrawEmboss.h b/libs/graphics/animator/SkDrawEmboss.h new file mode 100644 index 000000000..8014f45c8 --- /dev/null +++ b/libs/graphics/animator/SkDrawEmboss.h @@ -0,0 +1,16 @@ +#ifndef SkDrawEmboss_DEFINED +#define SkDrawEmboss_DEFINED + +#include "SkDrawBlur.h" + +class SkDrawEmboss : public SkDrawMaskFilter { + DECLARE_DRAW_MEMBER_INFO(Emboss); + SkDrawEmboss(); + virtual SkMaskFilter* getMaskFilter(); +protected: + SkTDScalarArray direction; + SkScalar radius, ambient, specular; +}; + +#endif // SkDrawEmboss_DEFINED + diff --git a/libs/graphics/animator/SkDrawExtraPathEffect.cpp b/libs/graphics/animator/SkDrawExtraPathEffect.cpp new file mode 100644 index 000000000..b008643ff --- /dev/null +++ b/libs/graphics/animator/SkDrawExtraPathEffect.cpp @@ -0,0 +1,499 @@ +#include "SkDrawExtraPathEffect.h" +#include "SkDrawPath.h" +#include "Sk1DPathEffect.h" +#include "Sk2DPathEffect.h" +#include "SkMemberInfo.h" +#include "SkPaintParts.h" +#include "SkPathEffect.h" +#include "SkCornerPathEffect.h" + +#include "SkDashPathEffect.h" + +class SkDrawShapePathEffect : public SkDrawPathEffect { + DECLARE_PRIVATE_MEMBER_INFO(DrawShapePathEffect); + SkDrawShapePathEffect(); + virtual ~SkDrawShapePathEffect(); + virtual bool add(SkAnimateMaker& , SkDisplayable* ); + virtual SkPathEffect* getPathEffect(); +protected: + SkDrawable* addPath; + SkDrawable* addMatrix; + SkDrawPath* path; + SkPathEffect* fPathEffect; + friend class SkShape1DPathEffect; + friend class SkShape2DPathEffect; +}; + +class SkDrawShape1DPathEffect : public SkDrawShapePathEffect { + DECLARE_EXTRAS_MEMBER_INFO(SkDrawShape1DPathEffect); + SkDrawShape1DPathEffect(SkDisplayTypes ); + virtual ~SkDrawShape1DPathEffect(); + virtual void onEndElement(SkAnimateMaker& ); +private: + SkString phase; + SkString spacing; + friend class SkShape1DPathEffect; + typedef SkDrawShapePathEffect INHERITED; +}; + +class SkDrawShape2DPathEffect : public SkDrawShapePathEffect { + DECLARE_EXTRAS_MEMBER_INFO(SkDrawShape2DPathEffect); + SkDrawShape2DPathEffect(SkDisplayTypes ); + virtual ~SkDrawShape2DPathEffect(); + virtual void onEndElement(SkAnimateMaker& ); +private: + SkDrawMatrix* matrix; + friend class SkShape2DPathEffect; + typedef SkDrawShapePathEffect INHERITED; +}; + +class SkDrawComposePathEffect : public SkDrawPathEffect { + DECLARE_EXTRAS_MEMBER_INFO(SkDrawComposePathEffect); + SkDrawComposePathEffect(SkDisplayTypes ); + virtual ~SkDrawComposePathEffect(); + virtual bool add(SkAnimateMaker& , SkDisplayable* ); + virtual SkPathEffect* getPathEffect(); + virtual bool isPaint() const; +private: + SkDrawPathEffect* effect1; + SkDrawPathEffect* effect2; +}; + +class SkDrawCornerPathEffect : public SkDrawPathEffect { + DECLARE_EXTRAS_MEMBER_INFO(SkDrawCornerPathEffect); + SkDrawCornerPathEffect(SkDisplayTypes ); + virtual ~SkDrawCornerPathEffect(); + virtual SkPathEffect* getPathEffect(); +private: + SkScalar radius; +}; + +//////////// SkShape1DPathEffect + +#include "SkAnimateMaker.h" +#include "SkAnimatorScript.h" +#include "SkDisplayApply.h" +#include "SkDrawMatrix.h" +#include "SkPaint.h" + +class SkShape1DPathEffect : public Sk1DPathEffect { +public: + SkShape1DPathEffect(SkDrawShape1DPathEffect* draw, SkAnimateMaker* maker) : + fDraw(draw), fMaker(maker) { + } + +protected: + virtual SkScalar begin(SkScalar contourLength) + { + SkScriptValue value; + SkAnimatorScript engine(*fMaker, nil, SkType_Float); + engine.propertyCallBack(GetContourLength, &contourLength); + value.fOperand.fScalar = 0; + engine.evaluate(fDraw->phase.c_str(), &value, SkType_Float); + return value.fOperand.fScalar; + } + + virtual SkScalar next(SkScalar distance, const SkMatrix& mat, SkPath* dst) + { + fMaker->setExtraPropertyCallBack(fDraw->fType, GetDistance, &distance); + SkDrawPath* drawPath = nil; + if (fDraw->addPath->isPath()) { + drawPath = (SkDrawPath*) fDraw->addPath; + } else { + SkApply* apply = (SkApply*) fDraw->addPath; + apply->refresh(*fMaker); + apply->activate(*fMaker); + apply->interpolate(*fMaker, SkScalarMulRound(distance, 1000)); + drawPath = (SkDrawPath*) apply->getScope(); + } + SkMatrix m(mat); + if (fDraw->addMatrix) { + SkDrawMatrix* matrix; + if (fDraw->addMatrix->getType() == SkType_Matrix) + matrix = (SkDrawMatrix*) fDraw->addMatrix; + else { + SkApply* apply = (SkApply*) fDraw->addMatrix; + apply->refresh(*fMaker); + apply->activate(*fMaker); + apply->interpolate(*fMaker, SkScalarMulRound(distance, 1000)); + matrix = (SkDrawMatrix*) apply->getScope(); + } + } + SkScalar result = 0; + SkAnimatorScript::EvaluateFloat(*fMaker, nil, fDraw->spacing.c_str(), &result); + if (drawPath) + dst->addPath(drawPath->getPath(), m); + fMaker->clearExtraPropertyCallBack(fDraw->fType); + return result; + } + +private: + + static bool GetContourLength(const char* token, size_t len, void* clen, SkScriptValue* value) { + if (SK_LITERAL_STR_EQUAL("contourLength", token, len)) { + value->fOperand.fScalar = *(SkScalar*) clen; + value->fType = SkType_Float; + return true; + } + return false; + } + + static bool GetDistance(const char* token, size_t len, void* dist, SkScriptValue* value) { + if (SK_LITERAL_STR_EQUAL("distance", token, len)) { + value->fOperand.fScalar = *(SkScalar*) dist; + value->fType = SkType_Float; + return true; + } + return false; + } + + SkDrawShape1DPathEffect* fDraw; + SkAnimateMaker* fMaker; +}; + +//////////// SkDrawShapePathEffect + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDrawShapePathEffect::fInfo[] = { + SK_MEMBER(addMatrix, Drawable), // either matrix or apply + SK_MEMBER(addPath, Drawable), // either path or apply + SK_MEMBER(path, Path), +}; + +#endif + +DEFINE_GET_MEMBER(SkDrawShapePathEffect); + +SkDrawShapePathEffect::SkDrawShapePathEffect() : + addPath(nil), addMatrix(nil), path(nil), fPathEffect(nil) { +} + +SkDrawShapePathEffect::~SkDrawShapePathEffect() { + fPathEffect->safeUnref(); +} + +bool SkDrawShapePathEffect::add(SkAnimateMaker& , SkDisplayable* child) { + path = (SkDrawPath*) child; + return true; +} + +SkPathEffect* SkDrawShapePathEffect::getPathEffect() { + fPathEffect->ref(); + return fPathEffect; +} + +//////////// SkDrawShape1DPathEffect + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDrawShape1DPathEffect::fInfo[] = { + SK_MEMBER_INHERITED, + SK_MEMBER(phase, String), + SK_MEMBER(spacing, String), +}; + +#endif + +DEFINE_GET_MEMBER(SkDrawShape1DPathEffect); + +SkDrawShape1DPathEffect::SkDrawShape1DPathEffect(SkDisplayTypes type) : fType(type) { +} + +SkDrawShape1DPathEffect::~SkDrawShape1DPathEffect() { +} + +void SkDrawShape1DPathEffect::onEndElement(SkAnimateMaker& maker) { + if (addPath == nil || (addPath->isPath() == false && addPath->isApply() == false)) + maker.setErrorCode(SkDisplayXMLParserError::kUnknownError); // !!! add error + else + fPathEffect = new SkShape1DPathEffect(this, &maker); +} + +////////// SkShape2DPathEffect + +class SkShape2DPathEffect : public Sk2DPathEffect { +public: + SkShape2DPathEffect(SkDrawShape2DPathEffect* draw, SkAnimateMaker* maker, + const SkMatrix& matrix) : Sk2DPathEffect(matrix), fDraw(draw), fMaker(maker) { + } + +protected: + virtual void begin(const SkRect16& uvBounds, SkPath* ) + { + fUVBounds.set(SkIntToScalar(uvBounds.fLeft), SkIntToScalar(uvBounds.fTop), + SkIntToScalar(uvBounds.fRight), SkIntToScalar(uvBounds.fBottom)); + } + + virtual void next(const SkPoint& loc, int u, int v, SkPath* dst) + { + fLoc = loc; + fU = u; + fV = v; + SkDrawPath* drawPath; + fMaker->setExtraPropertyCallBack(fDraw->fType, Get2D, this); + if (fDraw->addPath->isPath()) { + drawPath = (SkDrawPath*) fDraw->addPath; + } else { + SkApply* apply = (SkApply*) fDraw->addPath; + apply->refresh(*fMaker); + apply->activate(*fMaker); + apply->interpolate(*fMaker, v); + drawPath = (SkDrawPath*) apply->getScope(); + } + if (drawPath == nil) + goto clearCallBack; + if (fDraw->matrix) { + SkDrawMatrix* matrix; + if (fDraw->matrix->getType() == SkType_Matrix) + matrix = (SkDrawMatrix*) fDraw->matrix; + else { + SkApply* apply = (SkApply*) fDraw->matrix; + apply->activate(*fMaker); + apply->interpolate(*fMaker, v); + matrix = (SkDrawMatrix*) apply->getScope(); + } + if (matrix) { + dst->addPath(drawPath->getPath(), matrix->getMatrix()); + goto clearCallBack; + } + } + dst->addPath(drawPath->getPath()); +clearCallBack: + fMaker->clearExtraPropertyCallBack(fDraw->fType); + } + +private: + + static bool Get2D(const char* token, size_t len, void* s2D, SkScriptValue* value) { + static const char match[] = "locX|locY|left|top|right|bottom|u|v" ; + SkShape2DPathEffect* shape2D = (SkShape2DPathEffect*) s2D; + int index; + if (SkAnimatorScript::MapEnums(match, token, len, &index) == false) + return false; + SkASSERT((sizeof(SkPoint) + sizeof(SkRect)) / sizeof(SkScalar) == 6); + if (index < 6) { + value->fType = SkType_Float; + value->fOperand.fScalar = (&shape2D->fLoc.fX)[index]; + } else { + value->fType = SkType_Int; + value->fOperand.fS32 = (&shape2D->fU)[index - 6]; + } + return true; + } + + SkPoint fLoc; + SkRect fUVBounds; + S32 fU; + S32 fV; + SkDrawShape2DPathEffect* fDraw; + SkAnimateMaker* fMaker; + + // illegal + SkShape2DPathEffect(const SkShape2DPathEffect&); + SkShape2DPathEffect& operator=(const SkShape2DPathEffect&); +}; + +////////// SkDrawShape2DPathEffect + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDrawShape2DPathEffect::fInfo[] = { + SK_MEMBER_INHERITED, + SK_MEMBER(matrix, Matrix) +}; + +#endif + +DEFINE_GET_MEMBER(SkDrawShape2DPathEffect); + +SkDrawShape2DPathEffect::SkDrawShape2DPathEffect(SkDisplayTypes type) : fType(type) { +} + +SkDrawShape2DPathEffect::~SkDrawShape2DPathEffect() { +} + +void SkDrawShape2DPathEffect::onEndElement(SkAnimateMaker& maker) { + if (addPath == nil || (addPath->isPath() == false && addPath->isApply() == false) || + matrix == nil) + maker.setErrorCode(SkDisplayXMLParserError::kUnknownError); // !!! add error + else + fPathEffect = new SkShape2DPathEffect(this, &maker, matrix->getMatrix()); +} + +////////// SkDrawComposePathEffect + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDrawComposePathEffect::fInfo[] = { + SK_MEMBER(effect1, PathEffect), + SK_MEMBER(effect2, PathEffect) +}; + +#endif + +DEFINE_GET_MEMBER(SkDrawComposePathEffect); + +SkDrawComposePathEffect::SkDrawComposePathEffect(SkDisplayTypes type) : fType(type), + effect1(nil), effect2(nil) { +} + +SkDrawComposePathEffect::~SkDrawComposePathEffect() { + delete effect1; + delete effect2; +} + +bool SkDrawComposePathEffect::add(SkAnimateMaker& , SkDisplayable* child) { + if (effect1 == nil) + effect1 = (SkDrawPathEffect*) child; + else + effect2 = (SkDrawPathEffect*) child; + return true; +} + +SkPathEffect* SkDrawComposePathEffect::getPathEffect() { + SkPathEffect* e1 = effect1->getPathEffect(); + SkPathEffect* e2 = effect2->getPathEffect(); + SkPathEffect* composite = new SkComposePathEffect(e1, e2); + e1->unref(); + e2->unref(); + return composite; +} + +bool SkDrawComposePathEffect::isPaint() const { + return true; +} + +//////////// SkDrawCornerPathEffect + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDrawCornerPathEffect::fInfo[] = { + SK_MEMBER(radius, Float) +}; + +#endif + +DEFINE_GET_MEMBER(SkDrawCornerPathEffect); + +SkDrawCornerPathEffect::SkDrawCornerPathEffect(SkDisplayTypes type): + fType(type), radius(0) { +} + +SkDrawCornerPathEffect::~SkDrawCornerPathEffect() { +} + +SkPathEffect* SkDrawCornerPathEffect::getPathEffect() { + return new SkCornerPathEffect(radius); +} + +///////// + +#include "SkExtras.h" + +const char kDrawShape1DPathEffectName[] = "pathEffect:shape1D"; +const char kDrawShape2DPathEffectName[] = "pathEffect:shape2D"; +const char kDrawComposePathEffectName[] = "pathEffect:compose"; +const char kDrawCornerPathEffectName[] = "pathEffect:corner"; + +class SkExtraPathEffects : public SkExtras { +public: + SkExtraPathEffects(SkAnimator* animator) : + skDrawShape1DPathEffectType(SkType_Unknown), + skDrawShape2DPathEffectType(SkType_Unknown), + skDrawComposePathEffectType(SkType_Unknown), + skDrawCornerPathEffectType(SkType_Unknown) { + } + + virtual SkDisplayable* createInstance(SkDisplayTypes type) { + SkDisplayable* result = nil; + if (skDrawShape1DPathEffectType == type) + result = new SkDrawShape1DPathEffect(type); + else if (skDrawShape2DPathEffectType == type) + result = new SkDrawShape2DPathEffect(type); + else if (skDrawComposePathEffectType == type) + result = new SkDrawComposePathEffect(type); + else if (skDrawCornerPathEffectType == type) + result = new SkDrawCornerPathEffect(type); + return result; + } + + virtual bool definesType(SkDisplayTypes type) { + return type == skDrawShape1DPathEffectType || + type == skDrawShape2DPathEffectType || + type == skDrawComposePathEffectType || + type == skDrawCornerPathEffectType; + } + +#if SK_USE_CONDENSED_INFO == 0 + virtual const SkMemberInfo* getMembers(SkDisplayTypes type, int* infoCountPtr) { + const SkMemberInfo* info = nil; + int infoCount = 0; + if (skDrawShape1DPathEffectType == type) { + info = SkDrawShape1DPathEffect::fInfo; + infoCount = SkDrawShape1DPathEffect::fInfoCount; + } else if (skDrawShape2DPathEffectType == type) { + info = SkDrawShape2DPathEffect::fInfo; + infoCount = SkDrawShape2DPathEffect::fInfoCount; + } else if (skDrawComposePathEffectType == type) { + info = SkDrawComposePathEffect::fInfo; + infoCount = SkDrawShape1DPathEffect::fInfoCount; + } else if (skDrawCornerPathEffectType == type) { + info = SkDrawCornerPathEffect::fInfo; + infoCount = SkDrawCornerPathEffect::fInfoCount; + } + if (infoCountPtr) + *infoCountPtr = infoCount; + return info; + } +#endif + +#ifdef SK_DEBUG + virtual const char* getName(SkDisplayTypes type) { + if (skDrawShape1DPathEffectType == type) + return kDrawShape1DPathEffectName; + else if (skDrawShape2DPathEffectType == type) + return kDrawShape2DPathEffectName; + else if (skDrawComposePathEffectType == type) + return kDrawComposePathEffectName; + else if (skDrawCornerPathEffectType == type) + return kDrawCornerPathEffectName; + return NULL; + } +#endif + + virtual SkDisplayTypes getType(const char name[], size_t len ) { + SkDisplayTypes* type = nil; + if (SK_LITERAL_STR_EQUAL(kDrawShape1DPathEffectName, name, len)) + type = &skDrawShape1DPathEffectType; + else if (SK_LITERAL_STR_EQUAL(kDrawShape2DPathEffectName, name, len)) + type = &skDrawShape2DPathEffectType; + else if (SK_LITERAL_STR_EQUAL(kDrawComposePathEffectName, name, len)) + type = &skDrawComposePathEffectType; + else if (SK_LITERAL_STR_EQUAL(kDrawCornerPathEffectName, name, len)) + type = &skDrawCornerPathEffectType; + if (type) { + if (*type == SkType_Unknown) + *type = SkDisplayType::RegisterNewType(); + return *type; + } + return SkType_Unknown; + } + +private: + SkDisplayTypes skDrawShape1DPathEffectType; + SkDisplayTypes skDrawShape2DPathEffectType; + SkDisplayTypes skDrawComposePathEffectType; + SkDisplayTypes skDrawCornerPathEffectType; +}; + + +void InitializeSkExtraPathEffects(SkAnimator* animator) { + animator->addExtras(new SkExtraPathEffects(animator)); +} + +//////////////// + + +SkExtras::SkExtras() : fExtraCallBack(nil), fExtraStorage(nil) { +} diff --git a/libs/graphics/animator/SkDrawFull.cpp b/libs/graphics/animator/SkDrawFull.cpp new file mode 100644 index 000000000..3bf27d912 --- /dev/null +++ b/libs/graphics/animator/SkDrawFull.cpp @@ -0,0 +1,10 @@ +#include "SkDrawFull.h" +#include "SkAnimateMaker.h" +#include "SkCanvas.h" + +bool SkFull::draw(SkAnimateMaker& maker) { + SkBoundableAuto boundable(this, maker); + maker.fCanvas->drawPaint(*maker.fPaint); + return false; +} + diff --git a/libs/graphics/animator/SkDrawFull.h b/libs/graphics/animator/SkDrawFull.h new file mode 100644 index 000000000..8822b0266 --- /dev/null +++ b/libs/graphics/animator/SkDrawFull.h @@ -0,0 +1,13 @@ +#ifndef SkDrawFull_DEFINED +#define SkDrawFull_DEFINED + +#include "SkBoundable.h" + +class SkFull : public SkBoundable { + DECLARE_EMPTY_MEMBER_INFO(Full); + virtual bool draw(SkAnimateMaker& ); +private: + typedef SkBoundable INHERITED; +}; + +#endif // SkDrawFull_DEFINED diff --git a/libs/graphics/animator/SkDrawGradient.cpp b/libs/graphics/animator/SkDrawGradient.cpp new file mode 100644 index 000000000..ae40728d2 --- /dev/null +++ b/libs/graphics/animator/SkDrawGradient.cpp @@ -0,0 +1,214 @@ +#include "SkDrawGradient.h" +#include "SkAnimateMaker.h" +#include "SkAnimatorScript.h" +#include "SkGradientShader.h" +#include "SkUnitMapper.h" + +SkScalar SkUnitToScalar(U16CPU x) { +#ifdef SK_SCALAR_IS_FLOAT + return x / 65535.0f; +#else + return x + (x >> 8); +#endif +} + +U16CPU SkScalarToUnit(SkScalar x) { + SkScalar pin = SkScalarPin(x, 0, SK_Scalar1); +#ifdef SK_SCALAR_IS_FLOAT + return (int) (pin * 65535.0f); +#else + return pin - (pin >= 32768); +#endif +} + +class SkGradientUnitMapper : public SkUnitMapper { +public: + SkGradientUnitMapper(SkAnimateMaker* maker, const char* script) : fMaker(maker), fScript(script) { + } +protected: + virtual U16CPU mapUnit16(U16CPU x) { + fUnit = SkUnitToScalar(x); + SkScriptValue value; + SkAnimatorScript engine(*fMaker, nil, SkType_Float); + engine.propertyCallBack(GetUnitValue, &fUnit); + if (engine.evaluate(fScript, &value, SkType_Float)) + x = SkScalarToUnit(value.fOperand.fScalar); + return x; + } + + static bool GetUnitValue(const char* token, size_t len, void* unitPtr, SkScriptValue* value) { + if (SK_LITERAL_STR_EQUAL("unit", token, len)) { + value->fOperand.fScalar = *(SkScalar*) unitPtr; + value->fType = SkType_Float; + return true; + } + return false; + } + + SkAnimateMaker* fMaker; + const char* fScript; + SkScalar fUnit; +}; + + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkGradient::fInfo[] = { + SK_MEMBER_INHERITED, + SK_MEMBER_ARRAY(offsets, Float), + SK_MEMBER(unitMapper, String) +}; + +#endif + +DEFINE_GET_MEMBER(SkGradient); + +SkGradient::SkGradient() : fUnitMapper(nil) { +} + +SkGradient::~SkGradient() { + for (int index = 0; index < fDrawColors.count(); index++) + delete fDrawColors[index]; + delete fUnitMapper; +} + +bool SkGradient::add(SkAnimateMaker& , SkDisplayable* child) { + SkASSERT(child); + if (child->isColor()) { + SkDrawColor* color = (SkDrawColor*) child; + *fDrawColors.append() = color; + return true; + } + return false; +} + +int SkGradient::addPrelude() { + int count = fDrawColors.count(); + fColors.setCount(count); + for (int index = 0; index < count; index++) + fColors[index] = fDrawColors[index]->color; + return count; +} + +#ifdef SK_DUMP_ENABLED +void SkGradient::dumpRest(SkAnimateMaker* maker) { + dumpAttrs(maker); + //can a gradient have no colors? + bool closedYet = false; + SkDisplayList::fIndent += 4; + for (SkDrawColor** ptr = fDrawColors.begin(); ptr < fDrawColors.end(); ptr++) { + if (closedYet == false) { + SkDebugf(">\n"); + closedYet = true; + } + SkDrawColor* color = *ptr; + color->dump(maker); + } + SkDisplayList::fIndent -= 4; + dumpChildren(maker, closedYet); //dumps the matrix if it has one +} +#endif + +void SkGradient::onEndElement(SkAnimateMaker& maker) { + if (offsets.count() != 0) { + if (offsets.count() != fDrawColors.count()) { + maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsDontMatchColors); + return; + } + if (offsets[0] != 0) { + maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustStartWithZero); + return; + } + if (offsets[offsets.count()-1] != SK_Scalar1) { + maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustEndWithOne); + return; + } + for (int i = 1; i < offsets.count(); i++) { + if (offsets[i] <= offsets[i-1]) { + maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustIncrease); + return; + } + if (offsets[i] > SK_Scalar1) { + maker.setErrorCode(SkDisplayXMLParserError::kGradientOffsetsMustBeNoMoreThanOne); + return; + } + } + } + if (unitMapper.size() > 0) + fUnitMapper = new SkGradientUnitMapper(&maker, unitMapper.c_str()); + INHERITED::onEndElement(maker); +} + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkLinearGradient::fInfo[] = { + SK_MEMBER_INHERITED, + SK_MEMBER_ARRAY(points, Float), +}; + +#endif + +DEFINE_GET_MEMBER(SkLinearGradient); + +SkLinearGradient::SkLinearGradient() { +} + +void SkLinearGradient::onEndElement(SkAnimateMaker& maker) +{ + if (points.count() != 4) + maker.setErrorCode(SkDisplayXMLParserError::kGradientPointsLengthMustBeFour); + INHERITED::onEndElement(maker); +} + +#ifdef SK_DUMP_ENABLED +void SkLinearGradient::dump(SkAnimateMaker* maker) { + dumpBase(maker); + dumpRest(maker); + } +#endif + +SkShader* SkLinearGradient::getShader() { + if (addPrelude() == 0 || points.count() != 4) + return nil; + SkShader* shader = SkGradientShader::CreateLinear((SkPoint*)points.begin(), + fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode, fUnitMapper); + SkAutoTDelete autoDel(shader); + addPostlude(shader); + (void)autoDel.detach(); + return shader; +} + + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkRadialGradient::fInfo[] = { + SK_MEMBER_INHERITED, + SK_MEMBER(center, Point), + SK_MEMBER(radius, Float) +}; + +#endif + +DEFINE_GET_MEMBER(SkRadialGradient); + +SkRadialGradient::SkRadialGradient() : radius(0) { + center.set(0, 0); +} + +#ifdef SK_DUMP_ENABLED +void SkRadialGradient::dump(SkAnimateMaker* maker) { + dumpBase(maker); + dumpRest(maker); +} +#endif + +SkShader* SkRadialGradient::getShader() { + if (addPrelude() == 0) + return nil; + SkShader* shader = SkGradientShader::CreateRadial(center, + radius, fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode, fUnitMapper); + SkAutoTDelete autoDel(shader); + addPostlude(shader); + (void)autoDel.detach(); + return shader; +} diff --git a/libs/graphics/animator/SkDrawGradient.h b/libs/graphics/animator/SkDrawGradient.h new file mode 100644 index 000000000..2940b7614 --- /dev/null +++ b/libs/graphics/animator/SkDrawGradient.h @@ -0,0 +1,59 @@ +#ifndef SkDrawGradient_DEFINED +#define SkDrawGradient_DEFINED + +#include "SkDrawColor.h" +#include "SkDrawShader.h" +#include "SkIntArray.h" + +class SkUnitMapper; + +class SkGradient : public SkDrawShader { + DECLARE_PRIVATE_MEMBER_INFO(Gradient); + SkGradient(); + virtual ~SkGradient(); + virtual bool add(SkAnimateMaker& , SkDisplayable* child); +#ifdef SK_DUMP_ENABLED + virtual void dumpRest(SkAnimateMaker*); +#endif + virtual void onEndElement(SkAnimateMaker& ); +protected: + SkTDScalarArray offsets; + SkString unitMapper; + SkTDColorArray fColors; + SkTDDrawColorArray fDrawColors; + SkUnitMapper* fUnitMapper; + int addPrelude(); +private: + typedef SkDrawShader INHERITED; +}; + +class SkLinearGradient : public SkGradient { + DECLARE_MEMBER_INFO(LinearGradient); + SkLinearGradient(); + virtual void onEndElement(SkAnimateMaker& ); +#ifdef SK_DUMP_ENABLED + virtual void dump(SkAnimateMaker*); +#endif + virtual SkShader* getShader(); +protected: + SkTDScalarArray points; +private: + typedef SkGradient INHERITED; +}; + +class SkRadialGradient : public SkGradient { + DECLARE_MEMBER_INFO(RadialGradient); + SkRadialGradient(); +#ifdef SK_DUMP_ENABLED + virtual void dump(SkAnimateMaker*); +#endif + virtual SkShader* getShader(); +protected: + SkPoint center; + SkScalar radius; +private: + typedef SkGradient INHERITED; +}; + +#endif // SkDrawGradient_DEFINED + diff --git a/libs/graphics/animator/SkDrawGroup.cpp b/libs/graphics/animator/SkDrawGroup.cpp new file mode 100644 index 000000000..89232dd22 --- /dev/null +++ b/libs/graphics/animator/SkDrawGroup.cpp @@ -0,0 +1,314 @@ +#include "SkDrawGroup.h" +#include "SkAnimateMaker.h" +#include "SkAnimatorScript.h" +#include "SkCanvas.h" +#include "SkDisplayApply.h" +#include "SkPaint.h" +#ifdef SK_DEBUG +#include "SkDisplayList.h" +#endif + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkGroup::fInfo[] = { + SK_MEMBER(condition, String), + SK_MEMBER(enableCondition, String) +}; + +#endif + +DEFINE_GET_MEMBER(SkGroup); + +SkGroup::SkGroup() : fParentList(nil), fOriginal(nil) { +} + +SkGroup::~SkGroup() { + if (fOriginal) // has been copied + return; + int index = 0; + int max = fCopies.count() << 5; + for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) { + if (index >= max || markedForDelete(index)) + delete *ptr; +// else { +// SkApply* apply = (SkApply*) *ptr; +// SkASSERT(apply->isApply()); +// SkASSERT(apply->getScope()); +// delete apply->getScope(); +// } + index++; + } +} + +bool SkGroup::add(SkAnimateMaker& , SkDisplayable* child) { + SkASSERT(child); +// SkASSERT(child->isDrawable()); + *fChildren.append() = (SkDrawable*) child; + if (child->isGroup()) { + SkGroup* groupie = (SkGroup*) child; + SkASSERT(groupie->fParentList == nil); + groupie->fParentList = &fChildren; + } + return true; +} + +bool SkGroup::contains(SkDisplayable* match) { + for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) { + SkDrawable* drawable = *ptr; + if (drawable == match || drawable->contains(match)) + return true; + } + return false; +} + +SkGroup* SkGroup::copy() { + SkGroup* result = new SkGroup(); + result->fOriginal = this; + result->fChildren = fChildren; + return result; +} + +SkBool SkGroup::copySet(int index) { + return (fCopies[index >> 5] & 1 << (index & 0x1f)) != 0; +} + +SkDisplayable* SkGroup::deepCopy(SkAnimateMaker* maker) { + SkDisplayable* copy = INHERITED::deepCopy(maker); + for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) { + SkDisplayable* displayable = (SkDisplayable*)*ptr; + SkDisplayable* deeperCopy = displayable->deepCopy(maker); + ((SkGroup*)copy)->add(*maker, deeperCopy); + } + return copy; +} + +bool SkGroup::doEvent(SkDisplayEvent::Kind kind, SkEventState* state) { + bool handled = false; + for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) { + SkDrawable* drawable = *ptr; + if (drawable->isDrawable() == false) + continue; + handled |= drawable->doEvent(kind, state); + } + return handled; +} + +bool SkGroup::draw(SkAnimateMaker& maker) { + bool conditionTrue = ifCondition(maker, this, condition); + bool result = false; + for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) { + SkDrawable* drawable = *ptr; + if (drawable->isDrawable() == false) + continue; + if (conditionTrue == false) { + if (drawable->isApply()) + ((SkApply*) drawable)->disable(); + continue; + } + maker.validate(); + result |= drawable->draw(maker); + maker.validate(); + } + return result; +} + +#ifdef SK_DUMP_ENABLED +void SkGroup::dump(SkAnimateMaker* maker) { + dumpBase(maker); + if (condition.size() > 0) + SkDebugf("condition=\"%s\" ", condition.c_str()); + if (enableCondition.size() > 0) + SkDebugf("enableCondition=\"%s\" ", enableCondition.c_str()); + dumpDrawables(maker); +} + +void SkGroup::dumpDrawables(SkAnimateMaker* maker) { + SkDisplayList::fIndent += 4; + int save = SkDisplayList::fDumpIndex; + SkDisplayList::fDumpIndex = 0; + bool closedYet = false; + for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) { + if (closedYet == false) { + closedYet = true; + SkDebugf(">\n"); + } + SkDrawable* drawable = *ptr; + drawable->dump(maker); + SkDisplayList::fDumpIndex++; + } + SkDisplayList::fIndent -= 4; + SkDisplayList::fDumpIndex = save; + if (closedYet) //we had children, now it's time to close the group + dumpEnd(maker); + else //no children + SkDebugf("/>\n"); +} + +void SkGroup::dumpEvents() { + for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) { + SkDrawable* drawable = *ptr; + drawable->dumpEvents(); + } +} +#endif + +bool SkGroup::enable(SkAnimateMaker& maker ) { + reset(); + for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) { + SkDrawable* drawable = *ptr; + if (ifCondition(maker, drawable, enableCondition) == false) + continue; + drawable->enable(maker); + } + return true; // skip add; already added so that scope is findable by children +} + +int SkGroup::findGroup(SkDrawable* match, SkTDDrawableArray** list, + SkGroup** parent, SkGroup** found, SkTDDrawableArray** grandList) { + *list = &fChildren; + for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) { + SkDrawable* drawable = *ptr; + if (drawable->isGroup()) { + SkGroup* childGroup = (SkGroup*) drawable; + if (childGroup->fOriginal == match) + goto foundMatch; + } + if (drawable == match) { +foundMatch: + *parent = this; + return (int) (ptr - fChildren.begin()); + } + } + *grandList = &fChildren; + return SkDisplayList::SearchForMatch(match, list, parent, found, grandList); +} + +bool SkGroup::hasEnable() const { + return true; +} + +bool SkGroup::ifCondition(SkAnimateMaker& maker, SkDrawable* drawable, + SkString& conditionString) { + if (conditionString.size() == 0) + return true; + int32_t result; + bool success = SkAnimatorScript::EvaluateInt(maker, this, conditionString.c_str(), &result); +#ifdef SK_DUMP_ENABLED + if (maker.fDumpGConditions) { + SkDebugf("group: "); + dumpBase(&maker); + SkDebugf("condition=%s ", conditionString.c_str()); + if (success == false) + SkDebugf("(script failed)\n"); + else + SkDebugf("success=%s\n", result != 0 ? "true" : "false"); + } +#endif + return success && result != 0; +} + +void SkGroup::initialize() { + for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) { + SkDrawable* drawable = *ptr; + if (drawable->isDrawable() == false) + continue; + drawable->initialize(); + } +} + +void SkGroup::markCopyClear(int index) { + if (index < 0) + index = fChildren.count(); + fCopies[index >> 5] &= ~(1 << (index & 0x1f)); +} + +void SkGroup::markCopySet(int index) { + if (index < 0) + index = fChildren.count(); + fCopies[index >> 5] |= 1 << (index & 0x1f); +} + +void SkGroup::markCopySize(int index) { + if (index < 0) + index = fChildren.count() + 1; + int oldLongs = fCopies.count(); + int newLongs = (index >> 5) + 1; + if (oldLongs < newLongs) { + fCopies.setCount(newLongs); + memset(&fCopies[oldLongs], 0, (newLongs - oldLongs) << 2); + } +} + +void SkGroup::reset() { + if (fOriginal) // has been copied + return; + int index = 0; + int max = fCopies.count() << 5; + for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) { + if (index >= max || copySet(index) == false) + continue; + SkApply* apply = (SkApply*) *ptr; + SkASSERT(apply->isApply()); + SkASSERT(apply->getScope()); + *ptr = apply->getScope(); + markCopyClear(index); + index++; + } +} + +bool SkGroup::resolveIDs(SkAnimateMaker& maker, SkDisplayable* orig, SkApply* apply) { + SkGroup* original = (SkGroup*) orig; + SkTDDrawableArray& originalChildren = original->fChildren; + SkDrawable** originalPtr = originalChildren.begin(); + SkDrawable** ptr = fChildren.begin(); + SkDrawable** end = fChildren.end(); + SkDrawable** origChild = ((SkGroup*) orig)->fChildren.begin(); + while (ptr < end) { + SkDrawable* drawable = *ptr++; + maker.resolveID(drawable, *origChild++); + if (drawable->resolveIDs(maker, *originalPtr++, apply) == true) + return true; // failed + } + return false; +} + +void SkGroup::setSteps(int steps) { + for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) { + SkDrawable* drawable = *ptr; + if (drawable->isDrawable() == false) + continue; + drawable->setSteps(steps); + } +} + +#ifdef SK_DEBUG +void SkGroup::validate() { + for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) { + SkDrawable* drawable = *ptr; + drawable->validate(); + } +} +#endif + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkSave::fInfo[] = { + SK_MEMBER_INHERITED +}; + +#endif + +DEFINE_GET_MEMBER(SkSave); + +bool SkSave::draw(SkAnimateMaker& maker) { + maker.fCanvas->save(); + SkPaint* save = maker.fPaint; + SkPaint local = SkPaint(*maker.fPaint); + maker.fPaint = &local; + bool result = INHERITED::draw(maker); + maker.fPaint = save; + maker.fCanvas->restore(); + return result; +} + + diff --git a/libs/graphics/animator/SkDrawGroup.h b/libs/graphics/animator/SkDrawGroup.h new file mode 100644 index 000000000..45e3a43b9 --- /dev/null +++ b/libs/graphics/animator/SkDrawGroup.h @@ -0,0 +1,63 @@ +#ifndef SkDrawGroup_DEFINED +#define SkDrawGroup_DEFINED + +#include "SkDrawable.h" +#include "SkIntArray.h" +#include "SkMemberInfo.h" + +class SkGroup : public SkDrawable { //interface for schema element +public: + DECLARE_MEMBER_INFO(Group); + SkGroup(); + virtual ~SkGroup(); + virtual bool add(SkAnimateMaker& , SkDisplayable* child); + virtual bool contains(SkDisplayable* ); + SkGroup* copy(); + SkBool copySet(int index); + virtual SkDisplayable* deepCopy(SkAnimateMaker* ); + virtual bool doEvent(SkDisplayEvent::Kind , SkEventState* state ); + virtual bool draw(SkAnimateMaker& ); +#ifdef SK_DUMP_ENABLED + virtual void dump(SkAnimateMaker* ); + virtual void dumpDrawables(SkAnimateMaker* ); + virtual void dumpEvents(); +#endif + int findGroup(SkDrawable* drawable, SkTDDrawableArray** list, + SkGroup** parent, SkGroup** found, SkTDDrawableArray** grandList); + virtual bool enable(SkAnimateMaker& ); + SkTDDrawableArray* getChildren() { return &fChildren; } + SkGroup* getOriginal() { return fOriginal; } + virtual bool hasEnable() const; + virtual void initialize(); + SkBool isACopy() { return fOriginal != nil; } + void markCopyClear(int index); + void markCopySet(int index); + void markCopySize(int index); + bool markedForDelete(int index) const { return (fCopies[index >> 5] & 1 << (index & 0x1f)) == 0; } + void reset(); + bool resolveIDs(SkAnimateMaker& maker, SkDisplayable* original, SkApply* ); + virtual void setSteps(int steps); +#ifdef SK_DEBUG + virtual void validate(); +#endif +protected: + bool ifCondition(SkAnimateMaker& maker, SkDrawable* drawable, + SkString& conditionString); + SkString condition; + SkString enableCondition; + SkTDDrawableArray fChildren; + SkTDDrawableArray* fParentList; + SkTDIntArray fCopies; + SkGroup* fOriginal; +private: + typedef SkDrawable INHERITED; +}; + +class SkSave: public SkGroup { + DECLARE_MEMBER_INFO(Save); + virtual bool draw(SkAnimateMaker& ); +private: + typedef SkGroup INHERITED; +}; + +#endif // SkDrawGroup_DEFINED diff --git a/libs/graphics/animator/SkDrawLine.cpp b/libs/graphics/animator/SkDrawLine.cpp new file mode 100644 index 000000000..3c38fbe82 --- /dev/null +++ b/libs/graphics/animator/SkDrawLine.cpp @@ -0,0 +1,28 @@ +#include "SkDrawLine.h" +#include "SkAnimateMaker.h" +#include "SkCanvas.h" +#include "SkPaint.h" + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkLine::fInfo[] = { + SK_MEMBER(x1, Float), + SK_MEMBER(x2, Float), + SK_MEMBER(y1, Float), + SK_MEMBER(y2, Float) +}; + +#endif + +DEFINE_GET_MEMBER(SkLine); + +SkLine::SkLine() : x1(0), x2(0), y1(0), y2(0) { +} + +bool SkLine::draw(SkAnimateMaker& maker) { + SkPoint start = {x1, y1}; + SkPoint stop = {x2, y2}; + SkBoundableAuto boundable(this, maker); + maker.fCanvas->drawLine(start, stop, *maker.fPaint); + return false; +} diff --git a/libs/graphics/animator/SkDrawLine.h b/libs/graphics/animator/SkDrawLine.h new file mode 100644 index 000000000..682c7ee26 --- /dev/null +++ b/libs/graphics/animator/SkDrawLine.h @@ -0,0 +1,20 @@ +#ifndef SkDrawLine_DEFINED +#define SkDrawLine_DEFINED + +#include "SkBoundable.h" +#include "SkMemberInfo.h" + +class SkLine : public SkBoundable { + DECLARE_MEMBER_INFO(Line); + SkLine(); + virtual bool draw(SkAnimateMaker& ); +private: + SkScalar x1; + SkScalar x2; + SkScalar y1; + SkScalar y2; + typedef SkBoundable INHERITED; +}; + +#endif // SkDrawLine_DEFINED + diff --git a/libs/graphics/animator/SkDrawMatrix.cpp b/libs/graphics/animator/SkDrawMatrix.cpp new file mode 100644 index 000000000..18b30e6fe --- /dev/null +++ b/libs/graphics/animator/SkDrawMatrix.cpp @@ -0,0 +1,273 @@ +#include "SkDrawMatrix.h" +#include "SkAnimateMaker.h" +#include "SkCanvas.h" +#include "SkPaint.h" +#include "SkParse.h" +#include "SkMatrixParts.h" +#include "SkScript.h" +#include "SkTypedArray.h" + +enum SkDrawMatrix_Properties { + SK_PROPERTY(perspectX), + SK_PROPERTY(perspectY), + SK_PROPERTY(rotate), + SK_PROPERTY(scale), + SK_PROPERTY(scaleX), + SK_PROPERTY(scaleY), + SK_PROPERTY(skewX), + SK_PROPERTY(skewY), + SK_PROPERTY(translate), + SK_PROPERTY(translateX), + SK_PROPERTY(translateY) +}; + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDrawMatrix::fInfo[] = { + SK_MEMBER_ARRAY(matrix, Float), + SK_MEMBER_PROPERTY(perspectX, Float), + SK_MEMBER_PROPERTY(perspectY, Float), + SK_MEMBER_PROPERTY(rotate, Float), + SK_MEMBER_PROPERTY(scale, Float), + SK_MEMBER_PROPERTY(scaleX, Float), + SK_MEMBER_PROPERTY(scaleY, Float), + SK_MEMBER_PROPERTY(skewX, Float), + SK_MEMBER_PROPERTY(skewY, Float), + SK_MEMBER_PROPERTY(translate, Point), + SK_MEMBER_PROPERTY(translateX, Float), + SK_MEMBER_PROPERTY(translateY, Float) +}; + +#endif + +DEFINE_GET_MEMBER(SkDrawMatrix); + +SkDrawMatrix::SkDrawMatrix() : fChildHasID(false), fDirty(false) { + fConcat.reset(); + fMatrix.reset(); +} + +SkDrawMatrix::~SkDrawMatrix() { + for (SkMatrixPart** part = fParts.begin(); part < fParts.end(); part++) + delete *part; +} + +bool SkDrawMatrix::add(SkAnimateMaker& maker, SkDisplayable* child) { + SkASSERT(child && child->isMatrixPart()); + SkMatrixPart* part = (SkMatrixPart*) child; + *fParts.append() = part; + if (part->add()) + maker.setErrorCode(SkDisplayXMLParserError::kErrorAddingToMatrix); + return true; +} + +bool SkDrawMatrix::childrenNeedDisposing() const { + return false; +} + +SkDisplayable* SkDrawMatrix::deepCopy(SkAnimateMaker* maker) { + SkDrawMatrix* copy = (SkDrawMatrix*) + SkDisplayType::CreateInstance(maker, SkType_Matrix); + SkASSERT(fParts.count() == 0); + copy->fMatrix = fMatrix; + copy->fConcat = fConcat; + return copy; +} + +void SkDrawMatrix::dirty() { + fDirty = true; +} + +bool SkDrawMatrix::draw(SkAnimateMaker& maker) { + SkMatrix& concat = getMatrix(); + maker.fCanvas->concat(concat); + return false; +} + +#ifdef SK_DUMP_ENABLED +void SkDrawMatrix::dump(SkAnimateMaker* maker) { + dumpBase(maker); + if (fMatrix.isIdentity()) { + SkDebugf("matrix=\"identity\"/>\n"); + return; + } + SkScalar result; + result = fMatrix.getScaleX(); + if (result != SK_Scalar1) + SkDebugf("sx=\"%g\" ", SkScalarToFloat(result)); + result = fMatrix.getScaleY(); + if (result != SK_Scalar1) + SkDebugf("sy=\"%g\" ", SkScalarToFloat(result)); + result = fMatrix.getSkewX(); + if (result) + SkDebugf("skew-x=\"%g\" ", SkScalarToFloat(result)); + result = fMatrix.getSkewY(); + if (result) + SkDebugf("skew-y=\"%g\" ", SkScalarToFloat(result)); + result = fMatrix.getTranslateX(); + if (result) + SkDebugf("tx=\"%g\" ", SkScalarToFloat(result)); + result = fMatrix.getTranslateY(); + if (result) + SkDebugf("ty=\"%g\" ", SkScalarToFloat(result)); + result = fMatrix.getPerspX(); + if (result) + SkDebugf("perspect-x=\"%g\" ", SkScalarToFloat(result)); + result = fMatrix.getPerspY(); + if (result) + SkDebugf("perspect-y=\"%g\" ", SkScalarToFloat(result)); + SkDebugf("/>\n"); +} +#endif + +SkMatrix& SkDrawMatrix::getMatrix() { + if (fDirty == false) + return fConcat; + fMatrix.reset(); + for (SkMatrixPart** part = fParts.begin(); part < fParts.end(); part++) { + (*part)->add(); + fConcat = fMatrix; + } + fDirty = false; + return fConcat; +} + +bool SkDrawMatrix::getProperty(int index, SkScriptValue* value) const { + value->fType = SkType_Float; + SkScalar result; + switch (index) { + case SK_PROPERTY(perspectX): + result = fMatrix.getPerspX(); + break; + case SK_PROPERTY(perspectY): + result = fMatrix.getPerspY(); + break; + case SK_PROPERTY(scaleX): + result = fMatrix.getScaleX(); + break; + case SK_PROPERTY(scaleY): + result = fMatrix.getScaleY(); + break; + case SK_PROPERTY(skewX): + result = fMatrix.getSkewX(); + break; + case SK_PROPERTY(skewY): + result = fMatrix.getSkewY(); + break; + case SK_PROPERTY(translateX): + result = fMatrix.getTranslateX(); + break; + case SK_PROPERTY(translateY): + result = fMatrix.getTranslateY(); + break; + default: +// SkASSERT(0); + return false; + } + value->fOperand.fScalar = result; + return true; +} + +void SkDrawMatrix::initialize() { + fConcat = fMatrix; +} + +void SkDrawMatrix::onEndElement(SkAnimateMaker& ) { + if (matrix.count() > 0) { + SkScalar* vals = matrix.begin(); + fMatrix.setScaleX(vals[0]); + fMatrix.setSkewX(vals[1]); + fMatrix.setTranslateX(vals[2]); + fMatrix.setSkewY(vals[3]); + fMatrix.setScaleY(vals[4]); + fMatrix.setTranslateY(vals[5]); +#ifdef SK_SCALAR_IS_FIXED + fMatrix.setPerspX(SkFixedToFract(vals[6])); + fMatrix.setPerspY(SkFixedToFract(vals[7])); +#else + fMatrix.setPerspX(vals[6]); + fMatrix.setPerspY(vals[7]); +#endif +// fMatrix.setPerspW(vals[8]); + goto setConcat; + } + if (fChildHasID == false) { + { + for (SkMatrixPart** part = fParts.begin(); part < fParts.end(); part++) + delete *part; + } + fParts.reset(); +setConcat: + fConcat = fMatrix; + fDirty = false; + } +} + +void SkDrawMatrix::setChildHasID() { + fChildHasID = true; +} + +bool SkDrawMatrix::setProperty(int index, SkScriptValue& scriptValue) { + SkScalar number = scriptValue.fOperand.fScalar; + switch (index) { + case SK_PROPERTY(translate): + // SkScalar xy[2]; + SkASSERT(scriptValue.fType == SkType_Array); + SkASSERT(scriptValue.fOperand.fArray->getType() == SkType_Float); + SkASSERT(scriptValue.fOperand.fArray->count() == 2); + // SkParse::FindScalars(scriptValue.fOperand.fString->c_str(), xy, 2); + fMatrix.setTranslateX((*scriptValue.fOperand.fArray)[0].fScalar); + fMatrix.setTranslateY((*scriptValue.fOperand.fArray)[1].fScalar); + return true; + case SK_PROPERTY(perspectX): +#ifdef SK_SCALAR_IS_FIXED + fMatrix.setPerspX(SkFixedToFract(number)); +#else + fMatrix.setPerspX(number); +#endif + break; + case SK_PROPERTY(perspectY): +#ifdef SK_SCALAR_IS_FIXED + fMatrix.setPerspY(SkFixedToFract(number)); +#else + fMatrix.setPerspY(number); +#endif + break; + case SK_PROPERTY(rotate): { + SkMatrix temp; + temp.setRotate(number, 0, 0); + fMatrix.setScaleX(temp.getScaleX()); + fMatrix.setScaleY(temp.getScaleY()); + fMatrix.setSkewX(temp.getSkewX()); + fMatrix.setSkewY(temp.getSkewY()); + } break; + case SK_PROPERTY(scale): + fMatrix.setScaleX(number); + fMatrix.setScaleY(number); + break; + case SK_PROPERTY(scaleX): + fMatrix.setScaleX(number); + break; + case SK_PROPERTY(scaleY): + fMatrix.setScaleY(number); + break; + case SK_PROPERTY(skewX): + fMatrix.setSkewX(number); + break; + case SK_PROPERTY(skewY): + fMatrix.setSkewY(number); + break; + case SK_PROPERTY(translateX): + fMatrix.setTranslateX(number); + break; + case SK_PROPERTY(translateY): + fMatrix.setTranslateY(number); + break; + default: + SkASSERT(0); + return false; + } + fConcat = fMatrix; + return true; +} + diff --git a/libs/graphics/animator/SkDrawMatrix.h b/libs/graphics/animator/SkDrawMatrix.h new file mode 100644 index 000000000..df5529231 --- /dev/null +++ b/libs/graphics/animator/SkDrawMatrix.h @@ -0,0 +1,65 @@ +#ifndef SkDrawMatrix_DEFINED +#define SkDrawMatrix_DEFINED + +#include "SkDrawable.h" +#include "SkMatrix.h" +#include "SkMemberInfo.h" +#include "SkIntArray.h" + +class SkMatrixPart; + +class SkDrawMatrix : public SkDrawable { + DECLARE_DRAW_MEMBER_INFO(Matrix); + SkDrawMatrix(); + virtual ~SkDrawMatrix(); + virtual bool add(SkAnimateMaker& , SkDisplayable* child); + virtual bool childrenNeedDisposing() const; + virtual void dirty(); + virtual bool draw(SkAnimateMaker& ); +#ifdef SK_DUMP_ENABLED + virtual void dump(SkAnimateMaker* ); +#endif + SkMatrix& getMatrix(); + virtual bool getProperty(int index, SkScriptValue* value) const; + virtual void initialize(); + virtual void onEndElement(SkAnimateMaker& ); + virtual void setChildHasID(); + virtual bool setProperty(int index, SkScriptValue& ); + + void concat(SkMatrix& inMatrix) { + fConcat.preConcat(inMatrix); + } + + virtual SkDisplayable* deepCopy(SkAnimateMaker* ); + + + void rotate(SkScalar degrees, SkPoint& center) { + fMatrix.preRotate(degrees, center.fX, center.fY); + } + + void set(SkMatrix& src) { + fMatrix.preConcat(src); + } + + void scale(SkScalar scaleX, SkScalar scaleY, SkPoint& center) { + fMatrix.preScale(scaleX, scaleY, center.fX, center.fY); + } + + void skew(SkScalar skewX, SkScalar skewY, SkPoint& center) { + fMatrix.preSkew(skewX, skewY, center.fX, center.fY); + } + + void translate(SkScalar x, SkScalar y) { + fMatrix.preTranslate(x, y); + } +private: + SkTDScalarArray matrix; + SkMatrix fConcat; + SkMatrix fMatrix; + SkTDMatrixPartArray fParts; + SkBool8 fChildHasID; + SkBool8 fDirty; + typedef SkDrawable INHERITED; +}; + +#endif // SkDrawMatrix_DEFINED diff --git a/libs/graphics/animator/SkDrawOval.cpp b/libs/graphics/animator/SkDrawOval.cpp new file mode 100644 index 000000000..11614ebd1 --- /dev/null +++ b/libs/graphics/animator/SkDrawOval.cpp @@ -0,0 +1,20 @@ +#include "SkDrawOval.h" +#include "SkAnimateMaker.h" +#include "SkCanvas.h" + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkOval::fInfo[] = { + SK_MEMBER_INHERITED, +}; + +#endif + +DEFINE_GET_MEMBER(SkOval); + +bool SkOval::draw(SkAnimateMaker& maker) { + SkBoundableAuto boundable(this, maker); + maker.fCanvas->drawOval(fRect, *maker.fPaint); + return false; +} + diff --git a/libs/graphics/animator/SkDrawOval.h b/libs/graphics/animator/SkDrawOval.h new file mode 100644 index 000000000..e91576ada --- /dev/null +++ b/libs/graphics/animator/SkDrawOval.h @@ -0,0 +1,14 @@ +#ifndef SkDrawOval_DEFINED +#define SkDrawOval_DEFINED + +#include "SkDrawRectangle.h" + +class SkOval : public SkDrawRect { + DECLARE_MEMBER_INFO(Oval); + virtual bool draw(SkAnimateMaker& ); +private: + typedef SkDrawRect INHERITED; +}; + +#endif // SkDrawOval_DEFINED + diff --git a/libs/graphics/animator/SkDrawPaint.cpp b/libs/graphics/animator/SkDrawPaint.cpp new file mode 100644 index 000000000..1f13091f4 --- /dev/null +++ b/libs/graphics/animator/SkDrawPaint.cpp @@ -0,0 +1,260 @@ +#include "SkDrawPaint.h" +#include "SkAnimateMaker.h" +#include "SkDrawColor.h" +#include "SkDrawShader.h" +#include "SkMaskFilter.h" +#include "SkPaintParts.h" +#include "SkPathEffect.h" + +enum SkPaint_Functions { + SK_FUNCTION(measureText) +}; + +enum SkPaint_Properties { + SK_PROPERTY(ascent), + SK_PROPERTY(descent) +}; + +// !!! in the future, this could be compiled by build-condensed-info into an array of parameters +// with a lookup table to find the first parameter -- for now, it is iteratively searched through +const SkFunctionParamType SkDrawPaint::fFunctionParameters[] = { + (SkFunctionParamType) SkType_String, + (SkFunctionParamType) 0 // terminator for parameter list (there may be multiple parameter lists) +}; + + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDrawPaint::fInfo[] = { + SK_MEMBER(antiAlias, Boolean), + SK_MEMBER_PROPERTY(ascent, Float), + SK_MEMBER(color, Color), + SK_MEMBER_PROPERTY(descent, Float), + SK_MEMBER(fakeBold, Boolean), + SK_MEMBER(filterType, FilterType), + SK_MEMBER(linearText, Boolean), + SK_MEMBER(maskFilter, MaskFilter), + SK_MEMBER_FUNCTION(measureText, Float), + SK_MEMBER(pathEffect, PathEffect), + SK_MEMBER(shader, Shader), + SK_MEMBER(strikeThru, Boolean), + SK_MEMBER(stroke, Boolean), + SK_MEMBER(strokeCap, Cap), + SK_MEMBER(strokeJoin, Join), + SK_MEMBER(strokeMiter, Float), + SK_MEMBER(strokeWidth, Float), + SK_MEMBER(style, Style), + SK_MEMBER(textAlign, Align), + SK_MEMBER(textScaleX, Float), + SK_MEMBER(textSize, Float), + SK_MEMBER(textSkewX, Float), + SK_MEMBER(typeface, Typeface), + SK_MEMBER(underline, Boolean), + SK_MEMBER(xfermode, Xfermode) +}; + +#endif + +DEFINE_GET_MEMBER(SkDrawPaint); + +SkDrawPaint::SkDrawPaint() : antiAlias(-1), color(NULL), fakeBold(-1), filterType((SkPaint::FilterType) -1), + linearText(-1), maskFilter((SkDrawMaskFilter*) -1), pathEffect((SkDrawPathEffect*) -1), + shader((SkDrawShader*) -1), strikeThru(-1), stroke(-1), + strokeCap((SkPaint::Cap) -1), strokeJoin((SkPaint::Join) -1), strokeMiter(SK_ScalarNaN), + strokeWidth(SK_ScalarNaN), style((SkPaint::Style) -1), + textAlign((SkPaint::Align) -1), textScaleX(SK_ScalarNaN), textSize(SK_ScalarNaN), + textSkewX(SK_ScalarNaN), typeface((SkDrawTypeface*) -1), + underline(-1), xfermode((SkPorterDuff::Mode) -1), fOwnsColor(false), fOwnsMaskFilter(false), + fOwnsPathEffect(false), fOwnsShader(false), fOwnsTypeface(false) { +} + +SkDrawPaint::~SkDrawPaint() { + if (fOwnsColor) + delete color; + if (fOwnsMaskFilter) + delete maskFilter; + if (fOwnsPathEffect) + delete pathEffect; + if (fOwnsShader) + delete shader; + if (fOwnsTypeface) + delete typeface; +} + +bool SkDrawPaint::add(SkAnimateMaker& maker, SkDisplayable* child) { + SkASSERT(child && child->isPaintPart()); + SkPaintPart* part = (SkPaintPart*) child; + if (part->add()) + maker.setErrorCode(SkDisplayXMLParserError::kErrorAddingToPaint); + return true; +} + +SkDisplayable* SkDrawPaint::deepCopy(SkAnimateMaker* maker) { + SkDrawColor* tempColor = color; + color = NULL; + SkDrawPaint* copy = (SkDrawPaint*) INHERITED::deepCopy(maker); + color = tempColor; + tempColor = (SkDrawColor*) color->deepCopy(maker); + tempColor->setParent(copy); + tempColor->add(); + copy->fOwnsColor = true; + return copy; +} + +bool SkDrawPaint::draw(SkAnimateMaker& maker) { + SkPaint* paint = maker.fPaint; + setupPaint(paint); + return false; +} + +#ifdef SK_DUMP_ENABLED +void SkDrawPaint::dump(SkAnimateMaker* maker) { + dumpBase(maker); + dumpAttrs(maker); + bool closedYet = false; + SkDisplayList::fIndent +=4; + //should i say if (maskFilter && ...? + if (maskFilter != (SkDrawMaskFilter*)-1) { + SkDebugf(">\n"); + maskFilter->dump(maker); + closedYet = true; + } + if (pathEffect != (SkDrawPathEffect*) -1) { + if (closedYet == false) { + SkDebugf(">\n"); + closedYet = true; + } + pathEffect->dump(maker); + } + if (fOwnsTypeface) { + if (closedYet == false) { + SkDebugf(">\n"); + closedYet = true; + } + typeface->dump(maker); + } + SkDisplayList::fIndent -= 4; + dumpChildren(maker, closedYet); +} +#endif + +void SkDrawPaint::executeFunction(SkDisplayable* target, int index, + SkTDArray& parameters, SkDisplayTypes type, + SkScriptValue* scriptValue) { + if (scriptValue == NULL) + return; + SkASSERT(target == this); + switch (index) { + case SK_FUNCTION(measureText): { + SkASSERT(parameters.count() == 1); + SkASSERT(type == SkType_Float); + SkPaint paint; + setupPaint(&paint); + scriptValue->fType = SkType_Float; + SkASSERT(parameters[0].fType == SkType_String); + scriptValue->fOperand.fScalar = paint.measureText(parameters[0].fOperand.fString->c_str(), + parameters[0].fOperand.fString->size()); +// SkDebugf("measureText: %s = %g\n", parameters[0].fOperand.fString->c_str(), +// scriptValue->fOperand.fScalar / 65536.0f); + } break; + default: + SkASSERT(0); + } +} + +const SkFunctionParamType* SkDrawPaint::getFunctionsParameters() { + return fFunctionParameters; +} + +bool SkDrawPaint::getProperty(int index, SkScriptValue* value) const { + SkScalar above, below; + SkPaint paint; + setupPaint(&paint); + paint.measureText("", 0, &above, &below); + switch (index) { + case SK_PROPERTY(ascent): + value->fOperand.fScalar = above; + break; + case SK_PROPERTY(descent): + value->fOperand.fScalar = below; + break; + default: + SkASSERT(0); + return false; + } + value->fType = SkType_Float; + return true; +} + +bool SkDrawPaint::resolveIDs(SkAnimateMaker& maker, SkDisplayable* origDisp, SkApply* ) { + SkASSERT(origDisp->isPaint()); + SkDrawPaint* original = (SkDrawPaint*) origDisp; + if (fOwnsColor && maker.resolveID(color, original->color) == false) + return true; + if (fOwnsMaskFilter && maker.resolveID(maskFilter, original->maskFilter) == false) + return true; + if (fOwnsPathEffect && maker.resolveID(pathEffect, original->pathEffect) == false) + return true; + if (fOwnsShader && maker.resolveID(shader, original->shader) == false) + return true; + if (fOwnsTypeface && maker.resolveID(typeface, original->typeface) == false) + return true; + return false; // succeeded +} + +void SkDrawPaint::setupPaint(SkPaint* paint) const { + if (antiAlias != -1) + paint->setAntiAliasOn(SkToBool(antiAlias)); + if (color != NULL) + paint->setColor(color->getColor()); + if (fakeBold != -1) + paint->setFakeBoldTextOn(SkToBool(fakeBold)); + if (filterType != (SkPaint::FilterType) -1) + paint->setFilterType((SkPaint::FilterType) filterType); + // stroke is legacy; style setting if present overrides stroke + if (stroke != -1) + paint->setStyle(SkToBool(stroke) ? SkPaint::kStroke_Style : SkPaint::kFill_Style); + if (style != (SkPaint::Style) -1) + paint->setStyle((SkPaint::Style) style); + if (linearText != -1) + paint->setLinearTextOn(SkToBool(linearText)); + if (maskFilter == NULL) + paint->setMaskFilter(NULL); + else if (maskFilter != (SkDrawMaskFilter*) -1) + paint->setMaskFilter(maskFilter->getMaskFilter())->safeUnref(); + if (pathEffect == NULL) + paint->setPathEffect(NULL); + else if (pathEffect != (SkDrawPathEffect*) -1) + paint->setPathEffect(pathEffect->getPathEffect())->safeUnref(); + if (shader == NULL) + paint->setShader(NULL); + else if (shader != (SkDrawShader*) -1) + paint->setShader(shader->getShader())->safeUnref(); + if (strikeThru != -1) + paint->setStrikeThruTextOn(SkToBool(strikeThru)); + if (strokeCap != (SkPaint::Cap) -1) + paint->setStrokeCap((SkPaint::Cap) strokeCap); + if (strokeJoin != (SkPaint::Join) -1) + paint->setStrokeJoin((SkPaint::Join) strokeJoin); + if (SkScalarIsNaN(strokeMiter) == false) + paint->setStrokeMiter(strokeMiter); + if (SkScalarIsNaN(strokeWidth) == false) + paint->setStrokeWidth(strokeWidth); + if (textAlign != (SkPaint::Align) -1) + paint->setTextAlign((SkPaint::Align) textAlign); + if (SkScalarIsNaN(textScaleX) == false) + paint->setTextScaleX(textScaleX); + if (SkScalarIsNaN(textSize) == false) + paint->setTextSize(textSize); + if (SkScalarIsNaN(textSkewX) == false) + paint->setTextSkewX(textSkewX); + if (typeface == NULL) + paint->setTypeface(NULL); + else if (typeface != (SkDrawTypeface*) -1) + paint->setTypeface(typeface->getTypeface())->safeUnref(); + if (underline != -1) + paint->setUnderlineTextOn(SkToBool(underline)); + if (xfermode != (SkPorterDuff::Mode) -1) + paint->setPorterDuffXfermode((SkPorterDuff::Mode) xfermode); +} + diff --git a/libs/graphics/animator/SkDrawPaint.h b/libs/graphics/animator/SkDrawPaint.h new file mode 100644 index 000000000..3ae0ffa49 --- /dev/null +++ b/libs/graphics/animator/SkDrawPaint.h @@ -0,0 +1,71 @@ +#ifndef SkDrawPaint_DEFINED +#define SkDrawPaint_DEFINED + +#include "SkDrawable.h" +#include "SkIntArray.h" +#include "SkMemberInfo.h" +#include "SkPaint.h" +#include "SkXfermode.h" + +class SkDrawMaskFilter; +class SkDrawPathEffect; +class SkDrawShader; +class SkTransferMode; +class SkDrawTypeface; + +class SkDrawPaint : public SkDrawable { + DECLARE_DRAW_MEMBER_INFO(Paint); + SkDrawPaint(); + virtual ~SkDrawPaint(); + virtual bool add(SkAnimateMaker& , SkDisplayable* child); + virtual SkDisplayable* deepCopy(SkAnimateMaker* ); + virtual bool draw(SkAnimateMaker& ); +#ifdef SK_DUMP_ENABLED + virtual void dump(SkAnimateMaker* ); +#endif + virtual void executeFunction(SkDisplayable* target, int index, + SkTDArray& parameters, SkDisplayTypes type, + SkScriptValue* ); + virtual const SkFunctionParamType* getFunctionsParameters(); + virtual bool getProperty(int index, SkScriptValue* value) const; + virtual bool resolveIDs(SkAnimateMaker& maker, SkDisplayable* original, SkApply* apply); +protected: + static const SkFunctionParamType fFunctionParameters[]; + void setupPaint(SkPaint* paint) const; +public: + SkBool antiAlias; + SkDrawColor* color; + SkBool fakeBold; + int /*SkPaint::FilterType*/ filterType; + SkBool linearText; + SkDrawMaskFilter* maskFilter; + SkDrawPathEffect* pathEffect; + SkDrawShader* shader; + SkBool strikeThru; + SkBool stroke; + int /*SkPaint::Cap*/ strokeCap; + int /*SkPaint::Join */ strokeJoin; + SkScalar strokeMiter; + SkScalar strokeWidth; + int /* SkPaint::Style */ style; + int /* SkPaint::Align */ textAlign; + SkScalar textScaleX; + SkScalar textSize; + SkScalar textSkewX; + SkDrawTypeface* typeface; + SkBool underline; + int /*SkXfermode::Modes*/ xfermode; + SkBool8 fOwnsColor; + SkBool8 fOwnsMaskFilter; + SkBool8 fOwnsPathEffect; + SkBool8 fOwnsShader; + SkBool8 fOwnsTransferMode; + SkBool8 fOwnsTypeface; +private: + typedef SkDrawable INHERITED; + friend class SkTextToPath; + friend class SkSaveLayer; +}; + +#endif // SkDrawPaint_DEFINED + diff --git a/libs/graphics/animator/SkDrawPath.cpp b/libs/graphics/animator/SkDrawPath.cpp new file mode 100644 index 000000000..302460089 --- /dev/null +++ b/libs/graphics/animator/SkDrawPath.cpp @@ -0,0 +1,212 @@ +#include "SkDrawPath.h" +#include "SkAnimateMaker.h" +#include "SkCanvas.h" +#include "SkMath.h" +#include "SkMatrixParts.h" +#include "SkPaint.h" +#include "SkPathParts.h" + +enum SkPath_Properties { + SK_PROPERTY(fillType), + SK_PROPERTY(length) +}; + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDrawPath::fInfo[] = { + SK_MEMBER(d, String), + SK_MEMBER_PROPERTY(fillType, FillType), + SK_MEMBER_PROPERTY(length, Float) +}; + +#endif + +DEFINE_GET_MEMBER(SkDrawPath); + +SkDrawPath::SkDrawPath() +{ + fParent = nil; + fLength = SK_ScalarNaN; + fChildHasID = false; + fDirty = false; +} + +SkDrawPath::~SkDrawPath() { + for (SkPathPart** part = fParts.begin(); part < fParts.end(); part++) + delete *part; +} + +bool SkDrawPath::add(SkAnimateMaker& maker, SkDisplayable* child) { + SkASSERT(child && child->isPathPart()); + SkPathPart* part = (SkPathPart*) child; + *fParts.append() = part; + if (part->add()) + maker.setErrorCode(SkDisplayXMLParserError::kErrorAddingToPath); + fDirty = false; + return true; +} + +bool SkDrawPath::childrenNeedDisposing() const { + return false; +} + +void SkDrawPath::dirty() { + fDirty = true; + fLength = SK_ScalarNaN; + if (fParent) + fParent->dirty(); +} + +bool SkDrawPath::draw(SkAnimateMaker& maker) { + SkPath& path = getPath(); + SkBoundableAuto boundable(this, maker); + maker.fCanvas->drawPath(path, *maker.fPaint); + return false; +} + +SkDisplayable* SkDrawPath::getParent() const { + return fParent; +} + +#ifdef SK_DUMP_ENABLED +void SkDrawPath::dump(SkAnimateMaker* maker) { + dumpBase(maker); + dumpAttrs(maker); + bool closedYet = false; + SkDisplayList::fIndent += 4; + for(SkPathPart** part = fParts.begin(); part < fParts.end(); part++) { + if (closedYet == false) { + SkDebugf(">\n"); + closedYet = true; + } + (*part)->dump(maker); + } + SkDisplayList::fIndent -= 4; + if (closedYet) + dumpEnd(maker); + else + SkDebugf("/>\n"); +} +#endif + +SkPath& SkDrawPath::getPath() { + if (fDirty == false) + return fPath; + if (d.size() > 0) + { + parseSVG(); + d.reset(); + } + else + { + fPath.reset(); + for (SkPathPart** part = fParts.begin(); part < fParts.end(); part++) + (*part)->add(); + } + fDirty = false; + return fPath; +} + +void SkDrawPath::onEndElement(SkAnimateMaker& ) { + if (d.size() > 0) { + parseSVG(); + d.reset(); + fDirty = false; + return; + } + if (fChildHasID == false) { + for (SkPathPart** part = fParts.begin(); part < fParts.end(); part++) + delete *part; + fParts.reset(); + fDirty = false; + } +} + +bool SkDrawPath::getProperty(int index, SkScriptValue* value) const { + switch (index) { + case SK_PROPERTY(length): + if (SkScalarIsNaN(fLength)) { + const SkPath& path = ((SkDrawPath*) this)->getPath(); + SkPathMeasure pathMeasure(path, false); + fLength = pathMeasure.getLength(); + } + value->fType = SkType_Float; + value->fOperand.fScalar = fLength; + break; + case SK_PROPERTY(fillType): + value->fType = SkType_FillType; + value->fOperand.fS32 = (int) fPath.getFillType(); + break; + default: + SkASSERT(0); + return false; + } + return true; +} + +void SkDrawPath::setChildHasID() { + fChildHasID = true; +} + +bool SkDrawPath::setParent(SkDisplayable* parent) { + fParent = parent; + return false; +} + +bool SkDrawPath::setProperty(int index, SkScriptValue& value) +{ + switch (index) { + case SK_PROPERTY(fillType): + SkASSERT(value.fType == SkType_FillType); + SkASSERT(value.fOperand.fS32 >= SkPath::kWinding_FillType && + value.fOperand.fS32 <= SkPath::kEvenOdd_FillType); + fPath.setFillType((SkPath::FillType) value.fOperand.fS32); + break; + default: + SkASSERT(0); + return false; + } + return true; +} + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkPolyline::fInfo[] = { + SK_MEMBER_ARRAY(points, Float) +}; + +#endif + +DEFINE_GET_MEMBER(SkPolyline); + +bool SkPolyline::add(SkAnimateMaker& , SkDisplayable*) const { + return false; +} + +void SkPolyline::onEndElement(SkAnimateMaker& maker) { + INHERITED::onEndElement(maker); + if (points.count() <= 0) + return; + fPath.reset(); + fPath.moveTo(points[0], points[1]); + int count = points.count(); + for (int index = 2; index < count; index += 2) + fPath.lineTo(points[index], points[index+1]); +} + + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkPolygon::fInfo[] = { + SK_MEMBER_INHERITED +}; + +#endif + +DEFINE_GET_MEMBER(SkPolygon); + +void SkPolygon::onEndElement(SkAnimateMaker& maker) { + INHERITED::onEndElement(maker); + fPath.close(); +} + diff --git a/libs/graphics/animator/SkDrawPath.h b/libs/graphics/animator/SkDrawPath.h new file mode 100644 index 000000000..3c005a5df --- /dev/null +++ b/libs/graphics/animator/SkDrawPath.h @@ -0,0 +1,60 @@ +#ifndef SkDrawPath_DEFINED +#define SkDrawPath_DEFINED + +#include "SkBoundable.h" +#include "SkIntArray.h" +#include "SkMemberInfo.h" +#include "SkPath.h" + +class SkDrawPath : public SkBoundable { + DECLARE_DRAW_MEMBER_INFO(Path); + SkDrawPath(); + virtual ~SkDrawPath(); + virtual bool add(SkAnimateMaker& , SkDisplayable* child); + bool childHasID() { return SkToBool(fChildHasID); } + virtual bool childrenNeedDisposing() const; + virtual void dirty(); + virtual bool draw(SkAnimateMaker& ); + virtual SkDisplayable* getParent() const; +#ifdef SK_DUMP_ENABLED + virtual void dump(SkAnimateMaker* ); +#endif + SkPath& getPath(); + virtual bool getProperty(int index, SkScriptValue* value) const; + virtual bool setProperty(int index, SkScriptValue& value); + virtual void onEndElement(SkAnimateMaker& ); + virtual void setChildHasID(); + virtual bool setParent(SkDisplayable* parent); + virtual bool isPath() const { return true; } +public: + SkPath fPath; +protected: + void parseSVG(); + SkString d; + SkTDPathPartArray fParts; + mutable SkScalar fLength; + SkDisplayable* fParent; // SkPolyToPoly or SkFromPath, for instance + SkBool8 fChildHasID; + SkBool8 fDirty; +private: + typedef SkBoundable INHERITED; +}; + +class SkPolyline : public SkDrawPath { + DECLARE_MEMBER_INFO(Polyline); + virtual bool add(SkAnimateMaker& , SkDisplayable*) const; + virtual void onEndElement(SkAnimateMaker& ); +protected: + SkTDScalarArray points; +private: + typedef SkDrawPath INHERITED; +}; + +class SkPolygon : public SkPolyline { + DECLARE_MEMBER_INFO(Polygon); + virtual void onEndElement(SkAnimateMaker& ); +private: + typedef SkPolyline INHERITED; +}; + +#endif // SkDrawPath_DEFINED diff --git a/libs/graphics/animator/SkDrawPoint.cpp b/libs/graphics/animator/SkDrawPoint.cpp new file mode 100644 index 000000000..4bbd00611 --- /dev/null +++ b/libs/graphics/animator/SkDrawPoint.cpp @@ -0,0 +1,37 @@ +#include "SkDrawPoint.h" +#include "SkAnimateMaker.h" +#include "SkCanvas.h" +#include "SkPaint.h" + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo Sk_Point::fInfo[] = { + SK_MEMBER_ALIAS(x, fPoint.fX, Float), + SK_MEMBER_ALIAS(y, fPoint.fY, Float) +}; + +#endif + +DEFINE_NO_VIRTUALS_GET_MEMBER(Sk_Point); + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDrawPoint::fInfo[] = { + SK_MEMBER_ALIAS(x, fPoint.fX, Float), + SK_MEMBER_ALIAS(y, fPoint.fY, Float) +}; + +#endif + +DEFINE_GET_MEMBER(SkDrawPoint); + +SkDrawPoint::SkDrawPoint() { + fPoint.set(0, 0); +} + +void SkDrawPoint::getBounds(SkRect* rect ) { + rect->fLeft = rect->fRight = fPoint.fX; + rect->fTop = rect->fBottom = fPoint.fY; +} + + diff --git a/libs/graphics/animator/SkDrawPoint.h b/libs/graphics/animator/SkDrawPoint.h new file mode 100644 index 000000000..c59c78a97 --- /dev/null +++ b/libs/graphics/animator/SkDrawPoint.h @@ -0,0 +1,24 @@ +#ifndef SkDrawPoint_DEFINED +#define SkDrawPoint_DEFINED + +#include "SkBoundable.h" +#include "SkMemberInfo.h" +#include "SkPoint.h" + +struct Sk_Point { + DECLARE_NO_VIRTUALS_MEMBER_INFO(_Point); + Sk_Point(); +private: + SkPoint fPoint; +}; + +class SkDrawPoint : public SkDisplayable { + DECLARE_MEMBER_INFO(DrawPoint); + SkDrawPoint(); + virtual void getBounds(SkRect* ); +private: + SkPoint fPoint; + typedef SkDisplayable INHERITED; +}; + +#endif // SkDrawPoint_DEFINED diff --git a/libs/graphics/animator/SkDrawRectangle.cpp b/libs/graphics/animator/SkDrawRectangle.cpp new file mode 100644 index 000000000..3ccb347ed --- /dev/null +++ b/libs/graphics/animator/SkDrawRectangle.cpp @@ -0,0 +1,136 @@ +#include "SkDrawRectangle.h" +#include "SkAnimateMaker.h" +#include "SkCanvas.h" +#include "SkMatrixParts.h" +#include "SkPaint.h" +#include "SkScript.h" + +enum SkRectangle_Properties { + SK_PROPERTY(height), + SK_PROPERTY(needsRedraw), + SK_PROPERTY(width) +}; + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDrawRect::fInfo[] = { + SK_MEMBER_ALIAS(bottom, fRect.fBottom, Float), + SK_MEMBER_PROPERTY(height, Float), + SK_MEMBER_ALIAS(left, fRect.fLeft, Float), + SK_MEMBER_PROPERTY(needsRedraw, Boolean), + SK_MEMBER_ALIAS(right, fRect.fRight, Float), + SK_MEMBER_ALIAS(top, fRect.fTop, Float), + SK_MEMBER_PROPERTY(width, Float) +}; + +#endif + +DEFINE_GET_MEMBER(SkDrawRect); + +SkDrawRect::SkDrawRect() : fParent(nil) { + fRect.setEmpty(); +} + +void SkDrawRect::dirty() { + if (fParent) + fParent->dirty(); +} + +bool SkDrawRect::draw(SkAnimateMaker& maker) { + SkBoundableAuto boundable(this, maker); + maker.fCanvas->drawRect(fRect, *maker.fPaint); + return false; +} + +#ifdef SK_DUMP_ENABLED +void SkDrawRect::dump(SkAnimateMaker* maker) { + dumpBase(maker); + SkDebugf("left=\"%g\" top=\"%g\" right=\"%g\" bottom=\"%g\" />\n", + SkScalarToFloat(fRect.fLeft), SkScalarToFloat(fRect.fTop), SkScalarToFloat(fRect.fRight), + SkScalarToFloat(fRect.fBottom)); +} +#endif + +SkDisplayable* SkDrawRect::getParent() const { + return fParent; +} + +bool SkDrawRect::getProperty(int index, SkScriptValue* value) const { + SkScalar result; + switch (index) { + case SK_PROPERTY(height): + result = fRect.height(); + break; + case SK_PROPERTY(needsRedraw): + value->fType = SkType_Boolean; + value->fOperand.fS32 = fBounds.isEmpty() == false; + return true; + case SK_PROPERTY(width): + result = fRect.width(); + break; + default: + SkASSERT(0); + return false; + } + value->fType = SkType_Float; + value->fOperand.fScalar = result; + return true; +} + + +bool SkDrawRect::setParent(SkDisplayable* parent) { + fParent = parent; + return false; +} + +bool SkDrawRect::setProperty(int index, SkScriptValue& value) { + SkScalar scalar = value.fOperand.fScalar; + switch (index) { + case SK_PROPERTY(height): + SkASSERT(value.fType == SkType_Float); + fRect.fBottom = scalar + fRect.fTop; + return true; + case SK_PROPERTY(needsRedraw): + return false; + case SK_PROPERTY(width): + SkASSERT(value.fType == SkType_Float); + fRect.fRight = scalar + fRect.fLeft; + return true; + default: + SkASSERT(0); + } + return false; +} + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkRoundRect::fInfo[] = { + SK_MEMBER_INHERITED, + SK_MEMBER(rx, Float), + SK_MEMBER(ry, Float), +}; + +#endif + +DEFINE_GET_MEMBER(SkRoundRect); + +SkRoundRect::SkRoundRect() : rx(0), ry(0) { +} + +bool SkRoundRect::draw(SkAnimateMaker& maker) { + SkBoundableAuto boundable(this, maker); + maker.fCanvas->drawRoundRect(fRect, rx, ry, *maker.fPaint); + return false; +} + +#ifdef SK_DUMP_ENABLED +void SkRoundRect::dump(SkAnimateMaker* maker) { + dumpBase(maker); + SkDebugf("left=\"%g\" top=\"%g\" right=\"%g\" bottom=\"%g\" rx=\"%g\" ry=\"%g\" />\n", + SkScalarToFloat(fRect.fLeft), SkScalarToFloat(fRect.fTop), SkScalarToFloat(fRect.fRight), + SkScalarToFloat(fRect.fBottom), SkScalarToFloat(rx), SkScalarToFloat(ry)); +} +#endif + + + diff --git a/libs/graphics/animator/SkDrawRectangle.h b/libs/graphics/animator/SkDrawRectangle.h new file mode 100644 index 000000000..6abb6e486 --- /dev/null +++ b/libs/graphics/animator/SkDrawRectangle.h @@ -0,0 +1,47 @@ +#ifndef SkDrawRectangle_DEFINED +#define SkDrawRectangle_DEFINED + +#include "SkBoundable.h" +#include "SkMemberInfo.h" +#include "SkRect.h" + +class SkRectToRect; + +class SkDrawRect : public SkBoundable { + DECLARE_DRAW_MEMBER_INFO(Rect); + SkDrawRect(); + virtual void dirty(); + virtual bool draw(SkAnimateMaker& ); +#ifdef SK_DUMP_ENABLED + virtual void dump(SkAnimateMaker* ); +#endif + virtual SkDisplayable* getParent() const; + virtual bool getProperty(int index, SkScriptValue* value) const; + virtual bool setParent(SkDisplayable* parent); + virtual bool setProperty(int index, SkScriptValue& ); +protected: + SkRect fRect; + SkDisplayable* fParent; +private: + friend class SkDrawClip; + friend class SkRectToRect; + friend class SkSaveLayer; + typedef SkBoundable INHERITED; +}; + +class SkRoundRect : public SkDrawRect { + DECLARE_MEMBER_INFO(RoundRect); + SkRoundRect(); + virtual bool draw(SkAnimateMaker& ); +#ifdef SK_DUMP_ENABLED + virtual void dump(SkAnimateMaker* ); +#endif +protected: + SkScalar rx; + SkScalar ry; +private: + typedef SkDrawRect INHERITED; +}; + +#endif // SkDrawRectangle_DEFINED + diff --git a/libs/graphics/animator/SkDrawSaveLayer.cpp b/libs/graphics/animator/SkDrawSaveLayer.cpp new file mode 100644 index 000000000..c6addb888 --- /dev/null +++ b/libs/graphics/animator/SkDrawSaveLayer.cpp @@ -0,0 +1,67 @@ +#include "SkDrawSaveLayer.h" +#include "SkAnimateMaker.h" +#include "SkCanvas.h" +#include "SkDrawPaint.h" +#include "SkDrawRectangle.h" + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkSaveLayer::fInfo[] = { + SK_MEMBER(bounds, Rect), + SK_MEMBER(paint, Paint) +}; + +#endif + +DEFINE_GET_MEMBER(SkSaveLayer); + +SkSaveLayer::SkSaveLayer() : paint(NULL), bounds(NULL) { +} + +SkSaveLayer::~SkSaveLayer(){ +} + +bool SkSaveLayer::draw(SkAnimateMaker& maker) +{ + if (!bounds) { + return false; + } + SkPaint* save = maker.fPaint; + //paint is an SkDrawPaint + if (paint) + { + SkPaint realPaint; + paint->setupPaint(&realPaint); + maker.fCanvas->saveLayer(bounds->fRect, realPaint); + } + else + maker.fCanvas->saveLayer(bounds->fRect, *save); + SkPaint local = SkPaint(*maker.fPaint); + maker.fPaint = &local; + bool result = INHERITED::draw(maker); + maker.fPaint = save; + maker.fCanvas->restore(); + return result; +} + +#ifdef SK_DUMP_ENABLED +void SkSaveLayer::dump(SkAnimateMaker* maker) +{ + dumpBase(maker); + //would dump enabled be defined but not debug? +#ifdef SK_DEBUG + if (paint) + SkDebugf("paint=\"%s\" ", paint->id); + if (bounds) + SkDebugf("bounds=\"%s\" ", bounds->id); +#endif + dumpDrawables(maker); +} +#endif + +void SkSaveLayer::onEndElement(SkAnimateMaker& maker) +{ + if (!bounds) + maker.setErrorCode(SkDisplayXMLParserError::kSaveLayerNeedsBounds); + INHERITED::onEndElement(maker); +} \ No newline at end of file diff --git a/libs/graphics/animator/SkDrawSaveLayer.h b/libs/graphics/animator/SkDrawSaveLayer.h new file mode 100644 index 000000000..964445711 --- /dev/null +++ b/libs/graphics/animator/SkDrawSaveLayer.h @@ -0,0 +1,27 @@ +#ifndef SkDrawSaveLayer_DEFINED +#define SkDrawSaveLayer_DEFINED + +#include "SkDrawGroup.h" +#include "SkMemberInfo.h" + +class SkDrawPaint; +class SkDrawRect; + +class SkSaveLayer : public SkGroup { + DECLARE_MEMBER_INFO(SaveLayer); + SkSaveLayer(); + virtual ~SkSaveLayer(); + virtual bool draw(SkAnimateMaker& ); +#ifdef SK_DUMP_ENABLED + virtual void dump(SkAnimateMaker* ); +#endif + virtual void onEndElement(SkAnimateMaker& ); +protected: + SkDrawPaint* paint; + SkDrawRect* bounds; +private: + typedef SkGroup INHERITED; + +}; + +#endif //SkDrawSaveLayer_DEFINED diff --git a/libs/graphics/animator/SkDrawShader.cpp b/libs/graphics/animator/SkDrawShader.cpp new file mode 100644 index 000000000..4b071a15b --- /dev/null +++ b/libs/graphics/animator/SkDrawShader.cpp @@ -0,0 +1,74 @@ +#include "SkDrawShader.h" +#include "SkDrawBitmap.h" +#include "SkDrawMatrix.h" +#include "SkDrawPaint.h" +#include "SkTemplates.h" + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDrawShader::fInfo[] = { + SK_MEMBER(matrix, Matrix), + SK_MEMBER(tileMode, TileMode) +}; + +#endif + +DEFINE_GET_MEMBER(SkDrawShader); + +SkDrawShader::SkDrawShader() : matrix(nil), + tileMode(SkShader::kClamp_TileMode) { +} + +bool SkDrawShader::add() { + if (fPaint->shader != (SkDrawShader*) -1) + return true; + fPaint->shader = this; + fPaint->fOwnsShader = true; + return false; +} + +void SkDrawShader::addPostlude(SkShader* shader) { + if (matrix) + shader->setLocalMatrix(matrix->getMatrix()); +} + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDrawBitmapShader::fInfo[] = { + SK_MEMBER_INHERITED, + SK_MEMBER(filterType, FilterType), + SK_MEMBER(image, BaseBitmap) +}; + +#endif + +DEFINE_GET_MEMBER(SkDrawBitmapShader); + +SkDrawBitmapShader::SkDrawBitmapShader() : filterType(SkPaint::kNo_FilterType), image(nil) {} + +bool SkDrawBitmapShader::add() { + if (fPaint->shader != (SkDrawShader*) -1) + return true; + fPaint->shader = this; + fPaint->fOwnsShader = true; + return false; +} + +SkShader* SkDrawBitmapShader::getShader() { + if (image == NULL) + return NULL; + + // note: bitmap shader now supports independent tile modes for X and Y + // we pass the same to both, but later we should extend this flexibility + // to the xml (e.g. tileModeX="repeat" tileModeY="clmap") + // + SkShader* shader = SkShader::CreateBitmapShader(image->fBitmap, false, + (SkPaint::FilterType) filterType, + (SkShader::TileMode) tileMode, + (SkShader::TileMode) tileMode); + SkAutoTDelete autoDel(shader); + addPostlude(shader); + (void)autoDel.detach(); + return shader; +} + diff --git a/libs/graphics/animator/SkDrawShader.h b/libs/graphics/animator/SkDrawShader.h new file mode 100644 index 000000000..860140593 --- /dev/null +++ b/libs/graphics/animator/SkDrawShader.h @@ -0,0 +1,21 @@ +#ifndef SkDrawShader_DEFINED +#define SkDrawShader_DEFINED + +#include "SkPaintParts.h" +#include "SkShader.h" + +class SkBaseBitmap; + +class SkDrawBitmapShader : public SkDrawShader { + DECLARE_DRAW_MEMBER_INFO(BitmapShader); + SkDrawBitmapShader(); + virtual bool add(); + virtual SkShader* getShader(); +protected: + int /*SkPaint::FilterType*/ filterType; + SkBaseBitmap* image; +private: + typedef SkDrawShader INHERITED; +}; + +#endif // SkDrawShader_DEFINED diff --git a/libs/graphics/animator/SkDrawText.cpp b/libs/graphics/animator/SkDrawText.cpp new file mode 100644 index 000000000..093e7e496 --- /dev/null +++ b/libs/graphics/animator/SkDrawText.cpp @@ -0,0 +1,47 @@ +#include "SkDrawText.h" +#include "SkAnimateMaker.h" +#include "SkCanvas.h" +#include "SkPaint.h" + +enum SkText_Properties { + SK_PROPERTY(length) +}; + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkText::fInfo[] = { + SK_MEMBER_PROPERTY(length, Int), + SK_MEMBER(text, String), + SK_MEMBER(x, Float), + SK_MEMBER(y, Float) +}; + +#endif + +DEFINE_GET_MEMBER(SkText); + +SkText::SkText() : x(0), y(0) { +} + +SkText::~SkText() { +} + +bool SkText::draw(SkAnimateMaker& maker) { + SkBoundableAuto boundable(this, maker); + maker.fCanvas->drawText(text.c_str(), text.size(), x, y, *maker.fPaint); + return false; +} + +#ifdef SK_DUMP_ENABLED +void SkText::dump(SkAnimateMaker* maker) { + INHERITED::dump(maker); +} +#endif + +bool SkText::getProperty(int index, SkScriptValue* value) const { + SkASSERT(index == SK_PROPERTY(length)); + value->fType = SkType_Int; + value->fOperand.fS32 = (S32) text.size(); + return true; +} + diff --git a/libs/graphics/animator/SkDrawText.h b/libs/graphics/animator/SkDrawText.h new file mode 100644 index 000000000..2cc8c8623 --- /dev/null +++ b/libs/graphics/animator/SkDrawText.h @@ -0,0 +1,27 @@ +#ifndef SkDrawText_DEFINED +#define SkDrawText_DEFINED + +#include "SkBoundable.h" +#include "SkMemberInfo.h" + +class SkText : public SkBoundable { + DECLARE_MEMBER_INFO(Text); + SkText(); + virtual ~SkText(); + virtual bool draw(SkAnimateMaker& ); +#ifdef SK_DUMP_ENABLED + virtual void dump(SkAnimateMaker* ); +#endif + virtual bool getProperty(int index, SkScriptValue* value) const ; + const char* getText() { return text.c_str(); } + size_t getSize() { return text.size(); } +protected: + SkString text; + SkScalar x; + SkScalar y; +private: + friend class SkTextToPath; + typedef SkBoundable INHERITED; +}; + +#endif // SkDrawText_DEFINED diff --git a/libs/graphics/animator/SkDrawTextBox.cpp b/libs/graphics/animator/SkDrawTextBox.cpp new file mode 100644 index 000000000..204d39869 --- /dev/null +++ b/libs/graphics/animator/SkDrawTextBox.cpp @@ -0,0 +1,73 @@ +#include "SkDrawTextBox.h" +#include "SkAnimateMaker.h" +#include "SkCanvas.h" +#include "SkPaint.h" + +enum SkDrawTextBox_Properties { + foo = 100, + SK_PROPERTY(spacingAlign), + SK_PROPERTY(mode) +}; + + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDrawTextBox::fInfo[] = { + SK_MEMBER_INHERITED, + SK_MEMBER(mode, TextBoxMode), + SK_MEMBER_ALIAS(spacingAdd, fSpacingAdd, Float), + SK_MEMBER(spacingAlign, TextBoxAlign), + SK_MEMBER_ALIAS(spacingMul, fSpacingMul, Float), + SK_MEMBER_ALIAS(text, fText, String) +}; + +#endif + +DEFINE_GET_MEMBER(SkDrawTextBox); + +SkDrawTextBox::SkDrawTextBox() +{ + fSpacingMul = SK_Scalar1; + fSpacingAdd = 0; + spacingAlign = SkTextBox::kStart_SpacingAlign; + mode = SkTextBox::kLineBreak_Mode; +} + +#ifdef SK_DUMP_ENABLED +void SkDrawTextBox::dump(SkAnimateMaker* maker) +{ + dumpBase(maker); + dumpAttrs(maker); + if (mode == 0) + SkDebugf("mode=\"oneLine\" "); + if (spacingAlign == 1) + SkDebugf("spacingAlign=\"center\" "); + else if (spacingAlign == 2) + SkDebugf("spacingAlign=\"end\" "); + SkDebugf("/>\n"); +} +#endif + +bool SkDrawTextBox::getProperty(int index, SkScriptValue* value) const +{ + return this->INHERITED::getProperty(index, value); +} + +bool SkDrawTextBox::setProperty(int index, SkScriptValue& scriptValue) +{ + return this->INHERITED::setProperty(index, scriptValue); +} + +bool SkDrawTextBox::draw(SkAnimateMaker& maker) +{ + SkTextBox box; + box.setMode((SkTextBox::Mode) mode); + box.setSpacingAlign((SkTextBox::SpacingAlign) spacingAlign); + box.setBox(fRect); + box.setSpacing(fSpacingMul, fSpacingAdd); + SkBoundableAuto boundable(this, maker); + box.draw(maker.fCanvas, fText.c_str(), fText.size(), *maker.fPaint); + return false; +} + + diff --git a/libs/graphics/animator/SkDrawTextBox.h b/libs/graphics/animator/SkDrawTextBox.h new file mode 100644 index 000000000..20bb14c19 --- /dev/null +++ b/libs/graphics/animator/SkDrawTextBox.h @@ -0,0 +1,30 @@ +#ifndef SkDrawTextBox_DEFINED +#define SkDrawTextBox_DEFINED + +#include "SkDrawRectangle.h" +#include "SkTextBox.h" + +class SkDrawTextBox : public SkDrawRect { + DECLARE_DRAW_MEMBER_INFO(TextBox); + SkDrawTextBox(); + + // overrides + virtual bool draw(SkAnimateMaker& ); +#ifdef SK_DUMP_ENABLED + virtual void dump(SkAnimateMaker* ); +#endif + virtual bool getProperty(int index, SkScriptValue* value) const; + virtual bool setProperty(int index, SkScriptValue& ); + +private: + SkString fText; + SkScalar fSpacingMul; + SkScalar fSpacingAdd; + int /*SkTextBox::Mode*/ mode; + int /*SkTextBox::SpacingAlign*/ spacingAlign; + + typedef SkDrawRect INHERITED; +}; + +#endif // SkDrawTextBox_DEFINED + diff --git a/libs/graphics/animator/SkDrawTo.cpp b/libs/graphics/animator/SkDrawTo.cpp new file mode 100644 index 000000000..2019c4b1c --- /dev/null +++ b/libs/graphics/animator/SkDrawTo.cpp @@ -0,0 +1,47 @@ +#include "SkDrawTo.h" +#include "SkAnimateMaker.h" +#include "SkCanvas.h" +#include "SkDrawBitmap.h" + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDrawTo::fInfo[] = { + SK_MEMBER(drawOnce, Boolean), + SK_MEMBER(use, Bitmap) +}; + +#endif + +DEFINE_GET_MEMBER(SkDrawTo); + +SkDrawTo::SkDrawTo() : drawOnce(false), use(nil), fDrawnOnce(false) { +} + +#if 0 +SkDrawTo::~SkDrawTo() { + SkASSERT(0); +} +#endif + +bool SkDrawTo::draw(SkAnimateMaker& maker) { + if (fDrawnOnce) + return false; + SkCanvas canvas(use->fBitmap); + SkCanvas* save = maker.fCanvas; + maker.fCanvas = &canvas; + INHERITED::draw(maker); + maker.fCanvas = save; + fDrawnOnce = drawOnce; + return false; +} + +#ifdef SK_DUMP_ENABLED +void SkDrawTo::dump(SkAnimateMaker* maker) { + dumpBase(maker); + dumpAttrs(maker); + if (use) + SkDebugf("use=\"%s\" ", use->id); + dumpDrawables(maker); +} +#endif + diff --git a/libs/graphics/animator/SkDrawTo.h b/libs/graphics/animator/SkDrawTo.h new file mode 100644 index 000000000..403ced6f3 --- /dev/null +++ b/libs/graphics/animator/SkDrawTo.h @@ -0,0 +1,25 @@ +#ifndef SkDrawTo_DEFINED +#define SkDrawTo_DEFINED + +#include "SkDrawGroup.h" +#include "SkMemberInfo.h" + +class SkDrawBitmap; + +class SkDrawTo : public SkGroup { + DECLARE_MEMBER_INFO(DrawTo); + SkDrawTo(); +// virtual ~SkDrawTo(); + virtual bool draw(SkAnimateMaker& ); +#ifdef SK_DUMP_ENABLED + virtual void dump(SkAnimateMaker* ); +#endif +protected: + SkBool drawOnce; + SkDrawBitmap* use; +private: + typedef SkGroup INHERITED; + SkBool fDrawnOnce; +}; + +#endif // SkDrawTo_DEFINED diff --git a/libs/graphics/animator/SkDrawTransparentShader.cpp b/libs/graphics/animator/SkDrawTransparentShader.cpp new file mode 100644 index 000000000..c71fb3729 --- /dev/null +++ b/libs/graphics/animator/SkDrawTransparentShader.cpp @@ -0,0 +1,7 @@ +#include "SkDrawTransparentShader.h" +#include "SkTransparentShader.h" + +SkShader* SkDrawTransparentShader::getShader() { + return new SkTransparentShader(); +} + diff --git a/libs/graphics/animator/SkDrawTransparentShader.h b/libs/graphics/animator/SkDrawTransparentShader.h new file mode 100644 index 000000000..06599378d --- /dev/null +++ b/libs/graphics/animator/SkDrawTransparentShader.h @@ -0,0 +1,12 @@ +#ifndef SkDrawTransparentShader_DEFINED +#define SkDrawTransparentShader_DEFINED + +#include "SkPaintParts.h" + +class SkDrawTransparentShader : public SkDrawShader { + DECLARE_EMPTY_MEMBER_INFO(TransparentShader); + virtual SkShader* getShader(); +}; + +#endif // SkDrawTransparentShader_DEFINED + diff --git a/libs/graphics/animator/SkDrawable.cpp b/libs/graphics/animator/SkDrawable.cpp new file mode 100644 index 000000000..e3e366246 --- /dev/null +++ b/libs/graphics/animator/SkDrawable.cpp @@ -0,0 +1,16 @@ +#include "SkDrawable.h" + +bool SkDrawable::doEvent(SkDisplayEvent::Kind , SkEventState* ) { + return false; +} + +bool SkDrawable::isDrawable() const { + return true; +} + +void SkDrawable::initialize() { +} + +void SkDrawable::setSteps(int steps) { +} + diff --git a/libs/graphics/animator/SkDrawable.h b/libs/graphics/animator/SkDrawable.h new file mode 100644 index 000000000..6c62b1520 --- /dev/null +++ b/libs/graphics/animator/SkDrawable.h @@ -0,0 +1,19 @@ +#ifndef SkDrawable_DEFINED +#define SkDrawable_DEFINED + +#include "SkDisplayable.h" +#include "SkDisplayEvent.h" +#include "SkMath.h" + +struct SkEventState; + +class SkDrawable : public SkDisplayable { +public: + virtual bool doEvent(SkDisplayEvent::Kind , SkEventState* state ); + virtual bool draw(SkAnimateMaker& ) = 0; + virtual void initialize(); + virtual bool isDrawable() const; + virtual void setSteps(int steps); +}; + +#endif // SkDrawable_DEFINED diff --git a/libs/graphics/animator/SkDump.cpp b/libs/graphics/animator/SkDump.cpp new file mode 100644 index 000000000..cd7dcf09b --- /dev/null +++ b/libs/graphics/animator/SkDump.cpp @@ -0,0 +1,141 @@ +#include "SkDump.h" + +#ifdef SK_DUMP_ENABLED + +#include "SkAnimateMaker.h" +#include "SkAnimatorScript.h" +#include "SkDisplayEvents.h" +#include "SkDisplayList.h" +#include "SkString.h" + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkDump::fInfo[] = { + SK_MEMBER(displayList, Boolean), + SK_MEMBER(eventList, Boolean), + SK_MEMBER(events, Boolean), + SK_MEMBER(groups, Boolean), + SK_MEMBER(name, String), + SK_MEMBER(posts, Boolean), + SK_MEMBER(script, String) +}; + +#endif + +DEFINE_GET_MEMBER(SkDump); + +SkDump::SkDump() : displayList(-1), eventList(-1), events(-1), groups(-1), posts(-1) { +} + +bool SkDump::enable(SkAnimateMaker& maker ) { + if (script.size() > 0) + return evaluate(maker); + bool hasAttr = false; + if (events > 0) + hasAttr |= maker.fDumpEvents = true; + if (posts > 0) + hasAttr |= maker.fDumpPosts = true; + if (groups > 0) + hasAttr |= maker.fDumpGConditions = true; + if ((hasAttr |= (eventList > 0)) == true) + maker.fEvents.dump(maker); + if ((hasAttr |= (name.size() > 0)) == true) + maker.dump(name.c_str()); + if (displayList > 0 || displayList != 0 && hasAttr == false) + maker.fDisplayList.dump(&maker); + return true; +} + +bool SkDump::evaluate(SkAnimateMaker &maker) { + SkAnimatorScript scriptEngine(maker, nil, SkType_Int); + SkScriptValue value; + const char* cScript = script.c_str(); + bool success = scriptEngine.evaluateScript(&cScript, &value); + SkDebugf("%*s\n"); + return false; + } + switch (value.fType) { + case SkType_Float: + SkDebugf("%g\" />\n", SkScalarToFloat(value.fOperand.fScalar)); + break; + case SkType_Int: + SkDebugf("%d\" />\n", value.fOperand.fS32); + break; + case SkType_String: + SkDebugf("%s\" />\n", value.fOperand.fString->c_str()); + break; + default: + return false; + } + return true; +} + +bool SkDump::hasEnable() const { + return true; +} + +void SkDump::GetEnumString(SkDisplayTypes type, int index, SkString* result) { + int badEnum = index; + const SkDisplayEnumMap& map = SkAnimatorScript::GetEnumValues(type); + const char* str = map.fValues; + while (--index >= 0) { + str = strchr(str, '|'); + if (str == nil) { + result->reset(); + result->appendS32(badEnum); + return; + } + str += 1; + } + const char* end = strchr(str, '|'); + if (end == nil) + end = str + strlen(str); + result->set(str, end - str); +} + +#else + +// in the release version, is allowed, and its attributes are defined, but +// are not stored and have no effect + +#if SK_USE_CONDENSED_INFO == 0 + +enum SkDump_Properties { + SK_PROPERTY(displayList), + SK_PROPERTY(eventList), + SK_PROPERTY(events), + SK_PROPERTY(groups), + SK_PROPERTY(name), + SK_PROPERTY(posts), + SK_PROPERTY(script) +}; + +const SkMemberInfo SkDump::fInfo[] = { + SK_MEMBER_PROPERTY(displayList, Boolean), + SK_MEMBER_PROPERTY(eventList, Boolean), + SK_MEMBER_PROPERTY(events, Boolean), + SK_MEMBER_PROPERTY(groups, Boolean), + SK_MEMBER_PROPERTY(name, String), + SK_MEMBER_PROPERTY(posts, Boolean), + SK_MEMBER_PROPERTY(script, String) +}; + +#endif + +DEFINE_GET_MEMBER(SkDump); + +bool SkDump::enable(SkAnimateMaker& maker ) { + return true; +} + +bool SkDump::hasEnable() const { + return true; +} + +bool SkDump::setProperty(int index, SkScriptValue& ) { + return index <= SK_PROPERTY(posts); +} + +#endif diff --git a/libs/graphics/animator/SkDump.h b/libs/graphics/animator/SkDump.h new file mode 100644 index 000000000..2d9c99f4e --- /dev/null +++ b/libs/graphics/animator/SkDump.h @@ -0,0 +1,34 @@ +#ifndef SkDump_DEFINED +#define SkDump_DEFINED + +#include "SkDisplayable.h" +#include "SkMemberInfo.h" + +class SkAnimateMaker; +class SkString; + +class SkDump : public SkDisplayable { + DECLARE_MEMBER_INFO(Dump); +#ifdef SK_DUMP_ENABLED + SkDump(); + virtual bool enable(SkAnimateMaker & ); + bool evaluate(SkAnimateMaker &); + virtual bool hasEnable() const; + static void GetEnumString(SkDisplayTypes , int index, SkString* result); + SkBool displayList; + SkBool eventList; + SkBool events; + SkString name; + SkBool groups; + SkBool posts; + SkString script; +#else + virtual bool enable(SkAnimateMaker & ); + virtual bool hasEnable() const; + virtual bool setProperty(int index, SkScriptValue& ); +#endif +}; + + +#endif // SkDump_DEFINED + diff --git a/libs/graphics/animator/SkExtraPathEffects.xsd b/libs/graphics/animator/SkExtraPathEffects.xsd new file mode 100644 index 000000000..9592443a0 --- /dev/null +++ b/libs/graphics/animator/SkExtraPathEffects.xsd @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/graphics/animator/SkExtras.h b/libs/graphics/animator/SkExtras.h new file mode 100644 index 000000000..f8af4c504 --- /dev/null +++ b/libs/graphics/animator/SkExtras.h @@ -0,0 +1,25 @@ +#ifndef SkExtras_DEFINED +#define SkExtras_DEFINED + +#include "SkScript.h" + +class SkExtras { +public: + SkExtras(); + virtual ~SkExtras() {} + + virtual SkDisplayable* createInstance(SkDisplayTypes type) = 0; + virtual bool definesType(SkDisplayTypes type) = 0; +#if SK_USE_CONDENSED_INFO == 0 + virtual const SkMemberInfo* getMembers(SkDisplayTypes type, int* infoCountPtr) = 0; +#endif +#ifdef SK_DEBUG + virtual const char* getName(SkDisplayTypes type) = 0; +#endif + virtual SkDisplayTypes getType(const char match[], size_t len ) = 0; + + SkScriptEngine::_propertyCallBack fExtraCallBack; + void* fExtraStorage; +}; + +#endif // SkExtras_DEFINED diff --git a/libs/graphics/animator/SkGetCondensedInfo.cpp b/libs/graphics/animator/SkGetCondensedInfo.cpp new file mode 100644 index 000000000..28290fde1 --- /dev/null +++ b/libs/graphics/animator/SkGetCondensedInfo.cpp @@ -0,0 +1,113 @@ +#include "SkMemberInfo.h" + +#if SK_USE_CONDENSED_INFO == 1 + +// SkCondensed.cpp is auto-generated +// To generate it, execute SkDisplayType::BuildCondensedInfo() +#ifdef SK_DEBUG +#include "SkCondensedDebug.cpp" +#else +#include "SkCondensedRelease.cpp" +#endif + +static int _searchByName(const unsigned char* lengths, int count, const char* strings, const char target[]) { + int lo = 0; + int hi = count - 1; + while (lo < hi) { + int mid = (hi + lo) >> 1; + if (strcmp(&strings[lengths[mid << 2]], target) < 0) + lo = mid + 1; + else + hi = mid; + } + if (strcmp(&strings[lengths[hi << 2]], target) != 0) + return -1; + return hi; +} + +static int _searchByType(SkDisplayTypes type) { + unsigned char match = (unsigned char) type; + int lo = 0; + int hi = kTypeIDs - 1; + while (lo < hi) { + int mid = (hi + lo) >> 1; + if (gTypeIDs[mid] < match) + lo = mid + 1; + else + hi = mid; + } + if (gTypeIDs[hi] != type) + return -1; + return hi; +} + +const SkMemberInfo* SkDisplayType::GetMembers(SkAnimateMaker* , SkDisplayTypes type, int* infoCountPtr) { + int lookup = _searchByType(type); + if (lookup < 0) + return nil; + if (infoCountPtr) + *infoCountPtr = gInfoCounts[lookup]; + return gInfoTables[lookup]; +} + +// !!! replace with inline +const SkMemberInfo* SkDisplayType::GetMember(SkAnimateMaker* , SkDisplayTypes type, const char** matchPtr ) { + const SkMemberInfo* info = SkMemberInfo::Find(type, matchPtr); + SkASSERT(info); + return info; +} + +static const SkMemberInfo* _lookup(int lookup, const char** matchPtr) { + int count = gInfoCounts[lookup]; + const SkMemberInfo* info = gInfoTables[lookup]; + if (info->fType == SkType_BaseClassInfo) { + int baseTypeLookup = info->fOffset; + const SkMemberInfo* result = _lookup(baseTypeLookup, matchPtr); + if (result != nil) + return result; + if (--count == 0) + return nil; + info++; + } + SkASSERT(info->fType != SkType_BaseClassInfo); + const char* match = *matchPtr; + const char* strings = gInfoNames[lookup]; + int index = _searchByName(&info->fName, count, strings, match); + if (index < 0) + return nil; + return &info[index]; +} + +const SkMemberInfo* SkMemberInfo::Find(SkDisplayTypes type, int* index) { + int count = gInfoCounts[lookup]; + const SkMemberInfo* info = gInfoTables[lookup]; + if (info->fType == SkType_BaseClassInfo) { + int baseTypeLookup = info->fOffset; + const SkMemberInfo* result = Find(baseTypeLookup, index); + if (result != nil) + return result; + if (--count == 0) + return nil; + info++; + } + SkASSERT(info->fType != SkType_BaseClassInfo); + if (*index >= count) { + *index -= count; + return nil; + } + return &info[index]; +} + +const SkMemberInfo* SkMemberInfo::Find(SkDisplayTypes type, const char** matchPtr) { + int lookup = _searchByType(type); + SkASSERT(lookup >= 0); + return _lookup(lookup, matchPtr); +} + +const SkMemberInfo* SkMemberInfo::getInherited() const { + int baseTypeLookup = fOffset; + return gInfoTables[baseTypeLookup]; +} + +#endif + diff --git a/libs/graphics/animator/SkHitClear.cpp b/libs/graphics/animator/SkHitClear.cpp new file mode 100644 index 000000000..6d90a5a44 --- /dev/null +++ b/libs/graphics/animator/SkHitClear.cpp @@ -0,0 +1,24 @@ +#include "SkHitClear.h" + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkHitClear::fInfo[] = { + SK_MEMBER_ARRAY(targets, Displayable) +}; + +#endif + +DEFINE_GET_MEMBER(SkHitClear); + +bool SkHitClear::enable(SkAnimateMaker& maker) { + for (int tIndex = 0; tIndex < targets.count(); tIndex++) { + SkDisplayable* target = targets[tIndex]; + target->clearBounder(); + } + return true; +} + +bool SkHitClear::hasEnable() const { + return true; +} + diff --git a/libs/graphics/animator/SkHitClear.h b/libs/graphics/animator/SkHitClear.h new file mode 100644 index 000000000..57bc6b55a --- /dev/null +++ b/libs/graphics/animator/SkHitClear.h @@ -0,0 +1,16 @@ +#ifndef SkHitClear_DEFINED +#define SkHitClear_DEFINED + +#include "SkDisplayable.h" +#include "SkMemberInfo.h" +#include "SkTypedArray.h" + +class SkHitClear : public SkDisplayable { + DECLARE_MEMBER_INFO(HitClear); + virtual bool enable(SkAnimateMaker& ); + virtual bool hasEnable() const; +private: + SkTDDisplayableArray targets; +}; + +#endif // SkHitClear_DEFINED diff --git a/libs/graphics/animator/SkHitTest.cpp b/libs/graphics/animator/SkHitTest.cpp new file mode 100644 index 000000000..7e48adbe2 --- /dev/null +++ b/libs/graphics/animator/SkHitTest.cpp @@ -0,0 +1,66 @@ +#include "SkHitTest.h" + +#if SK_USE_CONDENSED_INFO == 0 + +const SkMemberInfo SkHitTest::fInfo[] = { + SK_MEMBER_ARRAY(bullets, Displayable), + SK_MEMBER_ARRAY(hits, Int), + SK_MEMBER_ARRAY(targets, Displayable), + SK_MEMBER(value, Boolean) +}; + +#endif + +DEFINE_GET_MEMBER(SkHitTest); + +SkHitTest::SkHitTest() : value(false) { +} + +bool SkHitTest::draw(SkAnimateMaker& maker) { + hits.setCount(bullets.count()); + value = false; + int bulletCount = bullets.count(); + int targetCount = targets.count(); + for (int bIndex = 0; bIndex < bulletCount; bIndex++) { + SkDisplayable* bullet = bullets[bIndex]; + SkRect bBounds; + bullet->getBounds(&bBounds); + hits[bIndex] = -1; + if (bBounds.fLeft == (S16)0x8000U) + continue; + for (int tIndex = 0; tIndex < targetCount; tIndex++) { + SkDisplayable* target = targets[tIndex]; + SkRect tBounds; + target->getBounds(&tBounds); + if (bBounds.intersect(tBounds)) { + hits[bIndex] = tIndex; + value = true; + break; + } + } + } + return false; +} + +bool SkHitTest::enable(SkAnimateMaker& maker) { + for (int bIndex = 0; bIndex < bullets.count(); bIndex++) { + SkDisplayable* bullet = bullets[bIndex]; + bullet->enableBounder(); + } + for (int tIndex = 0; tIndex < targets.count(); tIndex++) { + SkDisplayable* target = targets[tIndex]; + target->enableBounder(); + } + return false; +} + +bool SkHitTest::hasEnable() const { + return true; +} + +const SkMemberInfo* SkHitTest::preferredChild(SkDisplayTypes type) { + if (bullets.count() == 0) + return getMember("bullets"); + return getMember("targets"); // !!! cwap! need to refer to member through enum like kScope instead +} + diff --git a/libs/graphics/animator/SkHitTest.h b/libs/graphics/animator/SkHitTest.h new file mode 100644 index 000000000..a8c9fa457 --- /dev/null +++ b/libs/graphics/animator/SkHitTest.h @@ -0,0 +1,21 @@ +#ifndef SkHitTest_DEFINED +#define SkHitTest_DEFINED + +#include "SkDrawable.h" +#include "SkTypedArray.h" + +class SkHitTest : public SkDrawable { + DECLARE_MEMBER_INFO(HitTest); + SkHitTest(); + virtual bool draw(SkAnimateMaker& ); + virtual bool enable(SkAnimateMaker& ); + virtual bool hasEnable() const; + virtual const SkMemberInfo* preferredChild(SkDisplayTypes type); +private: + SkTDDisplayableArray bullets; + SkTDIntArray hits; + SkTDDisplayableArray targets; + SkBool value; +}; + +#endif // SkHitTest_DEFINED diff --git a/libs/graphics/animator/SkIntArray.h b/libs/graphics/animator/SkIntArray.h new file mode 100644 index 000000000..f1824a129 --- /dev/null +++ b/libs/graphics/animator/SkIntArray.h @@ -0,0 +1,49 @@ +#ifndef SkIntArray_DEFINED +#define SkIntArray_DEFINED + +#include "SkColor.h" +#include "SkDisplayType.h" +#include "SkMath.h" +#include "SkTDArray_Experimental.h" + +class SkActive; +class SkAnimateBase; +class SkData; +class SkDisplayable; +class SkDisplayEvent; +class SkDrawable; +class SkDrawColor; +class SkMatrixPart; +struct SkMemberInfo; +class SkPathPart; +class SkPaintPart; +class SkTypedArray; +class SkString; +union SkOperand; + +typedef SkIntArray(int) SkTDIntArray; +typedef SkIntArray(SkColor) SkTDColorArray; +typedef SkIntArray(SkDisplayTypes) SkTDDisplayTypesArray; +typedef SkIntArray(SkMSec) SkTDMSecArray; +typedef SkIntArray(SkScalar) SkTDScalarArray; + +typedef SkLongArray(SkActive*) SkTDActiveArray; +typedef SkLongArray(SkAnimateBase*) SkTDAnimateArray; +typedef SkLongArray(SkData*) SkTDDataArray; +typedef SkLongArray(SkDisplayable*) SkTDDisplayableArray; +typedef SkLongArray(SkDisplayEvent*) SkTDDisplayEventArray; +typedef SkLongArray(SkDrawable*) SkTDDrawableArray; +typedef SkLongArray(SkDrawColor*) SkTDDrawColorArray; +typedef SkLongArray(SkMatrixPart*) SkTDMatrixPartArray; +typedef SkLongArray(const SkMemberInfo*) SkTDMemberInfoArray; +typedef SkLongArray(SkPaintPart*) SkTDPaintPartArray; +typedef SkLongArray(SkPathPart*) SkTDPathPartArray; +typedef SkLongArray(SkTypedArray*) SkTDTypedArrayArray; +typedef SkLongArray(SkString*) SkTDStringArray; +typedef SkLongArray(SkOperand) SkTDOperandArray; +typedef SkLongArray(SkOperand*) SkTDOperandPtrArray; + +#endif // SkIntArray_DEFINED + + + diff --git a/libs/graphics/animator/SkInterpolator.cpp b/libs/graphics/animator/SkInterpolator.cpp new file mode 100644 index 000000000..f151bd4a2 --- /dev/null +++ b/libs/graphics/animator/SkInterpolator.cpp @@ -0,0 +1,252 @@ +#include "SkInterpolator.h" +#include "SkTSearch.h" + +SkInterpolatorBase::SkInterpolatorBase() +{ + fStorage = nil; + fTimes = nil; + SkDEBUGCODE(fTimesArray = nil;) +} + +SkInterpolatorBase::~SkInterpolatorBase() +{ + if (fStorage) + sk_free(fStorage); +} + +void SkInterpolatorBase::reset(int elemCount, int frameCount) +{ + fFlags = 0; + fElemCount = SkToU8(elemCount); + fFrameCount = SkToS16(frameCount); + fRepeat = SK_Scalar1; + if (fStorage) { + sk_free(fStorage); + fStorage = nil; + fTimes = nil; + SkDEBUGCODE(fTimesArray = nil); + } +} + +/* Each value[] run is formated as: +