summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/skia/src
diff options
context:
space:
mode:
authorJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-08 14:30:41 +0200
committerJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-12 13:49:54 +0200
commitab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch)
tree498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/third_party/skia/src
parent4ce69f7403811819800e7c5ae1318b2647e778d1 (diff)
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/third_party/skia/src')
-rw-r--r--chromium/third_party/skia/src/animator/SkAnimateBase.cpp6
-rw-r--r--chromium/third_party/skia/src/animator/SkAnimateSet.cpp2
-rw-r--r--chromium/third_party/skia/src/animator/SkBoundable.cpp4
-rw-r--r--chromium/third_party/skia/src/animator/SkDisplayList.h6
-rw-r--r--chromium/third_party/skia/src/animator/SkDisplayMath.cpp17
-rw-r--r--chromium/third_party/skia/src/animator/SkDisplayType.cpp2
-rw-r--r--chromium/third_party/skia/src/animator/SkDrawBitmap.cpp5
-rw-r--r--chromium/third_party/skia/src/animator/SkDrawBlur.cpp7
-rw-r--r--chromium/third_party/skia/src/animator/SkDrawBlur.h6
-rw-r--r--chromium/third_party/skia/src/animator/SkDrawColor.cpp10
-rw-r--r--chromium/third_party/skia/src/animator/SkDrawColor.h4
-rw-r--r--chromium/third_party/skia/src/animator/SkDrawDash.cpp2
-rw-r--r--chromium/third_party/skia/src/animator/SkDrawDash.h4
-rw-r--r--chromium/third_party/skia/src/animator/SkDrawDiscrete.cpp2
-rw-r--r--chromium/third_party/skia/src/animator/SkDrawDiscrete.h4
-rw-r--r--chromium/third_party/skia/src/animator/SkDrawExtraPathEffect.cpp12
-rw-r--r--chromium/third_party/skia/src/animator/SkDrawGradient.cpp64
-rw-r--r--chromium/third_party/skia/src/animator/SkDrawGradient.h3
-rw-r--r--chromium/third_party/skia/src/animator/SkDrawPaint.cpp4
-rw-r--r--chromium/third_party/skia/src/animator/SkDrawSaveLayer.cpp4
-rw-r--r--chromium/third_party/skia/src/animator/SkDrawShader.cpp9
-rw-r--r--chromium/third_party/skia/src/animator/SkDrawShader.h4
-rw-r--r--chromium/third_party/skia/src/animator/SkDrawTransparentShader.h4
-rw-r--r--chromium/third_party/skia/src/animator/SkMemberInfo.cpp2
-rw-r--r--chromium/third_party/skia/src/animator/SkOperandIterpolator.cpp2
-rw-r--r--chromium/third_party/skia/src/animator/SkPaintPart.cpp (renamed from chromium/third_party/skia/src/animator/SkPaintParts.cpp)4
-rw-r--r--chromium/third_party/skia/src/animator/SkPaintPart.h (renamed from chromium/third_party/skia/src/animator/SkPaintParts.h)10
-rw-r--r--chromium/third_party/skia/src/animator/SkScript.cpp13
-rw-r--r--chromium/third_party/skia/src/animator/SkScript2.h5
-rw-r--r--chromium/third_party/skia/src/animator/SkScriptRuntime.cpp2
-rw-r--r--chromium/third_party/skia/src/animator/SkScriptTokenizer.cpp13
-rw-r--r--chromium/third_party/skia/src/animator/SkSnapshot.cpp2
-rw-r--r--chromium/third_party/skia/src/animator/SkTime.cpp34
-rw-r--r--chromium/third_party/skia/src/core/ARGB32_Clamp_Bilinear_BitmapShader.h177
-rw-r--r--chromium/third_party/skia/src/core/Sk64.cpp345
-rw-r--r--chromium/third_party/skia/src/core/SkAAClip.cpp4
-rw-r--r--chromium/third_party/skia/src/core/SkAnnotation.cpp9
-rw-r--r--chromium/third_party/skia/src/core/SkBBHFactory.cpp44
-rw-r--r--chromium/third_party/skia/src/core/SkBBoxHierarchy.h12
-rw-r--r--chromium/third_party/skia/src/core/SkBBoxHierarchyRecord.cpp111
-rw-r--r--chromium/third_party/skia/src/core/SkBBoxHierarchyRecord.h40
-rw-r--r--chromium/third_party/skia/src/core/SkBBoxRecord.cpp54
-rw-r--r--chromium/third_party/skia/src/core/SkBBoxRecord.h28
-rw-r--r--chromium/third_party/skia/src/core/SkBitmap.cpp1265
-rw-r--r--chromium/third_party/skia/src/core/SkBitmapDevice.cpp319
-rw-r--r--chromium/third_party/skia/src/core/SkBitmapFilter.cpp8
-rw-r--r--chromium/third_party/skia/src/core/SkBitmapHeap.cpp17
-rw-r--r--chromium/third_party/skia/src/core/SkBitmapHeap.h6
-rw-r--r--chromium/third_party/skia/src/core/SkBitmapProcShader.cpp256
-rw-r--r--chromium/third_party/skia/src/core/SkBitmapProcShader.h62
-rw-r--r--chromium/third_party/skia/src/core/SkBitmapProcState.cpp51
-rw-r--r--chromium/third_party/skia/src/core/SkBitmapProcState.h6
-rw-r--r--chromium/third_party/skia/src/core/SkBitmapProcState_filter.h8
-rw-r--r--chromium/third_party/skia/src/core/SkBitmapProcState_matrix.h138
-rw-r--r--chromium/third_party/skia/src/core/SkBitmapProcState_matrixProcs.cpp117
-rw-r--r--chromium/third_party/skia/src/core/SkBitmapProcState_matrix_template.h124
-rw-r--r--chromium/third_party/skia/src/core/SkBitmapProcState_procs.h30
-rw-r--r--chromium/third_party/skia/src/core/SkBitmapScaler.cpp70
-rw-r--r--chromium/third_party/skia/src/core/SkBitmapScaler.h20
-rw-r--r--chromium/third_party/skia/src/core/SkBitmapShader16BilerpTemplate.h245
-rw-r--r--chromium/third_party/skia/src/core/SkBitmapShaderTemplate.h306
-rw-r--r--chromium/third_party/skia/src/core/SkBitmap_scroll.cpp22
-rw-r--r--chromium/third_party/skia/src/core/SkBlitMask.h8
-rw-r--r--chromium/third_party/skia/src/core/SkBlitMask_D32.cpp28
-rw-r--r--chromium/third_party/skia/src/core/SkBlitRow_D16.cpp6
-rw-r--r--chromium/third_party/skia/src/core/SkBlitRow_D32.cpp2
-rw-r--r--chromium/third_party/skia/src/core/SkBlitter.cpp395
-rw-r--r--chromium/third_party/skia/src/core/SkBlitter.h21
-rw-r--r--chromium/third_party/skia/src/core/SkBlitter_A8.cpp29
-rw-r--r--chromium/third_party/skia/src/core/SkBlitter_ARGB32.cpp78
-rw-r--r--chromium/third_party/skia/src/core/SkBlitter_RGB16.cpp134
-rw-r--r--chromium/third_party/skia/src/core/SkBlitter_Sprite.cpp23
-rw-r--r--chromium/third_party/skia/src/core/SkCanvas.cpp1137
-rw-r--r--chromium/third_party/skia/src/core/SkClipStack.cpp383
-rw-r--r--chromium/third_party/skia/src/core/SkColorFilter.cpp3
-rw-r--r--chromium/third_party/skia/src/core/SkColorTable.cpp18
-rw-r--r--chromium/third_party/skia/src/core/SkComposeShader.cpp121
-rw-r--r--chromium/third_party/skia/src/core/SkConfig8888.cpp333
-rw-r--r--chromium/third_party/skia/src/core/SkConfig8888.h81
-rw-r--r--chromium/third_party/skia/src/core/SkConvolver.cpp10
-rw-r--r--chromium/third_party/skia/src/core/SkConvolver.h2
-rw-r--r--chromium/third_party/skia/src/core/SkCordic.cpp289
-rw-r--r--chromium/third_party/skia/src/core/SkCordic.h28
-rw-r--r--chromium/third_party/skia/src/core/SkCoreBlitters.h37
-rw-r--r--chromium/third_party/skia/src/core/SkCubicClipper.cpp8
-rw-r--r--chromium/third_party/skia/src/core/SkData.cpp17
-rw-r--r--chromium/third_party/skia/src/core/SkDebug.cpp15
-rw-r--r--chromium/third_party/skia/src/core/SkDescriptor.h4
-rw-r--r--chromium/third_party/skia/src/core/SkDevice.cpp140
-rw-r--r--chromium/third_party/skia/src/core/SkDeviceImageFilterProxy.h11
-rwxr-xr-xchromium/third_party/skia/src/core/SkDistanceFieldGen.cpp521
-rw-r--r--chromium/third_party/skia/src/core/SkDistanceFieldGen.h61
-rw-r--r--chromium/third_party/skia/src/core/SkDraw.cpp940
-rw-r--r--chromium/third_party/skia/src/core/SkDrawLooper.cpp21
-rw-r--r--chromium/third_party/skia/src/core/SkDrawProcs.h69
-rw-r--r--chromium/third_party/skia/src/core/SkEdge.cpp30
-rw-r--r--chromium/third_party/skia/src/core/SkEdge.h8
-rw-r--r--chromium/third_party/skia/src/core/SkEdgeBuilder.cpp2
-rw-r--r--chromium/third_party/skia/src/core/SkError.cpp2
-rw-r--r--chromium/third_party/skia/src/core/SkFDot6.h9
-rw-r--r--chromium/third_party/skia/src/core/SkFP.h79
-rw-r--r--chromium/third_party/skia/src/core/SkFilterShader.cpp71
-rw-r--r--chromium/third_party/skia/src/core/SkFilterShader.h34
-rw-r--r--chromium/third_party/skia/src/core/SkFlate.cpp4
-rw-r--r--chromium/third_party/skia/src/core/SkFlate.h52
-rw-r--r--chromium/third_party/skia/src/core/SkFlattenable.cpp2
-rw-r--r--chromium/third_party/skia/src/core/SkFlattenableBuffers.cpp116
-rw-r--r--chromium/third_party/skia/src/core/SkFlattenableSerialization.cpp7
-rw-r--r--chromium/third_party/skia/src/core/SkFloat.cpp14
-rw-r--r--chromium/third_party/skia/src/core/SkFloat.h2
-rw-r--r--chromium/third_party/skia/src/core/SkFont.cpp156
-rw-r--r--chromium/third_party/skia/src/core/SkFontDescriptor.cpp2
-rw-r--r--chromium/third_party/skia/src/core/SkFontHost.cpp68
-rw-r--r--chromium/third_party/skia/src/core/SkGeometry.cpp644
-rw-r--r--chromium/third_party/skia/src/core/SkGeometry.h316
-rw-r--r--chromium/third_party/skia/src/core/SkGlyph.h2
-rwxr-xr-x[-rw-r--r--]chromium/third_party/skia/src/core/SkGlyphCache.cpp68
-rw-r--r--chromium/third_party/skia/src/core/SkGlyphCache.h75
-rw-r--r--chromium/third_party/skia/src/core/SkGraphics.cpp8
-rw-r--r--chromium/third_party/skia/src/core/SkImageFilter.cpp310
-rw-r--r--chromium/third_party/skia/src/core/SkImageFilterUtils.cpp59
-rw-r--r--chromium/third_party/skia/src/core/SkImageGenerator.cpp72
-rw-r--r--chromium/third_party/skia/src/core/SkImageGeneratorPriv.h39
-rw-r--r--chromium/third_party/skia/src/core/SkImageInfo.cpp7
-rw-r--r--chromium/third_party/skia/src/core/SkLazyFnPtr.h67
-rw-r--r--chromium/third_party/skia/src/core/SkLazyPtr.h146
-rw-r--r--chromium/third_party/skia/src/core/SkLineClipper.cpp16
-rw-r--r--chromium/third_party/skia/src/core/SkLineClipper.h47
-rw-r--r--chromium/third_party/skia/src/core/SkLocalMatrixShader.cpp65
-rw-r--r--chromium/third_party/skia/src/core/SkLocalMatrixShader.h78
-rw-r--r--chromium/third_party/skia/src/core/SkMallocPixelRef.cpp141
-rw-r--r--chromium/third_party/skia/src/core/SkMask.cpp11
-rw-r--r--chromium/third_party/skia/src/core/SkMaskFilter.cpp91
-rw-r--r--chromium/third_party/skia/src/core/SkMaskGamma.h16
-rw-r--r--chromium/third_party/skia/src/core/SkMath.cpp238
-rw-r--r--chromium/third_party/skia/src/core/SkMathPriv.h10
-rw-r--r--chromium/third_party/skia/src/core/SkMatrix.cpp1181
-rw-r--r--chromium/third_party/skia/src/core/SkMatrixClipStateMgr.cpp419
-rw-r--r--chromium/third_party/skia/src/core/SkMatrixClipStateMgr.h414
-rw-r--r--chromium/third_party/skia/src/core/SkMessageBus.h28
-rw-r--r--chromium/third_party/skia/src/core/SkMetaData.cpp4
-rw-r--r--chromium/third_party/skia/src/core/SkMipMap.cpp35
-rw-r--r--chromium/third_party/skia/src/core/SkOnce.h155
-rw-r--r--chromium/third_party/skia/src/core/SkOrderedReadBuffer.h139
-rw-r--r--chromium/third_party/skia/src/core/SkOrderedWriteBuffer.h117
-rw-r--r--chromium/third_party/skia/src/core/SkPackBits.cpp24
-rw-r--r--chromium/third_party/skia/src/core/SkPaint.cpp681
-rw-r--r--chromium/third_party/skia/src/core/SkPaintOptionsAndroid.cpp7
-rw-r--r--chromium/third_party/skia/src/core/SkPaintPriv.cpp19
-rw-r--r--chromium/third_party/skia/src/core/SkPaintPriv.h7
-rw-r--r--chromium/third_party/skia/src/core/SkPath.cpp114
-rw-r--r--chromium/third_party/skia/src/core/SkPathEffect.cpp11
-rw-r--r--chromium/third_party/skia/src/core/SkPathHeap.cpp40
-rw-r--r--chromium/third_party/skia/src/core/SkPathHeap.h34
-rw-r--r--chromium/third_party/skia/src/core/SkPathMeasure.cpp5
-rw-r--r--chromium/third_party/skia/src/core/SkPathRef.cpp40
-rw-r--r--chromium/third_party/skia/src/core/SkPicture.cpp352
-rw-r--r--chromium/third_party/skia/src/core/SkPictureFlat.cpp53
-rw-r--r--chromium/third_party/skia/src/core/SkPictureFlat.h312
-rw-r--r--chromium/third_party/skia/src/core/SkPicturePlayback.cpp892
-rw-r--r--chromium/third_party/skia/src/core/SkPicturePlayback.h270
-rw-r--r--chromium/third_party/skia/src/core/SkPictureRecord.cpp936
-rw-r--r--chromium/third_party/skia/src/core/SkPictureRecord.h155
-rw-r--r--chromium/third_party/skia/src/core/SkPictureRecorder.cpp106
-rw-r--r--chromium/third_party/skia/src/core/SkPictureShader.cpp207
-rw-r--r--chromium/third_party/skia/src/core/SkPictureShader.h79
-rw-r--r--chromium/third_party/skia/src/core/SkPictureStateTree.cpp100
-rw-r--r--chromium/third_party/skia/src/core/SkPictureStateTree.h26
-rw-r--r--chromium/third_party/skia/src/core/SkPixelRef.cpp125
-rw-r--r--chromium/third_party/skia/src/core/SkQuadTree.cpp219
-rw-r--r--chromium/third_party/skia/src/core/SkQuadTree.h113
-rw-r--r--chromium/third_party/skia/src/core/SkRRect.cpp97
-rw-r--r--chromium/third_party/skia/src/core/SkRTree.cpp4
-rw-r--r--chromium/third_party/skia/src/core/SkRTree.h18
-rw-r--r--chromium/third_party/skia/src/core/SkReadBuffer.cpp (renamed from chromium/third_party/skia/src/core/SkOrderedReadBuffer.cpp)147
-rw-r--r--chromium/third_party/skia/src/core/SkRecord.h234
-rw-r--r--chromium/third_party/skia/src/core/SkRecordDraw.cpp71
-rw-r--r--chromium/third_party/skia/src/core/SkRecordDraw.h55
-rw-r--r--chromium/third_party/skia/src/core/SkRecordOpts.cpp303
-rw-r--r--chromium/third_party/skia/src/core/SkRecordOpts.h35
-rw-r--r--chromium/third_party/skia/src/core/SkRecordPattern.h183
-rw-r--r--chromium/third_party/skia/src/core/SkRecorder.cpp263
-rw-r--r--chromium/third_party/skia/src/core/SkRecorder.h112
-rw-r--r--chromium/third_party/skia/src/core/SkRecording.cpp44
-rw-r--r--chromium/third_party/skia/src/core/SkRecords.h291
-rw-r--r--chromium/third_party/skia/src/core/SkRect.cpp67
-rw-r--r--chromium/third_party/skia/src/core/SkRegion.cpp10
-rw-r--r--chromium/third_party/skia/src/core/SkRegionPriv.h4
-rw-r--r--chromium/third_party/skia/src/core/SkRegion_path.cpp20
-rw-r--r--chromium/third_party/skia/src/core/SkRegion_rects.cpp290
-rw-r--r--chromium/third_party/skia/src/core/SkScaledImageCache.cpp106
-rw-r--r--chromium/third_party/skia/src/core/SkScalerContext.cpp34
-rw-r--r--chromium/third_party/skia/src/core/SkScalerContext.h17
-rw-r--r--chromium/third_party/skia/src/core/SkScan.cpp8
-rw-r--r--chromium/third_party/skia/src/core/SkScan.h38
-rw-r--r--chromium/third_party/skia/src/core/SkScan_AntiPath.cpp7
-rw-r--r--chromium/third_party/skia/src/core/SkScan_Antihair.cpp26
-rw-r--r--chromium/third_party/skia/src/core/SkScan_Hairline.cpp6
-rw-r--r--chromium/third_party/skia/src/core/SkScan_Path.cpp6
-rw-r--r--chromium/third_party/skia/src/core/SkShader.cpp279
-rw-r--r--chromium/third_party/skia/src/core/SkSmallAllocator.h176
-rw-r--r--chromium/third_party/skia/src/core/SkSpriteBlitter.h9
-rw-r--r--chromium/third_party/skia/src/core/SkSpriteBlitter_ARGB32.cpp30
-rw-r--r--chromium/third_party/skia/src/core/SkSpriteBlitter_RGB16.cpp48
-rw-r--r--chromium/third_party/skia/src/core/SkStream.cpp45
-rw-r--r--chromium/third_party/skia/src/core/SkString.cpp2
-rw-r--r--chromium/third_party/skia/src/core/SkStringUtils.h23
-rw-r--r--chromium/third_party/skia/src/core/SkStrokeRec.cpp10
-rw-r--r--chromium/third_party/skia/src/core/SkStrokerPriv.cpp6
-rw-r--r--chromium/third_party/skia/src/core/SkTDynamicHash.h159
-rw-r--r--chromium/third_party/skia/src/core/SkTInternalSList.h132
-rw-r--r--chromium/third_party/skia/src/core/SkTLList.h24
-rw-r--r--chromium/third_party/skia/src/core/SkTObjectPool.h109
-rw-r--r--[-rwxr-xr-x]chromium/third_party/skia/src/core/SkTRefArray.h0
-rw-r--r--chromium/third_party/skia/src/core/SkTemplatesPriv.h76
-rw-r--r--chromium/third_party/skia/src/core/SkTextMapStateProc.h76
-rw-r--r--chromium/third_party/skia/src/core/SkThreadPriv.h23
-rw-r--r--chromium/third_party/skia/src/core/SkTileGrid.cpp9
-rw-r--r--chromium/third_party/skia/src/core/SkTileGrid.h12
-rw-r--r--chromium/third_party/skia/src/core/SkTileGridPicture.cpp28
-rw-r--r--chromium/third_party/skia/src/core/SkTraceEvent.h1245
-rw-r--r--chromium/third_party/skia/src/core/SkTypeface.cpp71
-rw-r--r--chromium/third_party/skia/src/core/SkUnPreMultiply.cpp9
-rw-r--r--chromium/third_party/skia/src/core/SkUtils.cpp47
-rw-r--r--chromium/third_party/skia/src/core/SkUtilsArm.cpp10
-rw-r--r--chromium/third_party/skia/src/core/SkUtilsArm.h4
-rw-r--r--chromium/third_party/skia/src/core/SkValidatingReadBuffer.cpp35
-rw-r--r--chromium/third_party/skia/src/core/SkValidatingReadBuffer.h14
-rw-r--r--chromium/third_party/skia/src/core/SkValidationUtils.h6
-rw-r--r--chromium/third_party/skia/src/core/SkVertState.cpp106
-rw-r--r--chromium/third_party/skia/src/core/SkVertState.h58
-rw-r--r--chromium/third_party/skia/src/core/SkWriteBuffer.cpp (renamed from chromium/third_party/skia/src/core/SkOrderedWriteBuffer.cpp)146
-rw-r--r--chromium/third_party/skia/src/core/SkWriter32.cpp295
-rw-r--r--chromium/third_party/skia/src/core/SkXfermode.cpp370
-rw-r--r--chromium/third_party/skia/src/core/SkXfermode_proccoeff.h47
-rw-r--r--chromium/third_party/skia/src/device/xps/SkXPSDevice.cpp35
-rw-r--r--chromium/third_party/skia/src/effects/Sk1DPathEffect.cpp7
-rw-r--r--chromium/third_party/skia/src/effects/Sk2DPathEffect.cpp15
-rw-r--r--chromium/third_party/skia/src/effects/SkAlphaThresholdFilter.cpp366
-rw-r--r--chromium/third_party/skia/src/effects/SkArithmeticMode.cpp104
-rw-r--r--chromium/third_party/skia/src/effects/SkAvoidXfermode.cpp9
-rw-r--r--chromium/third_party/skia/src/effects/SkBicubicImageFilter.cpp35
-rw-r--r--chromium/third_party/skia/src/effects/SkBitmapAlphaThresholdShader.cpp277
-rw-r--r--chromium/third_party/skia/src/effects/SkBitmapSource.cpp50
-rw-r--r--chromium/third_party/skia/src/effects/SkBlurDrawLooper.cpp125
-rw-r--r--chromium/third_party/skia/src/effects/SkBlurImageFilter.cpp116
-rw-r--r--chromium/third_party/skia/src/effects/SkBlurMask.cpp169
-rw-r--r--chromium/third_party/skia/src/effects/SkBlurMask.h90
-rw-r--r--chromium/third_party/skia/src/effects/SkBlurMaskFilter.cpp772
-rwxr-xr-xchromium/third_party/skia/src/effects/SkColorFilterImageFilter.cpp27
-rw-r--r--chromium/third_party/skia/src/effects/SkColorFilters.cpp335
-rw-r--r--chromium/third_party/skia/src/effects/SkColorMatrix.cpp43
-rw-r--r--chromium/third_party/skia/src/effects/SkColorMatrixFilter.cpp48
-rw-r--r--chromium/third_party/skia/src/effects/SkComposeImageFilter.cpp17
-rw-r--r--chromium/third_party/skia/src/effects/SkCornerPathEffect.cpp7
-rw-r--r--chromium/third_party/skia/src/effects/SkDashPathEffect.cpp385
-rw-r--r--chromium/third_party/skia/src/effects/SkDiscretePathEffect.cpp23
-rw-r--r--chromium/third_party/skia/src/effects/SkDisplacementMapEffect.cpp243
-rw-r--r--chromium/third_party/skia/src/effects/SkDropShadowImageFilter.cpp77
-rw-r--r--chromium/third_party/skia/src/effects/SkEmbossMaskFilter.cpp34
-rw-r--r--chromium/third_party/skia/src/effects/SkGpuBlurUtils.cpp11
-rw-r--r--chromium/third_party/skia/src/effects/SkKernel33MaskFilter.cpp142
-rw-r--r--chromium/third_party/skia/src/effects/SkLayerDrawLooper.cpp245
-rw-r--r--chromium/third_party/skia/src/effects/SkLayerRasterizer.cpp108
-rw-r--r--chromium/third_party/skia/src/effects/SkLerpXfermode.cpp9
-rw-r--r--chromium/third_party/skia/src/effects/SkLightingImageFilter.cpp160
-rw-r--r--chromium/third_party/skia/src/effects/SkLumaColorFilter.cpp6
-rw-r--r--chromium/third_party/skia/src/effects/SkMagnifierImageFilter.cpp21
-rw-r--r--chromium/third_party/skia/src/effects/SkMatrixConvolutionImageFilter.cpp125
-rw-r--r--chromium/third_party/skia/src/effects/SkMatrixImageFilter.cpp126
-rwxr-xr-xchromium/third_party/skia/src/effects/SkMergeImageFilter.cpp55
-rw-r--r--chromium/third_party/skia/src/effects/SkMorphologyImageFilter.cpp284
-rw-r--r--chromium/third_party/skia/src/effects/SkOffsetImageFilter.cpp59
-rw-r--r--chromium/third_party/skia/src/effects/SkPerlinNoiseShader.cpp792
-rw-r--r--chromium/third_party/skia/src/effects/SkPictureImageFilter.cpp60
-rw-r--r--chromium/third_party/skia/src/effects/SkPixelXorXfermode.cpp9
-rw-r--r--chromium/third_party/skia/src/effects/SkRectShaderImageFilter.cpp28
-rw-r--r--chromium/third_party/skia/src/effects/SkStippleMaskFilter.cpp2
-rw-r--r--chromium/third_party/skia/src/effects/SkTableColorFilter.cpp19
-rw-r--r--chromium/third_party/skia/src/effects/SkTableMaskFilter.cpp11
-rwxr-xr-xchromium/third_party/skia/src/effects/SkTestImageFilters.cpp11
-rw-r--r--chromium/third_party/skia/src/effects/SkTileImageFilter.cpp50
-rw-r--r--chromium/third_party/skia/src/effects/SkTransparentShader.cpp59
-rw-r--r--chromium/third_party/skia/src/effects/SkXfermodeImageFilter.cpp96
-rw-r--r--chromium/third_party/skia/src/effects/gradients/SkClampRange.cpp5
-rw-r--r--chromium/third_party/skia/src/effects/gradients/SkClampRange.h1
-rw-r--r--chromium/third_party/skia/src/effects/gradients/SkGradientShader.cpp492
-rw-r--r--chromium/third_party/skia/src/effects/gradients/SkGradientShaderPriv.h151
-rw-r--r--chromium/third_party/skia/src/effects/gradients/SkLinearGradient.cpp100
-rw-r--r--chromium/third_party/skia/src/effects/gradients/SkLinearGradient.h30
-rw-r--r--chromium/third_party/skia/src/effects/gradients/SkRadialGradient.cpp89
-rw-r--r--chromium/third_party/skia/src/effects/gradients/SkRadialGradient.h30
-rw-r--r--chromium/third_party/skia/src/effects/gradients/SkSweepGradient.cpp295
-rw-r--r--chromium/third_party/skia/src/effects/gradients/SkSweepGradient.h31
-rw-r--r--chromium/third_party/skia/src/effects/gradients/SkTwoPointConicalGradient.cpp539
-rw-r--r--chromium/third_party/skia/src/effects/gradients/SkTwoPointConicalGradient.h62
-rw-r--r--chromium/third_party/skia/src/effects/gradients/SkTwoPointConicalGradient_gpu.cpp1330
-rw-r--r--chromium/third_party/skia/src/effects/gradients/SkTwoPointConicalGradient_gpu.h25
-rw-r--r--chromium/third_party/skia/src/effects/gradients/SkTwoPointRadialGradient.cpp125
-rw-r--r--chromium/third_party/skia/src/effects/gradients/SkTwoPointRadialGradient.h31
-rw-r--r--chromium/third_party/skia/src/fonts/SkFontMgr_fontconfig.cpp71
-rw-r--r--chromium/third_party/skia/src/fonts/SkFontMgr_indirect.cpp297
-rw-r--r--chromium/third_party/skia/src/fonts/SkGScalerContext.cpp5
-rw-r--r--chromium/third_party/skia/src/fonts/SkRemotableFontMgr.cpp26
-rw-r--r--chromium/third_party/skia/src/gpu/FlingState.cpp125
-rw-r--r--chromium/third_party/skia/src/gpu/GrAAConvexPathRenderer.cpp38
-rw-r--r--chromium/third_party/skia/src/gpu/GrAAHairLinePathRenderer.cpp47
-rw-r--r--chromium/third_party/skia/src/gpu/GrAARectRenderer.cpp74
-rw-r--r--chromium/third_party/skia/src/gpu/GrAARectRenderer.h2
-rw-r--r--chromium/third_party/skia/src/gpu/GrAddPathRenderers_none.cpp15
-rw-r--r--chromium/third_party/skia/src/gpu/GrAllocPool.cpp6
-rw-r--r--chromium/third_party/skia/src/gpu/GrAllocPool.h2
-rw-r--r--[-rwxr-xr-x]chromium/third_party/skia/src/gpu/GrAllocator.h6
-rw-r--r--chromium/third_party/skia/src/gpu/GrAtlas.cpp346
-rw-r--r--chromium/third_party/skia/src/gpu/GrAtlas.h61
-rwxr-xr-xchromium/third_party/skia/src/gpu/GrBitmapTextContext.cpp490
-rw-r--r--chromium/third_party/skia/src/gpu/GrBitmapTextContext.h57
-rw-r--r--chromium/third_party/skia/src/gpu/GrBufferAllocPool.cpp86
-rw-r--r--chromium/third_party/skia/src/gpu/GrBufferAllocPool.h26
-rw-r--r--chromium/third_party/skia/src/gpu/GrCacheID.cpp2
-rw-r--r--chromium/third_party/skia/src/gpu/GrCacheable.cpp17
-rw-r--r--chromium/third_party/skia/src/gpu/GrClipData.cpp6
-rw-r--r--chromium/third_party/skia/src/gpu/GrClipMaskCache.h2
-rw-r--r--chromium/third_party/skia/src/gpu/GrClipMaskManager.cpp334
-rw-r--r--chromium/third_party/skia/src/gpu/GrClipMaskManager.h33
-rw-r--r--chromium/third_party/skia/src/gpu/GrContext.cpp549
-rw-r--r--chromium/third_party/skia/src/gpu/GrDefaultPathRenderer.cpp10
-rwxr-xr-xchromium/third_party/skia/src/gpu/GrDistanceFieldTextContext.cpp380
-rw-r--r--chromium/third_party/skia/src/gpu/GrDistanceFieldTextContext.h57
-rw-r--r--chromium/third_party/skia/src/gpu/GrDrawState.h11
-rw-r--r--chromium/third_party/skia/src/gpu/GrDrawTarget.cpp202
-rw-r--r--chromium/third_party/skia/src/gpu/GrDrawTarget.h76
-rw-r--r--chromium/third_party/skia/src/gpu/GrDrawTargetCaps.h34
-rw-r--r--chromium/third_party/skia/src/gpu/GrGeometryBuffer.h82
-rw-r--r--chromium/third_party/skia/src/gpu/GrGpu.cpp108
-rw-r--r--chromium/third_party/skia/src/gpu/GrGpu.h69
-rw-r--r--chromium/third_party/skia/src/gpu/GrGpuObject.cpp (renamed from chromium/third_party/skia/src/gpu/GrResource.cpp)23
-rw-r--r--chromium/third_party/skia/src/gpu/GrInOrderDrawBuffer.cpp205
-rw-r--r--chromium/third_party/skia/src/gpu/GrInOrderDrawBuffer.h34
-rw-r--r--chromium/third_party/skia/src/gpu/GrIndexBuffer.h6
-rw-r--r--chromium/third_party/skia/src/gpu/GrLayerCache.cpp86
-rw-r--r--chromium/third_party/skia/src/gpu/GrLayerCache.h120
-rw-r--r--chromium/third_party/skia/src/gpu/GrMemory.cpp26
-rw-r--r--chromium/third_party/skia/src/gpu/GrMemoryPool.cpp6
-rw-r--r--chromium/third_party/skia/src/gpu/GrOrderedSet.h154
-rw-r--r--chromium/third_party/skia/src/gpu/GrOvalRenderer.cpp199
-rw-r--r--chromium/third_party/skia/src/gpu/GrOvalRenderer.h6
-rw-r--r--chromium/third_party/skia/src/gpu/GrPaint.cpp2
-rw-r--r--chromium/third_party/skia/src/gpu/GrPath.h6
-rw-r--r--chromium/third_party/skia/src/gpu/GrPathUtils.cpp142
-rw-r--r--chromium/third_party/skia/src/gpu/GrPathUtils.h33
-rw-r--r--chromium/third_party/skia/src/gpu/GrPictureUtils.cpp279
-rw-r--r--chromium/third_party/skia/src/gpu/GrPictureUtils.h79
-rw-r--r--chromium/third_party/skia/src/gpu/GrPlotMgr.h7
-rw-r--r--chromium/third_party/skia/src/gpu/GrRectanizer.cpp128
-rw-r--r--chromium/third_party/skia/src/gpu/GrRectanizer.h19
-rw-r--r--chromium/third_party/skia/src/gpu/GrRectanizer_fifo.cpp121
-rw-r--r--chromium/third_party/skia/src/gpu/GrRectanizer_pow2.cpp60
-rw-r--r--chromium/third_party/skia/src/gpu/GrRectanizer_pow2.h79
-rwxr-xr-xchromium/third_party/skia/src/gpu/GrRectanizer_skyline.cpp73
-rw-r--r--chromium/third_party/skia/src/gpu/GrRectanizer_skyline.h62
-rw-r--r--chromium/third_party/skia/src/gpu/GrRedBlackTree.h181
-rw-r--r--chromium/third_party/skia/src/gpu/GrReducedClip.cpp18
-rw-r--r--chromium/third_party/skia/src/gpu/GrReducedClip.h15
-rw-r--r--chromium/third_party/skia/src/gpu/GrRenderTarget.cpp13
-rw-r--r--chromium/third_party/skia/src/gpu/GrResourceCache.cpp130
-rw-r--r--chromium/third_party/skia/src/gpu/GrResourceCache.h126
-rw-r--r--chromium/third_party/skia/src/gpu/GrSWMaskHelper.cpp62
-rw-r--r--chromium/third_party/skia/src/gpu/GrSWMaskHelper.h7
-rw-r--r--chromium/third_party/skia/src/gpu/GrStencil.cpp2
-rw-r--r--chromium/third_party/skia/src/gpu/GrStencilBuffer.h9
-rw-r--r--chromium/third_party/skia/src/gpu/GrStrokeInfo.h99
-rw-r--r--chromium/third_party/skia/src/gpu/GrSurface.cpp18
-rw-r--r--chromium/third_party/skia/src/gpu/GrTBSearch.h5
-rw-r--r--chromium/third_party/skia/src/gpu/GrTHashTable.h7
-rw-r--r--chromium/third_party/skia/src/gpu/GrTMultiMap.h110
-rw-r--r--chromium/third_party/skia/src/gpu/GrTemplates.h2
-rw-r--r--chromium/third_party/skia/src/gpu/GrTest.cpp5
-rw-r--r--chromium/third_party/skia/src/gpu/GrTextContext.cpp62
-rw-r--r--chromium/third_party/skia/src/gpu/GrTextContext.h55
-rw-r--r--chromium/third_party/skia/src/gpu/GrTextStrike.cpp234
-rw-r--r--chromium/third_party/skia/src/gpu/GrTextStrike.h31
-rw-r--r--chromium/third_party/skia/src/gpu/GrTextStrike_impl.h8
-rw-r--r--chromium/third_party/skia/src/gpu/GrTexture.cpp67
-rw-r--r--chromium/third_party/skia/src/gpu/GrTextureAccess.cpp2
-rw-r--r--chromium/third_party/skia/src/gpu/GrTraceMarker.cpp87
-rw-r--r--chromium/third_party/skia/src/gpu/GrTraceMarker.h98
-rw-r--r--chromium/third_party/skia/src/gpu/GrTracing.h108
-rw-r--r--chromium/third_party/skia/src/gpu/GrVertexBuffer.h4
-rw-r--r--chromium/third_party/skia/src/gpu/SkGpuDevice.cpp1364
-rw-r--r--chromium/third_party/skia/src/gpu/SkGr.cpp292
-rw-r--r--chromium/third_party/skia/src/gpu/SkGrFontScaler.cpp42
-rw-r--r--chromium/third_party/skia/src/gpu/SkGrPixelRef.cpp51
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrBezierEffect.cpp63
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrBezierEffect.h162
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrBicubicEffect.cpp96
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrBicubicEffect.h60
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrConfigConversionEffect.cpp10
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrConvexPolyEffect.cpp374
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrConvexPolyEffect.h91
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrConvolutionEffect.cpp2
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrDashingEffect.cpp628
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrDashingEffect.h37
-rwxr-xr-xchromium/third_party/skia/src/gpu/effects/GrDistanceFieldTextureEffect.cpp423
-rw-r--r--[-rwxr-xr-x]chromium/third_party/skia/src/gpu/effects/GrDistanceFieldTextureEffect.h85
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrDitherEffect.cpp115
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrDitherEffect.h23
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrOvalEffect.cpp387
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrOvalEffect.h24
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrRRectEffect.cpp730
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrRRectEffect.h25
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrSimpleTextureEffect.cpp2
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrTextureDomain.cpp2
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrTextureDomain.h6
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrTextureStripAtlas.cpp2
-rw-r--r--chromium/third_party/skia/src/gpu/effects/GrTextureStripAtlas.h2
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLAssembleInterface.cpp295
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLAssembleInterface.h18
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLBufferImpl.cpp127
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLBufferImpl.h13
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLCaps.cpp298
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLCaps.h69
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLContext.cpp76
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLContext.h86
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLCreateNullInterface.cpp316
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLDefines.h89
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLExtensions.cpp87
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLIndexBuffer.cpp26
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLIndexBuffer.h16
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLInterface.cpp690
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLNameAllocator.cpp370
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLNameAllocator.h86
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLNoOpInterface.cpp65
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLNoOpInterface.h32
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLPath.cpp15
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLPath.h2
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLProgram.cpp215
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLProgram.h100
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLProgramDesc.cpp18
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLProgramDesc.h6
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLProgramEffects.cpp52
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLProgramEffects.h37
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLSL.cpp42
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLSL.h5
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLShaderBuilder.cpp364
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLShaderBuilder.h243
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLShaderVar.h10
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLStencilBuffer.cpp4
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLStencilBuffer.h2
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLTexture.h6
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLUniformManager.cpp4
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLUniformManager.h4
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLUtil.cpp44
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLUtil.h23
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLVertexArray.cpp65
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLVertexArray.h33
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLVertexBuffer.cpp27
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLVertexBuffer.h16
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGLVertexEffect.h2
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGpuGL.cpp646
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGpuGL.h75
-rw-r--r--chromium/third_party/skia/src/gpu/gl/GrGpuGL_program.cpp39
-rw-r--r--chromium/third_party/skia/src/gpu/gl/SkGLContextHelper.cpp15
-rw-r--r--chromium/third_party/skia/src/gpu/gl/android/GrGLCreateNativeInterface_android.cpp558
-rw-r--r--chromium/third_party/skia/src/gpu/gl/android/SkNativeGLContext_android.cpp8
-rw-r--r--chromium/third_party/skia/src/gpu/gl/angle/GrGLCreateANGLEInterface.cpp270
-rw-r--r--chromium/third_party/skia/src/gpu/gl/debug/GrBufferObj.h12
-rw-r--r--chromium/third_party/skia/src/gpu/gl/debug/GrFakeRefObj.h2
-rw-r--r--chromium/third_party/skia/src/gpu/gl/debug/GrGLCreateDebugInterface.cpp361
-rw-r--r--chromium/third_party/skia/src/gpu/gl/iOS/GrGLCreateNativeInterface_iOS.cpp264
-rw-r--r--chromium/third_party/skia/src/gpu/gl/mac/GrGLCreateNativeInterface_mac.cpp237
-rw-r--r--chromium/third_party/skia/src/gpu/gl/mesa/GrGLCreateMesaInterface.cpp219
-rw-r--r--chromium/third_party/skia/src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp277
-rw-r--r--chromium/third_party/skia/src/gpu/gl/win/GrGLCreateNativeInterface_win.cpp316
-rw-r--r--chromium/third_party/skia/src/gpu/gl/win/SkNativeGLContext_win.cpp3
-rw-r--r--chromium/third_party/skia/src/image/SkDataPixelRef.cpp46
-rw-r--r--chromium/third_party/skia/src/image/SkDataPixelRef.h36
-rw-r--r--chromium/third_party/skia/src/image/SkImage.cpp84
-rw-r--r--chromium/third_party/skia/src/image/SkImagePriv.cpp82
-rw-r--r--chromium/third_party/skia/src/image/SkImagePriv.h21
-rw-r--r--chromium/third_party/skia/src/image/SkImage_Base.h8
-rw-r--r--chromium/third_party/skia/src/image/SkImage_Codec.cpp9
-rw-r--r--chromium/third_party/skia/src/image/SkImage_Gpu.cpp9
-rw-r--r--chromium/third_party/skia/src/image/SkImage_Picture.cpp66
-rw-r--r--chromium/third_party/skia/src/image/SkImage_Raster.cpp63
-rw-r--r--chromium/third_party/skia/src/image/SkSurface.cpp33
-rw-r--r--chromium/third_party/skia/src/image/SkSurface_Base.h21
-rw-r--r--chromium/third_party/skia/src/image/SkSurface_Gpu.cpp84
-rw-r--r--chromium/third_party/skia/src/image/SkSurface_Picture.cpp92
-rw-r--r--chromium/third_party/skia/src/image/SkSurface_Raster.cpp41
-rw-r--r--chromium/third_party/skia/src/images/SkDecodingImageGenerator.cpp311
-rw-r--r--chromium/third_party/skia/src/images/SkDecodingImageGenerator.h120
-rw-r--r--chromium/third_party/skia/src/images/SkForceLinking.cpp2
-rw-r--r--chromium/third_party/skia/src/images/SkImageDecoder.cpp96
-rw-r--r--chromium/third_party/skia/src/images/SkImageDecoder_ktx.cpp277
-rw-r--r--chromium/third_party/skia/src/images/SkImageDecoder_libbmp.cpp11
-rw-r--r--chromium/third_party/skia/src/images/SkImageDecoder_libgif.cpp54
-rw-r--r--chromium/third_party/skia/src/images/SkImageDecoder_libico.cpp6
-rw-r--r--chromium/third_party/skia/src/images/SkImageDecoder_libjpeg.cpp115
-rw-r--r--chromium/third_party/skia/src/images/SkImageDecoder_libpng.cpp216
-rw-r--r--chromium/third_party/skia/src/images/SkImageDecoder_libwebp.cpp163
-rw-r--r--chromium/third_party/skia/src/images/SkImageDecoder_pkm.cpp133
-rw-r--r--chromium/third_party/skia/src/images/SkImageDecoder_wbmp.cpp4
-rw-r--r--chromium/third_party/skia/src/images/SkImageEncoder_argb.cpp15
-rw-r--r--chromium/third_party/skia/src/images/SkImageRef.cpp191
-rw-r--r--chromium/third_party/skia/src/images/SkImageRefPool.cpp192
-rw-r--r--chromium/third_party/skia/src/images/SkImageRefPool.h49
-rw-r--r--chromium/third_party/skia/src/images/SkImageRef_GlobalPool.cpp100
-rw-r--r--chromium/third_party/skia/src/images/SkImageRef_ashmem.cpp233
-rw-r--r--chromium/third_party/skia/src/images/SkImageRef_ashmem.h47
-rw-r--r--chromium/third_party/skia/src/images/SkImages.cpp21
-rw-r--r--chromium/third_party/skia/src/images/SkMovie_gif.cpp6
-rw-r--r--chromium/third_party/skia/src/images/SkScaledBitmapSampler.cpp116
-rw-r--r--chromium/third_party/skia/src/images/SkScaledBitmapSampler.h13
-rw-r--r--chromium/third_party/skia/src/images/SkStreamHelpers.cpp27
-rw-r--r--chromium/third_party/skia/src/images/SkStreamHelpers.h9
-rw-r--r--chromium/third_party/skia/src/lazy/SkCachingPixelRef.cpp24
-rw-r--r--chromium/third_party/skia/src/lazy/SkCachingPixelRef.h7
-rw-r--r--chromium/third_party/skia/src/lazy/SkDiscardableMemoryPool.cpp176
-rw-r--r--chromium/third_party/skia/src/lazy/SkDiscardableMemoryPool.h74
-rw-r--r--chromium/third_party/skia/src/lazy/SkDiscardablePixelRef.cpp69
-rw-r--r--chromium/third_party/skia/src/lazy/SkDiscardablePixelRef.h16
-rw-r--r--chromium/third_party/skia/src/lazy/SkPurgeableMemoryBlock.h94
-rw-r--r--chromium/third_party/skia/src/lazy/SkPurgeableMemoryBlock_common.cpp16
-rw-r--r--chromium/third_party/skia/src/opts/SkBitmapFilter_opts_SSE2.cpp793
-rw-r--r--chromium/third_party/skia/src/opts/SkBitmapFilter_opts_SSE2.h6
-rw-r--r--chromium/third_party/skia/src/opts/SkBitmapProcState_filter_neon.h22
-rw-r--r--chromium/third_party/skia/src/opts/SkBitmapProcState_matrixProcs_neon.cpp140
-rw-r--r--chromium/third_party/skia/src/opts/SkBitmapProcState_matrix_clamp_neon.h911
-rw-r--r--chromium/third_party/skia/src/opts/SkBitmapProcState_matrix_neon.h506
-rw-r--r--chromium/third_party/skia/src/opts/SkBitmapProcState_matrix_repeat_neon.h542
-rw-r--r--chromium/third_party/skia/src/opts/SkBitmapProcState_opts_SSE2.cpp32
-rw-r--r--chromium/third_party/skia/src/opts/SkBitmapProcState_opts_SSE2.h11
-rw-r--r--chromium/third_party/skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp47
-rw-r--r--chromium/third_party/skia/src/opts/SkBitmapProcState_opts_SSSE3.h5
-rw-r--r--chromium/third_party/skia/src/opts/SkBitmapProcState_opts_arm.cpp12
-rw-r--r--chromium/third_party/skia/src/opts/SkBlitMask_opts_arm.cpp15
-rw-r--r--chromium/third_party/skia/src/opts/SkBlitMask_opts_none.cpp10
-rw-r--r--chromium/third_party/skia/src/opts/SkBlitRect_opts_SSE2.cpp21
-rw-r--r--chromium/third_party/skia/src/opts/SkBlitRect_opts_SSE2.h8
-rw-r--r--chromium/third_party/skia/src/opts/SkBlitRow_opts_SSE2.cpp524
-rw-r--r--chromium/third_party/skia/src/opts/SkBlitRow_opts_SSE2.h18
-rw-r--r--chromium/third_party/skia/src/opts/SkBlitRow_opts_arm.cpp6
-rw-r--r--chromium/third_party/skia/src/opts/SkBlitRow_opts_arm_neon.cpp875
-rw-r--r--chromium/third_party/skia/src/opts/SkBlitRow_opts_mips_dsp.cpp848
-rw-r--r--chromium/third_party/skia/src/opts/SkBlurImage_opts_SSE2.cpp25
-rw-r--r--chromium/third_party/skia/src/opts/SkBlurImage_opts_SSE2.h5
-rw-r--r--chromium/third_party/skia/src/opts/SkBlurImage_opts_arm.cpp25
-rw-r--r--chromium/third_party/skia/src/opts/SkBlurImage_opts_neon.cpp93
-rw-r--r--chromium/third_party/skia/src/opts/SkCachePreload_arm.h34
-rw-r--r--chromium/third_party/skia/src/opts/SkColor_opts_SSE2.h186
-rw-r--r--chromium/third_party/skia/src/opts/SkMath_opts_SSE2.h51
-rw-r--r--chromium/third_party/skia/src/opts/SkMorphology_opts.h17
-rw-r--r--chromium/third_party/skia/src/opts/SkMorphology_opts_SSE2.cpp12
-rw-r--r--chromium/third_party/skia/src/opts/SkMorphology_opts_SSE2.h7
-rw-r--r--chromium/third_party/skia/src/opts/SkMorphology_opts_arm.cpp34
-rw-r--r--chromium/third_party/skia/src/opts/SkMorphology_opts_none.cpp2
-rw-r--r--chromium/third_party/skia/src/opts/SkUtils_opts_SSE2.cpp32
-rw-r--r--chromium/third_party/skia/src/opts/SkUtils_opts_SSE2.h6
-rw-r--r--chromium/third_party/skia/src/opts/SkUtils_opts_arm.cpp57
-rw-r--r--chromium/third_party/skia/src/opts/SkUtils_opts_none.cpp4
-rw-r--r--chromium/third_party/skia/src/opts/SkXfermode_opts_SSE2.cpp819
-rw-r--r--chromium/third_party/skia/src/opts/SkXfermode_opts_SSE2.h38
-rw-r--r--chromium/third_party/skia/src/opts/SkXfermode_opts_arm_neon.cpp80
-rw-r--r--chromium/third_party/skia/src/opts/SkXfermode_opts_arm_neon.h4
-rw-r--r--chromium/third_party/skia/src/opts/opts_check_SSE2.cpp294
-rw-r--r--chromium/third_party/skia/src/opts/opts_check_arm.cpp110
-rw-r--r--chromium/third_party/skia/src/opts/opts_check_x86.cpp379
-rw-r--r--chromium/third_party/skia/src/pathops/SkAddIntersections.cpp9
-rw-r--r--chromium/third_party/skia/src/pathops/SkDCubicIntersection.cpp69
-rw-r--r--chromium/third_party/skia/src/pathops/SkDCubicLineIntersection.cpp91
-rw-r--r--chromium/third_party/skia/src/pathops/SkDCubicToQuads.cpp12
-rw-r--r--chromium/third_party/skia/src/pathops/SkDLineIntersection.cpp70
-rw-r--r--chromium/third_party/skia/src/pathops/SkDQuadIntersection.cpp20
-rw-r--r--chromium/third_party/skia/src/pathops/SkDQuadLineIntersection.cpp58
-rw-r--r--chromium/third_party/skia/src/pathops/SkIntersectionHelper.h25
-rw-r--r--chromium/third_party/skia/src/pathops/SkIntersections.cpp25
-rw-r--r--chromium/third_party/skia/src/pathops/SkIntersections.h38
-rw-r--r--chromium/third_party/skia/src/pathops/SkLineParameters.h80
-rw-r--r--chromium/third_party/skia/src/pathops/SkOpAngle.cpp1289
-rw-r--r--chromium/third_party/skia/src/pathops/SkOpAngle.h121
-rw-r--r--chromium/third_party/skia/src/pathops/SkOpContour.cpp404
-rw-r--r--chromium/third_party/skia/src/pathops/SkOpContour.h104
-rw-r--r--chromium/third_party/skia/src/pathops/SkOpEdgeBuilder.cpp4
-rw-r--r--chromium/third_party/skia/src/pathops/SkOpSegment.cpp3137
-rw-r--r--chromium/third_party/skia/src/pathops/SkOpSegment.h243
-rw-r--r--chromium/third_party/skia/src/pathops/SkOpSpan.h20
-rw-r--r--chromium/third_party/skia/src/pathops/SkPathOpsCommon.cpp255
-rw-r--r--chromium/third_party/skia/src/pathops/SkPathOpsCommon.h6
-rw-r--r--chromium/third_party/skia/src/pathops/SkPathOpsCubic.cpp98
-rw-r--r--chromium/third_party/skia/src/pathops/SkPathOpsCubic.h40
-rw-r--r--chromium/third_party/skia/src/pathops/SkPathOpsCurve.h26
-rw-r--r--chromium/third_party/skia/src/pathops/SkPathOpsDebug.cpp514
-rw-r--r--chromium/third_party/skia/src/pathops/SkPathOpsDebug.h92
-rw-r--r--chromium/third_party/skia/src/pathops/SkPathOpsLine.cpp15
-rw-r--r--chromium/third_party/skia/src/pathops/SkPathOpsLine.h6
-rw-r--r--chromium/third_party/skia/src/pathops/SkPathOpsOp.cpp133
-rw-r--r--chromium/third_party/skia/src/pathops/SkPathOpsPoint.h57
-rw-r--r--chromium/third_party/skia/src/pathops/SkPathOpsQuad.cpp25
-rw-r--r--chromium/third_party/skia/src/pathops/SkPathOpsQuad.h7
-rw-r--r--chromium/third_party/skia/src/pathops/SkPathOpsSimplify.cpp44
-rw-r--r--chromium/third_party/skia/src/pathops/SkPathOpsTriangle.cpp2
-rw-r--r--chromium/third_party/skia/src/pathops/SkPathOpsTypes.cpp7
-rw-r--r--chromium/third_party/skia/src/pathops/SkPathOpsTypes.h96
-rw-r--r--chromium/third_party/skia/src/pathops/SkPathWriter.h1
-rw-r--r--chromium/third_party/skia/src/pathops/SkQuarticRoot.cpp7
-rw-r--r--chromium/third_party/skia/src/pathops/SkReduceOrder.cpp4
-rw-r--r--chromium/third_party/skia/src/pathops/main.cpp16
-rw-r--r--chromium/third_party/skia/src/pdf/SkPDFDevice.cpp111
-rw-r--r--chromium/third_party/skia/src/pdf/SkPDFDeviceFlattener.cpp7
-rw-r--r--chromium/third_party/skia/src/pdf/SkPDFDocument.cpp46
-rw-r--r--chromium/third_party/skia/src/pdf/SkPDFFont.cpp104
-rw-r--r--chromium/third_party/skia/src/pdf/SkPDFFont.h19
-rw-r--r--[-rwxr-xr-x]chromium/third_party/skia/src/pdf/SkPDFFontImpl.h0
-rw-r--r--chromium/third_party/skia/src/pdf/SkPDFGraphicState.cpp12
-rw-r--r--chromium/third_party/skia/src/pdf/SkPDFImage.cpp62
-rw-r--r--chromium/third_party/skia/src/pdf/SkPDFShader.cpp4
-rw-r--r--chromium/third_party/skia/src/pdf/SkPDFTypes.cpp12
-rw-r--r--chromium/third_party/skia/src/pdf/SkPDFTypes.h8
-rw-r--r--chromium/third_party/skia/src/pipe/SkGPipePriv.h3
-rw-r--r--chromium/third_party/skia/src/pipe/SkGPipeRead.cpp45
-rw-r--r--chromium/third_party/skia/src/pipe/SkGPipeWrite.cpp358
-rw-r--r--chromium/third_party/skia/src/pipe/utils/SamplePipeControllers.cpp2
-rw-r--r--chromium/third_party/skia/src/ports/SkAtomics_sync.h43
-rw-r--r--chromium/third_party/skia/src/ports/SkAtomics_win.h49
-rw-r--r--chromium/third_party/skia/src/ports/SkBarriers_arm.h26
-rw-r--r--chromium/third_party/skia/src/ports/SkBarriers_tsan.h25
-rw-r--r--chromium/third_party/skia/src/ports/SkBarriers_x86.h33
-rw-r--r--chromium/third_party/skia/src/ports/SkDiscardableMemory_ashmem.cpp113
-rw-r--r--chromium/third_party/skia/src/ports/SkFontConfigInterface_android.cpp99
-rw-r--r--chromium/third_party/skia/src/ports/SkFontConfigInterface_direct.cpp13
-rw-r--r--chromium/third_party/skia/src/ports/SkFontConfigParser_android.cpp21
-rw-r--r--chromium/third_party/skia/src/ports/SkFontConfigParser_android.h8
-rw-r--r--chromium/third_party/skia/src/ports/SkFontConfigTypeface.h34
-rw-r--r--chromium/third_party/skia/src/ports/SkFontHost_FreeType.cpp287
-rw-r--r--chromium/third_party/skia/src/ports/SkFontHost_FreeType_common.cpp56
-rw-r--r--chromium/third_party/skia/src/ports/SkFontHost_FreeType_common.h1
-rw-r--r--chromium/third_party/skia/src/ports/SkFontHost_fontconfig.cpp2
-rw-r--r--chromium/third_party/skia/src/ports/SkFontHost_linux.cpp36
-rwxr-xr-xchromium/third_party/skia/src/ports/SkFontHost_mac.cpp75
-rw-r--r--chromium/third_party/skia/src/ports/SkFontHost_sandbox_none.cpp0
-rwxr-xr-xchromium/third_party/skia/src/ports/SkFontHost_win.cpp170
-rw-r--r--chromium/third_party/skia/src/ports/SkFontHost_win_dw.cpp1912
-rw-r--r--chromium/third_party/skia/src/ports/SkFontMgr_win_dw.cpp764
-rw-r--r--chromium/third_party/skia/src/ports/SkGlobalInitialization_chromium.cpp15
-rw-r--r--chromium/third_party/skia/src/ports/SkGlobalInitialization_default.cpp16
-rw-r--r--chromium/third_party/skia/src/ports/SkHarfBuzzFont.cpp187
-rw-r--r--chromium/third_party/skia/src/ports/SkImageDecoder_CG.cpp37
-rw-r--r--chromium/third_party/skia/src/ports/SkImageDecoder_WIC.cpp6
-rw-r--r--chromium/third_party/skia/src/ports/SkImageDecoder_empty.cpp38
-rw-r--r--chromium/third_party/skia/src/ports/SkMutex_pthread.h91
-rw-r--r--chromium/third_party/skia/src/ports/SkMutex_win.h76
-rw-r--r--chromium/third_party/skia/src/ports/SkOSFile_win.cpp16
-rw-r--r--chromium/third_party/skia/src/ports/SkPurgeableMemoryBlock_android.cpp110
-rw-r--r--chromium/third_party/skia/src/ports/SkPurgeableMemoryBlock_mac.cpp104
-rw-r--r--chromium/third_party/skia/src/ports/SkPurgeableMemoryBlock_none.cpp40
-rw-r--r--chromium/third_party/skia/src/ports/SkRemotableFontMgr_win_dw.cpp527
-rw-r--r--chromium/third_party/skia/src/ports/SkScalerContext_win_dw.cpp747
-rw-r--r--chromium/third_party/skia/src/ports/SkScalerContext_win_dw.h63
-rw-r--r--chromium/third_party/skia/src/ports/SkThread_none.cpp43
-rw-r--r--chromium/third_party/skia/src/ports/SkThread_pthread.cpp197
-rw-r--r--chromium/third_party/skia/src/ports/SkThread_win.cpp65
-rw-r--r--chromium/third_party/skia/src/ports/SkTypeface_win_dw.cpp489
-rw-r--r--chromium/third_party/skia/src/ports/SkTypeface_win_dw.h117
-rw-r--r--chromium/third_party/skia/src/ports/SkXMLParser_expat.cpp140
-rw-r--r--chromium/third_party/skia/src/ports/SkXMLParser_tinyxml.cpp87
-rw-r--r--chromium/third_party/skia/src/ports/SkXMLPullParser_expat.cpp213
-rw-r--r--chromium/third_party/skia/src/sfnt/SkOTTableTypes.h15
-rw-r--r--chromium/third_party/skia/src/sfnt/SkOTTable_EBDT.h109
-rw-r--r--chromium/third_party/skia/src/sfnt/SkOTTable_EBLC.h152
-rw-r--r--chromium/third_party/skia/src/sfnt/SkOTTable_EBSC.h41
-rw-r--r--chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_V0.h22
-rw-r--r--chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_V1.h224
-rw-r--r--chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_V2.h252
-rw-r--r--chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_V3.h268
-rw-r--r--chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_V4.h346
-rw-r--r--chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_VA.h20
-rw-r--r--chromium/third_party/skia/src/sfnt/SkOTTable_gasp.h73
-rw-r--r--chromium/third_party/skia/src/sfnt/SkOTUtils.cpp6
-rw-r--r--chromium/third_party/skia/src/text/SkTextLayout.cpp78
-rw-r--r--chromium/third_party/skia/src/utils/SkBase64.cpp21
-rw-r--r--chromium/third_party/skia/src/utils/SkBase64.h5
-rw-r--r--[-rwxr-xr-x]chromium/third_party/skia/src/utils/SkBitSet.h0
-rw-r--r--chromium/third_party/skia/src/utils/SkBitmapHasher.cpp4
-rw-r--r--chromium/third_party/skia/src/utils/SkBitmapHasher.h2
-rw-r--r--chromium/third_party/skia/src/utils/SkCamera.cpp92
-rw-r--r--chromium/third_party/skia/src/utils/SkCanvasStack.cpp23
-rw-r--r--chromium/third_party/skia/src/utils/SkCanvasStack.h13
-rw-r--r--chromium/third_party/skia/src/utils/SkCanvasStateUtils.cpp131
-rw-r--r--chromium/third_party/skia/src/utils/SkCullPoints.cpp10
-rw-r--r--chromium/third_party/skia/src/utils/SkDashPath.cpp328
-rw-r--r--chromium/third_party/skia/src/utils/SkDashPathPriv.h32
-rw-r--r--chromium/third_party/skia/src/utils/SkDebugTrace.h24
-rw-r--r--chromium/third_party/skia/src/utils/SkDeferredCanvas.cpp351
-rw-r--r--chromium/third_party/skia/src/utils/SkDumpCanvas.cpp147
-rw-r--r--chromium/third_party/skia/src/utils/SkEventTracer.cpp59
-rw-r--r--chromium/third_party/skia/src/utils/SkFrontBufferedStream.cpp16
-rw-r--r--chromium/third_party/skia/src/utils/SkGatherPixelRefsAndRects.cpp25
-rw-r--r--chromium/third_party/skia/src/utils/SkGatherPixelRefsAndRects.h333
-rw-r--r--chromium/third_party/skia/src/utils/SkInterpolator.cpp8
-rw-r--r--chromium/third_party/skia/src/utils/SkJSON.cpp634
-rw-r--r--chromium/third_party/skia/src/utils/SkLua.cpp390
-rw-r--r--chromium/third_party/skia/src/utils/SkLuaCanvas.cpp137
-rw-r--r--chromium/third_party/skia/src/utils/SkMD5.h4
-rw-r--r--chromium/third_party/skia/src/utils/SkMatrix22.cpp40
-rw-r--r--chromium/third_party/skia/src/utils/SkMatrix22.h31
-rw-r--r--chromium/third_party/skia/src/utils/SkNWayCanvas.cpp124
-rw-r--r--chromium/third_party/skia/src/utils/SkPDFRasterizer.cpp18
-rw-r--r--chromium/third_party/skia/src/utils/SkPDFRasterizer.h2
-rw-r--r--chromium/third_party/skia/src/utils/SkParse.cpp45
-rw-r--r--chromium/third_party/skia/src/utils/SkParseColor.cpp8
-rw-r--r--chromium/third_party/skia/src/utils/SkParsePath.cpp5
-rw-r--r--chromium/third_party/skia/src/utils/SkPictureUtils.cpp92
-rw-r--r--chromium/third_party/skia/src/utils/SkProxyCanvas.cpp86
-rw-r--r--chromium/third_party/skia/src/utils/SkRTConf.cpp29
-rw-r--r--chromium/third_party/skia/src/utils/SkSHA1.h2
-rw-r--r--chromium/third_party/skia/src/utils/SkTLogic.h49
-rw-r--r--chromium/third_party/skia/src/utils/SkTextureCompressor.cpp210
-rw-r--r--chromium/third_party/skia/src/utils/SkTextureCompressor.h31
-rw-r--r--chromium/third_party/skia/src/utils/SkThreadPool.cpp127
-rw-r--r--chromium/third_party/skia/src/utils/SkUnitMappers.cpp59
-rw-r--r--chromium/third_party/skia/src/utils/android/ashmem.cpp87
-rw-r--r--chromium/third_party/skia/src/utils/android/ashmem.h50
-rw-r--r--chromium/third_party/skia/src/utils/debugger/SkDebugCanvas.cpp486
-rw-r--r--chromium/third_party/skia/src/utils/debugger/SkDebugCanvas.h141
-rw-r--r--chromium/third_party/skia/src/utils/debugger/SkDrawCommand.cpp213
-rw-r--r--chromium/third_party/skia/src/utils/debugger/SkDrawCommand.h96
-rw-r--r--chromium/third_party/skia/src/utils/debugger/SkObjectParser.cpp16
-rw-r--r--chromium/third_party/skia/src/utils/debugger/SkObjectParser.h2
-rwxr-xr-xchromium/third_party/skia/src/utils/ios/SkImageDecoder_iOS.mm3
-rw-r--r--chromium/third_party/skia/src/utils/mac/SkCreateCGImageRef.cpp166
-rw-r--r--chromium/third_party/skia/src/utils/win/SkDWrite.cpp130
-rw-r--r--chromium/third_party/skia/src/utils/win/SkDWrite.h76
-rw-r--r--chromium/third_party/skia/src/utils/win/SkDWriteFontFileStream.h1
-rw-r--r--chromium/third_party/skia/src/utils/win/SkHRESULT.cpp15
-rw-r--r--chromium/third_party/skia/src/views/SkParsePaint.cpp2
-rw-r--r--chromium/third_party/skia/src/views/SkStackViewLayout.cpp4
-rw-r--r--chromium/third_party/skia/src/views/SkWidgets.cpp8
-rw-r--r--chromium/third_party/skia/src/views/SkWindow.cpp146
-rw-r--r--chromium/third_party/skia/src/views/mac/SkNSView.mm3
-rw-r--r--chromium/third_party/skia/src/views/mac/SkOptionsTableView.mm10
-rw-r--r--chromium/third_party/skia/src/views/sdl/SkOSWindow_SDL.cpp13
-rw-r--r--chromium/third_party/skia/src/views/unix/SkOSWindow_Unix.cpp10
-rw-r--r--chromium/third_party/skia/src/views/unix/skia_unix.cpp19
-rw-r--r--chromium/third_party/skia/src/views/win/SkOSWindow_win.cpp11
-rw-r--r--chromium/third_party/skia/src/xml/SkJSDisplayable.cpp8
-rw-r--r--chromium/third_party/skia/src/xml/SkXMLWriter.cpp2
747 files changed, 53765 insertions, 34904 deletions
diff --git a/chromium/third_party/skia/src/animator/SkAnimateBase.cpp b/chromium/third_party/skia/src/animator/SkAnimateBase.cpp
index 3d50144abcd..8467ce6f358 100644
--- a/chromium/third_party/skia/src/animator/SkAnimateBase.cpp
+++ b/chromium/third_party/skia/src/animator/SkAnimateBase.cpp
@@ -163,8 +163,10 @@ void SkAnimateBase::packARGB(SkScalar array[], int count, SkTDOperandArray* conv
{
SkASSERT(count == 4);
converted->setCount(1);
- SkColor color = SkColorSetARGB(SkScalarRound(array[0]), SkScalarRound(array[1]),
- SkScalarRound(array[2]), SkScalarRound(array[3]));
+ SkColor color = SkColorSetARGB(SkScalarRoundToInt(array[0]),
+ SkScalarRoundToInt(array[1]),
+ SkScalarRoundToInt(array[2]),
+ SkScalarRoundToInt(array[3]));
(*converted)[0].fS32 = color;
}
diff --git a/chromium/third_party/skia/src/animator/SkAnimateSet.cpp b/chromium/third_party/skia/src/animator/SkAnimateSet.cpp
index f153b16bbd9..d146118e89b 100644
--- a/chromium/third_party/skia/src/animator/SkAnimateSet.cpp
+++ b/chromium/third_party/skia/src/animator/SkAnimateSet.cpp
@@ -62,7 +62,7 @@ void SkSet::onEndElement(SkAnimateMaker& maker) {
fReset = dur != 1;
SkDisplayTypes outType = fFieldInfo->getType();
int comps = outType == SkType_String || outType == SkType_DynamicString ? 1 :
- fFieldInfo->getSize((const SkDisplayable*) fTarget) / sizeof(int);
+ (int)fFieldInfo->getSize((const SkDisplayable*) fTarget) / sizeof(int);
if (fValues.getType() == SkType_Unknown) {
fValues.setType(outType);
fValues.setCount(comps);
diff --git a/chromium/third_party/skia/src/animator/SkBoundable.cpp b/chromium/third_party/skia/src/animator/SkBoundable.cpp
index 64a70057b9e..abc4f40d6ee 100644
--- a/chromium/third_party/skia/src/animator/SkBoundable.cpp
+++ b/chromium/third_party/skia/src/animator/SkBoundable.cpp
@@ -42,7 +42,7 @@ void SkBoundable::enableBounder() {
SkBoundableAuto::SkBoundableAuto(SkBoundable* boundable,
SkAnimateMaker& maker) : fBoundable(boundable), fMaker(maker) {
if (fBoundable->hasBounds()) {
- fMaker.fCanvas->setBounder(&maker.fDisplayList);
+// fMaker.fCanvas->setBounder(&maker.fDisplayList);
fMaker.fDisplayList.fBounds.setEmpty();
}
}
@@ -50,6 +50,6 @@ SkBoundableAuto::SkBoundableAuto(SkBoundable* boundable,
SkBoundableAuto::~SkBoundableAuto() {
if (fBoundable->hasBounds() == false)
return;
- fMaker.fCanvas->setBounder(NULL);
+// fMaker.fCanvas->setBounder(NULL);
fBoundable->setBounds(fMaker.fDisplayList.fBounds);
}
diff --git a/chromium/third_party/skia/src/animator/SkDisplayList.h b/chromium/third_party/skia/src/animator/SkDisplayList.h
index b8705982e4c..a856413def3 100644
--- a/chromium/third_party/skia/src/animator/SkDisplayList.h
+++ b/chromium/third_party/skia/src/animator/SkDisplayList.h
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -6,14 +5,13 @@
* found in the LICENSE file.
*/
-
#ifndef SkDisplayList_DEFINED
#define SkDisplayList_DEFINED
#include "SkOperand.h"
#include "SkIntArray.h"
-#include "SkBounder.h"
#include "SkRect.h"
+#include "SkRefCnt.h"
class SkAnimateMaker;
class SkActive;
@@ -21,7 +19,7 @@ class SkApply;
class SkDrawable;
class SkGroup;
-class SkDisplayList : public SkBounder {
+class SkDisplayList : public SkRefCnt {
public:
SkDisplayList();
virtual ~SkDisplayList();
diff --git a/chromium/third_party/skia/src/animator/SkDisplayMath.cpp b/chromium/third_party/skia/src/animator/SkDisplayMath.cpp
index bdf377b3026..7f406c1f655 100644
--- a/chromium/third_party/skia/src/animator/SkDisplayMath.cpp
+++ b/chromium/third_party/skia/src/animator/SkDisplayMath.cpp
@@ -21,7 +21,6 @@ enum SkDisplayMath_Properties {
};
const SkScalar SkDisplayMath::gConstants[] = {
-#ifdef SK_SCALAR_IS_FLOAT
2.718281828f, // E
2.302585093f, // LN10
0.693147181f, // LN2
@@ -30,16 +29,6 @@ const SkScalar SkDisplayMath::gConstants[] = {
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 {
@@ -166,7 +155,7 @@ void SkDisplayMath::executeFunction(SkDisplayable* target, int index,
scalarResult = SkScalarATan2(input, parameters[1].fOperand.fScalar);
break;
case SK_FUNCTION(ceil):
- scalarResult = SkIntToScalar(SkScalarCeil(input));
+ scalarResult = SkScalarCeilToScalar(input);
break;
case SK_FUNCTION(cos):
scalarResult = SkScalarCos(input);
@@ -175,7 +164,7 @@ void SkDisplayMath::executeFunction(SkDisplayable* target, int index,
scalarResult = SkScalarExp(input);
break;
case SK_FUNCTION(floor):
- scalarResult = SkIntToScalar(SkScalarFloor(input));
+ scalarResult = SkScalarFloorToScalar(input);
break;
case SK_FUNCTION(log):
scalarResult = SkScalarLog(input);
@@ -204,7 +193,7 @@ void SkDisplayMath::executeFunction(SkDisplayable* target, int index,
scalarResult = fRandom.nextUScalar1();
break;
case SK_FUNCTION(round):
- scalarResult = SkIntToScalar(SkScalarRound(input));
+ scalarResult = SkScalarRoundToScalar(input);
break;
case SK_FUNCTION(sin):
scalarResult = SkScalarSin(input);
diff --git a/chromium/third_party/skia/src/animator/SkDisplayType.cpp b/chromium/third_party/skia/src/animator/SkDisplayType.cpp
index dc52f0caccd..4461a4b77b0 100644
--- a/chromium/third_party/skia/src/animator/SkDisplayType.cpp
+++ b/chromium/third_party/skia/src/animator/SkDisplayType.cpp
@@ -372,7 +372,7 @@ const SkMemberInfo* SkDisplayType::GetMembers(SkAnimateMaker* maker,
const SkMemberInfo* SkDisplayType::GetMember(SkAnimateMaker* maker,
SkDisplayTypes type, const char** matchPtr ) {
- int infoCount;
+ int infoCount = 0; // Initialize to remove a warning.
const SkMemberInfo* info = GetMembers(maker, type, &infoCount);
info = SkMemberInfo::Find(info, infoCount, matchPtr);
// SkASSERT(info);
diff --git a/chromium/third_party/skia/src/animator/SkDrawBitmap.cpp b/chromium/third_party/skia/src/animator/SkDrawBitmap.cpp
index 327e81365af..f481ee7dba6 100644
--- a/chromium/third_party/skia/src/animator/SkDrawBitmap.cpp
+++ b/chromium/third_party/skia/src/animator/SkDrawBitmap.cpp
@@ -56,7 +56,7 @@ const SkMemberInfo SkDrawBitmap::fInfo[] = {
DEFINE_GET_MEMBER(SkDrawBitmap);
-SkDrawBitmap::SkDrawBitmap() : format((SkBitmap::Config) -1), height(-1),
+SkDrawBitmap::SkDrawBitmap() : format((SkColorType) -1), height(-1),
rowBytes(0), width(-1), fColor(0), fColorSet(false) {
}
@@ -88,7 +88,8 @@ void SkDrawBitmap::onEndElement(SkAnimateMaker&) {
SkASSERT(width != -1);
SkASSERT(height != -1);
SkASSERT(rowBytes >= 0);
- fBitmap.setConfig((SkBitmap::Config) format, width, height, rowBytes);
+ SkColorType colorType = SkColorType(format);
+ fBitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType), rowBytes);
fBitmap.allocPixels();
if (fColorSet)
fBitmap.eraseColor(fColor);
diff --git a/chromium/third_party/skia/src/animator/SkDrawBlur.cpp b/chromium/third_party/skia/src/animator/SkDrawBlur.cpp
index 5f388c9310f..36d645286fd 100644
--- a/chromium/third_party/skia/src/animator/SkDrawBlur.cpp
+++ b/chromium/third_party/skia/src/animator/SkDrawBlur.cpp
@@ -22,11 +22,12 @@ DEFINE_GET_MEMBER(SkDrawBlur);
SkDrawBlur::SkDrawBlur()
: fSigma(-1)
- , fBlurStyle(SkBlurMaskFilter::kNormal_BlurStyle) {
+ , fBlurStyle(kNormal_SkBlurStyle) {
}
SkMaskFilter* SkDrawBlur::getMaskFilter() {
- if (fSigma < 0)
+ if (fSigma <= 0) {
return NULL;
- return SkBlurMaskFilter::Create((SkBlurMaskFilter::BlurStyle) fBlurStyle, fSigma);
+ }
+ return SkBlurMaskFilter::Create((SkBlurStyle)fBlurStyle, fSigma);
}
diff --git a/chromium/third_party/skia/src/animator/SkDrawBlur.h b/chromium/third_party/skia/src/animator/SkDrawBlur.h
index 0c916a382f7..75075922dc7 100644
--- a/chromium/third_party/skia/src/animator/SkDrawBlur.h
+++ b/chromium/third_party/skia/src/animator/SkDrawBlur.h
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -6,11 +5,10 @@
* found in the LICENSE file.
*/
-
#ifndef SkDrawBlur_DEFINED
#define SkDrawBlur_DEFINED
-#include "SkPaintParts.h"
+#include "SkPaintPart.h"
#include "SkBlurMaskFilter.h"
class SkDrawBlur : public SkDrawMaskFilter {
@@ -19,7 +17,7 @@ class SkDrawBlur : public SkDrawMaskFilter {
virtual SkMaskFilter* getMaskFilter() SK_OVERRIDE;
protected:
SkScalar fSigma;
- int /*SkBlurMaskFilter::BlurStyle*/ fBlurStyle;
+ int /*SkBlurStyle*/ fBlurStyle;
typedef SkDrawMaskFilter INHERITED;
};
diff --git a/chromium/third_party/skia/src/animator/SkDrawColor.cpp b/chromium/third_party/skia/src/animator/SkDrawColor.cpp
index b6bc261d718..eb57d9dad49 100644
--- a/chromium/third_party/skia/src/animator/SkDrawColor.cpp
+++ b/chromium/third_party/skia/src/animator/SkDrawColor.cpp
@@ -69,7 +69,7 @@ static SkColor HSV_to_RGB(SkColor color, HSV_Choice choice, SkScalar hsv) {
red = green = blue = value;
else {
//SkScalar fraction = SkScalarMod(hue, 60 * SK_Scalar1);
- int sextant = SkScalarFloor(hue / 60);
+ int sextant = SkScalarFloorToInt(hue / 60);
SkScalar fraction = hue / 60 - SkIntToScalar(sextant);
SkScalar p = SkScalarMul(value , SK_Scalar1 - saturation);
SkScalar q = SkScalarMul(value, SK_Scalar1 - SkScalarMul(saturation, fraction));
@@ -85,8 +85,8 @@ static SkColor HSV_to_RGB(SkColor color, HSV_Choice choice, SkScalar hsv) {
}
}
//used to say SkToU8((U8CPU) red) etc
- return SkColorSetARGB(SkColorGetA(color), SkScalarRound(red),
- SkScalarRound(green), SkScalarRound(blue));
+ return SkColorSetARGB(SkColorGetA(color), SkScalarRoundToInt(red),
+ SkScalarRoundToInt(green), SkScalarRoundToInt(blue));
}
#if defined _WIN32 && _MSC_VER >= 1300
@@ -226,11 +226,7 @@ bool SkDrawColor::setProperty(int index, SkScriptValue& value) {
switch (index) {
case SK_PROPERTY(alpha):
uint8_t 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;
diff --git a/chromium/third_party/skia/src/animator/SkDrawColor.h b/chromium/third_party/skia/src/animator/SkDrawColor.h
index 281af0fb51d..17d1eef319d 100644
--- a/chromium/third_party/skia/src/animator/SkDrawColor.h
+++ b/chromium/third_party/skia/src/animator/SkDrawColor.h
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -6,11 +5,10 @@
* found in the LICENSE file.
*/
-
#ifndef SkDrawColor_DEFINED
#define SkDrawColor_DEFINED
-#include "SkPaintParts.h"
+#include "SkPaintPart.h"
#include "SkColor.h"
class SkDrawColor : public SkPaintPart {
diff --git a/chromium/third_party/skia/src/animator/SkDrawDash.cpp b/chromium/third_party/skia/src/animator/SkDrawDash.cpp
index 8e73aa1c2de..cfef30335b9 100644
--- a/chromium/third_party/skia/src/animator/SkDrawDash.cpp
+++ b/chromium/third_party/skia/src/animator/SkDrawDash.cpp
@@ -31,5 +31,5 @@ SkPathEffect* SkDash::getPathEffect() {
int count = intervals.count();
if (count == 0)
return NULL;
- return new SkDashPathEffect(intervals.begin(), count, phase);
+ return SkDashPathEffect::Create(intervals.begin(), count, phase);
}
diff --git a/chromium/third_party/skia/src/animator/SkDrawDash.h b/chromium/third_party/skia/src/animator/SkDrawDash.h
index 0000462ba7e..fafc4b07e27 100644
--- a/chromium/third_party/skia/src/animator/SkDrawDash.h
+++ b/chromium/third_party/skia/src/animator/SkDrawDash.h
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -6,11 +5,10 @@
* found in the LICENSE file.
*/
-
#ifndef SkDrawDash_DEFINED
#define SkDrawDash_DEFINED
-#include "SkPaintParts.h"
+#include "SkPaintPart.h"
#include "SkIntArray.h"
class SkDash : public SkDrawPathEffect {
diff --git a/chromium/third_party/skia/src/animator/SkDrawDiscrete.cpp b/chromium/third_party/skia/src/animator/SkDrawDiscrete.cpp
index 18c3ee0f61b..9376435950d 100644
--- a/chromium/third_party/skia/src/animator/SkDrawDiscrete.cpp
+++ b/chromium/third_party/skia/src/animator/SkDrawDiscrete.cpp
@@ -30,5 +30,5 @@ SkPathEffect* SkDiscrete::getPathEffect() {
if (deviation <= 0 || segLength <= 0)
return NULL;
else
- return new SkDiscretePathEffect(segLength, deviation);
+ return SkDiscretePathEffect::Create(segLength, deviation);
}
diff --git a/chromium/third_party/skia/src/animator/SkDrawDiscrete.h b/chromium/third_party/skia/src/animator/SkDrawDiscrete.h
index bd33d2fcd79..d0f9239c4c6 100644
--- a/chromium/third_party/skia/src/animator/SkDrawDiscrete.h
+++ b/chromium/third_party/skia/src/animator/SkDrawDiscrete.h
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -6,11 +5,10 @@
* found in the LICENSE file.
*/
-
#ifndef SkDrawDiscrete_DEFINED
#define SkDrawDiscrete_DEFINED
-#include "SkPaintParts.h"
+#include "SkPaintPart.h"
class SkDiscrete : public SkDrawPathEffect {
DECLARE_MEMBER_INFO(Discrete);
diff --git a/chromium/third_party/skia/src/animator/SkDrawExtraPathEffect.cpp b/chromium/third_party/skia/src/animator/SkDrawExtraPathEffect.cpp
index e973dbf7955..007fb5263bd 100644
--- a/chromium/third_party/skia/src/animator/SkDrawExtraPathEffect.cpp
+++ b/chromium/third_party/skia/src/animator/SkDrawExtraPathEffect.cpp
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -6,13 +5,12 @@
* found in the LICENSE file.
*/
-
#include "SkDrawExtraPathEffect.h"
#include "SkDrawPath.h"
#include "Sk1DPathEffect.h"
#include "Sk2DPathEffect.h"
#include "SkMemberInfo.h"
-#include "SkPaintParts.h"
+#include "SkPaintPart.h"
#include "SkPathEffect.h"
#include "SkCornerPathEffect.h"
@@ -112,7 +110,7 @@ protected:
SkApply* apply = (SkApply*) fDraw->addPath;
apply->refresh(*fMaker);
apply->activate(*fMaker);
- apply->interpolate(*fMaker, SkScalarMulRound(distance, 1000));
+ apply->interpolate(*fMaker, SkScalarRoundToInt(distance * 1000));
drawPath = (SkDrawPath*) apply->getScope();
}
SkMatrix m;
@@ -125,7 +123,7 @@ protected:
SkApply* apply = (SkApply*) fDraw->addMatrix;
apply->refresh(*fMaker);
apply->activate(*fMaker);
- apply->interpolate(*fMaker, SkScalarMulRound(distance, 1000));
+ apply->interpolate(*fMaker, SkScalarRoundToInt(distance * 1000));
matrix = (SkDrawMatrix*) apply->getScope();
}
if (matrix) {
@@ -371,7 +369,7 @@ bool SkDrawComposePathEffect::addChild(SkAnimateMaker& , SkDisplayable* child) {
SkPathEffect* SkDrawComposePathEffect::getPathEffect() {
SkPathEffect* e1 = effect1->getPathEffect();
SkPathEffect* e2 = effect2->getPathEffect();
- SkPathEffect* composite = new SkComposePathEffect(e1, e2);
+ SkPathEffect* composite = SkComposePathEffect::Create(e1, e2);
e1->unref();
e2->unref();
return composite;
@@ -401,7 +399,7 @@ SkDrawCornerPathEffect::~SkDrawCornerPathEffect() {
}
SkPathEffect* SkDrawCornerPathEffect::getPathEffect() {
- return new SkCornerPathEffect(radius);
+ return SkCornerPathEffect::Create(radius);
}
/////////
diff --git a/chromium/third_party/skia/src/animator/SkDrawGradient.cpp b/chromium/third_party/skia/src/animator/SkDrawGradient.cpp
index 44086e4269d..70e5e4493e0 100644
--- a/chromium/third_party/skia/src/animator/SkDrawGradient.cpp
+++ b/chromium/third_party/skia/src/animator/SkDrawGradient.cpp
@@ -11,57 +11,6 @@
#include "SkAnimateMaker.h"
#include "SkAnimatorScript.h"
#include "SkGradientShader.h"
-#include "SkUnitMapper.h"
-
-static SkScalar SkUnitToScalar(U16CPU x) {
-#ifdef SK_SCALAR_IS_FLOAT
- return x / 65535.0f;
-#else
- return x + (x >> 8);
-#endif
-}
-
-static 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 SkDrawGradientUnitMapper : public SkUnitMapper {
-public:
- SkDrawGradientUnitMapper(SkAnimateMaker* maker, const char* script) : fMaker(maker), fScript(script) {
- }
-
- SK_DECLARE_UNFLATTENABLE_OBJECT()
-
-protected:
- virtual uint16_t mapUnit16(uint16_t x) {
- fUnit = SkUnitToScalar(x);
- SkScriptValue value;
- SkAnimatorScript engine(*fMaker, NULL, 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
@@ -75,13 +24,12 @@ const SkMemberInfo SkDrawGradient::fInfo[] = {
DEFINE_GET_MEMBER(SkDrawGradient);
-SkDrawGradient::SkDrawGradient() : fUnitMapper(NULL) {
+SkDrawGradient::SkDrawGradient() {
}
SkDrawGradient::~SkDrawGradient() {
for (int index = 0; index < fDrawColors.count(); index++)
delete fDrawColors[index];
- delete fUnitMapper;
}
bool SkDrawGradient::addChild(SkAnimateMaker& , SkDisplayable* child) {
@@ -146,8 +94,6 @@ void SkDrawGradient::onEndElement(SkAnimateMaker& maker) {
}
}
}
- if (unitMapper.size() > 0)
- fUnitMapper = new SkDrawGradientUnitMapper(&maker, unitMapper.c_str());
INHERITED::onEndElement(maker);
}
@@ -183,9 +129,9 @@ SkShader* SkDrawLinearGradient::getShader() {
if (addPrelude() == 0 || points.count() != 4)
return NULL;
SkShader* shader = SkGradientShader::CreateLinear((SkPoint*)points.begin(),
- fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode, fUnitMapper);
+ fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode,
+ 0, getMatrix());
SkAutoTDelete<SkShader> autoDel(shader);
- addPostlude(shader);
(void)autoDel.detach();
return shader;
}
@@ -218,9 +164,9 @@ SkShader* SkDrawRadialGradient::getShader() {
if (addPrelude() == 0)
return NULL;
SkShader* shader = SkGradientShader::CreateRadial(center,
- radius, fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode, fUnitMapper);
+ radius, fColors.begin(), offsets.begin(), fColors.count(), (SkShader::TileMode) tileMode,
+ 0, getMatrix());
SkAutoTDelete<SkShader> autoDel(shader);
- addPostlude(shader);
(void)autoDel.detach();
return shader;
}
diff --git a/chromium/third_party/skia/src/animator/SkDrawGradient.h b/chromium/third_party/skia/src/animator/SkDrawGradient.h
index ff79e3fb912..fa46a9e6298 100644
--- a/chromium/third_party/skia/src/animator/SkDrawGradient.h
+++ b/chromium/third_party/skia/src/animator/SkDrawGradient.h
@@ -14,8 +14,6 @@
#include "SkDrawShader.h"
#include "SkIntArray.h"
-class SkUnitMapper;
-
class SkDrawGradient : public SkDrawShader {
DECLARE_PRIVATE_MEMBER_INFO(DrawGradient);
SkDrawGradient();
@@ -30,7 +28,6 @@ protected:
SkString unitMapper;
SkTDColorArray fColors;
SkTDDrawColorArray fDrawColors;
- SkUnitMapper* fUnitMapper;
int addPrelude();
private:
typedef SkDrawShader INHERITED;
diff --git a/chromium/third_party/skia/src/animator/SkDrawPaint.cpp b/chromium/third_party/skia/src/animator/SkDrawPaint.cpp
index 825d0486a7a..c882427585f 100644
--- a/chromium/third_party/skia/src/animator/SkDrawPaint.cpp
+++ b/chromium/third_party/skia/src/animator/SkDrawPaint.cpp
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -6,13 +5,12 @@
* found in the LICENSE file.
*/
-
#include "SkDrawPaint.h"
#include "SkAnimateMaker.h"
#include "SkDrawColor.h"
#include "SkDrawShader.h"
#include "SkMaskFilter.h"
-#include "SkPaintParts.h"
+#include "SkPaintPart.h"
#include "SkPathEffect.h"
enum SkPaint_Functions {
diff --git a/chromium/third_party/skia/src/animator/SkDrawSaveLayer.cpp b/chromium/third_party/skia/src/animator/SkDrawSaveLayer.cpp
index 4e97a044e5f..9623c905c9b 100644
--- a/chromium/third_party/skia/src/animator/SkDrawSaveLayer.cpp
+++ b/chromium/third_party/skia/src/animator/SkDrawSaveLayer.cpp
@@ -41,10 +41,10 @@ bool SkSaveLayer::draw(SkAnimateMaker& maker)
{
SkPaint realPaint;
paint->setupPaint(&realPaint);
- maker.fCanvas->saveLayer(&bounds->fRect, &realPaint, SkCanvas::kHasAlphaLayer_SaveFlag);
+ maker.fCanvas->saveLayer(&bounds->fRect, &realPaint);
}
else
- maker.fCanvas->saveLayer(&bounds->fRect, save, SkCanvas::kHasAlphaLayer_SaveFlag);
+ maker.fCanvas->saveLayer(&bounds->fRect, save);
SkPaint local = SkPaint(*maker.fPaint);
maker.fPaint = &local;
bool result = INHERITED::draw(maker);
diff --git a/chromium/third_party/skia/src/animator/SkDrawShader.cpp b/chromium/third_party/skia/src/animator/SkDrawShader.cpp
index e3aa4da028f..f9f379bf73b 100644
--- a/chromium/third_party/skia/src/animator/SkDrawShader.cpp
+++ b/chromium/third_party/skia/src/animator/SkDrawShader.cpp
@@ -36,9 +36,8 @@ bool SkDrawShader::add() {
return false;
}
-void SkDrawShader::addPostlude(SkShader* shader) {
- if (matrix)
- shader->setLocalMatrix(matrix->getMatrix());
+SkMatrix* SkDrawShader::getMatrix() {
+ return matrix ? &matrix->getMatrix() : NULL;
}
#if SK_USE_CONDENSED_INFO == 0
@@ -75,9 +74,9 @@ SkShader* SkDrawBitmapShader::getShader() {
// draw-time from the paint
SkShader* shader = SkShader::CreateBitmapShader(image->fBitmap,
(SkShader::TileMode) tileMode,
- (SkShader::TileMode) tileMode);
+ (SkShader::TileMode) tileMode,
+ getMatrix());
SkAutoTDelete<SkShader> autoDel(shader);
- addPostlude(shader);
(void)autoDel.detach();
return shader;
}
diff --git a/chromium/third_party/skia/src/animator/SkDrawShader.h b/chromium/third_party/skia/src/animator/SkDrawShader.h
index b6a487acdbb..2c46e077881 100644
--- a/chromium/third_party/skia/src/animator/SkDrawShader.h
+++ b/chromium/third_party/skia/src/animator/SkDrawShader.h
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -6,11 +5,10 @@
* found in the LICENSE file.
*/
-
#ifndef SkDrawShader_DEFINED
#define SkDrawShader_DEFINED
-#include "SkPaintParts.h"
+#include "SkPaintPart.h"
#include "SkShader.h"
class SkBaseBitmap;
diff --git a/chromium/third_party/skia/src/animator/SkDrawTransparentShader.h b/chromium/third_party/skia/src/animator/SkDrawTransparentShader.h
index bf6617403e7..e0f61edf933 100644
--- a/chromium/third_party/skia/src/animator/SkDrawTransparentShader.h
+++ b/chromium/third_party/skia/src/animator/SkDrawTransparentShader.h
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -6,11 +5,10 @@
* found in the LICENSE file.
*/
-
#ifndef SkDrawTransparentShader_DEFINED
#define SkDrawTransparentShader_DEFINED
-#include "SkPaintParts.h"
+#include "SkPaintPart.h"
class SkDrawTransparentShader : public SkDrawShader {
DECLARE_EMPTY_MEMBER_INFO(TransparentShader);
diff --git a/chromium/third_party/skia/src/animator/SkMemberInfo.cpp b/chromium/third_party/skia/src/animator/SkMemberInfo.cpp
index 5e54b53aed7..5cdc8d0de66 100644
--- a/chromium/third_party/skia/src/animator/SkMemberInfo.cpp
+++ b/chromium/third_party/skia/src/animator/SkMemberInfo.cpp
@@ -303,7 +303,7 @@ scriptCommon: {
return false;
}
if (type == SkType_MSec)
- scriptValue.fOperand.fMSec = SkScalarMulRound(scriptValue.fOperand.fScalar, 1000);
+ scriptValue.fOperand.fMSec = SkScalarRoundToInt(scriptValue.fOperand.fScalar * 1000);
scriptValue.fType = type;
break;
noScriptString:
diff --git a/chromium/third_party/skia/src/animator/SkOperandIterpolator.cpp b/chromium/third_party/skia/src/animator/SkOperandIterpolator.cpp
index 7822ee286e9..84b32823e1d 100644
--- a/chromium/third_party/skia/src/animator/SkOperandIterpolator.cpp
+++ b/chromium/third_party/skia/src/animator/SkOperandIterpolator.cpp
@@ -81,7 +81,7 @@ SkInterpolatorBase::Result SkOperandInterpolator::timeToValues(SkMSec time, SkOp
for (int i = fElemCount - 1; i >= 0; --i) {
int32_t a = prevSrc[i].fS32;
int32_t b = nextSrc[i].fS32;
- values[i].fS32 = a + SkScalarRound((b - a) * T);
+ values[i].fS32 = a + SkScalarRoundToInt((b - a) * T);
}
} else
memcpy(values, prevSrc, sizeof(SkOperand) * fElemCount);
diff --git a/chromium/third_party/skia/src/animator/SkPaintParts.cpp b/chromium/third_party/skia/src/animator/SkPaintPart.cpp
index 22119a4ff91..285b564c933 100644
--- a/chromium/third_party/skia/src/animator/SkPaintParts.cpp
+++ b/chromium/third_party/skia/src/animator/SkPaintPart.cpp
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -6,8 +5,7 @@
* found in the LICENSE file.
*/
-
-#include "SkPaintParts.h"
+#include "SkPaintPart.h"
#include "SkDrawPaint.h"
#ifdef SK_DUMP_ENABLED
#include "SkDisplayList.h"
diff --git a/chromium/third_party/skia/src/animator/SkPaintParts.h b/chromium/third_party/skia/src/animator/SkPaintPart.h
index 964bc359b0d..6f33cb4c39c 100644
--- a/chromium/third_party/skia/src/animator/SkPaintParts.h
+++ b/chromium/third_party/skia/src/animator/SkPaintPart.h
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -6,9 +5,8 @@
* found in the LICENSE file.
*/
-
-#ifndef SkPaintParts_DEFINED
-#define SkPaintParts_DEFINED
+#ifndef SkPaintPart_DEFINED
+#define SkPaintPart_DEFINED
#include "SkDisplayable.h"
#include "SkMemberInfo.h"
@@ -53,7 +51,7 @@ class SkDrawShader : public SkPaintPart {
virtual SkShader* getShader();
protected:
virtual bool add();
- void addPostlude(SkShader* shader);
+ SkMatrix* getMatrix(); // returns NULL if matrix is NULL
SkDrawMatrix* matrix;
int /*SkShader::TileMode*/ tileMode;
};
@@ -72,4 +70,4 @@ protected:
SkTypeface::Style style;
};
-#endif // SkPaintParts_DEFINED
+#endif // SkPaintPart_DEFINED
diff --git a/chromium/third_party/skia/src/animator/SkScript.cpp b/chromium/third_party/skia/src/animator/SkScript.cpp
index 934b0abe1a1..1d04d1b2763 100644
--- a/chromium/third_party/skia/src/animator/SkScript.cpp
+++ b/chromium/third_party/skia/src/animator/SkScript.cpp
@@ -1157,7 +1157,7 @@ noMatch:
}
SkOperand indexOperand;
fOperandStack.pop(&indexOperand);
- int index = indexType == kScalar ? SkScalarFloor(indexOperand.fScalar) :
+ int index = indexType == kScalar ? SkScalarFloorToInt(indexOperand.fScalar) :
indexOperand.fS32;
SkOpType arrayType;
fTypeStack.pop(&arrayType);
@@ -1324,7 +1324,7 @@ bool SkScriptEngine::processOp() {
type1 = kScalar;
}
if (type1 == kScalar && (attributes->fLeftType == kInt || type2 == kInt)) {
- operand1.fS32 = SkScalarFloor(operand1.fScalar);
+ operand1.fS32 = SkScalarFloorToInt(operand1.fScalar);
type1 = kInt;
}
}
@@ -1339,7 +1339,7 @@ bool SkScriptEngine::processOp() {
type2 = kScalar;
}
if (type2 == kScalar && (attributes->fRightType == kInt || type1 == kInt)) {
- operand2.fS32 = SkScalarFloor(operand2.fScalar);
+ operand2.fS32 = SkScalarFloorToInt(operand2.fScalar);
type2 = kInt;
}
}
@@ -1503,7 +1503,7 @@ bool SkScriptEngine::ConvertTo(SkScriptEngine* engine, SkDisplayTypes toType, Sk
if (type == SkType_Boolean)
break;
if (type == SkType_Float)
- operand.fS32 = SkScalarFloor(operand.fScalar);
+ operand.fS32 = SkScalarFloorToInt(operand.fScalar);
else {
if (type != SkType_String) {
success = false;
@@ -1650,13 +1650,8 @@ bool SkScriptEngine::ValueToString(SkScriptValue value, SkString* string) {
#define DEF_STRING_ANSWER NULL
#define testInt(expression) { #expression, SkType_Int, expression, DEF_SCALAR_ANSWER, DEF_STRING_ANSWER }
-#ifdef SK_SCALAR_IS_FLOAT
#define testScalar(expression) { #expression, SkType_Float, 0, (float) expression, DEF_STRING_ANSWER }
#define testRemainder(exp1, exp2) { #exp1 "%" #exp2, SkType_Float, 0, sk_float_mod(exp1, exp2), DEF_STRING_ANSWER }
-#else
- #define testScalar(expression) { #expression, SkType_Float, 0, (int) ((expression) * 65536.0f), DEF_STRING_ANSWER }
- #define testRemainder(exp1, exp2) { #exp1 "%" #exp2, SkType_Float, 0, (int) (sk_float_mod(exp1, exp2) * 65536.0f), DEF_STRING_ANSWER }
-#endif
#define testTrue(expression) { #expression, SkType_Int, 1, DEF_SCALAR_ANSWER, DEF_STRING_ANSWER }
#define testFalse(expression) { #expression, SkType_Int, 0, DEF_SCALAR_ANSWER, DEF_STRING_ANSWER }
diff --git a/chromium/third_party/skia/src/animator/SkScript2.h b/chromium/third_party/skia/src/animator/SkScript2.h
index 33e2af7fee7..d182e8c7c5d 100644
--- a/chromium/third_party/skia/src/animator/SkScript2.h
+++ b/chromium/third_party/skia/src/animator/SkScript2.h
@@ -188,8 +188,9 @@ protected:
Branch() {
}
- Branch(Op op, int depth, unsigned offset) : fOffset(offset), fOpStackDepth(depth), fOperator(op),
- fPrimed(kIsNotPrimed), fDone(kIsNotDone) {
+ Branch(Op op, int depth, size_t offset)
+ : fOffset(SkToU16(offset)), fOpStackDepth(depth), fOperator(op)
+ , fPrimed(kIsNotPrimed), fDone(kIsNotDone) {
}
enum Primed {
diff --git a/chromium/third_party/skia/src/animator/SkScriptRuntime.cpp b/chromium/third_party/skia/src/animator/SkScriptRuntime.cpp
index 061847ec126..78d9d5c2081 100644
--- a/chromium/third_party/skia/src/animator/SkScriptRuntime.cpp
+++ b/chromium/third_party/skia/src/animator/SkScriptRuntime.cpp
@@ -210,7 +210,7 @@ bool SkScriptRuntime::executeTokens(unsigned char* opCode) {
return false;
break;
case SkScriptEngine2::kScalarToInt:
- operand[0].fS32 = SkScalarFloor(operand[0].fScalar);
+ operand[0].fS32 = SkScalarFloorToInt(operand[0].fScalar);
break;
// arithmetic ops
case SkScriptEngine2::kAddInt:
diff --git a/chromium/third_party/skia/src/animator/SkScriptTokenizer.cpp b/chromium/third_party/skia/src/animator/SkScriptTokenizer.cpp
index 42954a77060..03ffaa4a721 100644
--- a/chromium/third_party/skia/src/animator/SkScriptTokenizer.cpp
+++ b/chromium/third_party/skia/src/animator/SkScriptTokenizer.cpp
@@ -170,7 +170,7 @@ void SkScriptEngine2::addTokenScalar(SkScalar scalar) {
}
void SkScriptEngine2::addTokenString(const SkString& string) {
- int size = string.size();
+ int size = SkToInt(string.size());
addTokenInt(size);
fActiveStream->write(string.c_str(), size);
}
@@ -984,7 +984,7 @@ void SkScriptEngine2::processLogicalOp(Op op) {
SkScriptValue2 value;
fValueStack.pop(&value);
SkASSERT(value.fType == SkOperand2::kS32 || value.fType == SkOperand2::kScalar); // !!! add error handling (although, could permit strings eventually)
- int index = value.fType == SkOperand2::kScalar ? SkScalarFloor(value.fOperand.fScalar) :
+ int index = value.fType == SkOperand2::kScalar ? SkScalarFloorToInt(value.fOperand.fScalar) :
value.fOperand.fS32;
SkScriptValue2 arrayValue;
fValueStack.pop(&arrayValue);
@@ -1023,7 +1023,7 @@ void SkScriptEngine2::processLogicalOp(Op op) {
branch.fOperator = op;
branch.fDone = Branch::kIsNotDone;
SkASSERT(branch.fOpStackDepth == fOpStack.count());
- branch.fOffset = newOffset;
+ branch.fOffset = SkToU16(newOffset);
fAccumulatorType = SkOperand2::kNoType;
} break;
case kLogicalAnd:
@@ -1200,7 +1200,7 @@ bool SkScriptEngine2::ConvertTo(SkScriptEngine2* engine, SkOperand2::OpType toTy
switch (toType) {
case SkOperand2::kS32:
if (type == SkOperand2::kScalar)
- operand.fS32 = SkScalarFloor(operand.fScalar);
+ operand.fS32 = SkScalarFloorToInt(operand.fScalar);
else {
SkASSERT(type == SkOperand2::kString);
success = SkParse::FindS32(operand.fString->c_str(), &operand.fS32) != NULL;
@@ -1274,13 +1274,8 @@ bool SkScriptEngine2::ValueToString(const SkScriptValue2& value, SkString* strin
#if defined(SK_SUPPORT_UNITTEST)
#define testInt(expression) { #expression, SkOperand2::kS32, expression, 0, NULL }
-#ifdef SK_SCALAR_IS_FLOAT
#define testScalar(expression) { #expression, SkOperand2::kScalar, 0, (float) (expression), NULL }
#define testRemainder(exp1, exp2) { #exp1 "%" #exp2, SkOperand2::kScalar, 0, fmodf((float) exp1, (float) exp2), NULL }
-#else
-#define testScalar(expression) { #expression, SkOperand2::kScalar, 0, (int) ((expression) * 65536.0f), NULL }
-#define testRemainder(exp1, exp2) { #exp1 "%" #exp2, SkOperand2::kScalar, 0, (int) (fmod(exp1, exp2) * 65536.0f), NULL }
-#endif
#define testTrue(expression) { #expression, SkOperand2::kS32, 1, 0, NULL }
#define testFalse(expression) { #expression, SkOperand2::kS32, 0, 0, NULL }
diff --git a/chromium/third_party/skia/src/animator/SkSnapshot.cpp b/chromium/third_party/skia/src/animator/SkSnapshot.cpp
index 493ce2b3e65..6f818a627d7 100644
--- a/chromium/third_party/skia/src/animator/SkSnapshot.cpp
+++ b/chromium/third_party/skia/src/animator/SkSnapshot.cpp
@@ -62,6 +62,6 @@ bool SkSnapshot::draw(SkAnimateMaker& maker) {
name.append(".png");
encoder->encodeFile(name.c_str(),
maker.fCanvas->getDevice()->accessBitmap(false),
- SkScalarFloor(quality));
+ SkScalarFloorToInt(quality));
return false;
}
diff --git a/chromium/third_party/skia/src/animator/SkTime.cpp b/chromium/third_party/skia/src/animator/SkTime.cpp
index ffd6f38d571..a4e035bd1e2 100644
--- a/chromium/third_party/skia/src/animator/SkTime.cpp
+++ b/chromium/third_party/skia/src/animator/SkTime.cpp
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -6,7 +5,6 @@
* found in the LICENSE file.
*/
-
#include "SkTime.h"
#ifdef SK_BUILD_FOR_WIN
@@ -15,10 +13,8 @@
SkMSec gForceTickCount = (SkMSec) -1;
#endif
-void SkTime::GetDateTime(DateTime* t)
-{
- if (t)
- {
+void SkTime::GetDateTime(DateTime* t) {
+ if (t) {
SYSTEMTIME syst;
::GetLocalTime(&syst);
@@ -32,11 +28,11 @@ void SkTime::GetDateTime(DateTime* t)
}
}
-SkMSec SkTime::GetMSecs()
-{
+SkMSec SkTime::GetMSecs() {
#ifdef SK_DEBUG
- if (gForceTickCount != (SkMSec) -1)
+ if (gForceTickCount != (SkMSec) -1) {
return gForceTickCount;
+ }
#endif
return ::GetTickCount();
}
@@ -45,10 +41,8 @@ SkMSec SkTime::GetMSecs()
#include <time.h>
-void SkTime::GetDateTime(DateTime* t)
-{
- if (t)
- {
+void SkTime::GetDateTime(DateTime* t) {
+ if (t) {
tm syst;
time_t tm;
@@ -64,17 +58,13 @@ void SkTime::GetDateTime(DateTime* t)
}
}
-#include "Sk64.h"
-
-SkMSec SkTime::GetMSecs()
-{
+SkMSec SkTime::GetMSecs() {
UnsignedWide wide;
- Sk64 s;
-
::Microseconds(&wide);
- s.set(wide.hi, wide.lo);
- s.div(1000, Sk64::kRound_DivOption);
- return s.get32();
+
+ int64_t s = ((int64_t)wide.hi << 32) | wide.lo;
+ s = (s + 500) / 1000; // rounded divide
+ return (SkMSec)s;
}
#endif
diff --git a/chromium/third_party/skia/src/core/ARGB32_Clamp_Bilinear_BitmapShader.h b/chromium/third_party/skia/src/core/ARGB32_Clamp_Bilinear_BitmapShader.h
deleted file mode 100644
index 87121cfdb2c..00000000000
--- a/chromium/third_party/skia/src/core/ARGB32_Clamp_Bilinear_BitmapShader.h
+++ /dev/null
@@ -1,177 +0,0 @@
-
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-class ARGB32_Clamp_Bilinear_BitmapShader : public SkBitmapShader {
-public:
- ARGB32_Clamp_Bilinear_BitmapShader(const SkBitmap& src)
- : SkBitmapShader(src, true,
- SkShader::kClamp_TileMode, SkShader::kClamp_TileMode)
- {}
-
- virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count);
-};
-
-SkPMColor sample_bilerp(SkFixed fx, SkFixed fy, unsigned srcMaxX, unsigned srcMaxY,
- const SkPMColor* srcPixels, int srcRB, const SkFilterPtrProc* proc_table);
-SkPMColor sample_bilerp(SkFixed fx, SkFixed fy, unsigned srcMaxX, unsigned srcMaxY,
- const SkPMColor* srcPixels, int srcRB, const SkFilterPtrProc* proc_table)
-{
- int ix = fx >> 16;
- int iy = fy >> 16;
-
- const SkPMColor *p00, *p01, *p10, *p11;
-
- p00 = p01 = ((const SkPMColor*)((const char*)srcPixels
- + SkClampMax(iy, srcMaxY) * srcRB))
- + SkClampMax(ix, srcMaxX);
-
- if ((unsigned)ix < srcMaxX)
- p01 += 1;
- p10 = p00;
- p11 = p01;
- if ((unsigned)iy < srcMaxY)
- {
- p10 = (const SkPMColor*)((const char*)p10 + srcRB);
- p11 = (const SkPMColor*)((const char*)p11 + srcRB);
- }
-
- SkFilterPtrProc proc = SkGetBilinearFilterPtrProc(proc_table, fx, fy);
- return proc(p00, p01, p10, p11);
-}
-
-static inline SkPMColor sample_bilerpx(SkFixed fx, unsigned srcMaxX, const SkPMColor* srcPixels,
- int srcRB, const SkFilterPtrProc* proc_table)
-{
- int ix = fx >> 16;
-
- const SkPMColor *p00, *p01, *p10, *p11;
-
- p00 = p01 = srcPixels + SkClampMax(ix, srcMaxX);
- if ((unsigned)ix < srcMaxX)
- p01 += 1;
-
- p10 = (const SkPMColor*)((const char*)p00 + srcRB);
- p11 = (const SkPMColor*)((const char*)p01 + srcRB);
-
- SkFilterPtrProc proc = SkGetBilinearFilterPtrXProc(proc_table, fx);
- return proc(p00, p01, p10, p11);
-}
-
-void ARGB32_Clamp_Bilinear_BitmapShader::shadeSpan(int x, int y, SkPMColor dstC[], int count)
-{
- SkASSERT(count > 0);
-
- unsigned srcScale = SkAlpha255To256(this->getPaintAlpha());
-
- const SkMatrix& inv = this->getTotalInverse();
- const SkBitmap& srcBitmap = this->getSrcBitmap();
- unsigned srcMaxX = srcBitmap.width() - 1;
- unsigned srcMaxY = srcBitmap.height() - 1;
- unsigned srcRB = srcBitmap.rowBytes();
-
- const SkFilterPtrProc* proc_table = SkGetBilinearFilterPtrProcTable();
- const SkPMColor* srcPixels = (const SkPMColor*)srcBitmap.getPixels();
-
- if (this->getInverseClass() == kPerspective_MatrixClass)
- {
- SkPerspIter iter(inv, SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, count);
-
- if (256 == srcScale)
- {
- while ((count = iter.next()) != 0)
- {
- const SkFixed* srcXY = iter.getXY();
- while (--count >= 0)
- {
- SkFixed fx = *srcXY++ - SK_FixedHalf;
- SkFixed fy = *srcXY++ - SK_FixedHalf;
- *dstC++ = sample_bilerp(fx, fy, srcMaxX, srcMaxY, srcPixels, srcRB, proc_table);
- }
- }
- }
- else // scale by srcScale
- {
- while ((count = iter.next()) != 0)
- {
- const SkFixed* srcXY = iter.getXY();
- while (--count >= 0)
- {
- SkFixed fx = *srcXY++ - SK_FixedHalf;
- SkFixed fy = *srcXY++ - SK_FixedHalf;
- SkPMColor c = sample_bilerp(fx, fy, srcMaxX, srcMaxY, srcPixels, srcRB, proc_table);
- *dstC++ = SkAlphaMulQ(c, srcScale);
- }
- }
- }
- }
- else // linear case
- {
- SkFixed fx, fy, dx, dy;
-
- // now init fx, fy, dx, dy
- {
- SkPoint srcPt;
- this->getInverseMapPtProc()(inv, SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf,
- &srcPt);
-
- fx = SkScalarToFixed(srcPt.fX) - SK_FixedHalf;
- fy = SkScalarToFixed(srcPt.fY) - SK_FixedHalf;
-
- if (this->getInverseClass() == kFixedStepInX_MatrixClass)
- (void)inv.fixedStepInX(SkIntToScalar(y), &dx, &dy);
- else
- {
- dx = SkScalarToFixed(inv.getScaleX());
- dy = SkScalarToFixed(inv.getSkewY());
- }
- }
-
- if (dy == 0 && (unsigned)(fy >> 16) < srcMaxY)
- {
- srcPixels = (const SkPMColor*)((const char*)srcPixels + (fy >> 16) * srcRB);
- proc_table = SkGetBilinearFilterPtrProcYTable(proc_table, fy);
- if (256 == srcScale)
- {
- do {
- *dstC++ = sample_bilerpx(fx, srcMaxX, srcPixels, srcRB, proc_table);
- fx += dx;
- } while (--count != 0);
- }
- else
- {
- do {
- SkPMColor c = sample_bilerpx(fx, srcMaxX, srcPixels, srcRB, proc_table);
- *dstC++ = SkAlphaMulQ(c, srcScale);
- fx += dx;
- } while (--count != 0);
- }
- }
- else // dy is != 0
- {
- if (256 == srcScale)
- {
- do {
- *dstC++ = sample_bilerp(fx, fy, srcMaxX, srcMaxY, srcPixels, srcRB, proc_table);
- fx += dx;
- fy += dy;
- } while (--count != 0);
- }
- else
- {
- do {
- SkPMColor c = sample_bilerp(fx, fy, srcMaxX, srcMaxY, srcPixels, srcRB, proc_table);
- *dstC++ = SkAlphaMulQ(c, srcScale);
- fx += dx;
- fy += dy;
- } while (--count != 0);
- }
- }
- }
-}
diff --git a/chromium/third_party/skia/src/core/Sk64.cpp b/chromium/third_party/skia/src/core/Sk64.cpp
deleted file mode 100644
index 54b30221c90..00000000000
--- a/chromium/third_party/skia/src/core/Sk64.cpp
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * Copyright 2006 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "Sk64.h"
-#include "SkMathPriv.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;
- }
-}
-
-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);
- if ((uint32_t)denom <= (uint32_t)hi)
- {
- hi -= denom;
- rlo |= 1;
- }
- 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 SkLONGLONG
- 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);
-}
diff --git a/chromium/third_party/skia/src/core/SkAAClip.cpp b/chromium/third_party/skia/src/core/SkAAClip.cpp
index a9d591a963b..14152f8317e 100644
--- a/chromium/third_party/skia/src/core/SkAAClip.cpp
+++ b/chromium/third_party/skia/src/core/SkAAClip.cpp
@@ -530,7 +530,7 @@ bool SkAAClip::trimTopBottom() {
do {
yoff -= 1;
} while (row_is_all_zeros(base + yoff->fOffset, width));
- skip = stop - yoff - 1;
+ skip = SkToInt(stop - yoff - 1);
SkASSERT(skip >= 0 && skip < head->fRowCount);
if (skip > 0) {
// removing from the bottom is easier than from the top, as we don't
@@ -1033,7 +1033,7 @@ public:
SkDEBUGCODE(prevY = row->fY);
yoffset->fY = row->fY - adjustY;
- yoffset->fOffset = data - baseData;
+ yoffset->fOffset = SkToU32(data - baseData);
yoffset += 1;
size_t n = row->fData->count();
diff --git a/chromium/third_party/skia/src/core/SkAnnotation.cpp b/chromium/third_party/skia/src/core/SkAnnotation.cpp
index 837cb62ad43..bddff64db84 100644
--- a/chromium/third_party/skia/src/core/SkAnnotation.cpp
+++ b/chromium/third_party/skia/src/core/SkAnnotation.cpp
@@ -7,7 +7,8 @@
#include "SkAnnotation.h"
#include "SkData.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkPoint.h"
#include "SkStream.h"
@@ -28,12 +29,12 @@ SkData* SkAnnotation::find(const char key[]) const {
return fKey.equals(key) ? fData : NULL;
}
-SkAnnotation::SkAnnotation(SkFlattenableReadBuffer& buffer) {
+SkAnnotation::SkAnnotation(SkReadBuffer& buffer) {
buffer.readString(&fKey);
fData = buffer.readByteArrayAsData();
}
-void SkAnnotation::writeToBuffer(SkFlattenableWriteBuffer& buffer) const {
+void SkAnnotation::writeToBuffer(SkWriteBuffer& buffer) const {
buffer.writeString(fKey.c_str());
buffer.writeDataAsByteArray(fData);
}
@@ -55,7 +56,7 @@ const char* SkAnnotationKeys::Link_Named_Dest_Key() {
#include "SkCanvas.h"
static void annotate_paint(SkPaint& paint, const char* key, SkData* value) {
- paint.setAnnotation(SkNEW_ARGS(SkAnnotation, (key, value)))->unref();
+ paint.setAnnotation(SkAnnotation::Create(key, value))->unref();
}
void SkAnnotateRectWithURL(SkCanvas* canvas, const SkRect& rect, SkData* value) {
diff --git a/chromium/third_party/skia/src/core/SkBBHFactory.cpp b/chromium/third_party/skia/src/core/SkBBHFactory.cpp
new file mode 100644
index 00000000000..7411eb34dab
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkBBHFactory.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkBBHFactory.h"
+#include "SkPictureStateTree.h"
+#include "SkQuadTree.h"
+#include "SkRTree.h"
+#include "SkTileGrid.h"
+
+
+SkBBoxHierarchy* SkQuadTreeFactory::operator()(int width, int height) const {
+ return SkNEW_ARGS(SkQuadTree, (SkIRect::MakeWH(width, height)));
+}
+
+SkBBoxHierarchy* SkRTreeFactory::operator()(int width, int height) const {
+ // These values were empirically determined to produce reasonable
+ // performance in most cases.
+ static const int kRTreeMinChildren = 6;
+ static const int kRTreeMaxChildren = 11;
+
+ SkScalar aspectRatio = SkScalarDiv(SkIntToScalar(width),
+ SkIntToScalar(height));
+ bool sortDraws = false; // Do not sort draw calls when bulk loading.
+
+ return SkRTree::Create(kRTreeMinChildren, kRTreeMaxChildren,
+ aspectRatio, sortDraws);
+}
+
+SkBBoxHierarchy* SkTileGridFactory::operator()(int width, int height) const {
+ SkASSERT(fInfo.fMargin.width() >= 0);
+ SkASSERT(fInfo.fMargin.height() >= 0);
+ // Note: SkIRects are non-inclusive of the right() column and bottom() row.
+ // For example, an SkIRect at 0,0 with a size of (1,1) will only have
+ // content at pixel (0,0) and will report left=0 and right=1, hence the
+ // "-1"s below.
+ int xTileCount = (width + fInfo.fTileInterval.width() - 1) / fInfo.fTileInterval.width();
+ int yTileCount = (height + fInfo.fTileInterval.height() - 1) / fInfo.fTileInterval.height();
+ return SkNEW_ARGS(SkTileGrid, (xTileCount, yTileCount, fInfo,
+ SkTileGridNextDatum<SkPictureStateTree::Draw>));
+}
diff --git a/chromium/third_party/skia/src/core/SkBBoxHierarchy.h b/chromium/third_party/skia/src/core/SkBBoxHierarchy.h
index 62b22d80e61..36047b9706c 100644
--- a/chromium/third_party/skia/src/core/SkBBoxHierarchy.h
+++ b/chromium/third_party/skia/src/core/SkBBoxHierarchy.h
@@ -64,11 +64,21 @@ public:
virtual void clear() = 0;
/**
- * Gets the number of insertions
+ * Gets the number of insertions actually made (does not include deferred insertions)
*/
virtual int getCount() const = 0;
/**
+ * Returns the depth of the currently allocated tree. The root node counts for 1 level,
+ * so it should be 1 or more if there's a root node. This information provides details
+ * about the underlying structure, which is useful mainly for testing purposes.
+ *
+ * Returns 0 if there are currently no nodes in the tree.
+ * Returns -1 if the structure isn't a tree.
+ */
+ virtual int getDepth() const = 0;
+
+ /**
* Rewinds all the most recently inserted data elements until an element
* is encountered for which client->shouldRewind(data) returns false. May
* not rewind elements that were inserted prior to the last call to
diff --git a/chromium/third_party/skia/src/core/SkBBoxHierarchyRecord.cpp b/chromium/third_party/skia/src/core/SkBBoxHierarchyRecord.cpp
index 8e5861bb21e..96e6cdf1024 100644
--- a/chromium/third_party/skia/src/core/SkBBoxHierarchyRecord.cpp
+++ b/chromium/third_party/skia/src/core/SkBBoxHierarchyRecord.cpp
@@ -9,10 +9,10 @@
#include "SkBBoxHierarchyRecord.h"
#include "SkPictureStateTree.h"
-SkBBoxHierarchyRecord::SkBBoxHierarchyRecord(uint32_t recordFlags,
- SkBBoxHierarchy* h,
- SkBaseDevice* device)
- : INHERITED(recordFlags, device) {
+SkBBoxHierarchyRecord::SkBBoxHierarchyRecord(const SkISize& size,
+ uint32_t recordFlags,
+ SkBBoxHierarchy* h)
+ : INHERITED(size, recordFlags) {
fStateTree = SkNEW(SkPictureStateTree);
fBoundingHierarchy = h;
fBoundingHierarchy->ref();
@@ -26,82 +26,79 @@ void SkBBoxHierarchyRecord::handleBBox(const SkRect& bounds) {
fBoundingHierarchy->insert(draw, r, true);
}
-int SkBBoxHierarchyRecord::save(SaveFlags flags) {
+void SkBBoxHierarchyRecord::willSave(SaveFlags flags) {
fStateTree->appendSave();
- return INHERITED::save(flags);
-}
-
-int SkBBoxHierarchyRecord::saveLayer(const SkRect* bounds, const SkPaint* paint,
- SaveFlags flags) {
+ this->INHERITED::willSave(flags);
+}
+
+SkCanvas::SaveLayerStrategy SkBBoxHierarchyRecord::willSaveLayer(const SkRect* bounds,
+ const SkPaint* paint,
+ SaveFlags flags) {
+ // For now, assume all filters affect transparent black.
+ // FIXME: This could be made less conservative as an optimization.
+ bool paintAffectsTransparentBlack = NULL != paint &&
+ ((NULL != paint->getImageFilter()) ||
+ (NULL != paint->getColorFilter()));
+ SkRect drawBounds;
+ if (paintAffectsTransparentBlack) {
+ if (bounds) {
+ drawBounds = *bounds;
+ this->getTotalMatrix().mapRect(&drawBounds);
+ } else {
+ SkIRect deviceBounds;
+ this->getClipDeviceBounds(&deviceBounds);
+ drawBounds.set(deviceBounds);
+ }
+ }
fStateTree->appendSaveLayer(this->writeStream().bytesWritten());
- return INHERITED::saveLayer(bounds, paint, flags);
+ SkCanvas::SaveLayerStrategy strategy = this->INHERITED::willSaveLayer(bounds, paint, flags);
+ if (paintAffectsTransparentBlack) {
+ this->handleBBox(drawBounds);
+ this->addNoOp();
+ }
+ return strategy;
}
-void SkBBoxHierarchyRecord::restore() {
+void SkBBoxHierarchyRecord::willRestore() {
fStateTree->appendRestore();
- INHERITED::restore();
-}
-
-bool SkBBoxHierarchyRecord::translate(SkScalar dx, SkScalar dy) {
- bool result = INHERITED::translate(dx, dy);
- fStateTree->appendTransform(getTotalMatrix());
- return result;
-}
-
-bool SkBBoxHierarchyRecord::scale(SkScalar sx, SkScalar sy) {
- bool result = INHERITED::scale(sx, sy);
- fStateTree->appendTransform(getTotalMatrix());
- return result;
-}
-
-bool SkBBoxHierarchyRecord::rotate(SkScalar degrees) {
- bool result = INHERITED::rotate(degrees);
- fStateTree->appendTransform(getTotalMatrix());
- return result;
-}
-
-bool SkBBoxHierarchyRecord::skew(SkScalar sx, SkScalar sy) {
- bool result = INHERITED::skew(sx, sy);
- fStateTree->appendTransform(getTotalMatrix());
- return result;
+ this->INHERITED::willRestore();
}
-bool SkBBoxHierarchyRecord::concat(const SkMatrix& matrix) {
- bool result = INHERITED::concat(matrix);
+void SkBBoxHierarchyRecord::didConcat(const SkMatrix& matrix) {
fStateTree->appendTransform(getTotalMatrix());
- return result;
+ INHERITED::didConcat(matrix);
}
-void SkBBoxHierarchyRecord::setMatrix(const SkMatrix& matrix) {
- INHERITED::setMatrix(matrix);
+void SkBBoxHierarchyRecord::didSetMatrix(const SkMatrix& matrix) {
fStateTree->appendTransform(getTotalMatrix());
+ INHERITED::didSetMatrix(matrix);
}
-bool SkBBoxHierarchyRecord::clipRect(const SkRect& rect,
- SkRegion::Op op,
- bool doAntiAlias) {
+void SkBBoxHierarchyRecord::onClipRect(const SkRect& rect,
+ SkRegion::Op op,
+ ClipEdgeStyle edgeStyle) {
fStateTree->appendClip(this->writeStream().bytesWritten());
- return INHERITED::clipRect(rect, op, doAntiAlias);
+ this->INHERITED::onClipRect(rect, op, edgeStyle);
}
-bool SkBBoxHierarchyRecord::clipRegion(const SkRegion& region,
- SkRegion::Op op) {
+void SkBBoxHierarchyRecord::onClipRegion(const SkRegion& region,
+ SkRegion::Op op) {
fStateTree->appendClip(this->writeStream().bytesWritten());
- return INHERITED::clipRegion(region, op);
+ this->INHERITED::onClipRegion(region, op);
}
-bool SkBBoxHierarchyRecord::clipPath(const SkPath& path,
- SkRegion::Op op,
- bool doAntiAlias) {
+void SkBBoxHierarchyRecord::onClipPath(const SkPath& path,
+ SkRegion::Op op,
+ ClipEdgeStyle edgeStyle) {
fStateTree->appendClip(this->writeStream().bytesWritten());
- return INHERITED::clipPath(path, op, doAntiAlias);
+ this->INHERITED::onClipPath(path, op, edgeStyle);
}
-bool SkBBoxHierarchyRecord::clipRRect(const SkRRect& rrect,
- SkRegion::Op op,
- bool doAntiAlias) {
+void SkBBoxHierarchyRecord::onClipRRect(const SkRRect& rrect,
+ SkRegion::Op op,
+ ClipEdgeStyle edgeStyle) {
fStateTree->appendClip(this->writeStream().bytesWritten());
- return INHERITED::clipRRect(rrect, op, doAntiAlias);
+ this->INHERITED::onClipRRect(rrect, op, edgeStyle);
}
bool SkBBoxHierarchyRecord::shouldRewind(void* data) {
diff --git a/chromium/third_party/skia/src/core/SkBBoxHierarchyRecord.h b/chromium/third_party/skia/src/core/SkBBoxHierarchyRecord.h
index 7284ab04ecd..51fce0d8bc8 100644
--- a/chromium/third_party/skia/src/core/SkBBoxHierarchyRecord.h
+++ b/chromium/third_party/skia/src/core/SkBBoxHierarchyRecord.h
@@ -19,38 +19,26 @@
class SkBBoxHierarchyRecord : public SkBBoxRecord, public SkBBoxHierarchyClient {
public:
/** This will take a ref of h */
- SkBBoxHierarchyRecord(uint32_t recordFlags, SkBBoxHierarchy* h,
- SkBaseDevice*);
+ SkBBoxHierarchyRecord(const SkISize& size, uint32_t recordFlags, SkBBoxHierarchy* h);
virtual void handleBBox(const SkRect& bounds) SK_OVERRIDE;
- virtual int save(SaveFlags flags = kMatrixClip_SaveFlag) SK_OVERRIDE;
- virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
- SaveFlags flags = kARGB_ClipLayer_SaveFlag) SK_OVERRIDE;
- virtual void restore() SK_OVERRIDE;
-
- virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE;
- virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE;
- virtual bool rotate(SkScalar degrees) SK_OVERRIDE;
- virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE;
- virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE;
- virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE;
-
- virtual bool clipRect(const SkRect& rect,
- SkRegion::Op op = SkRegion::kIntersect_Op,
- bool doAntiAlias = false) SK_OVERRIDE;
- virtual bool clipRegion(const SkRegion& region,
- SkRegion::Op op = SkRegion::kIntersect_Op) SK_OVERRIDE;
- virtual bool clipPath(const SkPath& path,
- SkRegion::Op op = SkRegion::kIntersect_Op,
- bool doAntiAlias = false) SK_OVERRIDE;
- virtual bool clipRRect(const SkRRect& rrect,
- SkRegion::Op op = SkRegion::kIntersect_Op,
- bool doAntiAlias = false) SK_OVERRIDE;
-
// Implementation of the SkBBoxHierarchyClient interface
virtual bool shouldRewind(void* data) SK_OVERRIDE;
+protected:
+ virtual void willSave(SaveFlags) SK_OVERRIDE;
+ virtual SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SaveFlags) SK_OVERRIDE;
+ virtual void willRestore() SK_OVERRIDE;
+
+ virtual void didConcat(const SkMatrix&) SK_OVERRIDE;
+ virtual void didSetMatrix(const SkMatrix&) SK_OVERRIDE;
+
+ virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
+ virtual void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
+ virtual void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
+ virtual void onClipRegion(const SkRegion&, SkRegion::Op) SK_OVERRIDE;
+
private:
typedef SkBBoxRecord INHERITED;
};
diff --git a/chromium/third_party/skia/src/core/SkBBoxRecord.cpp b/chromium/third_party/skia/src/core/SkBBoxRecord.cpp
index cdb70bb7301..a40ea8ba0d2 100644
--- a/chromium/third_party/skia/src/core/SkBBoxRecord.cpp
+++ b/chromium/third_party/skia/src/core/SkBBoxRecord.cpp
@@ -26,6 +26,13 @@ void SkBBoxRecord::drawRect(const SkRect& rect, const SkPaint& paint) {
}
}
+void SkBBoxRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
+ const SkPaint& paint) {
+ if (this->transformBounds(outer.rect(), &paint)) {
+ this->INHERITED::onDrawDRRect(outer, inner, paint);
+ }
+}
+
void SkBBoxRecord::drawPath(const SkPath& path, const SkPaint& paint) {
if (path.isInverseFillType()) {
// If path is inverse filled, use the current clip bounds as the
@@ -43,7 +50,7 @@ void SkBBoxRecord::drawPath(const SkPath& path, const SkPaint& paint) {
void SkBBoxRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
const SkPaint& paint) {
SkRect bbox;
- bbox.set(pts, count);
+ bbox.set(pts, SkToInt(count));
// Small min width value, just to ensure hairline point bounding boxes aren't empty.
// Even though we know hairline primitives are drawn one pixel wide, we do not use a
// minimum of 1 because the playback scale factor is unknown at record time. Later
@@ -77,8 +84,8 @@ void SkBBoxRecord::clear(SkColor color) {
INHERITED::clear(color);
}
-void SkBBoxRecord::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
- const SkPaint& paint) {
+void SkBBoxRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
+ const SkPaint& paint) {
SkRect bbox;
paint.measureText(text, byteLength, &bbox);
SkPaint::FontMetrics metrics;
@@ -121,7 +128,7 @@ void SkBBoxRecord::drawText(const void* text, size_t byteLength, SkScalar x, SkS
bbox.fTop += y;
bbox.fBottom += y;
if (this->transformBounds(bbox, &paint)) {
- INHERITED::drawText(text, byteLength, x, y, paint);
+ INHERITED::onDrawText(text, byteLength, x, y, paint);
}
}
@@ -158,8 +165,20 @@ void SkBBoxRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
}
}
-void SkBBoxRecord::drawPosText(const void* text, size_t byteLength,
- const SkPoint pos[], const SkPaint& paint) {
+// Hack to work-around https://code.google.com/p/chromium/issues/detail?id=373785
+// This logic assums that 'pad' is enough to add to the left and right to account for
+// big glyphs. For the font in question (a logo font) the glyphs is much wider than just
+// the pointsize (approx 3x wider).
+// As a temp work-around, we scale-up pad.
+// A more correct fix might be to add fontmetrics.fMaxX, but we don't have that value in hand
+// at the moment, and (possibly) the value in the font may not be accurate (but who knows).
+//
+static SkScalar hack_373785_amend_pad(SkScalar pad) {
+ return pad * 4;
+}
+
+void SkBBoxRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
+ const SkPaint& paint) {
SkRect bbox;
bbox.set(pos, paint.countText(text, byteLength));
SkPaint::FontMetrics metrics;
@@ -169,16 +188,17 @@ void SkBBoxRecord::drawPosText(const void* text, size_t byteLength,
// pad on left and right by half of max vertical glyph extents
SkScalar pad = (metrics.fTop - metrics.fBottom) / 2;
+ pad = hack_373785_amend_pad(pad);
bbox.fLeft += pad;
bbox.fRight -= pad;
if (this->transformBounds(bbox, &paint)) {
- INHERITED::drawPosText(text, byteLength, pos, paint);
+ INHERITED::onDrawPosText(text, byteLength, pos, paint);
}
}
-void SkBBoxRecord::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
- SkScalar constY, const SkPaint& paint) {
+void SkBBoxRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
+ SkScalar constY, const SkPaint& paint) {
size_t numChars = paint.countText(text, byteLength);
if (numChars == 0) {
return;
@@ -205,6 +225,7 @@ void SkBBoxRecord::drawPosTextH(const void* text, size_t byteLength, const SkSca
}
// pad horizontally by max glyph height
+ pad = hack_373785_amend_pad(pad);
bbox.fLeft += pad;
bbox.fRight -= pad;
@@ -228,9 +249,8 @@ void SkBBoxRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
INHERITED::drawSprite(bitmap, left, top, paint);
}
-void SkBBoxRecord::drawTextOnPath(const void* text, size_t byteLength,
- const SkPath& path, const SkMatrix* matrix,
- const SkPaint& paint) {
+void SkBBoxRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
+ const SkMatrix* matrix, const SkPaint& paint) {
SkRect bbox = path.getBounds();
SkPaint::FontMetrics metrics;
paint.getFontMetrics(&metrics);
@@ -243,7 +263,7 @@ void SkBBoxRecord::drawTextOnPath(const void* text, size_t byteLength,
bbox.fBottom -= pad;
if (this->transformBounds(bbox, &paint)) {
- INHERITED::drawTextOnPath(text, byteLength, path, matrix, paint);
+ INHERITED::onDrawTextOnPath(text, byteLength, path, matrix, paint);
}
}
@@ -260,10 +280,10 @@ void SkBBoxRecord::drawVertices(VertexMode mode, int vertexCount,
}
}
-void SkBBoxRecord::drawPicture(SkPicture& picture) {
- if (picture.width() > 0 && picture.height() > 0 &&
- this->transformBounds(SkRect::MakeWH(picture.width(), picture.height()), NULL)) {
- INHERITED::drawPicture(picture);
+void SkBBoxRecord::onDrawPicture(const SkPicture* picture) {
+ if (picture->width() > 0 && picture->height() > 0 &&
+ this->transformBounds(SkRect::MakeWH(picture->width(), picture->height()), NULL)) {
+ this->INHERITED::onDrawPicture(picture);
}
}
diff --git a/chromium/third_party/skia/src/core/SkBBoxRecord.h b/chromium/third_party/skia/src/core/SkBBoxRecord.h
index fa8b282247e..f3d72b04485 100644
--- a/chromium/third_party/skia/src/core/SkBBoxRecord.h
+++ b/chromium/third_party/skia/src/core/SkBBoxRecord.h
@@ -19,8 +19,9 @@
class SkBBoxRecord : public SkPictureRecord {
public:
- SkBBoxRecord(uint32_t recordFlags, SkBaseDevice* device)
- : INHERITED(recordFlags, device) { }
+ SkBBoxRecord(const SkISize& size, uint32_t recordFlags)
+ : INHERITED(size, recordFlags) {
+ }
virtual ~SkBBoxRecord() { }
/**
@@ -37,8 +38,6 @@ public:
const SkPaint& paint) SK_OVERRIDE;
virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
virtual void clear(SkColor) SK_OVERRIDE;
- virtual void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
- const SkPaint& paint) SK_OVERRIDE;
virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
const SkPaint* paint = NULL) SK_OVERRIDE;
virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
@@ -48,22 +47,25 @@ public:
const SkPaint* paint) SK_OVERRIDE;
virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
const SkRect& dst, const SkPaint* paint) SK_OVERRIDE;
- virtual void drawPosText(const void* text, size_t byteLength,
- const SkPoint pos[], const SkPaint& paint) SK_OVERRIDE;
- virtual void drawPosTextH(const void* text, size_t byteLength,
- const SkScalar xpos[], SkScalar constY,
- const SkPaint& paint) SK_OVERRIDE;
virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
const SkPaint* paint) SK_OVERRIDE;
- virtual void drawTextOnPath(const void* text, size_t byteLength,
- const SkPath& path, const SkMatrix* matrix,
- const SkPaint& paint) SK_OVERRIDE;
virtual void drawVertices(VertexMode mode, int vertexCount,
const SkPoint vertices[], const SkPoint texs[],
const SkColor colors[], SkXfermode* xfer,
const uint16_t indices[], int indexCount,
const SkPaint& paint) SK_OVERRIDE;
- virtual void drawPicture(SkPicture& picture) SK_OVERRIDE;
+
+protected:
+ virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) SK_OVERRIDE;
+ virtual void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
+ const SkPaint&) SK_OVERRIDE;
+ virtual void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
+ const SkPaint&) SK_OVERRIDE;
+ virtual void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
+ SkScalar constY, const SkPaint&) SK_OVERRIDE;
+ virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
+ const SkMatrix* matrix, const SkPaint&) SK_OVERRIDE;
+ virtual void onDrawPicture(const SkPicture* picture) SK_OVERRIDE;
private:
/**
diff --git a/chromium/third_party/skia/src/core/SkBitmap.cpp b/chromium/third_party/skia/src/core/SkBitmap.cpp
index b387795efe9..789bf11b4c4 100644
--- a/chromium/third_party/skia/src/core/SkBitmap.cpp
+++ b/chromium/third_party/skia/src/core/SkBitmap.cpp
@@ -14,8 +14,8 @@
#include "SkImagePriv.h"
#include "SkMallocPixelRef.h"
#include "SkMask.h"
-#include "SkOrderedReadBuffer.h"
-#include "SkOrderedWriteBuffer.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkPixelRef.h"
#include "SkThread.h"
#include "SkUnPreMultiply.h"
@@ -24,61 +24,11 @@
#include "SkPackBits.h"
#include <new>
-static bool isPos32Bits(const Sk64& value) {
- return !value.isNeg() && value.is32();
+static bool reset_return_false(SkBitmap* bm) {
+ bm->reset();
+ return false;
}
-struct MipLevel {
- void* fPixels;
- uint32_t fRowBytes;
- uint32_t fWidth, fHeight;
-};
-
-struct SkBitmap::MipMap : SkNoncopyable {
- int32_t fRefCnt;
- int fLevelCount;
-// MipLevel fLevel[fLevelCount];
-// Pixels[]
-
- static MipMap* Alloc(int levelCount, size_t pixelSize) {
- if (levelCount < 0) {
- return NULL;
- }
- Sk64 size;
- size.setMul(levelCount + 1, sizeof(MipLevel));
- size.add(sizeof(MipMap));
- size.add(SkToS32(pixelSize));
- if (!isPos32Bits(size)) {
- return NULL;
- }
- MipMap* mm = (MipMap*)sk_malloc_throw(size.get32());
- mm->fRefCnt = 1;
- mm->fLevelCount = levelCount;
- return mm;
- }
-
- const MipLevel* levels() const { return (const MipLevel*)(this + 1); }
- MipLevel* levels() { return (MipLevel*)(this + 1); }
-
- const void* pixels() const { return levels() + fLevelCount; }
- void* pixels() { return levels() + fLevelCount; }
-
- void ref() {
- if (SK_MaxS32 == sk_atomic_inc(&fRefCnt)) {
- sk_throw();
- }
- }
- void unref() {
- SkASSERT(fRefCnt > 0);
- if (sk_atomic_dec(&fRefCnt) == 1) {
- sk_free(this);
- }
- }
-};
-
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
SkBitmap::SkBitmap() {
sk_bzero(this, sizeof(*this));
}
@@ -102,20 +52,11 @@ SkBitmap& SkBitmap::operator=(const SkBitmap& src) {
// inc src reference counts
SkSafeRef(src.fPixelRef);
- SkSafeRef(src.fMipMap);
// we reset our locks if we get blown away
fPixelLockCount = 0;
- /* The src could be in 3 states
- 1. no pixelref, in which case we just copy/ref the pixels/ctable
- 2. unlocked pixelref, pixels/ctable should be null
- 3. locked pixelref, we should lock the ref again ourselves
- */
- if (NULL == fPixelRef) {
- // leave fPixels as it is
- SkSafeRef(fColorTable); // ref the user's ctable if present
- } else { // we have a pixelref, so pixels/ctable reflect it
+ if (fPixelRef) {
// ignore the values from the memcpy
fPixels = NULL;
fColorTable = NULL;
@@ -135,17 +76,12 @@ SkBitmap& SkBitmap::operator=(const SkBitmap& src) {
void SkBitmap::swap(SkBitmap& other) {
SkTSwap(fColorTable, other.fColorTable);
SkTSwap(fPixelRef, other.fPixelRef);
- SkTSwap(fPixelRefOffset, other.fPixelRefOffset);
+ SkTSwap(fPixelRefOrigin, other.fPixelRefOrigin);
SkTSwap(fPixelLockCount, other.fPixelLockCount);
- SkTSwap(fMipMap, other.fMipMap);
SkTSwap(fPixels, other.fPixels);
+ SkTSwap(fInfo, other.fInfo);
SkTSwap(fRowBytes, other.fRowBytes);
- SkTSwap(fWidth, other.fWidth);
- SkTSwap(fHeight, other.fHeight);
- SkTSwap(fConfig, other.fConfig);
- SkTSwap(fAlphaType, other.fAlphaType);
SkTSwap(fFlags, other.fFlags);
- SkTSwap(fBytesPerPixel, other.fBytesPerPixel);
SkDEBUGCODE(this->validate();)
}
@@ -155,6 +91,13 @@ void SkBitmap::reset() {
sk_bzero(this, sizeof(*this));
}
+#ifdef SK_SUPPORT_LEGACY_BITMAP_CONFIG
+SkBitmap::Config SkBitmap::config() const {
+ return SkColorTypeToBitmapConfig(fInfo.colorType());
+}
+#endif
+
+#ifdef SK_SUPPORT_LEGACY_COMPUTE_CONFIG_SIZE
int SkBitmap::ComputeBytesPerPixel(SkBitmap::Config config) {
int bpp;
switch (config) {
@@ -181,105 +124,54 @@ int SkBitmap::ComputeBytesPerPixel(SkBitmap::Config config) {
}
size_t SkBitmap::ComputeRowBytes(Config c, int width) {
- if (width < 0) {
- return 0;
- }
-
- Sk64 rowBytes;
- rowBytes.setZero();
-
- switch (c) {
- case kNo_Config:
- break;
- case kA8_Config:
- case kIndex8_Config:
- rowBytes.set(width);
- break;
- case kRGB_565_Config:
- case kARGB_4444_Config:
- rowBytes.set(width);
- rowBytes.shiftLeft(1);
- break;
- case kARGB_8888_Config:
- rowBytes.set(width);
- rowBytes.shiftLeft(2);
- break;
- default:
- SkDEBUGFAIL("unknown config");
- break;
- }
- return isPos32Bits(rowBytes) ? rowBytes.get32() : 0;
+ return SkColorTypeMinRowBytes(SkBitmapConfigToColorType(c), width);
}
-Sk64 SkBitmap::ComputeSize64(Config c, int width, int height) {
- Sk64 size;
- size.setMul(SkToS32(SkBitmap::ComputeRowBytes(c, width)), height);
- return size;
+int64_t SkBitmap::ComputeSize64(Config config, int width, int height) {
+ SkColorType ct = SkBitmapConfigToColorType(config);
+ int64_t rowBytes = sk_64_mul(SkColorTypeBytesPerPixel(ct), width);
+ return rowBytes * height;
}
size_t SkBitmap::ComputeSize(Config c, int width, int height) {
- Sk64 size = SkBitmap::ComputeSize64(c, width, height);
- return isPos32Bits(size) ? size.get32() : 0;
-}
-
-Sk64 SkBitmap::ComputeSafeSize64(Config config,
- uint32_t width,
- uint32_t height,
- size_t rowBytes) {
- Sk64 safeSize;
- safeSize.setZero();
- if (height > 0) {
- // TODO: Handle the case where the return value from
- // ComputeRowBytes is more than 31 bits.
- safeSize.set(SkToS32(ComputeRowBytes(config, width)));
- Sk64 sizeAllButLastRow;
- sizeAllButLastRow.setMul(height - 1, SkToS32(rowBytes));
- safeSize.add(sizeAllButLastRow);
- }
- SkASSERT(!safeSize.isNeg());
- return safeSize;
-}
-
-size_t SkBitmap::ComputeSafeSize(Config config,
- uint32_t width,
- uint32_t height,
- size_t rowBytes) {
- Sk64 safeSize = ComputeSafeSize64(config, width, height, rowBytes);
- return (safeSize.is32() ? safeSize.get32() : 0);
+ int64_t size = SkBitmap::ComputeSize64(c, width, height);
+ return sk_64_isS32(size) ? sk_64_asS32(size) : 0;
}
+#endif
void SkBitmap::getBounds(SkRect* bounds) const {
SkASSERT(bounds);
bounds->set(0, 0,
- SkIntToScalar(fWidth), SkIntToScalar(fHeight));
+ SkIntToScalar(fInfo.fWidth), SkIntToScalar(fInfo.fHeight));
}
void SkBitmap::getBounds(SkIRect* bounds) const {
SkASSERT(bounds);
- bounds->set(0, 0, fWidth, fHeight);
+ bounds->set(0, 0, fInfo.fWidth, fInfo.fHeight);
}
///////////////////////////////////////////////////////////////////////////////
-static bool validate_alphaType(SkBitmap::Config config, SkAlphaType alphaType,
+static bool validate_alphaType(SkColorType colorType, SkAlphaType alphaType,
SkAlphaType* canonical = NULL) {
- switch (config) {
- case SkBitmap::kNo_Config:
+ switch (colorType) {
+ case kUnknown_SkColorType:
alphaType = kIgnore_SkAlphaType;
break;
- case SkBitmap::kA8_Config:
+ case kAlpha_8_SkColorType:
if (kUnpremul_SkAlphaType == alphaType) {
alphaType = kPremul_SkAlphaType;
}
// fall-through
- case SkBitmap::kIndex8_Config:
- case SkBitmap::kARGB_4444_Config:
- case SkBitmap::kARGB_8888_Config:
+ case kIndex_8_SkColorType:
+ case kARGB_4444_SkColorType:
+ case kRGBA_8888_SkColorType:
+ case kBGRA_8888_SkColorType:
if (kIgnore_SkAlphaType == alphaType) {
return false;
}
break;
- case SkBitmap::kRGB_565_Config:
+ case kRGB_565_SkColorType:
alphaType = kOpaque_SkAlphaType;
break;
default:
@@ -291,51 +183,60 @@ static bool validate_alphaType(SkBitmap::Config config, SkAlphaType alphaType,
return true;
}
-bool SkBitmap::setConfig(Config config, int width, int height, size_t rowBytes,
- SkAlphaType alphaType) {
- if ((width | height) < 0) {
- goto BAD_CONFIG;
- }
- if (rowBytes == 0) {
- rowBytes = SkBitmap::ComputeRowBytes(config, width);
- if (0 == rowBytes && kNo_Config != config && width > 0) {
- goto BAD_CONFIG;
- }
+bool SkBitmap::setInfo(const SkImageInfo& origInfo, size_t rowBytes) {
+ SkImageInfo info = origInfo;
+
+ if (!validate_alphaType(info.fColorType, info.fAlphaType,
+ &info.fAlphaType)) {
+ return reset_return_false(this);
}
- if (!validate_alphaType(config, alphaType, &alphaType)) {
- goto BAD_CONFIG;
+ // require that rowBytes fit in 31bits
+ int64_t mrb = info.minRowBytes64();
+ if ((int32_t)mrb != mrb) {
+ return reset_return_false(this);
+ }
+ if ((int64_t)rowBytes != (int32_t)rowBytes) {
+ return reset_return_false(this);
}
- this->freePixels();
+ if (info.width() < 0 || info.height() < 0) {
+ return reset_return_false(this);
+ }
- fConfig = SkToU8(config);
- fAlphaType = SkToU8(alphaType);
- fWidth = width;
- fHeight = height;
- fRowBytes = SkToU32(rowBytes);
+ if (kUnknown_SkColorType == info.colorType()) {
+ rowBytes = 0;
+ } else if (0 == rowBytes) {
+ rowBytes = (size_t)mrb;
+ } else if (rowBytes < info.minRowBytes()) {
+ return reset_return_false(this);
+ }
- fBytesPerPixel = (uint8_t)ComputeBytesPerPixel(config);
+ this->freePixels();
- SkDEBUGCODE(this->validate();)
+ fInfo = info;
+ fRowBytes = SkToU32(rowBytes);
return true;
-
- // if we got here, we had an error, so we reset the bitmap to empty
-BAD_CONFIG:
- this->reset();
- return false;
}
-bool SkBitmap::setConfig(const SkImageInfo& info, size_t rowBytes) {
- return this->setConfig(SkImageInfoToBitmapConfig(info), info.fWidth,
- info.fHeight, rowBytes, info.fAlphaType);
+#ifdef SK_SUPPORT_LEGACY_SETCONFIG
+bool SkBitmap::setConfig(Config config, int width, int height, size_t rowBytes,
+ SkAlphaType alphaType) {
+ SkColorType ct = SkBitmapConfigToColorType(config);
+ return this->setInfo(SkImageInfo::Make(width, height, ct, alphaType), rowBytes);
}
+#endif
bool SkBitmap::setAlphaType(SkAlphaType alphaType) {
- if (!validate_alphaType(this->config(), alphaType, &alphaType)) {
+ if (!validate_alphaType(fInfo.fColorType, alphaType, &alphaType)) {
return false;
}
- fAlphaType = SkToU8(alphaType);
+ if (fInfo.fAlphaType != alphaType) {
+ fInfo.fAlphaType = alphaType;
+ if (fPixelRef) {
+ fPixelRef->changeAlphaType(alphaType);
+ }
+ }
return true;
}
@@ -346,78 +247,61 @@ void SkBitmap::updatePixelsFromRef() const {
void* p = fPixelRef->pixels();
if (NULL != p) {
- p = (char*)p + fPixelRefOffset;
+ p = (char*)p
+ + fPixelRefOrigin.fY * fRowBytes
+ + fPixelRefOrigin.fX * fInfo.bytesPerPixel();
}
fPixels = p;
- SkRefCnt_SafeAssign(fColorTable, fPixelRef->colorTable());
+ fColorTable = fPixelRef->colorTable();
} else {
SkASSERT(0 == fPixelLockCount);
fPixels = NULL;
- if (fColorTable) {
- fColorTable->unref();
- fColorTable = NULL;
- }
+ fColorTable = NULL;
}
}
}
-static bool config_to_colorType(SkBitmap::Config config, SkColorType* ctOut) {
- SkColorType ct;
- switch (config) {
- case SkBitmap::kA8_Config:
- ct = kAlpha_8_SkColorType;
- break;
- case SkBitmap::kIndex8_Config:
- ct = kIndex_8_SkColorType;
- break;
- case SkBitmap::kRGB_565_Config:
- ct = kRGB_565_SkColorType;
- break;
- case SkBitmap::kARGB_4444_Config:
- ct = kARGB_4444_SkColorType;
- break;
- case SkBitmap::kARGB_8888_Config:
- ct = kPMColor_SkColorType;
- break;
- case SkBitmap::kNo_Config:
- default:
- return false;
- }
- if (ctOut) {
- *ctOut = ct;
- }
- return true;
-}
-
-bool SkBitmap::asImageInfo(SkImageInfo* info) const {
- SkColorType ct;
- if (!config_to_colorType(this->config(), &ct)) {
- return false;
- }
- if (info) {
- info->fWidth = fWidth;
- info->fHeight = fHeight;
- info->fAlphaType = this->alphaType();
- info->fColorType = ct;
+SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, int dx, int dy) {
+#ifdef SK_DEBUG
+ if (pr) {
+ if (kUnknown_SkColorType != fInfo.colorType()) {
+ const SkImageInfo& prInfo = pr->info();
+ SkASSERT(fInfo.fWidth <= prInfo.fWidth);
+ SkASSERT(fInfo.fHeight <= prInfo.fHeight);
+ SkASSERT(fInfo.fColorType == prInfo.fColorType);
+ switch (prInfo.fAlphaType) {
+ case kIgnore_SkAlphaType:
+ SkASSERT(fInfo.fAlphaType == kIgnore_SkAlphaType);
+ break;
+ case kOpaque_SkAlphaType:
+ case kPremul_SkAlphaType:
+ SkASSERT(fInfo.fAlphaType == kOpaque_SkAlphaType ||
+ fInfo.fAlphaType == kPremul_SkAlphaType);
+ break;
+ case kUnpremul_SkAlphaType:
+ SkASSERT(fInfo.fAlphaType == kOpaque_SkAlphaType ||
+ fInfo.fAlphaType == kUnpremul_SkAlphaType);
+ break;
+ }
+ }
}
- return true;
-}
+#endif
-SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, size_t offset) {
- // do this first, we that we never have a non-zero offset with a null ref
- if (NULL == pr) {
- offset = 0;
+ if (pr) {
+ const SkImageInfo& info = pr->info();
+ fPixelRefOrigin.set(SkPin32(dx, 0, info.fWidth),
+ SkPin32(dy, 0, info.fHeight));
+ } else {
+ // ignore dx,dy if there is no pixelref
+ fPixelRefOrigin.setZero();
}
- if (fPixelRef != pr || fPixelRefOffset != offset) {
- if (fPixelRef != pr) {
- this->freePixels();
- SkASSERT(NULL == fPixelRef);
+ if (fPixelRef != pr) {
+ this->freePixels();
+ SkASSERT(NULL == fPixelRef);
- SkSafeRef(pr);
- fPixelRef = pr;
- }
- fPixelRefOffset = offset;
+ SkSafeRef(pr);
+ fPixelRef = pr;
this->updatePixelsFromRef();
}
@@ -449,19 +333,18 @@ bool SkBitmap::lockPixelsAreWritable() const {
void SkBitmap::setPixels(void* p, SkColorTable* ctable) {
if (NULL == p) {
- this->setPixelRef(NULL, 0);
+ this->setPixelRef(NULL);
return;
}
- SkImageInfo info;
- if (!this->asImageInfo(&info)) {
- this->setPixelRef(NULL, 0);
+ if (kUnknown_SkColorType == fInfo.colorType()) {
+ this->setPixelRef(NULL);
return;
}
- SkPixelRef* pr = SkMallocPixelRef::NewDirect(info, p, fRowBytes, ctable);
+ SkPixelRef* pr = SkMallocPixelRef::NewDirect(fInfo, p, fRowBytes, ctable);
if (NULL == pr) {
- this->setPixelRef(NULL, 0);
+ this->setPixelRef(NULL);
return;
}
@@ -481,32 +364,89 @@ bool SkBitmap::allocPixels(Allocator* allocator, SkColorTable* ctable) {
return allocator->allocPixelRef(this, ctable);
}
-void SkBitmap::freePixels() {
- // if we're gonna free the pixels, we certainly need to free the mipmap
- this->freeMipMap();
+///////////////////////////////////////////////////////////////////////////////
+
+bool SkBitmap::allocPixels(const SkImageInfo& requestedInfo, SkPixelRefFactory* factory,
+ SkColorTable* ctable) {
+ if (kIndex_8_SkColorType == requestedInfo.fColorType && NULL == ctable) {
+ return reset_return_false(this);
+ }
+ if (!this->setInfo(requestedInfo)) {
+ return reset_return_false(this);
+ }
- if (fColorTable) {
- fColorTable->unref();
- fColorTable = NULL;
+ // setInfo may have corrected info (e.g. 565 is always opaque).
+ const SkImageInfo& correctedInfo = this->info();
+
+ SkMallocPixelRef::PRFactory defaultFactory;
+ if (NULL == factory) {
+ factory = &defaultFactory;
+ }
+
+ SkPixelRef* pr = factory->create(correctedInfo, ctable);
+ if (NULL == pr) {
+ return reset_return_false(this);
+ }
+ this->setPixelRef(pr)->unref();
+
+ // TODO: lockPixels could/should return bool or void*/NULL
+ this->lockPixels();
+ if (NULL == this->getPixels()) {
+ return reset_return_false(this);
+ }
+ return true;
+}
+
+bool SkBitmap::installPixels(const SkImageInfo& requestedInfo, void* pixels, size_t rb,
+ SkColorTable* ct, void (*releaseProc)(void* addr, void* context),
+ void* context) {
+ if (!this->setInfo(requestedInfo, rb)) {
+ this->reset();
+ return false;
+ }
+
+ // setInfo may have corrected info (e.g. 565 is always opaque).
+ const SkImageInfo& correctedInfo = this->info();
+
+ SkPixelRef* pr = SkMallocPixelRef::NewWithProc(correctedInfo, rb, ct, pixels, releaseProc,
+ context);
+ if (!pr) {
+ this->reset();
+ return false;
}
+ this->setPixelRef(pr)->unref();
+
+ // since we're already allocated, we lockPixels right away
+ this->lockPixels();
+ SkDEBUGCODE(this->validate();)
+ return true;
+}
+
+bool SkBitmap::installMaskPixels(const SkMask& mask) {
+ if (SkMask::kA8_Format != mask.fFormat) {
+ this->reset();
+ return false;
+ }
+ return this->installPixels(SkImageInfo::MakeA8(mask.fBounds.width(),
+ mask.fBounds.height()),
+ mask.fImage, mask.fRowBytes);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SkBitmap::freePixels() {
if (NULL != fPixelRef) {
if (fPixelLockCount > 0) {
fPixelRef->unlockPixels();
}
fPixelRef->unref();
fPixelRef = NULL;
- fPixelRefOffset = 0;
+ fPixelRefOrigin.setZero();
}
fPixelLockCount = 0;
fPixels = NULL;
-}
-
-void SkBitmap::freeMipMap() {
- if (fMipMap) {
- fMipMap->unref();
- fMipMap = NULL;
- }
+ fColorTable = NULL;
}
uint32_t SkBitmap::getGenerationID() const {
@@ -531,19 +471,18 @@ GrTexture* SkBitmap::getTexture() const {
*/
bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst,
SkColorTable* ctable) {
- SkImageInfo info;
- if (!dst->asImageInfo(&info)) {
+ const SkImageInfo info = dst->info();
+ if (kUnknown_SkColorType == info.colorType()) {
// SkDebugf("unsupported config for info %d\n", dst->config());
return false;
}
-
- SkPixelRef* pr = SkMallocPixelRef::NewAllocate(info, dst->rowBytes(),
- ctable);
+
+ SkPixelRef* pr = SkMallocPixelRef::NewAllocate(info, dst->rowBytes(), ctable);
if (NULL == pr) {
return false;
}
- dst->setPixelRef(pr, 0)->unref();
+ dst->setPixelRef(pr)->unref();
// since we're already allocated, we lockPixels right away
dst->lockPixels();
return true;
@@ -551,17 +490,6 @@ bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst,
///////////////////////////////////////////////////////////////////////////////
-size_t SkBitmap::getSafeSize() const {
- // This is intended to be a size_t version of ComputeSafeSize64(), just
- // faster. The computation is meant to be identical.
- return (fHeight ? ((fHeight - 1) * fRowBytes) +
- ComputeRowBytes(this->config(), fWidth): 0);
-}
-
-Sk64 SkBitmap::getSafeSize64() const {
- return ComputeSafeSize64(this->config(), fWidth, fHeight, fRowBytes);
-}
-
bool SkBitmap::copyPixelsTo(void* const dst, size_t dstSize,
size_t dstRowBytes, bool preserveDstPad) const {
@@ -569,9 +497,10 @@ bool SkBitmap::copyPixelsTo(void* const dst, size_t dstSize,
dstRowBytes = fRowBytes;
}
- if (dstRowBytes < ComputeRowBytes(this->config(), fWidth) ||
- dst == NULL || (getPixels() == NULL && pixelRef() == NULL))
+ if (dstRowBytes < fInfo.minRowBytes() ||
+ dst == NULL || (getPixels() == NULL && pixelRef() == NULL)) {
return false;
+ }
if (!preserveDstPad && static_cast<uint32_t>(dstRowBytes) == fRowBytes) {
size_t safeSize = this->getSafeSize();
@@ -588,16 +517,15 @@ bool SkBitmap::copyPixelsTo(void* const dst, size_t dstSize,
}
} else {
// If destination has different stride than us, then copy line by line.
- if (ComputeSafeSize(this->config(), fWidth, fHeight, dstRowBytes) >
- dstSize)
+ if (fInfo.getSafeSize(dstRowBytes) > dstSize) {
return false;
- else {
+ } else {
// Just copy what we need on each line.
- size_t rowBytes = ComputeRowBytes(this->config(), fWidth);
+ size_t rowBytes = fInfo.minRowBytes();
SkAutoLockPixels lock(*this);
const uint8_t* srcP = reinterpret_cast<const uint8_t*>(getPixels());
uint8_t* dstP = reinterpret_cast<uint8_t*>(dst);
- for (uint32_t row = 0; row < fHeight;
+ for (int row = 0; row < fInfo.fHeight;
row++, srcP += fRowBytes, dstP += dstRowBytes) {
memcpy(dstP, srcP, rowBytes);
}
@@ -641,19 +569,19 @@ void* SkBitmap::getAddr(int x, int y) const {
char* base = (char*)this->getPixels();
if (base) {
base += y * this->rowBytes();
- switch (this->config()) {
- case SkBitmap::kARGB_8888_Config:
+ switch (this->colorType()) {
+ case kRGBA_8888_SkColorType:
+ case kBGRA_8888_SkColorType:
base += x << 2;
break;
- case SkBitmap::kARGB_4444_Config:
- case SkBitmap::kRGB_565_Config:
+ case kARGB_4444_SkColorType:
+ case kRGB_565_SkColorType:
base += x << 1;
break;
- case SkBitmap::kA8_Config:
- case SkBitmap::kIndex8_Config:
+ case kAlpha_8_SkColorType:
+ case kIndex_8_SkColorType:
base += x;
break;
- break;
default:
SkDEBUGFAIL("Can't return addr for config");
base = NULL;
@@ -667,29 +595,29 @@ SkColor SkBitmap::getColor(int x, int y) const {
SkASSERT((unsigned)x < (unsigned)this->width());
SkASSERT((unsigned)y < (unsigned)this->height());
- switch (this->config()) {
- case SkBitmap::kA8_Config: {
+ switch (this->colorType()) {
+ case kAlpha_8_SkColorType: {
uint8_t* addr = this->getAddr8(x, y);
return SkColorSetA(0, addr[0]);
}
- case SkBitmap::kIndex8_Config: {
+ case kIndex_8_SkColorType: {
SkPMColor c = this->getIndex8Color(x, y);
return SkUnPreMultiply::PMColorToColor(c);
}
- case SkBitmap::kRGB_565_Config: {
+ case kRGB_565_SkColorType: {
uint16_t* addr = this->getAddr16(x, y);
return SkPixel16ToColor(addr[0]);
}
- case SkBitmap::kARGB_4444_Config: {
+ case kARGB_4444_SkColorType: {
uint16_t* addr = this->getAddr16(x, y);
SkPMColor c = SkPixel4444ToPixel32(addr[0]);
return SkUnPreMultiply::PMColorToColor(c);
}
- case SkBitmap::kARGB_8888_Config: {
+ case kBGRA_8888_SkColorType:
+ case kRGBA_8888_SkColorType: {
uint32_t* addr = this->getAddr32(x, y);
return SkUnPreMultiply::PMColorToColor(addr[0]);
}
- case kNo_Config:
default:
SkASSERT(false);
return 0;
@@ -707,8 +635,8 @@ bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) {
const int height = bm.height();
const int width = bm.width();
- switch (bm.config()) {
- case SkBitmap::kA8_Config: {
+ switch (bm.colorType()) {
+ case kAlpha_8_SkColorType: {
unsigned a = 0xFF;
for (int y = 0; y < height; ++y) {
const uint8_t* row = bm.getAddr8(0, y);
@@ -721,7 +649,7 @@ bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) {
}
return true;
} break;
- case SkBitmap::kIndex8_Config: {
+ case kIndex_8_SkColorType: {
SkAutoLockColors alc(bm);
const SkPMColor* table = alc.colors();
if (!table) {
@@ -733,10 +661,10 @@ bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) {
}
return 0xFF == SkGetPackedA32(c);
} break;
- case SkBitmap::kRGB_565_Config:
+ case kRGB_565_SkColorType:
return true;
break;
- case SkBitmap::kARGB_4444_Config: {
+ case kARGB_4444_SkColorType: {
unsigned c = 0xFFFF;
for (int y = 0; y < height; ++y) {
const SkPMColor16* row = bm.getAddr16(0, y);
@@ -749,7 +677,8 @@ bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) {
}
return true;
} break;
- case SkBitmap::kARGB_8888_Config: {
+ case kBGRA_8888_SkColorType:
+ case kRGBA_8888_SkColorType: {
SkPMColor c = (SkPMColor)~0;
for (int y = 0; y < height; ++y) {
const SkPMColor* row = bm.getAddr32(0, y);
@@ -791,8 +720,12 @@ void SkBitmap::internalErase(const SkIRect& area,
}
#endif
- if (kNo_Config == fConfig || kIndex8_Config == fConfig) {
- return;
+ switch (fInfo.colorType()) {
+ case kUnknown_SkColorType:
+ case kIndex_8_SkColorType:
+ return; // can't erase. Should we bzero so the memory is not uninitialized?
+ default:
+ break;
}
SkAutoLockPixels alp(*this);
@@ -805,15 +738,8 @@ void SkBitmap::internalErase(const SkIRect& area,
const int width = area.width();
const int rowBytes = fRowBytes;
- // make rgb premultiplied
- if (255 != a) {
- r = SkAlphaMul(r, a);
- g = SkAlphaMul(g, a);
- b = SkAlphaMul(b, a);
- }
-
- switch (fConfig) {
- case kA8_Config: {
+ switch (this->colorType()) {
+ case kAlpha_8_SkColorType: {
uint8_t* p = this->getAddr8(area.fLeft, area.fTop);
while (--height >= 0) {
memset(p, a, width);
@@ -821,12 +747,19 @@ void SkBitmap::internalErase(const SkIRect& area,
}
break;
}
- case kARGB_4444_Config:
- case kRGB_565_Config: {
+ case kARGB_4444_SkColorType:
+ case kRGB_565_SkColorType: {
uint16_t* p = this->getAddr16(area.fLeft, area.fTop);;
uint16_t v;
- if (kARGB_4444_Config == fConfig) {
+ // make rgb premultiplied
+ if (255 != a) {
+ r = SkAlphaMul(r, a);
+ g = SkAlphaMul(g, a);
+ b = SkAlphaMul(b, a);
+ }
+
+ if (kARGB_4444_SkColorType == this->colorType()) {
v = pack_8888_to_4444(a, r, g, b);
} else {
v = SkPackRGB16(r >> (8 - SK_R16_BITS),
@@ -839,9 +772,17 @@ void SkBitmap::internalErase(const SkIRect& area,
}
break;
}
- case kARGB_8888_Config: {
+ case kBGRA_8888_SkColorType:
+ case kRGBA_8888_SkColorType: {
uint32_t* p = this->getAddr32(area.fLeft, area.fTop);
- uint32_t v = SkPackARGB32(a, r, g, b);
+
+ if (255 != a && kPremul_SkAlphaType == this->alphaType()) {
+ r = SkAlphaMul(r, a);
+ g = SkAlphaMul(g, a);
+ b = SkAlphaMul(b, a);
+ }
+ uint32_t v = kRGBA_8888_SkColorType == this->colorType() ?
+ SkPackARGB_as_RGBA(a, r, g, b) : SkPackARGB_as_BGRA(a, r, g, b);
while (--height >= 0) {
sk_memset32(p, v, width);
@@ -849,6 +790,8 @@ void SkBitmap::internalErase(const SkIRect& area,
}
break;
}
+ default:
+ return; // no change, so don't call notifyPixelsChanged()
}
this->notifyPixelsChanged();
@@ -872,84 +815,6 @@ void SkBitmap::eraseArea(const SkIRect& rect, SkColor c) const {
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
-#define SUB_OFFSET_FAILURE ((size_t)-1)
-
-/**
- * Based on the Config and rowBytes() of bm, return the offset into an SkPixelRef of the pixel at
- * (x, y).
- * Note that the SkPixelRef does not need to be set yet. deepCopyTo takes advantage of this fact.
- * Also note that (x, y) may be outside the range of (0 - width(), 0 - height()), so long as it is
- * within the bounds of the SkPixelRef being used.
- */
-static size_t get_sub_offset(const SkBitmap& bm, int x, int y) {
- switch (bm.config()) {
- case SkBitmap::kA8_Config:
- case SkBitmap:: kIndex8_Config:
- // x is fine as is for the calculation
- break;
-
- case SkBitmap::kRGB_565_Config:
- case SkBitmap::kARGB_4444_Config:
- x <<= 1;
- break;
-
- case SkBitmap::kARGB_8888_Config:
- x <<= 2;
- break;
-
- case SkBitmap::kNo_Config:
- default:
- return SUB_OFFSET_FAILURE;
- }
- return y * bm.rowBytes() + x;
-}
-
-/**
- * Using the pixelRefOffset(), rowBytes(), and Config of bm, determine the (x, y) coordinate of the
- * upper left corner of bm relative to its SkPixelRef.
- * x and y must be non-NULL.
- */
-bool get_upper_left_from_offset(SkBitmap::Config config, size_t offset, size_t rowBytes,
- int32_t* x, int32_t* y);
-bool get_upper_left_from_offset(SkBitmap::Config config, size_t offset, size_t rowBytes,
- int32_t* x, int32_t* y) {
- SkASSERT(x != NULL && y != NULL);
- if (0 == offset) {
- *x = *y = 0;
- return true;
- }
- // Use integer division to find the correct y position.
- // The remainder will be the x position, after we reverse get_sub_offset.
- SkTDivMod(offset, rowBytes, y, x);
- switch (config) {
- case SkBitmap::kA8_Config:
- // Fall through.
- case SkBitmap::kIndex8_Config:
- // x is unmodified
- break;
-
- case SkBitmap::kRGB_565_Config:
- // Fall through.
- case SkBitmap::kARGB_4444_Config:
- *x >>= 1;
- break;
-
- case SkBitmap::kARGB_8888_Config:
- *x >>= 2;
- break;
-
- case SkBitmap::kNo_Config:
- // Fall through.
- default:
- return false;
- }
- return true;
-}
-
-static bool get_upper_left_from_offset(const SkBitmap& bm, int32_t* x, int32_t* y) {
- return get_upper_left_from_offset(bm.config(), bm.pixelRefOffset(), bm.rowBytes(), x, y);
-}
-
bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const {
SkDEBUGCODE(this->validate();)
@@ -965,11 +830,11 @@ bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const {
if (fPixelRef->getTexture() != NULL) {
// Do a deep copy
- SkPixelRef* pixelRef = fPixelRef->deepCopy(this->config(), &subset);
+ SkPixelRef* pixelRef = fPixelRef->deepCopy(this->colorType(), &subset);
if (pixelRef != NULL) {
SkBitmap dst;
- dst.setConfig(this->config(), subset.width(), subset.height(), 0,
- this->alphaType());
+ dst.setInfo(SkImageInfo::Make(subset.width(), subset.height(),
+ this->colorType(), this->alphaType()));
dst.setIsVolatile(this->isVolatile());
dst.setPixelRef(pixelRef)->unref();
SkDEBUGCODE(dst.validate());
@@ -983,19 +848,17 @@ bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const {
SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width()));
SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height()));
- size_t offset = get_sub_offset(*this, r.fLeft, r.fTop);
- if (SUB_OFFSET_FAILURE == offset) {
- return false; // config not supported
- }
-
SkBitmap dst;
- dst.setConfig(this->config(), r.width(), r.height(), this->rowBytes(),
- this->alphaType());
+ dst.setInfo(SkImageInfo::Make(r.width(), r.height(), this->colorType(), this->alphaType()),
+ this->rowBytes());
dst.setIsVolatile(this->isVolatile());
if (fPixelRef) {
+ SkIPoint origin = fPixelRefOrigin;
+ origin.fX += r.fLeft;
+ origin.fY += r.fTop;
// share the pixelref with a custom offset
- dst.setPixelRef(fPixelRef, fPixelRefOffset + offset);
+ dst.setPixelRef(fPixelRef, origin);
}
SkDEBUGCODE(dst.validate();)
@@ -1009,32 +872,34 @@ bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const {
#include "SkCanvas.h"
#include "SkPaint.h"
-bool SkBitmap::canCopyTo(Config dstConfig) const {
- if (this->config() == kNo_Config) {
+bool SkBitmap::canCopyTo(SkColorType dstColorType) const {
+ if (this->colorType() == kUnknown_SkColorType) {
return false;
}
- bool sameConfigs = (this->config() == dstConfig);
- switch (dstConfig) {
- case kA8_Config:
- case kRGB_565_Config:
- case kARGB_8888_Config:
+ bool sameConfigs = (this->colorType() == dstColorType);
+ switch (dstColorType) {
+ case kAlpha_8_SkColorType:
+ case kRGB_565_SkColorType:
+ case kRGBA_8888_SkColorType:
+ case kBGRA_8888_SkColorType:
break;
- case kIndex8_Config:
+ case kIndex_8_SkColorType:
if (!sameConfigs) {
return false;
}
break;
- case kARGB_4444_Config:
- return sameConfigs || kARGB_8888_Config == this->config();
+ case kARGB_4444_SkColorType:
+ return sameConfigs || kN32_SkColorType == this->colorType();
default:
return false;
}
return true;
}
-bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const {
- if (!this->canCopyTo(dstConfig)) {
+bool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType,
+ Allocator* alloc) const {
+ if (!this->canCopyTo(dstColorType)) {
return false;
}
@@ -1044,26 +909,29 @@ bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const {
if (fPixelRef) {
SkIRect subset;
- if (get_upper_left_from_offset(*this, &subset.fLeft, &subset.fTop)) {
- subset.fRight = subset.fLeft + fWidth;
- subset.fBottom = subset.fTop + fHeight;
- if (fPixelRef->readPixels(&tmpSrc, &subset)) {
- SkASSERT(tmpSrc.width() == this->width());
- SkASSERT(tmpSrc.height() == this->height());
-
- // did we get lucky and we can just return tmpSrc?
- if (tmpSrc.config() == dstConfig && NULL == alloc) {
- dst->swap(tmpSrc);
- if (dst->pixelRef() && this->config() == dstConfig) {
- // TODO(scroggo): fix issue 1742
- dst->pixelRef()->cloneGenID(*fPixelRef);
- }
- return true;
+ subset.setXYWH(fPixelRefOrigin.fX, fPixelRefOrigin.fY,
+ fInfo.width(), fInfo.height());
+ if (fPixelRef->readPixels(&tmpSrc, &subset)) {
+ if (fPixelRef->info().alphaType() == kUnpremul_SkAlphaType) {
+ // FIXME: The only meaningful implementation of readPixels
+ // (GrPixelRef) assumes premultiplied pixels.
+ return false;
+ }
+ SkASSERT(tmpSrc.width() == this->width());
+ SkASSERT(tmpSrc.height() == this->height());
+
+ // did we get lucky and we can just return tmpSrc?
+ if (tmpSrc.colorType() == dstColorType && NULL == alloc) {
+ dst->swap(tmpSrc);
+ // If the result is an exact copy, clone the gen ID.
+ if (dst->pixelRef() && dst->pixelRef()->info() == fPixelRef->info()) {
+ dst->pixelRef()->cloneGenID(*fPixelRef);
}
-
- // fall through to the raster case
- src = &tmpSrc;
+ return true;
}
+
+ // fall through to the raster case
+ src = &tmpSrc;
}
}
@@ -1073,14 +941,23 @@ bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const {
return false;
}
+ // The only way to be readyToDraw is if fPixelRef is non NULL.
+ SkASSERT(fPixelRef != NULL);
+
+ SkImageInfo dstInfo = src->info();
+ dstInfo.fColorType = dstColorType;
+
SkBitmap tmpDst;
- tmpDst.setConfig(dstConfig, src->width(), src->height(), 0,
- src->alphaType());
+ if (!tmpDst.setInfo(dstInfo)) {
+ return false;
+ }
// allocate colortable if srcConfig == kIndex8_Config
- SkColorTable* ctable = (dstConfig == kIndex8_Config) ?
- new SkColorTable(*src->getColorTable()) : NULL;
- SkAutoUnref au(ctable);
+ SkAutoTUnref<SkColorTable> ctable;
+ if (dstColorType == kIndex_8_SkColorType) {
+ // TODO: can we just ref() the src colortable? Is it reentrant-safe?
+ ctable.reset(SkNEW_ARGS(SkColorTable, (*src->getColorTable())));
+ }
if (!tmpDst.allocPixels(alloc, ctable)) {
return false;
}
@@ -1090,15 +967,19 @@ bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const {
return false;
}
+ // pixelRef must be non NULL or tmpDst.readyToDraw() would have
+ // returned false.
+ SkASSERT(tmpDst.pixelRef() != NULL);
+
/* do memcpy for the same configs cases, else use drawing
*/
- if (src->config() == dstConfig) {
+ if (src->colorType() == dstColorType) {
if (tmpDst.getSize() == src->getSize()) {
memcpy(tmpDst.getPixels(), src->getPixels(), src->getSafeSize());
- SkPixelRef* pixelRef = tmpDst.pixelRef();
- if (NULL != pixelRef && NULL != fPixelRef) {
- // TODO(scroggo): fix issue 1742
- pixelRef->cloneGenID(*fPixelRef);
+
+ SkPixelRef* dstPixelRef = tmpDst.pixelRef();
+ if (dstPixelRef->info() == fPixelRef->info()) {
+ dstPixelRef->cloneGenID(*fPixelRef);
}
} else {
const char* srcP = reinterpret_cast<const char*>(src->getPixels());
@@ -1111,8 +992,12 @@ bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const {
dstP += tmpDst.rowBytes();
}
}
- } else if (SkBitmap::kARGB_4444_Config == dstConfig
- && SkBitmap::kARGB_8888_Config == src->config()) {
+ } else if (kARGB_4444_SkColorType == dstColorType
+ && kN32_SkColorType == src->colorType()) {
+ if (src->alphaType() == kUnpremul_SkAlphaType) {
+ // Our method for converting to 4444 assumes premultiplied.
+ return false;
+ }
SkASSERT(src->height() == tmpDst.height());
SkASSERT(src->width() == tmpDst.width());
for (int y = 0; y < src->height(); ++y) {
@@ -1125,6 +1010,11 @@ bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const {
}
}
} else {
+ if (tmpDst.alphaType() == kUnpremul_SkAlphaType) {
+ // We do not support drawing to unpremultiplied bitmaps.
+ return false;
+ }
+
// Always clear the dest in case one of the blitters accesses it
// TODO: switch the allocation of tmpDst to call sk_calloc_throw
tmpDst.eraseColor(SK_ColorTRANSPARENT);
@@ -1140,45 +1030,37 @@ bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const {
return true;
}
-bool SkBitmap::deepCopyTo(SkBitmap* dst, Config dstConfig) const {
- if (!this->canCopyTo(dstConfig)) {
+bool SkBitmap::deepCopyTo(SkBitmap* dst) const {
+ const SkColorType dstCT = this->colorType();
+
+ if (!this->canCopyTo(dstCT)) {
return false;
}
// If we have a PixelRef, and it supports deep copy, use it.
// Currently supported only by texture-backed bitmaps.
if (fPixelRef) {
- SkPixelRef* pixelRef = fPixelRef->deepCopy(dstConfig);
+ SkPixelRef* pixelRef = fPixelRef->deepCopy(dstCT, NULL);
if (pixelRef) {
uint32_t rowBytes;
- if (dstConfig == fConfig) {
- // TODO(scroggo): fix issue 1742
+ if (this->colorType() == dstCT) {
+ // Since there is no subset to pass to deepCopy, and deepCopy
+ // succeeded, the new pixel ref must be identical.
+ SkASSERT(fPixelRef->info() == pixelRef->info());
pixelRef->cloneGenID(*fPixelRef);
// Use the same rowBytes as the original.
rowBytes = fRowBytes;
} else {
- // With the new config, an appropriate fRowBytes will be computed by setConfig.
+ // With the new config, an appropriate fRowBytes will be computed by setInfo.
rowBytes = 0;
}
- dst->setConfig(dstConfig, fWidth, fHeight, rowBytes);
- size_t pixelRefOffset;
- if (0 == fPixelRefOffset || dstConfig == fConfig) {
- // Use the same offset as the original.
- pixelRefOffset = fPixelRefOffset;
- } else {
- // Find the correct offset in the new config. This needs to be done after calling
- // setConfig so dst's fConfig and fRowBytes have been set properly.
- int32_t x, y;
- if (!get_upper_left_from_offset(*this, &x, &y)) {
- return false;
- }
- pixelRefOffset = get_sub_offset(*dst, x, y);
- if (SUB_OFFSET_FAILURE == pixelRefOffset) {
- return false;
- }
+ SkImageInfo info = fInfo;
+ info.fColorType = dstCT;
+ if (!dst->setInfo(info, rowBytes)) {
+ return false;
}
- dst->setPixelRef(pixelRef, pixelRefOffset)->unref();
+ dst->setPixelRef(pixelRef, fPixelRefOrigin)->unref();
return true;
}
}
@@ -1186,266 +1068,21 @@ bool SkBitmap::deepCopyTo(SkBitmap* dst, Config dstConfig) const {
if (this->getTexture()) {
return false;
} else {
- return this->copyTo(dst, dstConfig, NULL);
+ return this->copyTo(dst, dstCT, NULL);
}
}
///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-static void downsampleby2_proc32(SkBitmap* dst, int x, int y,
- const SkBitmap& src) {
- x <<= 1;
- y <<= 1;
- const SkPMColor* p = src.getAddr32(x, y);
- const SkPMColor* baseP = p;
- SkPMColor c, ag, rb;
-
- c = *p; ag = (c >> 8) & 0xFF00FF; rb = c & 0xFF00FF;
- if (x < src.width() - 1) {
- p += 1;
- }
- c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
-
- p = baseP;
- if (y < src.height() - 1) {
- p += src.rowBytes() >> 2;
- }
- c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
- if (x < src.width() - 1) {
- p += 1;
- }
- c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
-
- *dst->getAddr32(x >> 1, y >> 1) =
- ((rb >> 2) & 0xFF00FF) | ((ag << 6) & 0xFF00FF00);
-}
-
-static inline uint32_t expand16(U16CPU c) {
- return (c & ~SK_G16_MASK_IN_PLACE) | ((c & SK_G16_MASK_IN_PLACE) << 16);
-}
-
-// returns dirt in the top 16bits, but we don't care, since we only
-// store the low 16bits.
-static inline U16CPU pack16(uint32_t c) {
- return (c & ~SK_G16_MASK_IN_PLACE) | ((c >> 16) & SK_G16_MASK_IN_PLACE);
-}
-
-static void downsampleby2_proc16(SkBitmap* dst, int x, int y,
- const SkBitmap& src) {
- x <<= 1;
- y <<= 1;
- const uint16_t* p = src.getAddr16(x, y);
- const uint16_t* baseP = p;
- SkPMColor c;
-
- c = expand16(*p);
- if (x < src.width() - 1) {
- p += 1;
- }
- c += expand16(*p);
-
- p = baseP;
- if (y < src.height() - 1) {
- p += src.rowBytes() >> 1;
- }
- c += expand16(*p);
- if (x < src.width() - 1) {
- p += 1;
- }
- c += expand16(*p);
-
- *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)pack16(c >> 2);
-}
-
-static uint32_t expand4444(U16CPU c) {
- return (c & 0xF0F) | ((c & ~0xF0F) << 12);
-}
-
-static U16CPU collaps4444(uint32_t c) {
- return (c & 0xF0F) | ((c >> 12) & ~0xF0F);
-}
-
-static void downsampleby2_proc4444(SkBitmap* dst, int x, int y,
- const SkBitmap& src) {
- x <<= 1;
- y <<= 1;
- const uint16_t* p = src.getAddr16(x, y);
- const uint16_t* baseP = p;
- uint32_t c;
-
- c = expand4444(*p);
- if (x < src.width() - 1) {
- p += 1;
- }
- c += expand4444(*p);
-
- p = baseP;
- if (y < src.height() - 1) {
- p += src.rowBytes() >> 1;
- }
- c += expand4444(*p);
- if (x < src.width() - 1) {
- p += 1;
- }
- c += expand4444(*p);
-
- *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)collaps4444(c >> 2);
-}
-
-void SkBitmap::buildMipMap(bool forceRebuild) {
- if (forceRebuild)
- this->freeMipMap();
- else if (fMipMap)
- return; // we're already built
-
- SkASSERT(NULL == fMipMap);
-
- void (*proc)(SkBitmap* dst, int x, int y, const SkBitmap& src);
-
- const SkBitmap::Config config = this->config();
-
- switch (config) {
- case kARGB_8888_Config:
- proc = downsampleby2_proc32;
- break;
- case kRGB_565_Config:
- proc = downsampleby2_proc16;
- break;
- case kARGB_4444_Config:
- proc = downsampleby2_proc4444;
- break;
- case kIndex8_Config:
- case kA8_Config:
- default:
- return; // don't build mipmaps for these configs
- }
-
- SkAutoLockPixels alp(*this);
- if (!this->readyToDraw()) {
- return;
- }
-
- // whip through our loop to compute the exact size needed
- size_t size = 0;
- int maxLevels = 0;
- {
- int width = this->width();
- int height = this->height();
- for (;;) {
- width >>= 1;
- height >>= 1;
- if (0 == width || 0 == height) {
- break;
- }
- size += ComputeRowBytes(config, width) * height;
- maxLevels += 1;
- }
- }
-
- // nothing to build
- if (0 == maxLevels) {
- return;
- }
-
- SkBitmap srcBM(*this);
- srcBM.lockPixels();
- if (!srcBM.readyToDraw()) {
- return;
- }
-
- MipMap* mm = MipMap::Alloc(maxLevels, size);
- if (NULL == mm) {
- return;
- }
-
- MipLevel* level = mm->levels();
- uint8_t* addr = (uint8_t*)mm->pixels();
- int width = this->width();
- int height = this->height();
- uint32_t rowBytes;
- SkBitmap dstBM;
-
- for (int i = 0; i < maxLevels; i++) {
- width >>= 1;
- height >>= 1;
- rowBytes = SkToU32(ComputeRowBytes(config, width));
-
- level[i].fPixels = addr;
- level[i].fWidth = width;
- level[i].fHeight = height;
- level[i].fRowBytes = rowBytes;
-
- dstBM.setConfig(config, width, height, rowBytes);
- dstBM.setPixels(addr);
-
- srcBM.lockPixels();
- for (int y = 0; y < height; y++) {
- for (int x = 0; x < width; x++) {
- proc(&dstBM, x, y, srcBM);
- }
- }
- srcBM.unlockPixels();
-
- srcBM = dstBM;
- addr += height * rowBytes;
- }
- SkASSERT(addr == (uint8_t*)mm->pixels() + size);
- fMipMap = mm;
-}
-
-bool SkBitmap::hasMipMap() const {
- return fMipMap != NULL;
-}
-
-int SkBitmap::extractMipLevel(SkBitmap* dst, SkFixed sx, SkFixed sy) {
- if (NULL == fMipMap) {
- return 0;
- }
-
- int level = ComputeMipLevel(sx, sy) >> 16;
- SkASSERT(level >= 0);
- if (level <= 0) {
- return 0;
- }
-
- if (level >= fMipMap->fLevelCount) {
- level = fMipMap->fLevelCount - 1;
- }
- if (dst) {
- const MipLevel& mip = fMipMap->levels()[level - 1];
- dst->setConfig((SkBitmap::Config)this->config(),
- mip.fWidth, mip.fHeight, mip.fRowBytes);
- dst->setPixels(mip.fPixels);
- }
- return level;
-}
-
-SkFixed SkBitmap::ComputeMipLevel(SkFixed sx, SkFixed sy) {
- sx = SkAbs32(sx);
- sy = SkAbs32(sy);
- if (sx < sy) {
- sx = sy;
- }
- if (sx < SK_Fixed1) {
- return 0;
- }
- int clz = SkCLZ(sx);
- SkASSERT(clz >= 1 && clz <= 15);
- return SkIntToFixed(15 - clz) + ((unsigned)(sx << (clz + 1)) >> 16);
-}
-
-///////////////////////////////////////////////////////////////////////////////
static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha,
int alphaRowBytes) {
SkASSERT(alpha != NULL);
SkASSERT(alphaRowBytes >= src.width());
- SkBitmap::Config config = src.config();
- int w = src.width();
- int h = src.height();
- size_t rb = src.rowBytes();
+ SkColorType colorType = src.colorType();
+ int w = src.width();
+ int h = src.height();
+ size_t rb = src.rowBytes();
SkAutoLockPixels alp(src);
if (!src.readyToDraw()) {
@@ -1457,14 +1094,14 @@ static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha,
return false;
}
- if (SkBitmap::kA8_Config == config && !src.isOpaque()) {
+ if (kAlpha_8_SkColorType == colorType && !src.isOpaque()) {
const uint8_t* s = src.getAddr8(0, 0);
while (--h >= 0) {
memcpy(alpha, s, w);
s += rb;
alpha += alphaRowBytes;
}
- } else if (SkBitmap::kARGB_8888_Config == config && !src.isOpaque()) {
+ } else if (kN32_SkColorType == colorType && !src.isOpaque()) {
const SkPMColor* SK_RESTRICT s = src.getAddr32(0, 0);
while (--h >= 0) {
for (int x = 0; x < w; x++) {
@@ -1473,7 +1110,7 @@ static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha,
s = (const SkPMColor*)((const char*)s + rb);
alpha += alphaRowBytes;
}
- } else if (SkBitmap::kARGB_4444_Config == config && !src.isOpaque()) {
+ } else if (kARGB_4444_SkColorType == colorType && !src.isOpaque()) {
const SkPMColor16* SK_RESTRICT s = src.getAddr16(0, 0);
while (--h >= 0) {
for (int x = 0; x < w; x++) {
@@ -1482,7 +1119,7 @@ static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha,
s = (const SkPMColor16*)((const char*)s + rb);
alpha += alphaRowBytes;
}
- } else if (SkBitmap::kIndex8_Config == config && !src.isOpaque()) {
+ } else if (kIndex_8_SkColorType == colorType && !src.isOpaque()) {
SkColorTable* ct = src.getColorTable();
if (ct) {
const SkPMColor* SK_RESTRICT table = ct->lockColors();
@@ -1530,8 +1167,7 @@ bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
dstM.fRowBytes = SkAlign4(dstM.fBounds.width());
} else {
NO_FILTER_CASE:
- tmpBitmap.setConfig(SkBitmap::kA8_Config, this->width(), this->height(),
- srcM.fRowBytes);
+ tmpBitmap.setInfo(SkImageInfo::MakeA8(this->width(), this->height()), srcM.fRowBytes);
if (!tmpBitmap.allocPixels(allocator, NULL)) {
// Allocation of pixels for alpha bitmap failed.
SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
@@ -1554,8 +1190,8 @@ bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
}
SkAutoMaskFreeImage dstCleanup(dstM.fImage);
- tmpBitmap.setConfig(SkBitmap::kA8_Config, dstM.fBounds.width(),
- dstM.fBounds.height(), dstM.fRowBytes);
+ tmpBitmap.setInfo(SkImageInfo::MakeA8(dstM.fBounds.width(), dstM.fBounds.height()),
+ dstM.fRowBytes);
if (!tmpBitmap.allocPixels(allocator, NULL)) {
// Allocation of pixels for alpha bitmap failed.
SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
@@ -1574,61 +1210,121 @@ bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
///////////////////////////////////////////////////////////////////////////////
-enum {
- SERIALIZE_PIXELTYPE_NONE,
- SERIALIZE_PIXELTYPE_REF_DATA
-};
+void SkBitmap::WriteRawPixels(SkWriteBuffer* buffer, const SkBitmap& bitmap) {
+ const SkImageInfo info = bitmap.info();
+ SkAutoLockPixels alp(bitmap);
+ if (0 == info.width() || 0 == info.height() || NULL == bitmap.getPixels()) {
+ buffer->writeUInt(0); // instead of snugRB, signaling no pixels
+ return;
+ }
-void SkBitmap::flatten(SkFlattenableWriteBuffer& buffer) const {
- buffer.writeInt(fWidth);
- buffer.writeInt(fHeight);
- buffer.writeInt(fRowBytes);
- buffer.writeInt(fConfig);
- buffer.writeInt(fAlphaType);
+ const size_t snugRB = info.width() * info.bytesPerPixel();
+ const char* src = (const char*)bitmap.getPixels();
+ const size_t ramRB = bitmap.rowBytes();
- if (fPixelRef) {
- if (fPixelRef->getFactory()) {
- buffer.writeInt(SERIALIZE_PIXELTYPE_REF_DATA);
- buffer.writeUInt(SkToU32(fPixelRefOffset));
- buffer.writeFlattenable(fPixelRef);
- return;
- }
- // if we get here, we can't record the pixels
- buffer.writeInt(SERIALIZE_PIXELTYPE_NONE);
+ buffer->write32(SkToU32(snugRB));
+ info.flatten(*buffer);
+
+ const size_t size = snugRB * info.height();
+ SkAutoMalloc storage(size);
+ char* dst = (char*)storage.get();
+ for (int y = 0; y < info.height(); ++y) {
+ memcpy(dst, src, snugRB);
+ dst += snugRB;
+ src += ramRB;
+ }
+ buffer->writeByteArray(storage.get(), size);
+
+ SkColorTable* ct = bitmap.getColorTable();
+ if (kIndex_8_SkColorType == info.colorType() && ct) {
+ buffer->writeBool(true);
+ ct->writeToBuffer(*buffer);
} else {
- buffer.writeInt(SERIALIZE_PIXELTYPE_NONE);
+ buffer->writeBool(false);
}
}
-void SkBitmap::unflatten(SkFlattenableReadBuffer& buffer) {
+bool SkBitmap::ReadRawPixels(SkReadBuffer* buffer, SkBitmap* bitmap) {
+ const size_t snugRB = buffer->readUInt();
+ if (0 == snugRB) { // no pixels
+ return false;
+ }
+
+ SkImageInfo info;
+ info.unflatten(*buffer);
+
+ const size_t ramRB = info.minRowBytes();
+ const int height = info.height();
+ const size_t snugSize = snugRB * height;
+ const size_t ramSize = ramRB * height;
+ if (!buffer->validate(snugSize <= ramSize)) {
+ return false;
+ }
+
+ char* dst = (char*)sk_malloc_throw(ramSize);
+ buffer->readByteArray(dst, snugSize);
+ SkAutoDataUnref data(SkData::NewFromMalloc(dst, ramSize));
+
+ if (snugSize != ramSize) {
+ const char* srcRow = dst + snugRB * (height - 1);
+ char* dstRow = dst + ramRB * (height - 1);
+ for (int y = height - 1; y >= 1; --y) {
+ memmove(dstRow, srcRow, snugRB);
+ srcRow -= snugRB;
+ dstRow -= ramRB;
+ }
+ SkASSERT(srcRow == dstRow); // first row does not need to be moved
+ }
+
+ SkAutoTUnref<SkColorTable> ctable;
+ if (buffer->readBool()) {
+ ctable.reset(SkNEW_ARGS(SkColorTable, (*buffer)));
+ }
+
+ SkAutoTUnref<SkPixelRef> pr(SkMallocPixelRef::NewWithData(info, info.minRowBytes(),
+ ctable.get(), data.get()));
+ bitmap->setInfo(pr->info());
+ bitmap->setPixelRef(pr, 0, 0);
+ return true;
+}
+
+enum {
+ SERIALIZE_PIXELTYPE_NONE,
+ SERIALIZE_PIXELTYPE_REF_DATA
+};
+
+void SkBitmap::legacyUnflatten(SkReadBuffer& buffer) {
this->reset();
- int width = buffer.readInt();
- int height = buffer.readInt();
- int rowBytes = buffer.readInt();
- Config config = (Config)buffer.readInt();
- SkAlphaType alphaType = (SkAlphaType)buffer.readInt();
- buffer.validate((width >= 0) && (height >= 0) && (rowBytes >= 0) &&
- SkIsValidConfig(config) && validate_alphaType(config, alphaType));
+ SkImageInfo info;
+ info.unflatten(buffer);
+ size_t rowBytes = buffer.readInt();
+ if (!buffer.validate((info.width() >= 0) && (info.height() >= 0) &&
+ SkColorTypeIsValid(info.fColorType) &&
+ SkAlphaTypeIsValid(info.fAlphaType) &&
+ validate_alphaType(info.fColorType, info.fAlphaType) &&
+ info.validRowBytes(rowBytes))) {
+ return;
+ }
- bool configIsValid = this->setConfig(config, width, height, rowBytes, alphaType);
- // Note : Using (fRowBytes >= (fWidth * fBytesPerPixel)) in the following test can create false
- // positives if the multiplication causes an integer overflow. Use the division instead.
- buffer.validate(configIsValid && (fBytesPerPixel > 0) &&
- ((fRowBytes / fBytesPerPixel) >= fWidth));
+ bool configIsValid = this->setInfo(info, rowBytes);
+ buffer.validate(configIsValid);
int reftype = buffer.readInt();
if (buffer.validate((SERIALIZE_PIXELTYPE_REF_DATA == reftype) ||
(SERIALIZE_PIXELTYPE_NONE == reftype))) {
switch (reftype) {
case SERIALIZE_PIXELTYPE_REF_DATA: {
- size_t offset = buffer.readUInt();
+ SkIPoint origin;
+ origin.fX = buffer.readInt();
+ origin.fY = buffer.readInt();
+ size_t offset = origin.fY * rowBytes + origin.fX * info.bytesPerPixel();
SkPixelRef* pr = buffer.readPixelRef();
if (!buffer.validate((NULL == pr) ||
(pr->getAllocatedSizeInBytes() >= (offset + this->getSafeSize())))) {
- offset = 0;
+ origin.setZero();
}
- SkSafeUnref(this->setPixelRef(pr, offset));
+ SkSafeUnref(this->setPixelRef(pr, origin));
break;
}
case SERIALIZE_PIXELTYPE_NONE:
@@ -1655,39 +1351,47 @@ SkBitmap::RLEPixels::~RLEPixels() {
#ifdef SK_DEBUG
void SkBitmap::validate() const {
- SkASSERT(fConfig < kConfigCount);
- SkASSERT(fRowBytes >= (unsigned)ComputeRowBytes((Config)fConfig, fWidth));
+ fInfo.validate();
+
+ // ImageInfo may not require this, but Bitmap ensures that opaque-only
+ // colorTypes report opaque for their alphatype
+ if (kRGB_565_SkColorType == fInfo.colorType()) {
+ SkASSERT(kOpaque_SkAlphaType == fInfo.alphaType());
+ }
+
+ SkASSERT(fInfo.validRowBytes(fRowBytes));
uint8_t allFlags = kImageIsOpaque_Flag | kImageIsVolatile_Flag | kImageIsImmutable_Flag;
#ifdef SK_BUILD_FOR_ANDROID
allFlags |= kHasHardwareMipMap_Flag;
#endif
SkASSERT(fFlags <= allFlags);
SkASSERT(fPixelLockCount >= 0);
- SkASSERT(NULL == fColorTable || (unsigned)fColorTable->getRefCnt() < 10000);
- SkASSERT((uint8_t)ComputeBytesPerPixel((Config)fConfig) == fBytesPerPixel);
-#if 0 // these asserts are not thread-correct, so disable for now
- if (fPixelRef) {
- if (fPixelLockCount > 0) {
- SkASSERT(fPixelRef->isLocked());
- } else {
- SkASSERT(NULL == fPixels);
- SkASSERT(NULL == fColorTable);
- }
+ if (fPixels) {
+ SkASSERT(fPixelRef);
+ SkASSERT(fPixelLockCount > 0);
+ SkASSERT(fPixelRef->isLocked());
+ SkASSERT(fPixelRef->rowBytes() == fRowBytes);
+ SkASSERT(fPixelRefOrigin.fX >= 0);
+ SkASSERT(fPixelRefOrigin.fY >= 0);
+ SkASSERT(fPixelRef->info().width() >= (int)this->width() + fPixelRefOrigin.fX);
+ SkASSERT(fPixelRef->info().fHeight >= (int)this->height() + fPixelRefOrigin.fY);
+ SkASSERT(fPixelRef->rowBytes() >= fInfo.minRowBytes());
+ } else {
+ SkASSERT(NULL == fColorTable);
}
-#endif
}
#endif
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkBitmap::toString(SkString* str) const {
- static const char* gConfigNames[kConfigCount] = {
- "NONE", "A8", "INDEX8", "565", "4444", "8888"
+ static const char* gColorTypeNames[kLastEnum_SkColorType + 1] = {
+ "UNKNOWN", "A8", "565", "4444", "RGBA", "BGRA", "INDEX8",
};
str->appendf("bitmap: ((%d, %d) %s", this->width(), this->height(),
- gConfigNames[this->config()]);
+ gColorTypeNames[this->colorType()]);
str->append(" (");
if (this->isOpaque()) {
@@ -1718,3 +1422,14 @@ void SkBitmap::toString(SkString* str) const {
str->append(")");
}
#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef SK_DEBUG
+void SkImageInfo::validate() const {
+ SkASSERT(fWidth >= 0);
+ SkASSERT(fHeight >= 0);
+ SkASSERT(SkColorTypeIsValid(fColorType));
+ SkASSERT(SkAlphaTypeIsValid(fAlphaType));
+}
+#endif
diff --git a/chromium/third_party/skia/src/core/SkBitmapDevice.cpp b/chromium/third_party/skia/src/core/SkBitmapDevice.cpp
index 1668618cf74..0f3cc2be501 100644
--- a/chromium/third_party/skia/src/core/SkBitmapDevice.cpp
+++ b/chromium/third_party/skia/src/core/SkBitmapDevice.cpp
@@ -10,48 +10,95 @@
#include "SkDraw.h"
#include "SkRasterClip.h"
#include "SkShader.h"
+#include "SkSurface.h"
#define CHECK_FOR_ANNOTATION(paint) \
do { if (paint.getAnnotation()) { return; } } while (0)
-SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap)
- : fBitmap(bitmap) {
- SkASSERT(SkBitmap::kARGB_4444_Config != bitmap.config());
+static bool valid_for_bitmap_device(const SkImageInfo& info,
+ SkAlphaType* newAlphaType) {
+ if (info.width() < 0 || info.height() < 0) {
+ return false;
+ }
+
+ // TODO: can we stop supporting kUnknown in SkBitmkapDevice?
+ if (kUnknown_SkColorType == info.colorType()) {
+ if (newAlphaType) {
+ *newAlphaType = kIgnore_SkAlphaType;
+ }
+ return true;
+ }
+
+ switch (info.alphaType()) {
+ case kPremul_SkAlphaType:
+ case kOpaque_SkAlphaType:
+ break;
+ default:
+ return false;
+ }
+
+ SkAlphaType canonicalAlphaType = info.alphaType();
+
+ switch (info.colorType()) {
+ case kAlpha_8_SkColorType:
+ break;
+ case kRGB_565_SkColorType:
+ canonicalAlphaType = kOpaque_SkAlphaType;
+ break;
+ case kN32_SkColorType:
+ break;
+ default:
+ return false;
+ }
+
+ if (newAlphaType) {
+ *newAlphaType = canonicalAlphaType;
+ }
+ return true;
+}
+
+SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap) : fBitmap(bitmap) {
+ SkASSERT(valid_for_bitmap_device(bitmap.info(), NULL));
}
SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap, const SkDeviceProperties& deviceProperties)
: SkBaseDevice(deviceProperties)
- , fBitmap(bitmap) {
+ , fBitmap(bitmap)
+{
+ SkASSERT(valid_for_bitmap_device(bitmap.info(), NULL));
}
-SkBitmapDevice::SkBitmapDevice(SkBitmap::Config config, int width, int height, bool isOpaque) {
- fBitmap.setConfig(config, width, height, 0, isOpaque ?
- kOpaque_SkAlphaType : kPremul_SkAlphaType);
- if (!fBitmap.allocPixels()) {
- fBitmap.setConfig(config, 0, 0, 0, isOpaque ?
- kOpaque_SkAlphaType : kPremul_SkAlphaType);
+SkBitmapDevice* SkBitmapDevice::Create(const SkImageInfo& origInfo,
+ const SkDeviceProperties* props) {
+ SkImageInfo info = origInfo;
+ if (!valid_for_bitmap_device(info, &info.fAlphaType)) {
+ return NULL;
}
- if (!isOpaque) {
- fBitmap.eraseColor(SK_ColorTRANSPARENT);
- }
-}
-SkBitmapDevice::SkBitmapDevice(SkBitmap::Config config, int width, int height, bool isOpaque,
- const SkDeviceProperties& deviceProperties)
- : SkBaseDevice(deviceProperties) {
+ SkBitmap bitmap;
- fBitmap.setConfig(config, width, height, 0, isOpaque ?
- kOpaque_SkAlphaType : kPremul_SkAlphaType);
- if (!fBitmap.allocPixels()) {
- fBitmap.setConfig(config, 0, 0, 0, isOpaque ?
- kOpaque_SkAlphaType : kPremul_SkAlphaType);
+ if (kUnknown_SkColorType == info.colorType()) {
+ if (!bitmap.setInfo(info)) {
+ return NULL;
+ }
+ } else {
+ if (!bitmap.allocPixels(info)) {
+ return NULL;
+ }
+ if (!bitmap.info().isOpaque()) {
+ bitmap.eraseColor(SK_ColorTRANSPARENT);
+ }
}
- if (!isOpaque) {
- fBitmap.eraseColor(SK_ColorTRANSPARENT);
+
+ if (props) {
+ return SkNEW_ARGS(SkBitmapDevice, (bitmap, *props));
+ } else {
+ return SkNEW_ARGS(SkBitmapDevice, (bitmap));
}
}
-SkBitmapDevice::~SkBitmapDevice() {
+SkImageInfo SkBitmapDevice::imageInfo() const {
+ return fBitmap.info();
}
void SkBitmapDevice::replaceBitmapBackendForRasterSurface(const SkBitmap& bm) {
@@ -61,18 +108,8 @@ void SkBitmapDevice::replaceBitmapBackendForRasterSurface(const SkBitmap& bm) {
fBitmap.lockPixels();
}
-SkBaseDevice* SkBitmapDevice::onCreateCompatibleDevice(SkBitmap::Config config,
- int width, int height,
- bool isOpaque,
- Usage usage) {
- SkBitmapDevice* device = SkNEW_ARGS(SkBitmapDevice,(config, width, height,
- isOpaque, this->getDeviceProperties()));
- // Check if allocation failed and delete device if it did fail
- if ((device->width() != width) || (device->height() != height)) {
- SkDELETE(device);
- device = NULL;
- }
- return device;
+SkBaseDevice* SkBitmapDevice::onCreateDevice(const SkImageInfo& info, Usage usage) {
+ return SkBitmapDevice::Create(info, &this->getDeviceProperties());
}
void SkBitmapDevice::lockPixels() {
@@ -95,113 +132,127 @@ const SkBitmap& SkBitmapDevice::onAccessBitmap() {
return fBitmap;
}
-bool SkBitmapDevice::canHandleImageFilter(SkImageFilter*) {
+bool SkBitmapDevice::canHandleImageFilter(const SkImageFilter*) {
return false;
}
-bool SkBitmapDevice::filterImage(SkImageFilter* filter, const SkBitmap& src,
- const SkMatrix& ctm, SkBitmap* result,
+bool SkBitmapDevice::filterImage(const SkImageFilter* filter, const SkBitmap& src,
+ const SkImageFilter::Context& ctx, SkBitmap* result,
SkIPoint* offset) {
return false;
}
-bool SkBitmapDevice::allowImageFilter(SkImageFilter*) {
+bool SkBitmapDevice::allowImageFilter(const SkImageFilter*) {
return true;
}
-bool SkBitmapDevice::onReadPixels(const SkBitmap& bitmap,
- int x, int y,
- SkCanvas::Config8888 config8888) {
- SkASSERT(SkBitmap::kARGB_8888_Config == bitmap.config());
- SkASSERT(!bitmap.isNull());
- SkASSERT(SkIRect::MakeWH(this->width(), this->height()).contains(SkIRect::MakeXYWH(x, y,
- bitmap.width(),
- bitmap.height())));
+void* SkBitmapDevice::onAccessPixels(SkImageInfo* info, size_t* rowBytes) {
+ if (fBitmap.getPixels()) {
+ *info = fBitmap.info();
+ *rowBytes = fBitmap.rowBytes();
+ return fBitmap.getPixels();
+ }
+ return NULL;
+}
+
+static void rect_memcpy(void* dst, size_t dstRB, const void* src, size_t srcRB, size_t bytesPerRow,
+ int rowCount) {
+ SkASSERT(bytesPerRow <= srcRB);
+ SkASSERT(bytesPerRow <= dstRB);
+ for (int i = 0; i < rowCount; ++i) {
+ memcpy(dst, src, bytesPerRow);
+ dst = (char*)dst + dstRB;
+ src = (const char*)src + srcRB;
+ }
+}
- SkIRect srcRect = SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height());
- const SkBitmap& src = this->accessBitmap(false);
+#include "SkConfig8888.h"
- SkBitmap subset;
- if (!src.extractSubset(&subset, srcRect)) {
+static bool copy_pixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
+ const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRowBytes) {
+ if (srcInfo.dimensions() != dstInfo.dimensions()) {
return false;
}
- if (SkBitmap::kARGB_8888_Config != subset.config()) {
- // It'd be preferable to do this directly to bitmap.
- subset.copyTo(&subset, SkBitmap::kARGB_8888_Config);
+ if (4 == srcInfo.bytesPerPixel() && 4 == dstInfo.bytesPerPixel()) {
+ SkDstPixelInfo dstPI;
+ dstPI.fColorType = dstInfo.colorType();
+ dstPI.fAlphaType = dstInfo.alphaType();
+ dstPI.fPixels = dstPixels;
+ dstPI.fRowBytes = dstRowBytes;
+
+ SkSrcPixelInfo srcPI;
+ srcPI.fColorType = srcInfo.colorType();
+ srcPI.fAlphaType = srcInfo.alphaType();
+ srcPI.fPixels = srcPixels;
+ srcPI.fRowBytes = srcRowBytes;
+
+ return srcPI.convertPixelsTo(&dstPI, srcInfo.width(), srcInfo.height());
}
- SkAutoLockPixels alp(bitmap);
- uint32_t* bmpPixels = reinterpret_cast<uint32_t*>(bitmap.getPixels());
- SkCopyBitmapToConfig8888(bmpPixels, bitmap.rowBytes(), config8888, subset);
- return true;
+ if (srcInfo.colorType() == dstInfo.colorType()) {
+ switch (srcInfo.colorType()) {
+ case kRGB_565_SkColorType:
+ case kAlpha_8_SkColorType:
+ break;
+ case kARGB_4444_SkColorType:
+ if (srcInfo.alphaType() != dstInfo.alphaType()) {
+ return false;
+ }
+ break;
+ default:
+ return false;
+ }
+ rect_memcpy(dstPixels, dstRowBytes, srcPixels, srcRowBytes,
+ srcInfo.width() * srcInfo.bytesPerPixel(), srcInfo.height());
+ }
+ // TODO: add support for more conversions as needed
+ return false;
}
-void SkBitmapDevice::writePixels(const SkBitmap& bitmap,
- int x, int y,
- SkCanvas::Config8888 config8888) {
- if (bitmap.isNull() || bitmap.getTexture()) {
- return;
+bool SkBitmapDevice::onWritePixels(const SkImageInfo& srcInfo, const void* srcPixels,
+ size_t srcRowBytes, int x, int y) {
+ // since we don't stop creating un-pixeled devices yet, check for no pixels here
+ if (NULL == fBitmap.getPixels()) {
+ return false;
}
- const SkBitmap* sprite = &bitmap;
- // check whether we have to handle a config8888 that doesn't match SkPMColor
- if (SkBitmap::kARGB_8888_Config == bitmap.config() &&
- SkCanvas::kNative_Premul_Config8888 != config8888 &&
- kPMColorAlias != config8888) {
-
- // We're going to have to convert from a config8888 to the native config
- // First we clip to the device bounds.
- SkBitmap dstBmp = this->accessBitmap(true);
- SkIRect spriteRect = SkIRect::MakeXYWH(x, y,
- bitmap.width(), bitmap.height());
- SkIRect devRect = SkIRect::MakeWH(dstBmp.width(), dstBmp.height());
- if (!spriteRect.intersect(devRect)) {
- return;
- }
- // write directly to the device if it has pixels and is SkPMColor
- bool drawSprite;
- if (SkBitmap::kARGB_8888_Config == dstBmp.config() && !dstBmp.isNull()) {
- // we can write directly to the dst when doing the conversion
- dstBmp.extractSubset(&dstBmp, spriteRect);
- drawSprite = false;
- } else {
- // we convert to a temporary bitmap and draw that as a sprite
- dstBmp.setConfig(SkBitmap::kARGB_8888_Config,
- spriteRect.width(),
- spriteRect.height());
- if (!dstBmp.allocPixels()) {
- return;
- }
- drawSprite = true;
- }
+ SkImageInfo dstInfo = fBitmap.info();
+ dstInfo.fWidth = srcInfo.width();
+ dstInfo.fHeight = srcInfo.height();
- // copy pixels to dstBmp and convert from config8888 to native config.
- SkAutoLockPixels alp(bitmap);
- uint32_t* srcPixels = bitmap.getAddr32(spriteRect.fLeft - x,
- spriteRect.fTop - y);
- SkCopyConfig8888ToBitmap(dstBmp,
- srcPixels,
- bitmap.rowBytes(),
- config8888);
-
- if (drawSprite) {
- // we've clipped the sprite when we made a copy
- x = spriteRect.fLeft;
- y = spriteRect.fTop;
- sprite = &dstBmp;
- } else {
- return;
- }
+ void* dstPixels = fBitmap.getAddr(x, y);
+ size_t dstRowBytes = fBitmap.rowBytes();
+
+ if (copy_pixels(dstInfo, dstPixels, dstRowBytes, srcInfo, srcPixels, srcRowBytes)) {
+ fBitmap.notifyPixelsChanged();
+ return true;
+ }
+ return false;
+}
+
+bool SkBitmapDevice::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
+ int x, int y) {
+ // since we don't stop creating un-pixeled devices yet, check for no pixels here
+ if (NULL == fBitmap.getPixels()) {
+ return false;
}
- SkPaint paint;
- paint.setXfermodeMode(SkXfermode::kSrc_Mode);
- SkRasterClip clip(SkIRect::MakeWH(fBitmap.width(), fBitmap.height()));
- SkDraw draw;
- draw.fRC = &clip;
- draw.fClip = &clip.bwRgn();
- draw.fBitmap = &fBitmap; // canvas should have already called accessBitmap
- draw.fMatrix = &SkMatrix::I();
- this->drawSprite(draw, *sprite, x, y, paint);
+ SkImageInfo srcInfo = fBitmap.info();
+
+ // perhaps can relax these in the future
+ if (4 != dstInfo.bytesPerPixel()) {
+ return false;
+ }
+ if (4 != srcInfo.bytesPerPixel()) {
+ return false;
+ }
+
+ srcInfo.fWidth = dstInfo.width();
+ srcInfo.fHeight = dstInfo.height();
+
+ const void* srcPixels = fBitmap.getAddr(x, y);
+ const size_t srcRowBytes = fBitmap.rowBytes();
+
+ return copy_pixels(dstInfo, dstPixels, dstRowBytes, srcInfo, srcPixels, srcRowBytes);
}
///////////////////////////////////////////////////////////////////////////////
@@ -330,11 +381,11 @@ void SkBitmapDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
// construct a shader, so we can call drawRect with the dst
SkShader* s = SkShader::CreateBitmapShader(*bitmapPtr,
SkShader::kClamp_TileMode,
- SkShader::kClamp_TileMode);
+ SkShader::kClamp_TileMode,
+ &matrix);
if (NULL == s) {
return;
}
- s->setLocalMatrix(matrix);
SkPaint paintWithShader(paint);
paintWithShader.setStyle(SkPaint::kFill_Style);
@@ -384,6 +435,24 @@ void SkBitmapDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device,
draw.drawSprite(src, x, y, paint);
}
+SkSurface* SkBitmapDevice::newSurface(const SkImageInfo& info) {
+ return SkSurface::NewRaster(info);
+}
+
+const void* SkBitmapDevice::peekPixels(SkImageInfo* info, size_t* rowBytes) {
+ const SkImageInfo bmInfo = fBitmap.info();
+ if (fBitmap.getPixels() && (kUnknown_SkColorType != bmInfo.colorType())) {
+ if (info) {
+ *info = bmInfo;
+ }
+ if (rowBytes) {
+ *rowBytes = fBitmap.rowBytes();
+ }
+ return fBitmap.getPixels();
+ }
+ return NULL;
+}
+
///////////////////////////////////////////////////////////////////////////////
bool SkBitmapDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
@@ -392,7 +461,7 @@ bool SkBitmapDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
return false;
}
- if (SkBitmap::kARGB_8888_Config != fBitmap.config() ||
+ if (kN32_SkColorType != fBitmap.colorType() ||
paint.getRasterizer() ||
paint.getPathEffect() ||
paint.isFakeBoldText() ||
diff --git a/chromium/third_party/skia/src/core/SkBitmapFilter.cpp b/chromium/third_party/skia/src/core/SkBitmapFilter.cpp
index 8c11f7c4c5d..a9c3223fbc7 100644
--- a/chromium/third_party/skia/src/core/SkBitmapFilter.cpp
+++ b/chromium/third_party/skia/src/core/SkBitmapFilter.cpp
@@ -26,8 +26,8 @@ namespace {
template <typename Color, typename ColorPacker>
void highQualityFilter(ColorPacker pack, const SkBitmapProcState& s, int x, int y, Color* SK_RESTRICT colors, int count) {
- const int maxX = s.fBitmap->width() - 1;
- const int maxY = s.fBitmap->height() - 1;
+ const int maxX = s.fBitmap->width();
+ const int maxY = s.fBitmap->height();
while (count-- > 0) {
SkPoint srcPt;
@@ -123,8 +123,8 @@ bool SkBitmapProcState::setBitmapFilterProcs() {
return false;
}
- // TODO: consider supporting other configs (e.g. 565, A8)
- if (fBitmap->config() != SkBitmap::kARGB_8888_Config) {
+ // TODO: consider supporting other colortypes (e.g. 565, A8)
+ if (fBitmap->colorType() != kN32_SkColorType) {
return false;
}
diff --git a/chromium/third_party/skia/src/core/SkBitmapHeap.cpp b/chromium/third_party/skia/src/core/SkBitmapHeap.cpp
index 1f2f3dcf36e..efaa23fc64a 100644
--- a/chromium/third_party/skia/src/core/SkBitmapHeap.cpp
+++ b/chromium/third_party/skia/src/core/SkBitmapHeap.cpp
@@ -9,7 +9,8 @@
#include "SkBitmapHeap.h"
#include "SkBitmap.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkTSearch.h"
SkBitmapHeapEntry::SkBitmapHeapEntry()
@@ -35,15 +36,23 @@ void SkBitmapHeapEntry::addReferences(int count) {
///////////////////////////////////////////////////////////////////////////////
+static bool operator<(const SkIPoint& a, const SkIPoint& b) {
+ return *(const int64_t*)&a < *(const int64_t*)&b;
+}
+
+static bool operator>(const SkIPoint& a, const SkIPoint& b) {
+ return *(const int64_t*)&a > *(const int64_t*)&b;
+}
+
bool SkBitmapHeap::LookupEntry::Less(const SkBitmapHeap::LookupEntry& a,
const SkBitmapHeap::LookupEntry& b) {
if (a.fGenerationId < b.fGenerationId) {
return true;
} else if (a.fGenerationId > b.fGenerationId) {
return false;
- } else if (a.fPixelOffset < b.fPixelOffset) {
+ } else if (a.fPixelOrigin < b.fPixelOrigin) {
return true;
- } else if (a.fPixelOffset > b.fPixelOffset) {
+ } else if (a.fPixelOrigin > b.fPixelOrigin) {
return false;
} else if (a.fWidth < b.fWidth) {
return true;
@@ -256,7 +265,7 @@ bool SkBitmapHeap::copyBitmap(const SkBitmap& originalBitmap, SkBitmap& copiedBi
// copiedBitmap.setPixelRef(sharedPixelRef, originalBitmap.pixelRefOffset());
} else if (originalBitmap.empty()) {
copiedBitmap.reset();
- } else if (!originalBitmap.deepCopyTo(&copiedBitmap, originalBitmap.config())) {
+ } else if (!originalBitmap.deepCopyTo(&copiedBitmap)) {
return false;
}
copiedBitmap.setImmutable();
diff --git a/chromium/third_party/skia/src/core/SkBitmapHeap.h b/chromium/third_party/skia/src/core/SkBitmapHeap.h
index 2547eeec74a..56ed3584e81 100644
--- a/chromium/third_party/skia/src/core/SkBitmapHeap.h
+++ b/chromium/third_party/skia/src/core/SkBitmapHeap.h
@@ -111,7 +111,7 @@ public:
*/
SkBitmapHeap(ExternalStorage* externalStorage, int32_t heapSize = UNLIMITED_SIZE);
- ~SkBitmapHeap();
+ virtual ~SkBitmapHeap();
/**
* Makes a shallow copy of all bitmaps currently in the heap and returns them as an array. The
@@ -220,14 +220,14 @@ private:
struct LookupEntry {
LookupEntry(const SkBitmap& bm)
: fGenerationId(bm.getGenerationID())
- , fPixelOffset(bm.pixelRefOffset())
+ , fPixelOrigin(bm.pixelRefOrigin())
, fWidth(bm.width())
, fHeight(bm.height())
, fMoreRecentlyUsed(NULL)
, fLessRecentlyUsed(NULL){}
const uint32_t fGenerationId; // SkPixelRef GenerationID.
- const size_t fPixelOffset;
+ const SkIPoint fPixelOrigin;
const uint32_t fWidth;
const uint32_t fHeight;
diff --git a/chromium/third_party/skia/src/core/SkBitmapProcShader.cpp b/chromium/third_party/skia/src/core/SkBitmapProcShader.cpp
index bb161192763..8e03a804271 100644
--- a/chromium/third_party/skia/src/core/SkBitmapProcShader.cpp
+++ b/chromium/third_party/skia/src/core/SkBitmapProcShader.cpp
@@ -6,7 +6,8 @@
* found in the LICENSE file.
*/
#include "SkColorPriv.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkPixelRef.h"
#include "SkErrorInternals.h"
#include "SkBitmapProcShader.h"
@@ -17,11 +18,11 @@
#endif
bool SkBitmapProcShader::CanDo(const SkBitmap& bm, TileMode tx, TileMode ty) {
- switch (bm.config()) {
- case SkBitmap::kA8_Config:
- case SkBitmap::kRGB_565_Config:
- case SkBitmap::kIndex8_Config:
- case SkBitmap::kARGB_8888_Config:
+ switch (bm.colorType()) {
+ case kAlpha_8_SkColorType:
+ case kRGB_565_SkColorType:
+ case kIndex_8_SkColorType:
+ case kN32_SkColorType:
// if (tx == ty && (kClamp_TileMode == tx || kRepeat_TileMode == tx))
return true;
default:
@@ -30,21 +31,20 @@ bool SkBitmapProcShader::CanDo(const SkBitmap& bm, TileMode tx, TileMode ty) {
return false;
}
-SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src,
- TileMode tmx, TileMode tmy) {
+SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src, TileMode tmx, TileMode tmy,
+ const SkMatrix* localMatrix)
+ : INHERITED(localMatrix) {
fRawBitmap = src;
- fState.fTileModeX = (uint8_t)tmx;
- fState.fTileModeY = (uint8_t)tmy;
- fFlags = 0; // computed in setContext
+ fTileModeX = (uint8_t)tmx;
+ fTileModeY = (uint8_t)tmy;
}
-SkBitmapProcShader::SkBitmapProcShader(SkFlattenableReadBuffer& buffer)
+SkBitmapProcShader::SkBitmapProcShader(SkReadBuffer& buffer)
: INHERITED(buffer) {
buffer.readBitmap(&fRawBitmap);
fRawBitmap.setImmutable();
- fState.fTileModeX = buffer.readUInt();
- fState.fTileModeY = buffer.readUInt();
- fFlags = 0; // computed in setContext
+ fTileModeX = buffer.readUInt();
+ fTileModeY = buffer.readUInt();
}
SkShader::BitmapType SkBitmapProcShader::asABitmap(SkBitmap* texture,
@@ -57,18 +57,18 @@ SkShader::BitmapType SkBitmapProcShader::asABitmap(SkBitmap* texture,
texM->reset();
}
if (xy) {
- xy[0] = (TileMode)fState.fTileModeX;
- xy[1] = (TileMode)fState.fTileModeY;
+ xy[0] = (TileMode)fTileModeX;
+ xy[1] = (TileMode)fTileModeY;
}
return kDefault_BitmapType;
}
-void SkBitmapProcShader::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkBitmapProcShader::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeBitmap(fRawBitmap);
- buffer.writeUInt(fState.fTileModeX);
- buffer.writeUInt(fState.fTileModeY);
+ buffer.writeUInt(fTileModeX);
+ buffer.writeUInt(fTileModeY);
}
static bool only_scale_and_translate(const SkMatrix& matrix) {
@@ -87,7 +87,7 @@ static bool valid_for_drawing(const SkBitmap& bm) {
if (NULL == bm.pixelRef()) {
return false; // no pixels to read
}
- if (SkBitmap::kIndex8_Config == bm.config()) {
+ if (kIndex_8_SkColorType == bm.colorType()) {
// ugh, I have to lock-pixels to inspect the colortable
SkAutoLockPixels alp(bm);
if (!bm.getColorTable()) {
@@ -97,25 +97,44 @@ static bool valid_for_drawing(const SkBitmap& bm) {
return true;
}
-bool SkBitmapProcShader::setContext(const SkBitmap& device,
- const SkPaint& paint,
- const SkMatrix& matrix) {
+SkShader::Context* SkBitmapProcShader::onCreateContext(const ContextRec& rec, void* storage) const {
if (!fRawBitmap.getTexture() && !valid_for_drawing(fRawBitmap)) {
- return false;
+ return NULL;
}
- // do this first, so we have a correct inverse matrix
- if (!this->INHERITED::setContext(device, paint, matrix)) {
- return false;
+ SkMatrix totalInverse;
+ // Do this first, so we know the matrix can be inverted.
+ if (!this->computeTotalInverse(rec, &totalInverse)) {
+ return NULL;
}
- fState.fOrigBitmap = fRawBitmap;
- if (!fState.chooseProcs(this->getTotalInverse(), paint)) {
- this->INHERITED::endContext();
- return false;
+ void* stateStorage = (char*)storage + sizeof(BitmapProcShaderContext);
+ SkBitmapProcState* state = SkNEW_PLACEMENT(stateStorage, SkBitmapProcState);
+
+ SkASSERT(state);
+ state->fTileModeX = fTileModeX;
+ state->fTileModeY = fTileModeY;
+ state->fOrigBitmap = fRawBitmap;
+ if (!state->chooseProcs(totalInverse, *rec.fPaint)) {
+ state->~SkBitmapProcState();
+ return NULL;
}
- const SkBitmap& bitmap = *fState.fBitmap;
+ return SkNEW_PLACEMENT_ARGS(storage, BitmapProcShaderContext, (*this, rec, state));
+}
+
+size_t SkBitmapProcShader::contextSize() const {
+ // The SkBitmapProcState is stored outside of the context object, with the context holding
+ // a pointer to it.
+ return sizeof(BitmapProcShaderContext) + sizeof(SkBitmapProcState);
+}
+
+SkBitmapProcShader::BitmapProcShaderContext::BitmapProcShaderContext(
+ const SkBitmapProcShader& shader, const ContextRec& rec, SkBitmapProcState* state)
+ : INHERITED(shader, rec)
+ , fState(state)
+{
+ const SkBitmap& bitmap = *fState->fBitmap;
bool bitmapIsOpaque = bitmap.isOpaque();
// update fFlags
@@ -124,23 +143,23 @@ bool SkBitmapProcShader::setContext(const SkBitmap& device,
flags |= kOpaqueAlpha_Flag;
}
- switch (bitmap.config()) {
- case SkBitmap::kRGB_565_Config:
+ switch (bitmap.colorType()) {
+ case kRGB_565_SkColorType:
flags |= (kHasSpan16_Flag | kIntrinsicly16_Flag);
break;
- case SkBitmap::kIndex8_Config:
- case SkBitmap::kARGB_8888_Config:
+ case kIndex_8_SkColorType:
+ case kN32_SkColorType:
if (bitmapIsOpaque) {
flags |= kHasSpan16_Flag;
}
break;
- case SkBitmap::kA8_Config:
+ case kAlpha_8_SkColorType:
break; // never set kHasSpan16_Flag
default:
break;
}
- if (paint.isDither() && bitmap.config() != SkBitmap::kRGB_565_Config) {
+ if (rec.fPaint->isDither() && bitmap.colorType() != kRGB_565_SkColorType) {
// gradients can auto-dither in their 16bit sampler, but we don't so
// we clear the flag here.
flags &= ~kHasSpan16_Flag;
@@ -156,12 +175,12 @@ bool SkBitmapProcShader::setContext(const SkBitmap& device,
}
fFlags = flags;
- return true;
}
-void SkBitmapProcShader::endContext() {
- fState.endContext();
- this->INHERITED::endContext();
+SkBitmapProcShader::BitmapProcShaderContext::~BitmapProcShaderContext() {
+ // The bitmap proc state has been created outside of the context on memory that will be freed
+ // elsewhere. Only call the destructor but leave the freeing of the memory to the caller.
+ fState->~SkBitmapProcState();
}
#define BUF_MAX 128
@@ -175,8 +194,9 @@ void SkBitmapProcShader::endContext() {
#define TEST_BUFFER_EXTRA 0
#endif
-void SkBitmapProcShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
- const SkBitmapProcState& state = fState;
+void SkBitmapProcShader::BitmapProcShaderContext::shadeSpan(int x, int y, SkPMColor dstC[],
+ int count) {
+ const SkBitmapProcState& state = *fState;
if (state.getShaderProc32()) {
state.getShaderProc32()(state, x, y, dstC, count);
return;
@@ -185,7 +205,7 @@ void SkBitmapProcShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
uint32_t buffer[BUF_MAX + TEST_BUFFER_EXTRA];
SkBitmapProcState::MatrixProc mproc = state.getMatrixProc();
SkBitmapProcState::SampleProc32 sproc = state.getSampleProc32();
- int max = fState.maxCountForBufferSize(sizeof(buffer[0]) * BUF_MAX);
+ int max = state.maxCountForBufferSize(sizeof(buffer[0]) * BUF_MAX);
SkASSERT(state.fBitmap->getPixels());
SkASSERT(state.fBitmap->pixelRef() == NULL ||
@@ -219,16 +239,17 @@ void SkBitmapProcShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
}
}
-SkShader::ShadeProc SkBitmapProcShader::asAShadeProc(void** ctx) {
- if (fState.getShaderProc32()) {
- *ctx = &fState;
- return (ShadeProc)fState.getShaderProc32();
+SkShader::Context::ShadeProc SkBitmapProcShader::BitmapProcShaderContext::asAShadeProc(void** ctx) {
+ if (fState->getShaderProc32()) {
+ *ctx = fState;
+ return (ShadeProc)fState->getShaderProc32();
}
return NULL;
}
-void SkBitmapProcShader::shadeSpan16(int x, int y, uint16_t dstC[], int count) {
- const SkBitmapProcState& state = fState;
+void SkBitmapProcShader::BitmapProcShaderContext::shadeSpan16(int x, int y, uint16_t dstC[],
+ int count) {
+ const SkBitmapProcState& state = *fState;
if (state.getShaderProc16()) {
state.getShaderProc16()(state, x, y, dstC, count);
return;
@@ -237,7 +258,7 @@ void SkBitmapProcShader::shadeSpan16(int x, int y, uint16_t dstC[], int count) {
uint32_t buffer[BUF_MAX];
SkBitmapProcState::MatrixProc mproc = state.getMatrixProc();
SkBitmapProcState::SampleProc16 sproc = state.getSampleProc16();
- int max = fState.maxCountForBufferSize(sizeof(buffer));
+ int max = state.maxCountForBufferSize(sizeof(buffer));
SkASSERT(state.fBitmap->getPixels());
SkASSERT(state.fBitmap->pixelRef() == NULL ||
@@ -277,14 +298,14 @@ static bool canUseColorShader(const SkBitmap& bm, SkColor* color) {
return false;
}
- switch (bm.config()) {
- case SkBitmap::kARGB_8888_Config:
+ switch (bm.colorType()) {
+ case kN32_SkColorType:
*color = SkUnPreMultiply::PMColorToColor(*bm.getAddr32(0, 0));
return true;
- case SkBitmap::kRGB_565_Config:
+ case kRGB_565_SkColorType:
*color = SkPixel16ToColor(*bm.getAddr16(0, 0));
return true;
- case SkBitmap::kIndex8_Config:
+ case kIndex_8_SkColorType:
*color = SkUnPreMultiply::PMColorToColor(bm.getIndex8Color(0, 0));
return true;
default: // just skip the other configs for now
@@ -293,8 +314,6 @@ static bool canUseColorShader(const SkBitmap& bm, SkColor* color) {
return false;
}
-#include "SkTemplatesPriv.h"
-
static bool bitmapIsTooBig(const SkBitmap& bm) {
// SkBitmapProcShader stores bitmap coordinates in a 16bit buffer, as it
// communicates between its matrix-proc and its sampler-proc. Until we can
@@ -305,27 +324,36 @@ static bool bitmapIsTooBig(const SkBitmap& bm) {
return bm.width() > maxSize || bm.height() > maxSize;
}
-SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
- TileMode tmx, TileMode tmy,
- void* storage, size_t storageSize) {
+SkShader* CreateBitmapShader(const SkBitmap& src, SkShader::TileMode tmx,
+ SkShader::TileMode tmy, const SkMatrix* localMatrix, SkTBlitterAllocator* allocator) {
SkShader* shader;
SkColor color;
if (src.isNull() || bitmapIsTooBig(src)) {
- SK_PLACEMENT_NEW(shader, SkEmptyShader, storage, storageSize);
+ if (NULL == allocator) {
+ shader = SkNEW(SkEmptyShader);
+ } else {
+ shader = allocator->createT<SkEmptyShader>();
+ }
}
else if (canUseColorShader(src, &color)) {
- SK_PLACEMENT_NEW_ARGS(shader, SkColorShader, storage, storageSize,
- (color));
+ if (NULL == allocator) {
+ shader = SkNEW_ARGS(SkColorShader, (color));
+ } else {
+ shader = allocator->createT<SkColorShader>(color);
+ }
} else {
- SK_PLACEMENT_NEW_ARGS(shader, SkBitmapProcShader, storage,
- storageSize, (src, tmx, tmy));
+ if (NULL == allocator) {
+ shader = SkNEW_ARGS(SkBitmapProcShader, (src, tmx, tmy, localMatrix));
+ } else {
+ shader = allocator->createT<SkBitmapProcShader>(src, tmx, tmy, localMatrix);
+ }
}
return shader;
}
///////////////////////////////////////////////////////////////////////////////
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkBitmapProcShader::toString(SkString* str) const {
static const char* gTileModeName[SkShader::kTileModeCount] = {
"clamp", "repeat", "mirror"
@@ -334,8 +362,8 @@ void SkBitmapProcShader::toString(SkString* str) const {
str->append("BitmapShader: (");
str->appendf("(%s, %s)",
- gTileModeName[fState.fTileModeX],
- gTileModeName[fState.fTileModeY]);
+ gTileModeName[fTileModeX],
+ gTileModeName[fTileModeY]);
str->append(" ");
fRawBitmap.toString(str);
@@ -354,51 +382,60 @@ void SkBitmapProcShader::toString(SkString* str) const {
#include "effects/GrSimpleTextureEffect.h"
#include "SkGr.h"
-GrEffectRef* SkBitmapProcShader::asNewEffect(GrContext* context, const SkPaint& paint) const {
+bool SkBitmapProcShader::asNewEffect(GrContext* context, const SkPaint& paint,
+ const SkMatrix* localMatrix, GrColor* grColor,
+ GrEffectRef** grEffect) const {
SkMatrix matrix;
matrix.setIDiv(fRawBitmap.width(), fRawBitmap.height());
- SkMatrix inverse;
- if (!this->getLocalMatrix().invert(&inverse)) {
- return NULL;
+ SkMatrix lmInverse;
+ if (!this->getLocalMatrix().invert(&lmInverse)) {
+ return false;
}
- matrix.preConcat(inverse);
+ if (localMatrix) {
+ SkMatrix inv;
+ if (!localMatrix->invert(&inv)) {
+ return false;
+ }
+ lmInverse.postConcat(inv);
+ }
+ matrix.preConcat(lmInverse);
SkShader::TileMode tm[] = {
- (TileMode)fState.fTileModeX,
- (TileMode)fState.fTileModeY,
+ (TileMode)fTileModeX,
+ (TileMode)fTileModeY,
};
- // Must set wrap and filter on the sampler before requesting a texture.
- SkPaint::FilterLevel paintFilterLevel = paint.getFilterLevel();
+ // Must set wrap and filter on the sampler before requesting a texture. In two places below
+ // we check the matrix scale factors to determine how to interpret the filter quality setting.
+ // This completely ignores the complexity of the drawVertices case where explicit local coords
+ // are provided by the caller.
+ bool useBicubic = false;
GrTextureParams::FilterMode textureFilterMode;
- switch(paintFilterLevel) {
+ switch(paint.getFilterLevel()) {
case SkPaint::kNone_FilterLevel:
textureFilterMode = GrTextureParams::kNone_FilterMode;
break;
case SkPaint::kLow_FilterLevel:
textureFilterMode = GrTextureParams::kBilerp_FilterMode;
break;
- case SkPaint::kMedium_FilterLevel:
- textureFilterMode = GrTextureParams::kMipMap_FilterMode;
- break;
- case SkPaint::kHigh_FilterLevel:
- // Minification can look bad with the bicubic effect. This is an overly aggressive
- // check for MIP fallbacks. It doesn't consider the fact that minification in the local
- // matrix could be offset by the view matrix and vice versa. We also don't know whether
- // the draw has explicit local coords (e.g. drawVertices) where the scale factor is
- // unknown and varies.
- if (context->getMatrix().getMinStretch() >= SK_Scalar1 &&
- this->getLocalMatrix().getMaxStretch() <= SK_Scalar1) {
- // fall back to no filtering here; we will install another
- // shader that will do the HQ filtering.
- textureFilterMode = GrTextureParams::kNone_FilterMode;
- } else {
- // Fall back to mip-mapping.
- paintFilterLevel = SkPaint::kMedium_FilterLevel;
+ case SkPaint::kMedium_FilterLevel: {
+ SkMatrix matrix;
+ matrix.setConcat(context->getMatrix(), this->getLocalMatrix());
+ if (matrix.getMinScale() < SK_Scalar1) {
textureFilterMode = GrTextureParams::kMipMap_FilterMode;
+ } else {
+ // Don't trigger MIP level generation unnecessarily.
+ textureFilterMode = GrTextureParams::kBilerp_FilterMode;
}
break;
+ }
+ case SkPaint::kHigh_FilterLevel: {
+ SkMatrix matrix;
+ matrix.setConcat(context->getMatrix(), this->getLocalMatrix());
+ useBicubic = GrBicubicEffect::ShouldUseBicubic(matrix, &textureFilterMode);
+ break;
+ }
default:
SkErrorInternals::SetError( kInvalidPaint_SkError,
"Sorry, I don't understand the filtering "
@@ -414,16 +451,29 @@ GrEffectRef* SkBitmapProcShader::asNewEffect(GrContext* context, const SkPaint&
if (NULL == texture) {
SkErrorInternals::SetError( kInternalError_SkError,
"Couldn't convert bitmap to texture.");
- return NULL;
+ return false;
}
+
+ *grColor = (kAlpha_8_SkColorType == fRawBitmap.colorType()) ? SkColor2GrColor(paint.getColor())
+ : SkColor2GrColorJustAlpha(paint.getColor());
- GrEffectRef* effect = NULL;
- if (paintFilterLevel == SkPaint::kHigh_FilterLevel) {
- effect = GrBicubicEffect::Create(texture, matrix, tm);
+ if (useBicubic) {
+ *grEffect = GrBicubicEffect::Create(texture, matrix, tm);
} else {
- effect = GrSimpleTextureEffect::Create(texture, matrix, params);
+ *grEffect = GrSimpleTextureEffect::Create(texture, matrix, params);
}
GrUnlockAndUnrefCachedBitmapTexture(texture);
- return effect;
+
+ return true;
}
+
+#else
+
+bool SkBitmapProcShader::asNewEffect(GrContext* context, const SkPaint& paint,
+ const SkMatrix* localMatrix, GrColor* grColor,
+ GrEffectRef** grEffect) const {
+ SkDEBUGFAIL("Should not call in GPU-less build");
+ return false;
+}
+
#endif
diff --git a/chromium/third_party/skia/src/core/SkBitmapProcShader.h b/chromium/third_party/skia/src/core/SkBitmapProcShader.h
index 5a599c3b924..08e8397a735 100644
--- a/chromium/third_party/skia/src/core/SkBitmapProcShader.h
+++ b/chromium/third_party/skia/src/core/SkBitmapProcShader.h
@@ -12,40 +12,70 @@
#include "SkShader.h"
#include "SkBitmapProcState.h"
+#include "SkSmallAllocator.h"
class SkBitmapProcShader : public SkShader {
public:
- SkBitmapProcShader(const SkBitmap& src, TileMode tx, TileMode ty);
+ SkBitmapProcShader(const SkBitmap& src, TileMode tx, TileMode ty,
+ const SkMatrix* localMatrix = NULL);
// overrides from SkShader
virtual bool isOpaque() const SK_OVERRIDE;
- virtual bool setContext(const SkBitmap&, const SkPaint&, const SkMatrix&) SK_OVERRIDE;
- virtual void endContext() SK_OVERRIDE;
- virtual uint32_t getFlags() SK_OVERRIDE { return fFlags; }
- virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE;
- virtual ShadeProc asAShadeProc(void** ctx) SK_OVERRIDE;
- virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count) SK_OVERRIDE;
virtual BitmapType asABitmap(SkBitmap*, SkMatrix*, TileMode*) const SK_OVERRIDE;
+ virtual size_t contextSize() const SK_OVERRIDE;
+
static bool CanDo(const SkBitmap&, TileMode tx, TileMode ty);
- SK_DEVELOPER_TO_STRING()
+ SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBitmapProcShader)
-#if SK_SUPPORT_GPU
- GrEffectRef* asNewEffect(GrContext*, const SkPaint&) const SK_OVERRIDE;
-#endif
+
+ bool asNewEffect(GrContext*, const SkPaint&, const SkMatrix*, GrColor*, GrEffectRef**)
+ const SK_OVERRIDE;
+
+ class BitmapProcShaderContext : public SkShader::Context {
+ public:
+ // The context takes ownership of the state. It will call its destructor
+ // but will NOT free the memory.
+ BitmapProcShaderContext(const SkBitmapProcShader&, const ContextRec&, SkBitmapProcState*);
+ virtual ~BitmapProcShaderContext();
+
+ virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE;
+ virtual ShadeProc asAShadeProc(void** ctx) SK_OVERRIDE;
+ virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count) SK_OVERRIDE;
+
+ virtual uint32_t getFlags() const SK_OVERRIDE { return fFlags; }
+
+ private:
+ SkBitmapProcState* fState;
+ uint32_t fFlags;
+
+ typedef SkShader::Context INHERITED;
+ };
protected:
- SkBitmapProcShader(SkFlattenableReadBuffer& );
- virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+ SkBitmapProcShader(SkReadBuffer& );
+ virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
+ virtual Context* onCreateContext(const ContextRec&, void* storage) const SK_OVERRIDE;
- SkBitmap fRawBitmap; // experimental for RLE encoding
- SkBitmapProcState fState;
- uint32_t fFlags;
+ SkBitmap fRawBitmap; // experimental for RLE encoding
+ uint8_t fTileModeX, fTileModeY;
private:
typedef SkShader INHERITED;
};
+// Commonly used allocator. It currently is only used to allocate up to 3 objects. The total
+// bytes requested is calculated using one of our large shaders, its context size plus the size of
+// an Sk3DBlitter in SkDraw.cpp
+// Note that some contexts may contain other contexts (e.g. for compose shaders), but we've not
+// yet found a situation where the size below isn't big enough.
+typedef SkSmallAllocator<3, 768> SkTBlitterAllocator;
+
+// If alloc is non-NULL, it will be used to allocate the returned SkShader, and MUST outlive
+// the SkShader.
+SkShader* CreateBitmapShader(const SkBitmap& src, SkShader::TileMode, SkShader::TileMode,
+ const SkMatrix* localMatrix, SkTBlitterAllocator* alloc);
+
#endif
diff --git a/chromium/third_party/skia/src/core/SkBitmapProcState.cpp b/chromium/third_party/skia/src/core/SkBitmapProcState.cpp
index cdc582bfeec..f6f9f3fa06c 100644
--- a/chromium/third_party/skia/src/core/SkBitmapProcState.cpp
+++ b/chromium/third_party/skia/src/core/SkBitmapProcState.cpp
@@ -15,6 +15,7 @@
#include "SkMipMap.h"
#include "SkPixelRef.h"
#include "SkScaledImageCache.h"
+#include "SkImageEncoder.h"
#if !SK_ARM_NEON_IS_NONE
// These are defined in src/opts/SkBitmapProcState_arm_neon.cpp
@@ -146,7 +147,7 @@ bool SkBitmapProcState::possiblyScaleImage() {
if (SkPaint::kHigh_FilterLevel == fFilterLevel &&
fInvMatrix.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask) &&
- fOrigBitmap.config() == SkBitmap::kARGB_8888_Config) {
+ kN32_SkColorType == fOrigBitmap.colorType()) {
SkScalar invScaleX = fInvMatrix.getScaleX();
SkScalar invScaleY = fInvMatrix.getScaleY();
@@ -166,8 +167,8 @@ bool SkBitmapProcState::possiblyScaleImage() {
}
if (NULL == fScaledCacheID) {
- int dest_width = SkScalarCeilToInt(fOrigBitmap.width() / invScaleX);
- int dest_height = SkScalarCeilToInt(fOrigBitmap.height() / invScaleY);
+ float dest_width = fOrigBitmap.width() / invScaleX;
+ float dest_height = fOrigBitmap.height() / invScaleY;
// All the criteria are met; let's make a new bitmap.
@@ -187,6 +188,7 @@ bool SkBitmapProcState::possiblyScaleImage() {
return false;
}
+
SkASSERT(NULL != fScaledBitmap.getPixels());
fScaledCacheID = SkScaledImageCache::AddAndLock(fOrigBitmap,
invScaleX,
@@ -263,6 +265,7 @@ bool SkBitmapProcState::possiblyScaleImage() {
if (mip) {
fScaledCacheID = SkScaledImageCache::AddAndLockMip(fOrigBitmap,
mip);
+ SkASSERT(mip->getRefCnt() > 1);
mip->unref(); // the cache took a ref
SkASSERT(fScaledCacheID);
}
@@ -277,10 +280,10 @@ bool SkBitmapProcState::possiblyScaleImage() {
SkScalar invScaleFixup = level.fScale;
fInvMatrix.postScale(invScaleFixup, invScaleFixup);
- fScaledBitmap.setConfig(fOrigBitmap.config(),
- level.fWidth, level.fHeight,
- level.fRowBytes);
- fScaledBitmap.setPixels(level.fPixels);
+ SkImageInfo info = fOrigBitmap.info();
+ info.fWidth = level.fWidth;
+ info.fHeight = level.fHeight;
+ fScaledBitmap.installPixels(info, level.fPixels, level.fRowBytes);
fBitmap = &fScaledBitmap;
fFilterLevel = SkPaint::kLow_FilterLevel;
unlocker.release();
@@ -359,17 +362,6 @@ bool SkBitmapProcState::lockBaseBitmap() {
return true;
}
-void SkBitmapProcState::endContext() {
- SkDELETE(fBitmapFilter);
- fBitmapFilter = NULL;
- fScaledBitmap.reset();
-
- if (fScaledCacheID) {
- SkScaledImageCache::Unlock(fScaledCacheID);
- fScaledCacheID = NULL;
- }
-}
-
SkBitmapProcState::~SkBitmapProcState() {
if (fScaledCacheID) {
SkScaledImageCache::Unlock(fScaledCacheID);
@@ -398,10 +390,17 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
}
// The above logic should have always assigned fBitmap, but in case it
// didn't, we check for that now...
+ // TODO(dominikg): Ask humper@ if we can just use an SkASSERT(fBitmap)?
if (NULL == fBitmap) {
return false;
}
+ // If we are "still" kMedium_FilterLevel, then the request was not fulfilled by possiblyScale,
+ // so we downgrade to kLow (so the rest of the sniffing code can assume that)
+ if (SkPaint::kMedium_FilterLevel == fFilterLevel) {
+ fFilterLevel = SkPaint::kLow_FilterLevel;
+ }
+
bool trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0;
bool clampClamp = SkShader::kClamp_TileMode == fTileModeX &&
SkShader::kClamp_TileMode == fTileModeY;
@@ -480,6 +479,7 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
// shader will perform.
fMatrixProc = this->chooseMatrixProc(trivialMatrix);
+ // TODO(dominikg): SkASSERT(fMatrixProc) instead? chooseMatrixProc never returns NULL.
if (NULL == fMatrixProc) {
return false;
}
@@ -503,24 +503,25 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
index |= 4;
}
// bits 3,4,5 encoding the source bitmap format
- switch (fBitmap->config()) {
- case SkBitmap::kARGB_8888_Config:
+ switch (fBitmap->colorType()) {
+ case kN32_SkColorType:
index |= 0;
break;
- case SkBitmap::kRGB_565_Config:
+ case kRGB_565_SkColorType:
index |= 8;
break;
- case SkBitmap::kIndex8_Config:
+ case kIndex_8_SkColorType:
index |= 16;
break;
- case SkBitmap::kARGB_4444_Config:
+ case kARGB_4444_SkColorType:
index |= 24;
break;
- case SkBitmap::kA8_Config:
+ case kAlpha_8_SkColorType:
index |= 32;
fPaintPMColor = SkPreMultiplyColor(paint.getColor());
break;
default:
+ // TODO(dominikg): Should we ever get here? SkASSERT(false) instead?
return false;
}
@@ -880,7 +881,7 @@ bool SkBitmapProcState::setupForTranslate() {
SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() {
- if (SkBitmap::kARGB_8888_Config != fBitmap->config()) {
+ if (kN32_SkColorType != fBitmap->colorType()) {
return NULL;
}
diff --git a/chromium/third_party/skia/src/core/SkBitmapProcState.h b/chromium/third_party/skia/src/core/SkBitmapProcState.h
index d5a354e36ac..663bcb8be91 100644
--- a/chromium/third_party/skia/src/core/SkBitmapProcState.h
+++ b/chromium/third_party/skia/src/core/SkBitmapProcState.h
@@ -89,12 +89,6 @@ struct SkBitmapProcState {
uint8_t fTileModeY; // CONSTRUCTOR
uint8_t fFilterLevel; // chooseProcs
- /** The shader will let us know when we can release some of our resources
- * like scaled bitmaps.
- */
-
- void endContext();
-
/** Platforms implement this, and can optionally overwrite only the
following fields:
diff --git a/chromium/third_party/skia/src/core/SkBitmapProcState_filter.h b/chromium/third_party/skia/src/core/SkBitmapProcState_filter.h
index 12606656dd8..99f40eca560 100644
--- a/chromium/third_party/skia/src/core/SkBitmapProcState_filter.h
+++ b/chromium/third_party/skia/src/core/SkBitmapProcState_filter.h
@@ -26,7 +26,7 @@ static inline void Filter_32_opaque(unsigned x, unsigned y,
SkASSERT((unsigned)y <= 0xF);
int xy = x * y;
- static const uint32_t mask = gMask_00FF00FF; //0xFF00FF;
+ const uint32_t mask = 0xFF00FF;
int scale = 256 - 16*y - 16*x + xy;
uint32_t lo = (a00 & mask) * scale;
@@ -56,7 +56,7 @@ static inline void Filter_32_alpha(unsigned x, unsigned y,
SkASSERT(alphaScale <= 256);
int xy = x * y;
- static const uint32_t mask = gMask_00FF00FF; //0xFF00FF;
+ const uint32_t mask = 0xFF00FF;
int scale = 256 - 16*y - 16*x + xy;
uint32_t lo = (a00 & mask) * scale;
@@ -86,7 +86,7 @@ static inline void Filter_32_opaque(unsigned t,
SkPMColor* dstColor) {
SkASSERT((unsigned)t <= 0xF);
- static const uint32_t mask = gMask_00FF00FF; //0x00FF00FF;
+ const uint32_t mask = 0xFF00FF;
int scale = 256 - 16*t;
uint32_t lo = (color0 & mask) * scale;
@@ -108,7 +108,7 @@ static inline void Filter_32_alpha(unsigned t,
SkASSERT((unsigned)t <= 0xF);
SkASSERT(alphaScale <= 256);
- static const uint32_t mask = gMask_00FF00FF; //0x00FF00FF;
+ const uint32_t mask = 0xFF00FF;
int scale = 256 - 16*t;
uint32_t lo = (color0 & mask) * scale;
diff --git a/chromium/third_party/skia/src/core/SkBitmapProcState_matrix.h b/chromium/third_party/skia/src/core/SkBitmapProcState_matrix.h
index d796d0b04c4..b71c3c3b75d 100644
--- a/chromium/third_party/skia/src/core/SkBitmapProcState_matrix.h
+++ b/chromium/third_party/skia/src/core/SkBitmapProcState_matrix.h
@@ -9,11 +9,8 @@
#include "SkMath.h"
#include "SkMathPriv.h"
-#define SCALE_NOFILTER_NAME MAKENAME(_nofilter_scale)
#define SCALE_FILTER_NAME MAKENAME(_filter_scale)
-#define AFFINE_NOFILTER_NAME MAKENAME(_nofilter_affine)
#define AFFINE_FILTER_NAME MAKENAME(_filter_affine)
-#define PERSP_NOFILTER_NAME MAKENAME(_nofilter_persp)
#define PERSP_FILTER_NAME MAKENAME(_filter_persp)
#define PACK_FILTER_X_NAME MAKENAME(_pack_filter_x)
@@ -28,13 +25,6 @@
#endif
// declare functions externally to suppress warnings.
-void SCALE_NOFILTER_NAME(const SkBitmapProcState& s,
- uint32_t xy[], int count, int x, int y);
-void AFFINE_NOFILTER_NAME(const SkBitmapProcState& s,
- uint32_t xy[], int count, int x, int y);
-void PERSP_NOFILTER_NAME(const SkBitmapProcState& s,
- uint32_t* SK_RESTRICT xy,
- int count, int x, int y);
void SCALE_FILTER_NAME(const SkBitmapProcState& s,
uint32_t xy[], int count, int x, int y);
void AFFINE_FILTER_NAME(const SkBitmapProcState& s,
@@ -43,122 +33,6 @@ void PERSP_FILTER_NAME(const SkBitmapProcState& s,
uint32_t* SK_RESTRICT xy, int count,
int x, int y);
-void SCALE_NOFILTER_NAME(const SkBitmapProcState& s,
- uint32_t xy[], int count, int x, int y) {
- SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
- SkMatrix::kScale_Mask)) == 0);
-
- PREAMBLE(s);
- // we store y, x, x, x, x, x
-
- const unsigned maxX = s.fBitmap->width() - 1;
- SkFractionalInt fx;
- {
- SkPoint pt;
- s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, &pt);
- fx = SkScalarToFractionalInt(pt.fY);
- const unsigned maxY = s.fBitmap->height() - 1;
- *xy++ = TILEY_PROCF(SkFractionalIntToFixed(fx), maxY);
- fx = SkScalarToFractionalInt(pt.fX);
- }
-
- if (0 == maxX) {
- // all of the following X values must be 0
- memset(xy, 0, count * sizeof(uint16_t));
- return;
- }
-
- const SkFractionalInt dx = s.fInvSxFractionalInt;
-
-#ifdef CHECK_FOR_DECAL
- if (can_truncate_to_fixed_for_decal(fx, dx, count, maxX)) {
- decal_nofilter_scale(xy, SkFractionalIntToFixed(fx),
- SkFractionalIntToFixed(dx), count);
- } else
-#endif
- {
- int i;
- for (i = (count >> 2); i > 0; --i) {
- unsigned a, b;
- a = TILEX_PROCF(SkFractionalIntToFixed(fx), maxX); fx += dx;
- b = TILEX_PROCF(SkFractionalIntToFixed(fx), maxX); fx += dx;
-#ifdef SK_CPU_BENDIAN
- *xy++ = (a << 16) | b;
-#else
- *xy++ = (b << 16) | a;
-#endif
- a = TILEX_PROCF(SkFractionalIntToFixed(fx), maxX); fx += dx;
- b = TILEX_PROCF(SkFractionalIntToFixed(fx), maxX); fx += dx;
-#ifdef SK_CPU_BENDIAN
- *xy++ = (a << 16) | b;
-#else
- *xy++ = (b << 16) | a;
-#endif
- }
- uint16_t* xx = (uint16_t*)xy;
- for (i = (count & 3); i > 0; --i) {
- *xx++ = TILEX_PROCF(SkFractionalIntToFixed(fx), maxX); fx += dx;
- }
- }
-}
-
-// note: we could special-case on a matrix which is skewed in X but not Y.
-// this would require a more general setup thatn SCALE does, but could use
-// SCALE's inner loop that only looks at dx
-
-void AFFINE_NOFILTER_NAME(const SkBitmapProcState& s,
- uint32_t xy[], int count, int x, int y) {
- SkASSERT(s.fInvType & SkMatrix::kAffine_Mask);
- SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
- SkMatrix::kScale_Mask |
- SkMatrix::kAffine_Mask)) == 0);
-
- PREAMBLE(s);
- SkPoint srcPt;
- s.fInvProc(s.fInvMatrix,
- SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
-
- SkFractionalInt fx = SkScalarToFractionalInt(srcPt.fX);
- SkFractionalInt fy = SkScalarToFractionalInt(srcPt.fY);
- SkFractionalInt dx = s.fInvSxFractionalInt;
- SkFractionalInt dy = s.fInvKyFractionalInt;
- int maxX = s.fBitmap->width() - 1;
- int maxY = s.fBitmap->height() - 1;
-
- for (int i = count; i > 0; --i) {
- *xy++ = (TILEY_PROCF(SkFractionalIntToFixed(fy), maxY) << 16) |
- TILEX_PROCF(SkFractionalIntToFixed(fx), maxX);
- fx += dx; fy += dy;
- }
-}
-
-void PERSP_NOFILTER_NAME(const SkBitmapProcState& s,
- uint32_t* SK_RESTRICT xy,
- int count, int x, int y) {
- SkASSERT(s.fInvType & SkMatrix::kPerspective_Mask);
-
- PREAMBLE(s);
- int maxX = s.fBitmap->width() - 1;
- int maxY = s.fBitmap->height() - 1;
-
- SkPerspIter iter(s.fInvMatrix,
- SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, count);
-
- while ((count = iter.next()) != 0) {
- const SkFixed* SK_RESTRICT srcXY = iter.getXY();
- while (--count >= 0) {
- *xy++ = (TILEY_PROCF(srcXY[1], maxY) << 16) |
- TILEX_PROCF(srcXY[0], maxX);
- srcXY += 2;
- }
- }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
static inline uint32_t PACK_FILTER_Y_NAME(SkFixed f, unsigned max,
SkFixed one PREAMBLE_PARAM_Y) {
unsigned i = TILEY_PROCF(f, max);
@@ -270,15 +144,6 @@ void PERSP_FILTER_NAME(const SkBitmapProcState& s,
}
}
-static SkBitmapProcState::MatrixProc MAKENAME(_Procs)[] = {
- SCALE_NOFILTER_NAME,
- SCALE_FILTER_NAME,
- AFFINE_NOFILTER_NAME,
- AFFINE_FILTER_NAME,
- PERSP_NOFILTER_NAME,
- PERSP_FILTER_NAME
-};
-
#undef MAKENAME
#undef TILEX_PROCF
#undef TILEY_PROCF
@@ -286,11 +151,8 @@ static SkBitmapProcState::MatrixProc MAKENAME(_Procs)[] = {
#undef CHECK_FOR_DECAL
#endif
-#undef SCALE_NOFILTER_NAME
#undef SCALE_FILTER_NAME
-#undef AFFINE_NOFILTER_NAME
#undef AFFINE_FILTER_NAME
-#undef PERSP_NOFILTER_NAME
#undef PERSP_FILTER_NAME
#undef PREAMBLE
diff --git a/chromium/third_party/skia/src/core/SkBitmapProcState_matrixProcs.cpp b/chromium/third_party/skia/src/core/SkBitmapProcState_matrixProcs.cpp
index 57376d5699d..02204b676b2 100644
--- a/chromium/third_party/skia/src/core/SkBitmapProcState_matrixProcs.cpp
+++ b/chromium/third_party/skia/src/core/SkBitmapProcState_matrixProcs.cpp
@@ -33,6 +33,10 @@ static inline int sk_int_mod(int x, int n) {
void decal_nofilter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count);
void decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count);
+#include "SkBitmapProcState_matrix_template.h"
+
+///////////////////////////////////////////////////////////////////////////////
+
// Compile neon code paths if needed
#if !SK_ARM_NEON_IS_NONE
@@ -52,12 +56,59 @@ extern const SkBitmapProcState::MatrixProc RepeatX_RepeatY_Procs_neon[];
#define CHECK_FOR_DECAL
#include "SkBitmapProcState_matrix.h"
+struct ClampTileProcs {
+ static unsigned X(const SkBitmapProcState&, SkFixed fx, int max) {
+ return SkClampMax(fx >> 16, max);
+ }
+ static unsigned Y(const SkBitmapProcState&, SkFixed fy, int max) {
+ return SkClampMax(fy >> 16, max);
+ }
+};
+
+// Referenced in opts_check_x86.cpp
+void ClampX_ClampY_nofilter_scale(const SkBitmapProcState& s, uint32_t xy[],
+ int count, int x, int y) {
+ return NoFilterProc_Scale<ClampTileProcs, true>(s, xy, count, x, y);
+}
+void ClampX_ClampY_nofilter_affine(const SkBitmapProcState& s, uint32_t xy[],
+ int count, int x, int y) {
+ return NoFilterProc_Affine<ClampTileProcs>(s, xy, count, x, y);
+}
+
+static SkBitmapProcState::MatrixProc ClampX_ClampY_Procs[] = {
+ // only clamp lives in the right coord space to check for decal
+ ClampX_ClampY_nofilter_scale,
+ ClampX_ClampY_filter_scale,
+ ClampX_ClampY_nofilter_affine,
+ ClampX_ClampY_filter_affine,
+ NoFilterProc_Persp<ClampTileProcs>,
+ ClampX_ClampY_filter_persp
+};
+
#define MAKENAME(suffix) RepeatX_RepeatY ## suffix
#define TILEX_PROCF(fx, max) SK_USHIFT16(((fx) & 0xFFFF) * ((max) + 1))
#define TILEY_PROCF(fy, max) SK_USHIFT16(((fy) & 0xFFFF) * ((max) + 1))
#define TILEX_LOW_BITS(fx, max) ((((fx) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
#define TILEY_LOW_BITS(fy, max) ((((fy) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
#include "SkBitmapProcState_matrix.h"
+
+struct RepeatTileProcs {
+ static unsigned X(const SkBitmapProcState&, SkFixed fx, int max) {
+ return SK_USHIFT16(((fx) & 0xFFFF) * ((max) + 1));
+ }
+ static unsigned Y(const SkBitmapProcState&, SkFixed fy, int max) {
+ return SK_USHIFT16(((fy) & 0xFFFF) * ((max) + 1));
+ }
+};
+
+static SkBitmapProcState::MatrixProc RepeatX_RepeatY_Procs[] = {
+ NoFilterProc_Scale<RepeatTileProcs, false>,
+ RepeatX_RepeatY_filter_scale,
+ NoFilterProc_Affine<RepeatTileProcs>,
+ RepeatX_RepeatY_filter_affine,
+ NoFilterProc_Persp<RepeatTileProcs>,
+ RepeatX_RepeatY_filter_persp
+};
#endif
#define MAKENAME(suffix) GeneralXY ## suffix
@@ -75,8 +126,27 @@ extern const SkBitmapProcState::MatrixProc RepeatX_RepeatY_Procs_neon[];
#define TILEY_LOW_BITS(fy, max) tileLowBitsProcY(fy, (max) + 1)
#include "SkBitmapProcState_matrix.h"
-static inline U16CPU fixed_clamp(SkFixed x)
-{
+struct GeneralTileProcs {
+ static unsigned X(const SkBitmapProcState& s, SkFixed fx, int max) {
+ return SK_USHIFT16(s.fTileProcX(fx) * ((max) + 1));
+ }
+ static unsigned Y(const SkBitmapProcState& s, SkFixed fy, int max) {
+ return SK_USHIFT16(s.fTileProcY(fy) * ((max) + 1));
+ }
+};
+
+static SkBitmapProcState::MatrixProc GeneralXY_Procs[] = {
+ NoFilterProc_Scale<GeneralTileProcs, false>,
+ GeneralXY_filter_scale,
+ NoFilterProc_Affine<GeneralTileProcs>,
+ GeneralXY_filter_affine,
+ NoFilterProc_Persp<GeneralTileProcs>,
+ GeneralXY_filter_persp
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+static inline U16CPU fixed_clamp(SkFixed x) {
if (x < 0) {
x = 0;
}
@@ -86,8 +156,7 @@ static inline U16CPU fixed_clamp(SkFixed x)
return x;
}
-static inline U16CPU fixed_repeat(SkFixed x)
-{
+static inline U16CPU fixed_repeat(SkFixed x) {
return x & 0xFFFF;
}
@@ -97,8 +166,7 @@ static inline U16CPU fixed_repeat(SkFixed x)
#pragma optimize("", off)
#endif
-static inline U16CPU fixed_mirror(SkFixed x)
-{
+static inline U16CPU fixed_mirror(SkFixed x) {
SkFixed s = x << 15 >> 31;
// s is FFFFFFFF if we're on an odd interval, or 0 if an even interval
return (x ^ s) & 0xFFFF;
@@ -108,12 +176,13 @@ static inline U16CPU fixed_mirror(SkFixed x)
#pragma optimize("", on)
#endif
-static SkBitmapProcState::FixedTileProc choose_tile_proc(unsigned m)
-{
- if (SkShader::kClamp_TileMode == m)
+static SkBitmapProcState::FixedTileProc choose_tile_proc(unsigned m) {
+ if (SkShader::kClamp_TileMode == m) {
return fixed_clamp;
- if (SkShader::kRepeat_TileMode == m)
+ }
+ if (SkShader::kRepeat_TileMode == m) {
return fixed_repeat;
+ }
SkASSERT(SkShader::kMirror_TileMode == m);
return fixed_mirror;
}
@@ -178,12 +247,10 @@ static SkBitmapProcState::IntTileProc choose_int_tile_proc(unsigned tm) {
//////////////////////////////////////////////////////////////////////////////
-void decal_nofilter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count)
-{
+void decal_nofilter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count) {
int i;
- for (i = (count >> 2); i > 0; --i)
- {
+ for (i = (count >> 2); i > 0; --i) {
*dst++ = pack_two_shorts(fx >> 16, (fx + dx) >> 16);
fx += dx+dx;
*dst++ = pack_two_shorts(fx >> 16, (fx + dx) >> 16);
@@ -197,18 +264,13 @@ void decal_nofilter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count)
}
}
-void decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count)
-{
-
-
- if (count & 1)
- {
+void decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count) {
+ if (count & 1) {
SkASSERT((fx >> (16 + 14)) == 0);
*dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
fx += dx;
}
- while ((count -= 2) >= 0)
- {
+ while ((count -= 2) >= 0) {
SkASSERT((fx >> (16 + 14)) == 0);
*dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
fx += dx;
@@ -412,8 +474,7 @@ static void mirrorx_nofilter_trans(const SkBitmapProcState& s,
///////////////////////////////////////////////////////////////////////////////
-SkBitmapProcState::MatrixProc
-SkBitmapProcState::chooseMatrixProc(bool trivial_matrix) {
+SkBitmapProcState::MatrixProc SkBitmapProcState::chooseMatrixProc(bool trivial_matrix) {
// test_int_tileprocs();
// check for our special case when there is no scale/affine/perspective
if (trivial_matrix) {
@@ -439,9 +500,7 @@ SkBitmapProcState::chooseMatrixProc(bool trivial_matrix) {
index += 2;
}
- if (SkShader::kClamp_TileMode == fTileModeX &&
- SkShader::kClamp_TileMode == fTileModeY)
- {
+ if (SkShader::kClamp_TileMode == fTileModeX && SkShader::kClamp_TileMode == fTileModeY) {
// clamp gets special version of filterOne
fFilterOneX = SK_Fixed1;
fFilterOneY = SK_Fixed1;
@@ -452,9 +511,7 @@ SkBitmapProcState::chooseMatrixProc(bool trivial_matrix) {
fFilterOneX = SK_Fixed1 / fBitmap->width();
fFilterOneY = SK_Fixed1 / fBitmap->height();
- if (SkShader::kRepeat_TileMode == fTileModeX &&
- SkShader::kRepeat_TileMode == fTileModeY)
- {
+ if (SkShader::kRepeat_TileMode == fTileModeX && SkShader::kRepeat_TileMode == fTileModeY) {
return SK_ARM_NEON_WRAP(RepeatX_RepeatY_Procs)[index];
}
diff --git a/chromium/third_party/skia/src/core/SkBitmapProcState_matrix_template.h b/chromium/third_party/skia/src/core/SkBitmapProcState_matrix_template.h
new file mode 100644
index 00000000000..4b0044b46ad
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkBitmapProcState_matrix_template.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkBitmapProcState_MatrixTemplates_DEFINED
+#define SkBitmapProcState_MatrixTemplates_DEFINED
+
+#include "SkMath.h"
+#include "SkMathPriv.h"
+
+template <typename TileProc, bool tryDecal>
+void NoFilterProc_Scale(const SkBitmapProcState& s, uint32_t xy[],
+ int count, int x, int y) {
+ SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
+ SkMatrix::kScale_Mask)) == 0);
+
+ // we store y, x, x, x, x, x
+
+ const unsigned maxX = s.fBitmap->width() - 1;
+ SkFractionalInt fx;
+ {
+ SkPoint pt;
+ s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
+ SkIntToScalar(y) + SK_ScalarHalf, &pt);
+ fx = SkScalarToFractionalInt(pt.fY);
+ const unsigned maxY = s.fBitmap->height() - 1;
+ *xy++ = TileProc::Y(s, SkFractionalIntToFixed(fx), maxY);
+ fx = SkScalarToFractionalInt(pt.fX);
+ }
+
+ if (0 == maxX) {
+ // all of the following X values must be 0
+ memset(xy, 0, count * sizeof(uint16_t));
+ return;
+ }
+
+ const SkFractionalInt dx = s.fInvSxFractionalInt;
+
+ if (tryDecal && can_truncate_to_fixed_for_decal(fx, dx, count, maxX)) {
+ decal_nofilter_scale(xy, SkFractionalIntToFixed(fx),
+ SkFractionalIntToFixed(dx), count);
+ } else {
+ int i;
+ for (i = (count >> 2); i > 0; --i) {
+ unsigned a, b;
+ a = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx;
+ b = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx;
+#ifdef SK_CPU_BENDIAN
+ *xy++ = (a << 16) | b;
+#else
+ *xy++ = (b << 16) | a;
+#endif
+ a = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx;
+ b = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx;
+#ifdef SK_CPU_BENDIAN
+ *xy++ = (a << 16) | b;
+#else
+ *xy++ = (b << 16) | a;
+#endif
+ }
+ uint16_t* xx = (uint16_t*)xy;
+ for (i = (count & 3); i > 0; --i) {
+ *xx++ = TileProc::X(s, SkFractionalIntToFixed(fx), maxX); fx += dx;
+ }
+ }
+}
+
+// note: we could special-case on a matrix which is skewed in X but not Y.
+// this would require a more general setup thatn SCALE does, but could use
+// SCALE's inner loop that only looks at dx
+
+template <typename TileProc>
+void NoFilterProc_Affine(const SkBitmapProcState& s, uint32_t xy[],
+ int count, int x, int y) {
+ SkASSERT(s.fInvType & SkMatrix::kAffine_Mask);
+ SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
+ SkMatrix::kScale_Mask |
+ SkMatrix::kAffine_Mask)) == 0);
+
+ SkPoint srcPt;
+ s.fInvProc(s.fInvMatrix,
+ SkIntToScalar(x) + SK_ScalarHalf,
+ SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
+
+ SkFractionalInt fx = SkScalarToFractionalInt(srcPt.fX);
+ SkFractionalInt fy = SkScalarToFractionalInt(srcPt.fY);
+ SkFractionalInt dx = s.fInvSxFractionalInt;
+ SkFractionalInt dy = s.fInvKyFractionalInt;
+ int maxX = s.fBitmap->width() - 1;
+ int maxY = s.fBitmap->height() - 1;
+
+ for (int i = count; i > 0; --i) {
+ *xy++ = (TileProc::Y(s, SkFractionalIntToFixed(fy), maxY) << 16) |
+ TileProc::X(s, SkFractionalIntToFixed(fx), maxX);
+ fx += dx; fy += dy;
+ }
+}
+
+template <typename TileProc>
+void NoFilterProc_Persp(const SkBitmapProcState& s, uint32_t* SK_RESTRICT xy,
+ int count, int x, int y) {
+ SkASSERT(s.fInvType & SkMatrix::kPerspective_Mask);
+
+ int maxX = s.fBitmap->width() - 1;
+ int maxY = s.fBitmap->height() - 1;
+
+ SkPerspIter iter(s.fInvMatrix,
+ SkIntToScalar(x) + SK_ScalarHalf,
+ SkIntToScalar(y) + SK_ScalarHalf, count);
+
+ while ((count = iter.next()) != 0) {
+ const SkFixed* SK_RESTRICT srcXY = iter.getXY();
+ while (--count >= 0) {
+ *xy++ = (TileProc::Y(s, srcXY[1], maxY) << 16) |
+ TileProc::X(s, srcXY[0], maxX);
+ srcXY += 2;
+ }
+ }
+}
+
+#endif
diff --git a/chromium/third_party/skia/src/core/SkBitmapProcState_procs.h b/chromium/third_party/skia/src/core/SkBitmapProcState_procs.h
index 68c79835a9d..0d3b723e676 100644
--- a/chromium/third_party/skia/src/core/SkBitmapProcState_procs.h
+++ b/chromium/third_party/skia/src/core/SkBitmapProcState_procs.h
@@ -90,7 +90,7 @@ static inline U8CPU Filter_8(unsigned x, unsigned y,
#define MAKENAME(suffix) NAME_WRAP(S32_opaque_D32 ## suffix)
#define DSTSIZE 32
#define SRCTYPE SkPMColor
-#define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kARGB_8888_Config); \
+#define CHECKSTATE(state) SkASSERT(4 == state.fBitmap->bytesPerPixel()); \
SkASSERT(state.fAlphaScale == 256)
#define RETURNDST(src) src
#define SRC_TO_FILTER(src) src
@@ -102,7 +102,7 @@ static inline U8CPU Filter_8(unsigned x, unsigned y,
#define MAKENAME(suffix) NAME_WRAP(S32_alpha_D32 ## suffix)
#define DSTSIZE 32
#define SRCTYPE SkPMColor
-#define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kARGB_8888_Config); \
+#define CHECKSTATE(state) SkASSERT(4 == state.fBitmap->bytesPerPixel()); \
SkASSERT(state.fAlphaScale < 256)
#define PREAMBLE(state) unsigned alphaScale = state.fAlphaScale
#define RETURNDST(src) SkAlphaMulQ(src, alphaScale)
@@ -121,7 +121,7 @@ static inline U8CPU Filter_8(unsigned x, unsigned y,
#define MAKENAME(suffix) NAME_WRAP(S16_opaque_D32 ## suffix)
#define DSTSIZE 32
#define SRCTYPE uint16_t
-#define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kRGB_565_Config); \
+#define CHECKSTATE(state) SkASSERT(kRGB_565_SkColorType == state.fBitmap->colorType()); \
SkASSERT(state.fAlphaScale == 256)
#define RETURNDST(src) SkPixel16ToPixel32(src)
#define SRC_TO_FILTER(src) src
@@ -137,7 +137,7 @@ static inline U8CPU Filter_8(unsigned x, unsigned y,
#define MAKENAME(suffix) NAME_WRAP(S16_alpha_D32 ## suffix)
#define DSTSIZE 32
#define SRCTYPE uint16_t
-#define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kRGB_565_Config); \
+#define CHECKSTATE(state) SkASSERT(kRGB_565_SkColorType == state.fBitmap->colorType()); \
SkASSERT(state.fAlphaScale < 256)
#define PREAMBLE(state) unsigned alphaScale = state.fAlphaScale
#define RETURNDST(src) SkAlphaMulQ(SkPixel16ToPixel32(src), alphaScale)
@@ -152,7 +152,7 @@ static inline U8CPU Filter_8(unsigned x, unsigned y,
#define MAKENAME(suffix) NAME_WRAP(SI8_opaque_D32 ## suffix)
#define DSTSIZE 32
#define SRCTYPE uint8_t
-#define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kIndex8_Config); \
+#define CHECKSTATE(state) SkASSERT(kIndex_8_SkColorType == state.fBitmap->colorType()); \
SkASSERT(state.fAlphaScale == 256)
#define PREAMBLE(state) const SkPMColor* SK_RESTRICT table = state.fBitmap->getColorTable()->lockColors()
#define RETURNDST(src) table[src]
@@ -166,7 +166,7 @@ static inline U8CPU Filter_8(unsigned x, unsigned y,
#define MAKENAME(suffix) NAME_WRAP(SI8_alpha_D32 ## suffix)
#define DSTSIZE 32
#define SRCTYPE uint8_t
-#define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kIndex8_Config); \
+#define CHECKSTATE(state) SkASSERT(kIndex_8_SkColorType == state.fBitmap->colorType()); \
SkASSERT(state.fAlphaScale < 256)
#define PREAMBLE(state) unsigned alphaScale = state.fAlphaScale; \
const SkPMColor* SK_RESTRICT table = state.fBitmap->getColorTable()->lockColors()
@@ -183,7 +183,7 @@ static inline U8CPU Filter_8(unsigned x, unsigned y,
#define MAKENAME(suffix) NAME_WRAP(S4444_opaque_D32 ## suffix)
#define DSTSIZE 32
#define SRCTYPE SkPMColor16
-#define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kARGB_4444_Config); \
+#define CHECKSTATE(state) SkASSERT(kARGB_4444_SkColorType == state.fBitmap->colorType()); \
SkASSERT(state.fAlphaScale == 256)
#define RETURNDST(src) SkPixel4444ToPixel32(src)
#define SRC_TO_FILTER(src) src
@@ -199,7 +199,7 @@ static inline U8CPU Filter_8(unsigned x, unsigned y,
#define MAKENAME(suffix) NAME_WRAP(S4444_alpha_D32 ## suffix)
#define DSTSIZE 32
#define SRCTYPE SkPMColor16
-#define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kARGB_4444_Config); \
+#define CHECKSTATE(state) SkASSERT(kARGB_4444_SkColorType == state.fBitmap->colorType()); \
SkASSERT(state.fAlphaScale < 256)
#define PREAMBLE(state) unsigned alphaScale = state.fAlphaScale
#define RETURNDST(src) SkAlphaMulQ(SkPixel4444ToPixel32(src), alphaScale)
@@ -218,7 +218,7 @@ static inline U8CPU Filter_8(unsigned x, unsigned y,
#define MAKENAME(suffix) NAME_WRAP(SA8_alpha_D32 ## suffix)
#define DSTSIZE 32
#define SRCTYPE uint8_t
-#define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kA8_Config);
+#define CHECKSTATE(state) SkASSERT(kAlpha_8_SkColorType == state.fBitmap->colorType());
#define PREAMBLE(state) const SkPMColor pmColor = state.fPaintPMColor;
#define RETURNDST(src) SkAlphaMulQ(pmColor, SkAlpha255To256(src))
#define SRC_TO_FILTER(src) src
@@ -243,7 +243,7 @@ static inline U8CPU Filter_8(unsigned x, unsigned y,
#define MAKENAME(suffix) NAME_WRAP(S32_D16 ## suffix)
#define DSTSIZE 16
#define SRCTYPE SkPMColor
-#define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kARGB_8888_Config); \
+#define CHECKSTATE(state) SkASSERT(4 == state.fBitmap->bytesPerPixel()); \
SkASSERT(state.fBitmap->isOpaque())
#define RETURNDST(src) SkPixel32ToPixel16(src)
#define SRC_TO_FILTER(src) src
@@ -261,7 +261,7 @@ static inline U8CPU Filter_8(unsigned x, unsigned y,
#define MAKENAME(suffix) NAME_WRAP(S16_D16 ## suffix)
#define DSTSIZE 16
#define SRCTYPE uint16_t
-#define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kRGB_565_Config)
+#define CHECKSTATE(state) SkASSERT(kRGB_565_SkColorType == state.fBitmap->colorType())
#define RETURNDST(src) src
#define SRC_TO_FILTER(src) src
#include "SkBitmapProcState_sample.h"
@@ -278,7 +278,7 @@ static inline U8CPU Filter_8(unsigned x, unsigned y,
#define MAKENAME(suffix) NAME_WRAP(SI8_D16 ## suffix)
#define DSTSIZE 16
#define SRCTYPE uint8_t
-#define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kIndex8_Config); \
+#define CHECKSTATE(state) SkASSERT(kIndex_8_SkColorType == state.fBitmap->colorType()); \
SkASSERT(state.fBitmap->isOpaque())
#define PREAMBLE(state) const uint16_t* SK_RESTRICT table = state.fBitmap->getColorTable()->lock16BitCache()
#define RETURNDST(src) table[src]
@@ -306,7 +306,7 @@ static inline U8CPU Filter_8(unsigned x, unsigned y,
#define MAKENAME(suffix) NAME_WRAP(Clamp_S16_D16 ## suffix)
#define SRCTYPE uint16_t
#define DSTTYPE uint16_t
-#define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kRGB_565_Config)
+#define CHECKSTATE(state) SkASSERT(kRGB_565_SkColorType == state.fBitmap->colorType())
#define SRC_TO_FILTER(src) src
#include "SkBitmapProcState_shaderproc.h"
@@ -319,7 +319,7 @@ static inline U8CPU Filter_8(unsigned x, unsigned y,
#define MAKENAME(suffix) NAME_WRAP(Repeat_S16_D16 ## suffix)
#define SRCTYPE uint16_t
#define DSTTYPE uint16_t
-#define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kRGB_565_Config)
+#define CHECKSTATE(state) SkASSERT(kRGB_565_SkColorType == state.fBitmap->colorType())
#define SRC_TO_FILTER(src) src
#include "SkBitmapProcState_shaderproc.h"
@@ -334,7 +334,7 @@ static inline U8CPU Filter_8(unsigned x, unsigned y,
#define MAKENAME(suffix) NAME_WRAP(Clamp_SI8_opaque_D32 ## suffix)
#define SRCTYPE uint8_t
#define DSTTYPE uint32_t
-#define CHECKSTATE(state) SkASSERT(state.fBitmap->config() == SkBitmap::kIndex8_Config)
+#define CHECKSTATE(state) SkASSERT(kIndex_8_SkColorType == state.fBitmap->colorType())
#define PREAMBLE(state) const SkPMColor* SK_RESTRICT table = state.fBitmap->getColorTable()->lockColors()
#define SRC_TO_FILTER(src) table[src]
#define POSTAMBLE(state) state.fBitmap->getColorTable()->unlockColors()
diff --git a/chromium/third_party/skia/src/core/SkBitmapScaler.cpp b/chromium/third_party/skia/src/core/SkBitmapScaler.cpp
index 67a9508ee98..be32a891fcd 100644
--- a/chromium/third_party/skia/src/core/SkBitmapScaler.cpp
+++ b/chromium/third_party/skia/src/core/SkBitmapScaler.cpp
@@ -13,8 +13,8 @@ class SkResizeFilter {
public:
SkResizeFilter(SkBitmapScaler::ResizeMethod method,
int srcFullWidth, int srcFullHeight,
- int destWidth, int destHeight,
- const SkIRect& destSubset,
+ float destWidth, float destHeight,
+ const SkRect& destSubset,
const SkConvolutionProcs& convolveProcs);
~SkResizeFilter() {
SkDELETE( fBitmapFilter );
@@ -40,7 +40,7 @@ private:
// for the transform is also specified.
void computeFilters(int srcSize,
- int destSubsetLo, int destSubsetSize,
+ float destSubsetLo, float destSubsetSize,
float scale,
SkConvolutionFilter1D* output,
const SkConvolutionProcs& convolveProcs);
@@ -51,8 +51,8 @@ private:
SkResizeFilter::SkResizeFilter(SkBitmapScaler::ResizeMethod method,
int srcFullWidth, int srcFullHeight,
- int destWidth, int destHeight,
- const SkIRect& destSubset,
+ float destWidth, float destHeight,
+ const SkRect& destSubset,
const SkConvolutionProcs& convolveProcs) {
// method will only ever refer to an "algorithm method".
@@ -82,15 +82,20 @@ SkResizeFilter::SkResizeFilter(SkBitmapScaler::ResizeMethod method,
}
- float scaleX = static_cast<float>(destWidth) /
- static_cast<float>(srcFullWidth);
- float scaleY = static_cast<float>(destHeight) /
- static_cast<float>(srcFullHeight);
+ float scaleX = destWidth / srcFullWidth;
+ float scaleY = destHeight / srcFullHeight;
this->computeFilters(srcFullWidth, destSubset.fLeft, destSubset.width(),
scaleX, &fXFilter, convolveProcs);
- this->computeFilters(srcFullHeight, destSubset.fTop, destSubset.height(),
- scaleY, &fYFilter, convolveProcs);
+ if (srcFullWidth == srcFullHeight &&
+ destSubset.fLeft == destSubset.fTop &&
+ destSubset.width() == destSubset.height()&&
+ scaleX == scaleY) {
+ fYFilter = fXFilter;
+ } else {
+ this->computeFilters(srcFullHeight, destSubset.fTop, destSubset.height(),
+ scaleY, &fYFilter, convolveProcs);
+ }
}
// TODO(egouriou): Take advantage of periods in the convolution.
@@ -105,11 +110,11 @@ SkResizeFilter::SkResizeFilter(SkBitmapScaler::ResizeMethod method,
// the coefficients can be shared. For periods of 1 we can consider
// loading the factors only once outside the borders.
void SkResizeFilter::computeFilters(int srcSize,
- int destSubsetLo, int destSubsetSize,
+ float destSubsetLo, float destSubsetSize,
float scale,
SkConvolutionFilter1D* output,
const SkConvolutionProcs& convolveProcs) {
- int destSubsetHi = destSubsetLo + destSubsetSize; // [lo, hi)
+ float destSubsetHi = destSubsetLo + destSubsetSize; // [lo, hi)
// When we're doing a magnification, the scale will be larger than one. This
// means the destination pixels are much smaller than the source pixels, and
@@ -131,7 +136,7 @@ void SkResizeFilter::computeFilters(int srcSize,
// Loop over all pixels in the output range. We will generate one set of
// filter values for each one. Those values will tell us how to blend the
// source pixels to compute the destination pixel.
- for (int destSubsetI = destSubsetLo; destSubsetI < destSubsetHi;
+ for (int destSubsetI = SkScalarFloorToInt(destSubsetLo); destSubsetI < SkScalarCeilToInt(destSubsetHi);
destSubsetI++) {
// Reset the arrays. We don't declare them inside so they can re-use the
// same malloc-ed buffer.
@@ -228,7 +233,11 @@ static SkBitmapScaler::ResizeMethod ResizeMethodToAlgorithmMethod(
case SkBitmapScaler::RESIZE_BETTER:
return SkBitmapScaler::RESIZE_HAMMING;
default:
+#ifdef SK_HIGH_QUALITY_IS_LANCZOS
+ return SkBitmapScaler::RESIZE_LANCZOS3;
+#else
return SkBitmapScaler::RESIZE_MITCHELL;
+#endif
}
}
@@ -236,22 +245,23 @@ static SkBitmapScaler::ResizeMethod ResizeMethodToAlgorithmMethod(
bool SkBitmapScaler::Resize(SkBitmap* resultPtr,
const SkBitmap& source,
ResizeMethod method,
- int destWidth, int destHeight,
- const SkIRect& destSubset,
+ float destWidth, float destHeight,
const SkConvolutionProcs& convolveProcs,
SkBitmap::Allocator* allocator) {
+
+ SkRect destSubset = { 0, 0, destWidth, destHeight };
+
// Ensure that the ResizeMethod enumeration is sound.
SkASSERT(((RESIZE_FIRST_QUALITY_METHOD <= method) &&
(method <= RESIZE_LAST_QUALITY_METHOD)) ||
((RESIZE_FIRST_ALGORITHM_METHOD <= method) &&
(method <= RESIZE_LAST_ALGORITHM_METHOD)));
- SkIRect dest = { 0, 0, destWidth, destHeight };
+ SkRect dest = { 0, 0, destWidth, destHeight };
if (!dest.contains(destSubset)) {
SkErrorInternals::SetError( kInvalidArgument_SkError,
- "Sorry, you passed me a bitmap resize "
- " method I have never heard of: %d",
- method );
+ "Sorry, the destination bitmap scale subset "
+ "falls outside the full destination bitmap." );
}
// If the size of source or destination is 0, i.e. 0x0, 0xN or Nx0, just
@@ -271,7 +281,7 @@ bool SkBitmapScaler::Resize(SkBitmap* resultPtr,
SkAutoLockPixels locker(source);
if (!source.readyToDraw() ||
- source.config() != SkBitmap::kARGB_8888_Config) {
+ source.colorType() != kN32_SkColorType) {
return false;
}
@@ -286,9 +296,9 @@ bool SkBitmapScaler::Resize(SkBitmap* resultPtr,
// Convolve into the result.
SkBitmap result;
- result.setConfig(SkBitmap::kARGB_8888_Config,
- destSubset.width(), destSubset.height(), 0,
- source.alphaType());
+ result.setInfo(SkImageInfo::MakeN32(SkScalarCeilToInt(destSubset.width()),
+ SkScalarCeilToInt(destSubset.height()),
+ source.alphaType()));
result.allocPixels(allocator, NULL);
if (!result.readyToDraw()) {
return false;
@@ -305,15 +315,3 @@ bool SkBitmapScaler::Resize(SkBitmap* resultPtr,
SkASSERT(NULL != resultPtr->getPixels());
return true;
}
-
-// static
-bool SkBitmapScaler::Resize(SkBitmap* resultPtr,
- const SkBitmap& source,
- ResizeMethod method,
- int destWidth, int destHeight,
- const SkConvolutionProcs& convolveProcs,
- SkBitmap::Allocator* allocator) {
- SkIRect destSubset = { 0, 0, destWidth, destHeight };
- return Resize(resultPtr, source, method, destWidth, destHeight, destSubset,
- convolveProcs, allocator);
-}
diff --git a/chromium/third_party/skia/src/core/SkBitmapScaler.h b/chromium/third_party/skia/src/core/SkBitmapScaler.h
index c8d8a84185e..d6636cf34ea 100644
--- a/chromium/third_party/skia/src/core/SkBitmapScaler.h
+++ b/chromium/third_party/skia/src/core/SkBitmapScaler.h
@@ -79,28 +79,10 @@ public:
RESIZE_LAST_ALGORITHM_METHOD = RESIZE_MITCHELL,
};
- // Resizes the given source bitmap using the specified resize method, so that
- // the entire image is (dest_size) big. The dest_subset is the rectangle in
- // this destination image that should actually be returned.
- //
- // The output image will be (dest_subset.width(), dest_subset.height()). This
- // will save work if you do not need the entire bitmap.
- //
- // The destination subset must be smaller than the destination image.
static bool Resize(SkBitmap* result,
const SkBitmap& source,
ResizeMethod method,
- int dest_width, int dest_height,
- const SkIRect& dest_subset,
- const SkConvolutionProcs&,
- SkBitmap::Allocator* allocator = NULL);
-
- // Alternate version for resizing and returning the entire bitmap rather than
- // a subset.
- static bool Resize(SkBitmap* result,
- const SkBitmap& source,
- ResizeMethod method,
- int dest_width, int dest_height,
+ float dest_width, float dest_height,
const SkConvolutionProcs&,
SkBitmap::Allocator* allocator = NULL);
};
diff --git a/chromium/third_party/skia/src/core/SkBitmapShader16BilerpTemplate.h b/chromium/third_party/skia/src/core/SkBitmapShader16BilerpTemplate.h
deleted file mode 100644
index 435b806bb28..00000000000
--- a/chromium/third_party/skia/src/core/SkBitmapShader16BilerpTemplate.h
+++ /dev/null
@@ -1,245 +0,0 @@
-
-/*
- * Copyright 2006 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#include "SkFilterProc.h"
-
-class BILERP_BITMAP16_SHADER_CLASS : public HasSpan16_Sampler_BitmapShader {
-public:
- BILERP_BITMAP16_SHADER_CLASS(const SkBitmap& src)
- : HasSpan16_Sampler_BitmapShader(src, true,
- SkShader::kClamp_TileMode,
- SkShader::kClamp_TileMode)
- {
- }
-
- virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count)
- {
- SkASSERT(count > 0);
-
- U8CPU alpha = this->getPaintAlpha();
-
- const SkMatrix& inv = this->getTotalInverse();
- const SkBitmap& srcBitmap = this->getSrcBitmap();
- unsigned srcMaxX = srcBitmap.width() - 1;
- unsigned srcMaxY = srcBitmap.height() - 1;
- unsigned srcRB = srcBitmap.rowBytes();
-
- BILERP_BITMAP16_SHADER_PREAMBLE(srcBitmap);
-
- const SkFilterProc* proc_table = SkGetBilinearFilterProcTable();
- const BILERP_BITMAP16_SHADER_TYPE* srcPixels = (const BILERP_BITMAP16_SHADER_TYPE*)srcBitmap.getPixels();
-
- if (this->getInverseClass() == kPerspective_MatrixClass)
- {
- SkPerspIter iter(inv, SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, count);
- while ((count = iter.next()) != 0)
- {
- const SkFixed* srcXY = iter.getXY();
- while (--count >= 0)
- {
- SkFixed fx = *srcXY++ - SK_FixedHalf;
- SkFixed fy = *srcXY++ - SK_FixedHalf;
- int ix = fx >> 16;
- int iy = fy >> 16;
- int x = SkClampMax(ix, srcMaxX);
- int y = SkClampMax(iy, srcMaxY);
-
- const BILERP_BITMAP16_SHADER_TYPE *p00, *p01, *p10, *p11;
-
- p00 = p01 = ((const BILERP_BITMAP16_SHADER_TYPE*)((const char*)srcPixels + y * srcRB)) + x;
- if ((unsigned)ix < srcMaxX)
- p01 += 1;
- p10 = p00;
- p11 = p01;
- if ((unsigned)iy < srcMaxY)
- {
- p10 = (const BILERP_BITMAP16_SHADER_TYPE*)((const char*)p10 + srcRB);
- p11 = (const BILERP_BITMAP16_SHADER_TYPE*)((const char*)p11 + srcRB);
- }
-
- SkFilterProc proc = SkGetBilinearFilterProc(proc_table, fx, fy);
- uint32_t c = proc(SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p00)),
- SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p01)),
- SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p10)),
- SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p11)));
-
- *dstC++ = expanded_rgb16_to_8888(c, alpha);
- }
- }
- }
- else // linear case
- {
- SkFixed fx, fy, dx, dy;
-
- // now init fx, fy, dx, dy
- {
- SkPoint srcPt;
- this->getInverseMapPtProc()(inv, SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
-
- fx = SkScalarToFixed(srcPt.fX) - SK_FixedHalf;
- fy = SkScalarToFixed(srcPt.fY) - SK_FixedHalf;
-
- if (this->getInverseClass() == kFixedStepInX_MatrixClass)
- (void)inv.fixedStepInX(SkIntToScalar(y), &dx, &dy);
- else
- {
- dx = SkScalarToFixed(inv.getScaleX());
- dy = SkScalarToFixed(inv.getSkewY());
- }
- }
-
- do {
- int ix = fx >> 16;
- int iy = fy >> 16;
-
- const BILERP_BITMAP16_SHADER_TYPE *p00, *p01, *p10, *p11;
-
- p00 = p01 = ((const BILERP_BITMAP16_SHADER_TYPE*)((const char*)srcPixels +
- SkClampMax(iy, srcMaxY) * srcRB)) +
- SkClampMax(ix, srcMaxX);
- if ((unsigned)ix < srcMaxX)
- p01 += 1;
- p10 = p00;
- p11 = p01;
- if ((unsigned)iy < srcMaxY)
- {
- p10 = (const BILERP_BITMAP16_SHADER_TYPE*)((const char*)p10 + srcRB);
- p11 = (const BILERP_BITMAP16_SHADER_TYPE*)((const char*)p11 + srcRB);
- }
-
- SkFilterProc proc = SkGetBilinearFilterProc(proc_table, fx, fy);
- uint32_t c = proc(SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p00)),
- SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p01)),
- SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p10)),
- SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p11)));
- *dstC++ = expanded_rgb16_to_8888(c, alpha);
-
- fx += dx;
- fy += dy;
- } while (--count != 0);
- }
- BILERP_BITMAP16_SHADER_POSTAMBLE(srcBitmap);
- }
-
- virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count)
- {
- SkASSERT(count > 0);
-
- const SkMatrix& inv = this->getTotalInverse();
- const SkBitmap& srcBitmap = this->getSrcBitmap();
- unsigned srcMaxX = srcBitmap.width() - 1;
- unsigned srcMaxY = srcBitmap.height() - 1;
- unsigned srcRB = srcBitmap.rowBytes();
-
- BILERP_BITMAP16_SHADER_PREAMBLE(srcBitmap);
-
- const SkFilterProc* proc_table = SkGetBilinearFilterProcTable();
- const BILERP_BITMAP16_SHADER_TYPE* srcPixels = (const BILERP_BITMAP16_SHADER_TYPE*)srcBitmap.getPixels();
-
- if (this->getInverseClass() == kPerspective_MatrixClass)
- {
- SkPerspIter iter(inv, SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, count);
- while ((count = iter.next()) != 0)
- {
- const SkFixed* srcXY = iter.getXY();
- while (--count >= 0)
- {
- SkFixed fx = *srcXY++ - SK_FixedHalf;
- SkFixed fy = *srcXY++ - SK_FixedHalf;
- int ix = fx >> 16;
- int iy = fy >> 16;
-
- const BILERP_BITMAP16_SHADER_TYPE *p00, *p01, *p10, *p11;
-
- p00 = p01 = ((const BILERP_BITMAP16_SHADER_TYPE*)((const char*)srcPixels +
- SkClampMax(iy, srcMaxY) * srcRB)) +
- SkClampMax(ix, srcMaxX);
- if ((unsigned)ix < srcMaxX)
- p01 += 1;
- p10 = p00;
- p11 = p01;
- if ((unsigned)iy < srcMaxY)
- {
- p10 = (const BILERP_BITMAP16_SHADER_TYPE*)((const char*)p10 + srcRB);
- p11 = (const BILERP_BITMAP16_SHADER_TYPE*)((const char*)p11 + srcRB);
- }
-
- SkFilterProc proc = SkGetBilinearFilterProc(proc_table, fx, fy);
- uint32_t c = proc(SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p00)),
- SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p01)),
- SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p10)),
- SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p11)));
- *dstC++ = SkCompact_rgb_16(c);
- }
- }
- }
- else // linear case
- {
- SkFixed fx, fy, dx, dy;
-
- // now init fx, fy, dx, dy
- {
- SkPoint srcPt;
- this->getInverseMapPtProc()(inv, SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
-
- fx = SkScalarToFixed(srcPt.fX) - SK_FixedHalf;
- fy = SkScalarToFixed(srcPt.fY) - SK_FixedHalf;
-
- if (this->getInverseClass() == kFixedStepInX_MatrixClass)
- (void)inv.fixedStepInX(SkIntToScalar(y), &dx, &dy);
- else
- {
- dx = SkScalarToFixed(inv.getScaleX());
- dy = SkScalarToFixed(inv.getSkewY());
- }
- }
-
- do {
- int ix = fx >> 16;
- int iy = fy >> 16;
-
- const BILERP_BITMAP16_SHADER_TYPE *p00, *p01, *p10, *p11;
-
- p00 = p01 = ((const BILERP_BITMAP16_SHADER_TYPE*)((const char*)srcPixels +
- SkClampMax(iy, srcMaxY) * srcRB)) +
- SkClampMax(ix, srcMaxX);
- if ((unsigned)ix < srcMaxX)
- p01 += 1;
- p10 = p00;
- p11 = p01;
- if ((unsigned)iy < srcMaxY)
- {
- p10 = (const BILERP_BITMAP16_SHADER_TYPE*)((const char*)p10 + srcRB);
- p11 = (const BILERP_BITMAP16_SHADER_TYPE*)((const char*)p11 + srcRB);
- }
-
- SkFilterProc proc = SkGetBilinearFilterProc(proc_table, fx, fy);
- uint32_t c = proc(SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p00)),
- SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p01)),
- SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p10)),
- SkExpand_rgb_16(BILERP_BITMAP16_SHADER_PIXEL(*p11)));
- *dstC++ = SkCompact_rgb_16(c);
-
- fx += dx;
- fy += dy;
- } while (--count != 0);
- }
- BILERP_BITMAP16_SHADER_POSTAMBLE(srcBitmap);
- }
-};
-
-#undef BILERP_BITMAP16_SHADER_CLASS
-#undef BILERP_BITMAP16_SHADER_TYPE
-#undef BILERP_BITMAP16_SHADER_PREAMBLE
-#undef BILERP_BITMAP16_SHADER_PIXEL
-#undef BILERP_BITMAP16_SHADER_POSTAMBLE
diff --git a/chromium/third_party/skia/src/core/SkBitmapShaderTemplate.h b/chromium/third_party/skia/src/core/SkBitmapShaderTemplate.h
deleted file mode 100644
index 20e55188e03..00000000000
--- a/chromium/third_party/skia/src/core/SkBitmapShaderTemplate.h
+++ /dev/null
@@ -1,306 +0,0 @@
-
-/*
- * Copyright 2006 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-
-#ifndef NOFILTER_BITMAP_SHADER_PREAMBLE
- #define NOFILTER_BITMAP_SHADER_PREAMBLE(bitmap, rb)
-#endif
-#ifndef NOFILTER_BITMAP_SHADER_POSTAMBLE
- #define NOFILTER_BITMAP_SHADER_POSTAMBLE(bitmap)
-#endif
-#ifndef NOFILTER_BITMAP_SHADER_PREAMBLE16
- #define NOFILTER_BITMAP_SHADER_PREAMBLE16(bitmap, rb)
-#endif
-#ifndef NOFILTER_BITMAP_SHADER_POSTAMBLE16
- #define NOFILTER_BITMAP_SHADER_POSTAMBLE16(bitmap)
-#endif
-
-class NOFILTER_BITMAP_SHADER_CLASS : public HasSpan16_Sampler_BitmapShader {
-public:
- NOFILTER_BITMAP_SHADER_CLASS(const SkBitmap& src)
- : HasSpan16_Sampler_BitmapShader(src, false,
- NOFILTER_BITMAP_SHADER_TILEMODE,
- NOFILTER_BITMAP_SHADER_TILEMODE)
- {
- }
-
- virtual bool setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix)
- {
- if (!this->INHERITED::setContext(device, paint, matrix))
- return false;
-
-#ifdef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
- this->computeUnitInverse();
-#endif
- return true;
- }
-
- virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count)
- {
- SkASSERT(count > 0);
-
-#ifdef NOFILTER_BITMAP_SHADER_SPRITEPROC32
- if ((this->getTotalInverse().getType() & ~SkMatrix::kTranslate_Mask) == 0)
- {
- NOFILTER_BITMAP_SHADER_SPRITEPROC32(this, x, y, dstC, count);
- return;
- }
-#endif
-
- unsigned scale = SkAlpha255To256(this->getPaintAlpha());
-#ifdef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
- const SkMatrix& inv = this->getUnitInverse();
- SkMatrix::MapPtProc invProc = this->getUnitInverseProc();
-#else
- const SkMatrix& inv = this->getTotalInverse();
- SkMatrix::MapPtProc invProc = this->getInverseMapPtProc();
-#endif
- const SkBitmap& srcBitmap = this->getSrcBitmap();
- unsigned srcMaxX = srcBitmap.width() - 1;
- unsigned srcMaxY = srcBitmap.height() - 1;
- unsigned srcRB = srcBitmap.rowBytes();
- SkFixed fx, fy, dx, dy;
-
- const NOFILTER_BITMAP_SHADER_TYPE* srcPixels = (const NOFILTER_BITMAP_SHADER_TYPE*)srcBitmap.getPixels();
- NOFILTER_BITMAP_SHADER_PREAMBLE(srcBitmap, srcRB);
-
- if (this->getInverseClass() == kPerspective_MatrixClass)
- {
- SkPerspIter iter(inv, SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, count);
- while ((count = iter.next()) != 0)
- {
- const SkFixed* srcXY = iter.getXY();
-
-/* Do I need this?
-#ifndef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
- fx >>= level;
- fy >>= level;
-#endif
-*/
- if (256 == scale)
- {
- while (--count >= 0)
- {
- fx = *srcXY++;
- fy = *srcXY++;
- unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
- unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
- *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_XY(srcPixels, x, y, srcRB);
- }
- }
- else
- {
- while (--count >= 0)
- {
- fx = *srcXY++;
- fy = *srcXY++;
- unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
- unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
- uint32_t c = NOFILTER_BITMAP_SHADER_SAMPLE_XY(srcPixels, x, y, srcRB);
- *dstC++ = SkAlphaMulQ(c, scale);
- }
- }
- }
- return;
- }
-
- // now init fx, fy, dx, dy
- {
- SkPoint srcPt;
- invProc(inv, SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
-
- fx = SkScalarToFixed(srcPt.fX);
- fy = SkScalarToFixed(srcPt.fY);
-
- if (this->getInverseClass() == kFixedStepInX_MatrixClass)
- (void)inv.fixedStepInX(SkIntToScalar(y), &dx, &dy);
- else
- {
- dx = SkScalarToFixed(inv.getScaleX());
- dy = SkScalarToFixed(inv.getSkewY());
- }
- }
-
-#ifndef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
- { int level = this->getMipLevel() >> 16;
- fx >>= level;
- fy >>= level;
- dx >>= level;
- dy >>= level;
- }
-#endif
-
- if (dy == 0)
- {
- int y_index = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
-// SkDEBUGF(("fy = %g, srcMaxY = %d, y_index = %d\n", SkFixedToFloat(fy), srcMaxY, y_index));
- srcPixels = (const NOFILTER_BITMAP_SHADER_TYPE*)((const char*)srcPixels + y_index * srcRB);
- if (scale == 256)
- while (--count >= 0)
- {
- unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
- fx += dx;
- *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_X(srcPixels, x);
- }
- else
- while (--count >= 0)
- {
- unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
- SkPMColor c = NOFILTER_BITMAP_SHADER_SAMPLE_X(srcPixels, x);
- fx += dx;
- *dstC++ = SkAlphaMulQ(c, scale);
- }
- }
- else // dy != 0
- {
- if (scale == 256)
- while (--count >= 0)
- {
- unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
- unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
- fx += dx;
- fy += dy;
- *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_XY(srcPixels, x, y, srcRB);
- }
- else
- while (--count >= 0)
- {
- unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
- unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
- SkPMColor c = NOFILTER_BITMAP_SHADER_SAMPLE_XY(srcPixels, x, y, srcRB);
- fx += dx;
- fy += dy;
- *dstC++ = SkAlphaMulQ(c, scale);
- }
- }
-
- NOFILTER_BITMAP_SHADER_POSTAMBLE(srcBitmap);
- }
-
- virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count)
- {
- SkASSERT(count > 0);
- SkASSERT(this->getFlags() & SkShader::kHasSpan16_Flag);
-
-#ifdef NOFILTER_BITMAP_SHADER_SPRITEPROC16
- if ((this->getTotalInverse().getType() & ~SkMatrix::kTranslate_Mask) == 0)
- {
- NOFILTER_BITMAP_SHADER_SPRITEPROC16(this, x, y, dstC, count);
- return;
- }
-#endif
-
-#ifdef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
- const SkMatrix& inv = this->getUnitInverse();
- SkMatrix::MapPtProc invProc = this->getUnitInverseProc();
-#else
- const SkMatrix& inv = this->getTotalInverse();
- SkMatrix::MapPtProc invProc = this->getInverseMapPtProc();
-#endif
- const SkBitmap& srcBitmap = this->getSrcBitmap();
- unsigned srcMaxX = srcBitmap.width() - 1;
- unsigned srcMaxY = srcBitmap.height() - 1;
- unsigned srcRB = srcBitmap.rowBytes();
- SkFixed fx, fy, dx, dy;
-
- const NOFILTER_BITMAP_SHADER_TYPE* srcPixels = (const NOFILTER_BITMAP_SHADER_TYPE*)srcBitmap.getPixels();
- NOFILTER_BITMAP_SHADER_PREAMBLE16(srcBitmap, srcRB);
-
- if (this->getInverseClass() == kPerspective_MatrixClass)
- {
- SkPerspIter iter(inv, SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, count);
- while ((count = iter.next()) != 0)
- {
- const SkFixed* srcXY = iter.getXY();
-
- while (--count >= 0)
- {
- fx = *srcXY++;
- fy = *srcXY++;
- unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
- unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
- *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_XY16(srcPixels, x, y, srcRB);
- }
- }
- return;
- }
-
- // now init fx, fy, dx, dy
- {
- SkPoint srcPt;
- invProc(inv, SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
-
- fx = SkScalarToFixed(srcPt.fX);
- fy = SkScalarToFixed(srcPt.fY);
-
- if (this->getInverseClass() == kFixedStepInX_MatrixClass)
- (void)inv.fixedStepInX(SkIntToScalar(y), &dx, &dy);
- else
- {
- dx = SkScalarToFixed(inv.getScaleX());
- dy = SkScalarToFixed(inv.getSkewY());
- }
- }
-
-#ifndef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
- { int level = this->getMipLevel() >> 16;
- fx >>= level;
- fy >>= level;
- dx >>= level;
- dy >>= level;
- }
-#endif
-
- if (dy == 0)
- {
- srcPixels = (const NOFILTER_BITMAP_SHADER_TYPE*)((const char*)srcPixels + NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY) * srcRB);
- do {
- unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
- fx += dx;
- *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_X16(srcPixels, x);
- } while (--count != 0);
- }
- else // dy != 0
- {
- do {
- unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX);
- unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY);
- fx += dx;
- fy += dy;
- *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_XY16(srcPixels, x, y, srcRB);
- } while (--count != 0);
- }
-
- NOFILTER_BITMAP_SHADER_POSTAMBLE16(srcBitmap);
- }
-private:
- typedef HasSpan16_Sampler_BitmapShader INHERITED;
-};
-
-#undef NOFILTER_BITMAP_SHADER_CLASS
-#undef NOFILTER_BITMAP_SHADER_TYPE
-#undef NOFILTER_BITMAP_SHADER_PREAMBLE
-#undef NOFILTER_BITMAP_SHADER_POSTAMBLE
-#undef NOFILTER_BITMAP_SHADER_SAMPLE_X //(x)
-#undef NOFILTER_BITMAP_SHADER_SAMPLE_XY //(x, y, rowBytes)
-#undef NOFILTER_BITMAP_SHADER_TILEMODE
-#undef NOFILTER_BITMAP_SHADER_TILEPROC
-
-#undef NOFILTER_BITMAP_SHADER_PREAMBLE16
-#undef NOFILTER_BITMAP_SHADER_POSTAMBLE16
-#undef NOFILTER_BITMAP_SHADER_SAMPLE_X16 //(x)
-#undef NOFILTER_BITMAP_SHADER_SAMPLE_XY16 //(x, y, rowBytes)
-
-#undef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE
-#undef NOFILTER_BITMAP_SHADER_SPRITEPROC16
-#undef NOFILTER_BITMAP_SHADER_SPRITEPROC32
diff --git a/chromium/third_party/skia/src/core/SkBitmap_scroll.cpp b/chromium/third_party/skia/src/core/SkBitmap_scroll.cpp
index e9c886f4a0e..00a72aa1cab 100644
--- a/chromium/third_party/skia/src/core/SkBitmap_scroll.cpp
+++ b/chromium/third_party/skia/src/core/SkBitmap_scroll.cpp
@@ -11,7 +11,7 @@
bool SkBitmap::scrollRect(const SkIRect* subset, int dx, int dy,
SkRegion* inval) const
{
- if (this->isImmutable()) {
+ if (this->isImmutable() || kUnknown_SkColorType == this->colorType()) {
return false;
}
@@ -23,25 +23,7 @@ bool SkBitmap::scrollRect(const SkIRect* subset, int dx, int dy,
tmp.scrollRect(NULL, dx, dy, inval);
}
- int shift;
-
- switch (this->config()) {
- case kIndex8_Config:
- case kA8_Config:
- shift = 0;
- break;
- case kARGB_4444_Config:
- case kRGB_565_Config:
- shift = 1;
- break;
- case kARGB_8888_Config:
- shift = 2;
- break;
- default:
- // can't scroll this config
- return false;
- }
-
+ int shift = this->bytesPerPixel() >> 1;
int width = this->width();
int height = this->height();
diff --git a/chromium/third_party/skia/src/core/SkBlitMask.h b/chromium/third_party/skia/src/core/SkBlitMask.h
index ea1da257b7b..32db43c3d8c 100644
--- a/chromium/third_party/skia/src/core/SkBlitMask.h
+++ b/chromium/third_party/skia/src/core/SkBlitMask.h
@@ -51,13 +51,13 @@ public:
* Public entry-point to return a blitmask ColorProc.
* May return NULL if config or format are not supported.
*/
- static ColorProc ColorFactory(SkBitmap::Config, SkMask::Format, SkColor);
+ static ColorProc ColorFactory(SkColorType, SkMask::Format, SkColor);
/**
* Return either platform specific optimized blitmask ColorProc,
* or NULL if no optimized routine is available.
*/
- static ColorProc PlatformColorProcs(SkBitmap::Config, SkMask::Format, SkColor);
+ static ColorProc PlatformColorProcs(SkColorType, SkMask::Format, SkColor);
/**
* Public entry-point to return a blitcolor BlitLCD16RowProc.
@@ -78,13 +78,13 @@ public:
* Public entry-point to return a blitmask RowProc.
* May return NULL if config or format are not supported.
*/
- static RowProc RowFactory(SkBitmap::Config, SkMask::Format, RowFlags);
+ static RowProc RowFactory(SkColorType, SkMask::Format, RowFlags);
/**
* Return either platform specific optimized blitmask RowProc,
* or NULL if no optimized routine is available.
*/
- static RowProc PlatformRowProcs(SkBitmap::Config, SkMask::Format, RowFlags);
+ static RowProc PlatformRowProcs(SkColorType, SkMask::Format, RowFlags);
};
#endif
diff --git a/chromium/third_party/skia/src/core/SkBlitMask_D32.cpp b/chromium/third_party/skia/src/core/SkBlitMask_D32.cpp
index 1f16d775b51..ef4d84bfcf8 100644
--- a/chromium/third_party/skia/src/core/SkBlitMask_D32.cpp
+++ b/chromium/third_party/skia/src/core/SkBlitMask_D32.cpp
@@ -1,3 +1,10 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
#include "SkBlitMask.h"
#include "SkColor.h"
#include "SkColorPriv.h"
@@ -230,16 +237,16 @@ static SkBlitMask::ColorProc D32_LCD32_Factory(SkColor color) {
return (0xFF == SkColorGetA(color)) ? D32_LCD32_Opaque : D32_LCD32_Blend;
}
-SkBlitMask::ColorProc SkBlitMask::ColorFactory(SkBitmap::Config config,
+SkBlitMask::ColorProc SkBlitMask::ColorFactory(SkColorType ct,
SkMask::Format format,
SkColor color) {
- ColorProc proc = PlatformColorProcs(config, format, color);
+ ColorProc proc = PlatformColorProcs(ct, format, color);
if (proc) {
return proc;
}
- switch (config) {
- case SkBitmap::kARGB_8888_Config:
+ switch (ct) {
+ case kN32_SkColorType:
switch (format) {
case SkMask::kA8_Format:
return D32_A8_Factory(color);
@@ -259,7 +266,7 @@ SkBlitMask::ColorProc SkBlitMask::ColorFactory(SkBitmap::Config config,
bool SkBlitMask::BlitColor(const SkBitmap& device, const SkMask& mask,
const SkIRect& clip, SkColor color) {
- ColorProc proc = ColorFactory(device.config(), mask.fFormat, color);
+ ColorProc proc = ColorFactory(device.colorType(), mask.fFormat, color);
if (proc) {
int x = clip.fLeft;
int y = clip.fTop;
@@ -353,9 +360,6 @@ static void A8_RowProc_Blend(SkPMColor* SK_RESTRICT dst,
static void A8_RowProc_Opaque(SkPMColor* SK_RESTRICT dst,
const uint8_t* SK_RESTRICT mask,
const SkPMColor* SK_RESTRICT src, int count) {
-#if 0 // suppress warning
- const uint32_t rbmask = gMask_00FF00FF;
-#endif
for (int i = 0; i < count; ++i) {
int m = mask[i];
if (m) {
@@ -551,11 +555,11 @@ static void LCD32_RowProc_Opaque(SkPMColor* SK_RESTRICT dst,
}
}
-SkBlitMask::RowProc SkBlitMask::RowFactory(SkBitmap::Config config,
+SkBlitMask::RowProc SkBlitMask::RowFactory(SkColorType ct,
SkMask::Format format,
RowFlags flags) {
// make this opt-in until chrome can rebaseline
- RowProc proc = PlatformRowProcs(config, format, flags);
+ RowProc proc = PlatformRowProcs(ct, format, flags);
if (proc) {
return proc;
}
@@ -570,8 +574,8 @@ SkBlitMask::RowProc SkBlitMask::RowFactory(SkBitmap::Config config,
};
int index;
- switch (config) {
- case SkBitmap::kARGB_8888_Config:
+ switch (ct) {
+ case kN32_SkColorType:
switch (format) {
case SkMask::kBW_Format: index = 0; break;
case SkMask::kA8_Format: index = 2; break;
diff --git a/chromium/third_party/skia/src/core/SkBlitRow_D16.cpp b/chromium/third_party/skia/src/core/SkBlitRow_D16.cpp
index e244723986a..1b2be06d125 100644
--- a/chromium/third_party/skia/src/core/SkBlitRow_D16.cpp
+++ b/chromium/third_party/skia/src/core/SkBlitRow_D16.cpp
@@ -224,15 +224,15 @@ static const SkBlitRow::Proc gDefault_565_Procs[] = {
S32A_D565_Blend_Dither
};
-SkBlitRow::Proc SkBlitRow::Factory(unsigned flags, SkBitmap::Config config) {
+SkBlitRow::Proc SkBlitRow::Factory(unsigned flags, SkColorType ct) {
SkASSERT(flags < SK_ARRAY_COUNT(gDefault_565_Procs));
// just so we don't crash
flags &= kFlags16_Mask;
SkBlitRow::Proc proc = NULL;
- switch (config) {
- case SkBitmap::kRGB_565_Config:
+ switch (ct) {
+ case kRGB_565_SkColorType:
proc = PlatformProcs565(flags);
if (NULL == proc) {
proc = gDefault_565_Procs[flags];
diff --git a/chromium/third_party/skia/src/core/SkBlitRow_D32.cpp b/chromium/third_party/skia/src/core/SkBlitRow_D32.cpp
index c858af6318a..f8cf9a34a9c 100644
--- a/chromium/third_party/skia/src/core/SkBlitRow_D32.cpp
+++ b/chromium/third_party/skia/src/core/SkBlitRow_D32.cpp
@@ -18,7 +18,7 @@ static void S32_Opaque_BlitRow32(SkPMColor* SK_RESTRICT dst,
const SkPMColor* SK_RESTRICT src,
int count, U8CPU alpha) {
SkASSERT(255 == alpha);
- memcpy(dst, src, count * sizeof(SkPMColor));
+ sk_memcpy32(dst, src, count);
}
static void S32_Blend_BlitRow32(SkPMColor* SK_RESTRICT dst,
diff --git a/chromium/third_party/skia/src/core/SkBlitter.cpp b/chromium/third_party/skia/src/core/SkBlitter.cpp
index 9682d5572a9..cb84ec7d9db 100644
--- a/chromium/third_party/skia/src/core/SkBlitter.cpp
+++ b/chromium/third_party/skia/src/core/SkBlitter.cpp
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -6,25 +5,33 @@
* found in the LICENSE file.
*/
-
#include "SkBlitter.h"
#include "SkAntiRun.h"
#include "SkColor.h"
#include "SkColorFilter.h"
+#include "SkCoreBlitters.h"
#include "SkFilterShader.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkMask.h"
#include "SkMaskFilter.h"
-#include "SkTemplatesPriv.h"
+#include "SkString.h"
#include "SkTLazy.h"
#include "SkUtils.h"
#include "SkXfermode.h"
-#include "SkString.h"
SkBlitter::~SkBlitter() {}
bool SkBlitter::isNullBlitter() const { return false; }
+bool SkBlitter::resetShaderContext(const SkShader::ContextRec&) {
+ return true;
+}
+
+SkShader::Context* SkBlitter::getShaderContext() const {
+ return NULL;
+}
+
const SkBitmap* SkBlitter::justAnOpaqueColor(uint32_t* value) {
return NULL;
}
@@ -567,104 +574,129 @@ class Sk3DShader : public SkShader {
public:
Sk3DShader(SkShader* proxy) : fProxy(proxy) {
SkSafeRef(proxy);
- fMask = NULL;
}
virtual ~Sk3DShader() {
SkSafeUnref(fProxy);
}
- void setMask(const SkMask* mask) { fMask = mask; }
-
- virtual bool setContext(const SkBitmap& device, const SkPaint& paint,
- const SkMatrix& matrix) SK_OVERRIDE {
- if (!this->INHERITED::setContext(device, paint, matrix)) {
- return false;
- }
+ virtual size_t contextSize() const SK_OVERRIDE {
+ size_t size = sizeof(Sk3DShaderContext);
if (fProxy) {
- if (!fProxy->setContext(device, paint, matrix)) {
- // must keep our set/end context calls balanced
- this->INHERITED::endContext();
- return false;
- }
- } else {
- fPMColor = SkPreMultiplyColor(paint.getColor());
+ size += fProxy->contextSize();
}
- return true;
+ return size;
}
- virtual void endContext() SK_OVERRIDE {
+ virtual Context* onCreateContext(const ContextRec& rec, void* storage) const SK_OVERRIDE {
+ SkShader::Context* proxyContext = NULL;
if (fProxy) {
- fProxy->endContext();
+ char* proxyContextStorage = (char*) storage + sizeof(Sk3DShaderContext);
+ proxyContext = fProxy->createContext(rec, proxyContextStorage);
+ if (!proxyContext) {
+ return NULL;
+ }
}
- this->INHERITED::endContext();
+ return SkNEW_PLACEMENT_ARGS(storage, Sk3DShaderContext, (*this, rec, proxyContext));
}
- virtual void shadeSpan(int x, int y, SkPMColor span[], int count) SK_OVERRIDE {
- if (fProxy) {
- fProxy->shadeSpan(x, y, span, count);
+ class Sk3DShaderContext : public SkShader::Context {
+ public:
+ // Calls proxyContext's destructor but will NOT free its memory.
+ Sk3DShaderContext(const Sk3DShader& shader, const ContextRec& rec,
+ SkShader::Context* proxyContext)
+ : INHERITED(shader, rec)
+ , fMask(NULL)
+ , fProxyContext(proxyContext)
+ {
+ if (!fProxyContext) {
+ fPMColor = SkPreMultiplyColor(rec.fPaint->getColor());
+ }
}
- if (fMask == NULL) {
- if (fProxy == NULL) {
- sk_memset32(span, fPMColor, count);
+ virtual ~Sk3DShaderContext() {
+ if (fProxyContext) {
+ fProxyContext->~Context();
}
- return;
}
- SkASSERT(fMask->fBounds.contains(x, y));
- SkASSERT(fMask->fBounds.contains(x + count - 1, y));
+ void setMask(const SkMask* mask) { fMask = mask; }
- size_t size = fMask->computeImageSize();
- const uint8_t* alpha = fMask->getAddr8(x, y);
- const uint8_t* mulp = alpha + size;
- const uint8_t* addp = mulp + size;
+ virtual void shadeSpan(int x, int y, SkPMColor span[], int count) SK_OVERRIDE {
+ if (fProxyContext) {
+ fProxyContext->shadeSpan(x, y, span, count);
+ }
- if (fProxy) {
- for (int i = 0; i < count; i++) {
- if (alpha[i]) {
- SkPMColor c = span[i];
- if (c) {
- unsigned a = SkGetPackedA32(c);
- unsigned r = SkGetPackedR32(c);
- unsigned g = SkGetPackedG32(c);
- unsigned b = SkGetPackedB32(c);
+ if (fMask == NULL) {
+ if (fProxyContext == NULL) {
+ sk_memset32(span, fPMColor, count);
+ }
+ return;
+ }
+ SkASSERT(fMask->fBounds.contains(x, y));
+ SkASSERT(fMask->fBounds.contains(x + count - 1, y));
+
+ size_t size = fMask->computeImageSize();
+ const uint8_t* alpha = fMask->getAddr8(x, y);
+ const uint8_t* mulp = alpha + size;
+ const uint8_t* addp = mulp + size;
+
+ if (fProxyContext) {
+ for (int i = 0; i < count; i++) {
+ if (alpha[i]) {
+ SkPMColor c = span[i];
+ if (c) {
+ unsigned a = SkGetPackedA32(c);
+ unsigned r = SkGetPackedR32(c);
+ unsigned g = SkGetPackedG32(c);
+ unsigned b = SkGetPackedB32(c);
+
+ unsigned mul = SkAlpha255To256(mulp[i]);
+ unsigned add = addp[i];
+
+ r = SkFastMin32(SkAlphaMul(r, mul) + add, a);
+ g = SkFastMin32(SkAlphaMul(g, mul) + add, a);
+ b = SkFastMin32(SkAlphaMul(b, mul) + add, a);
+
+ span[i] = SkPackARGB32(a, r, g, b);
+ }
+ } else {
+ span[i] = 0;
+ }
+ }
+ } else { // color
+ unsigned a = SkGetPackedA32(fPMColor);
+ unsigned r = SkGetPackedR32(fPMColor);
+ unsigned g = SkGetPackedG32(fPMColor);
+ unsigned b = SkGetPackedB32(fPMColor);
+ for (int i = 0; i < count; i++) {
+ if (alpha[i]) {
unsigned mul = SkAlpha255To256(mulp[i]);
unsigned add = addp[i];
- r = SkFastMin32(SkAlphaMul(r, mul) + add, a);
- g = SkFastMin32(SkAlphaMul(g, mul) + add, a);
- b = SkFastMin32(SkAlphaMul(b, mul) + add, a);
-
- span[i] = SkPackARGB32(a, r, g, b);
+ span[i] = SkPackARGB32( a,
+ SkFastMin32(SkAlphaMul(r, mul) + add, a),
+ SkFastMin32(SkAlphaMul(g, mul) + add, a),
+ SkFastMin32(SkAlphaMul(b, mul) + add, a));
+ } else {
+ span[i] = 0;
}
- } else {
- span[i] = 0;
- }
- }
- } else { // color
- unsigned a = SkGetPackedA32(fPMColor);
- unsigned r = SkGetPackedR32(fPMColor);
- unsigned g = SkGetPackedG32(fPMColor);
- unsigned b = SkGetPackedB32(fPMColor);
- for (int i = 0; i < count; i++) {
- if (alpha[i]) {
- unsigned mul = SkAlpha255To256(mulp[i]);
- unsigned add = addp[i];
-
- span[i] = SkPackARGB32( a,
- SkFastMin32(SkAlphaMul(r, mul) + add, a),
- SkFastMin32(SkAlphaMul(g, mul) + add, a),
- SkFastMin32(SkAlphaMul(b, mul) + add, a));
- } else {
- span[i] = 0;
}
}
}
- }
-#ifdef SK_DEVELOPER
+ private:
+ // Unowned.
+ const SkMask* fMask;
+ // Memory is unowned, but we need to call the destructor.
+ SkShader::Context* fProxyContext;
+ SkPMColor fPMColor;
+
+ typedef SkShader::Context INHERITED;
+ };
+
+#ifndef SK_IGNORE_TO_STRING
virtual void toString(SkString* str) const SK_OVERRIDE {
str->append("Sk3DShader: (");
@@ -682,37 +714,33 @@ public:
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Sk3DShader)
protected:
- Sk3DShader(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
+ Sk3DShader(SkReadBuffer& buffer) : INHERITED(buffer) {
fProxy = buffer.readShader();
- fPMColor = buffer.readColor();
- fMask = NULL;
+ // Leaving this here until we bump the picture version, though this
+ // shader should never be recorded.
+ buffer.readColor();
}
- virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
+ virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE {
this->INHERITED::flatten(buffer);
buffer.writeFlattenable(fProxy);
- buffer.writeColor(fPMColor);
+ // Leaving this here until we bump the picture version, though this
+ // shader should never be recorded.
+ buffer.writeColor(SkColor());
}
private:
SkShader* fProxy;
- SkPMColor fPMColor;
- const SkMask* fMask;
typedef SkShader INHERITED;
};
class Sk3DBlitter : public SkBlitter {
public:
- Sk3DBlitter(SkBlitter* proxy, Sk3DShader* shader, void (*killProc)(void*))
- : fProxy(proxy), f3DShader(shader), fKillProc(killProc) {
- shader->ref();
- }
-
- virtual ~Sk3DBlitter() {
- f3DShader->unref();
- fKillProc(fProxy);
- }
+ Sk3DBlitter(SkBlitter* proxy, Sk3DShader::Sk3DShaderContext* shaderContext)
+ : fProxy(proxy)
+ , f3DShaderContext(shaderContext)
+ {}
virtual void blitH(int x, int y, int width) {
fProxy->blitH(x, y, width);
@@ -733,68 +761,32 @@ public:
virtual void blitMask(const SkMask& mask, const SkIRect& clip) {
if (mask.fFormat == SkMask::k3D_Format) {
- f3DShader->setMask(&mask);
+ f3DShaderContext->setMask(&mask);
((SkMask*)&mask)->fFormat = SkMask::kA8_Format;
fProxy->blitMask(mask, clip);
((SkMask*)&mask)->fFormat = SkMask::k3D_Format;
- f3DShader->setMask(NULL);
+ f3DShaderContext->setMask(NULL);
} else {
fProxy->blitMask(mask, clip);
}
}
private:
- SkBlitter* fProxy;
- Sk3DShader* f3DShader;
- void (*fKillProc)(void*);
+ // Both pointers are unowned. They will be deleted by SkSmallAllocator.
+ SkBlitter* fProxy;
+ Sk3DShader::Sk3DShaderContext* f3DShaderContext;
};
///////////////////////////////////////////////////////////////////////////////
#include "SkCoreBlitters.h"
-class SkAutoCallProc {
-public:
- typedef void (*Proc)(void*);
-
- SkAutoCallProc(void* obj, Proc proc)
- : fObj(obj), fProc(proc) {}
-
- ~SkAutoCallProc() {
- if (fObj && fProc) {
- fProc(fObj);
- }
- }
-
- void* get() const { return fObj; }
-
- void* detach() {
- void* obj = fObj;
- fObj = NULL;
- return obj;
- }
-
-private:
- void* fObj;
- Proc fProc;
-};
-#define SkAutoCallProc(...) SK_REQUIRE_LOCAL_VAR(SkAutoCallProc)
-
-static void destroy_blitter(void* blitter) {
- ((SkBlitter*)blitter)->~SkBlitter();
-}
-
-static void delete_blitter(void* blitter) {
- SkDELETE((SkBlitter*)blitter);
-}
-
static bool just_solid_color(const SkPaint& paint) {
if (paint.getAlpha() == 0xFF && paint.getColorFilter() == NULL) {
SkShader* shader = paint.getShader();
- if (NULL == shader ||
- (shader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
+ if (NULL == shader) {
return true;
}
}
@@ -811,7 +803,7 @@ enum XferInterp {
};
static XferInterp interpret_xfermode(const SkPaint& paint, SkXfermode* xfer,
- SkBitmap::Config deviceConfig) {
+ SkColorType deviceCT) {
SkXfermode::Mode mode;
if (SkXfermode::AsMode(xfer, &mode)) {
@@ -826,12 +818,12 @@ static XferInterp interpret_xfermode(const SkPaint& paint, SkXfermode* xfer,
case SkXfermode::kSrcOver_Mode:
return kSrcOver_XferInterp;
case SkXfermode::kDstOver_Mode:
- if (SkBitmap::kRGB_565_Config == deviceConfig) {
+ if (kRGB_565_SkColorType == deviceCT) {
return kSkipDrawing_XferInterp;
}
break;
case SkXfermode::kSrcIn_Mode:
- if (SkBitmap::kRGB_565_Config == deviceConfig &&
+ if (kRGB_565_SkColorType == deviceCT &&
just_solid_color(paint)) {
return kSrcOver_XferInterp;
}
@@ -851,17 +843,17 @@ static XferInterp interpret_xfermode(const SkPaint& paint, SkXfermode* xfer,
SkBlitter* SkBlitter::Choose(const SkBitmap& device,
const SkMatrix& matrix,
const SkPaint& origPaint,
- void* storage, size_t storageSize,
+ SkTBlitterAllocator* allocator,
bool drawCoverage) {
- SkASSERT(storageSize == 0 || storage != NULL);
+ SkASSERT(allocator != NULL);
SkBlitter* blitter = NULL;
// which check, in case we're being called by a client with a dummy device
// (e.g. they have a bounder that always aborts the draw)
- if (SkBitmap::kNo_Config == device.config() ||
- (drawCoverage && (SkBitmap::kA8_Config != device.config()))) {
- SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
+ if (kUnknown_SkColorType == device.colorType() ||
+ (drawCoverage && (kAlpha_8_SkColorType != device.colorType()))) {
+ blitter = allocator->createT<SkNullBlitter>();
return blitter;
}
@@ -881,14 +873,15 @@ SkBlitter* SkBlitter::Choose(const SkBitmap& device,
}
if (NULL != mode) {
- switch (interpret_xfermode(*paint, mode, device.config())) {
+ switch (interpret_xfermode(*paint, mode, device.colorType())) {
case kSrcOver_XferInterp:
mode = NULL;
paint.writable()->setXfermode(NULL);
break;
- case kSkipDrawing_XferInterp:
- SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
+ case kSkipDrawing_XferInterp:{
+ blitter = allocator->createT<SkNullBlitter>();
return blitter;
+ }
default:
break;
}
@@ -910,8 +903,9 @@ SkBlitter* SkBlitter::Choose(const SkBitmap& device,
if (NULL == shader) {
if (mode) {
// xfermodes (and filters) require shaders for our current blitters
- shader = SkNEW(SkColorShader);
+ shader = SkNEW_ARGS(SkColorShader, (paint->getColor()));
paint.writable()->setShader(shader)->unref();
+ paint.writable()->setAlpha(0xFF);
} else if (cf) {
// if no shader && no xfermode, we just apply the colorfilter to
// our color and move on.
@@ -931,90 +925,117 @@ SkBlitter* SkBlitter::Choose(const SkBitmap& device,
}
/*
- * We need to have balanced calls to the shader:
- * setContext
- * endContext
- * We make the first call here, in case it fails we can abort the draw.
- * The endContext() call is made by the blitter (assuming setContext did
- * not fail) in its destructor.
+ * We create a SkShader::Context object, and store it on the blitter.
*/
- if (shader && !shader->setContext(device, *paint, matrix)) {
- SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
- return blitter;
+ SkShader::Context* shaderContext;
+ if (shader) {
+ SkShader::ContextRec rec(device, *paint, matrix);
+ // Try to create the ShaderContext
+ void* storage = allocator->reserveT<SkShader::Context>(shader->contextSize());
+ shaderContext = shader->createContext(rec, storage);
+ if (!shaderContext) {
+ allocator->freeLast();
+ blitter = allocator->createT<SkNullBlitter>();
+ return blitter;
+ }
+ SkASSERT(shaderContext);
+ SkASSERT((void*) shaderContext == storage);
+ } else {
+ shaderContext = NULL;
}
- switch (device.config()) {
- case SkBitmap::kA8_Config:
+ switch (device.colorType()) {
+ case kAlpha_8_SkColorType:
if (drawCoverage) {
SkASSERT(NULL == shader);
SkASSERT(NULL == paint->getXfermode());
- SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Coverage_Blitter,
- storage, storageSize, (device, *paint));
+ blitter = allocator->createT<SkA8_Coverage_Blitter>(device, *paint);
} else if (shader) {
- SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Shader_Blitter,
- storage, storageSize, (device, *paint));
+ blitter = allocator->createT<SkA8_Shader_Blitter>(device, *paint, shaderContext);
} else {
- SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Blitter,
- storage, storageSize, (device, *paint));
+ blitter = allocator->createT<SkA8_Blitter>(device, *paint);
}
break;
- case SkBitmap::kRGB_565_Config:
- blitter = SkBlitter_ChooseD565(device, *paint, storage, storageSize);
+ case kRGB_565_SkColorType:
+ blitter = SkBlitter_ChooseD565(device, *paint, shaderContext, allocator);
break;
- case SkBitmap::kARGB_8888_Config:
+ case kN32_SkColorType:
if (shader) {
- SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Shader_Blitter,
- storage, storageSize, (device, *paint));
+ blitter = allocator->createT<SkARGB32_Shader_Blitter>(
+ device, *paint, shaderContext);
} else if (paint->getColor() == SK_ColorBLACK) {
- SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Black_Blitter,
- storage, storageSize, (device, *paint));
+ blitter = allocator->createT<SkARGB32_Black_Blitter>(device, *paint);
} else if (paint->getAlpha() == 0xFF) {
- SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Opaque_Blitter,
- storage, storageSize, (device, *paint));
+ blitter = allocator->createT<SkARGB32_Opaque_Blitter>(device, *paint);
} else {
- SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Blitter,
- storage, storageSize, (device, *paint));
+ blitter = allocator->createT<SkARGB32_Blitter>(device, *paint);
}
break;
default:
SkDEBUGFAIL("unsupported device config");
- SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
+ blitter = allocator->createT<SkNullBlitter>();
break;
}
if (shader3D) {
- void (*proc)(void*) = ((void*)storage == (void*)blitter) ? destroy_blitter : delete_blitter;
- SkAutoCallProc tmp(blitter, proc);
-
- blitter = SkNEW_ARGS(Sk3DBlitter, (blitter, shader3D, proc));
- (void)tmp.detach();
+ SkBlitter* innerBlitter = blitter;
+ // innerBlitter was allocated by allocator, which will delete it.
+ // We know shaderContext is of type Sk3DShaderContext because it belongs to shader3D.
+ blitter = allocator->createT<Sk3DBlitter>(innerBlitter,
+ static_cast<Sk3DShader::Sk3DShaderContext*>(shaderContext));
}
return blitter;
}
///////////////////////////////////////////////////////////////////////////////
-const uint16_t gMask_0F0F = 0xF0F;
-const uint32_t gMask_00FF00FF = 0xFF00FF;
+class SkTransparentShaderContext : public SkShader::Context {
+public:
+ SkTransparentShaderContext(const SkShader& shader, const SkShader::ContextRec& rec)
+ // Override rec with the identity matrix, so it is guaranteed to be invertible.
+ : INHERITED(shader, SkShader::ContextRec(*rec.fDevice, *rec.fPaint, SkMatrix::I())) {}
-///////////////////////////////////////////////////////////////////////////////
+ virtual void shadeSpan(int x, int y, SkPMColor colors[], int count) SK_OVERRIDE {
+ sk_bzero(colors, count * sizeof(SkPMColor));
+ }
+
+private:
+ typedef SkShader::Context INHERITED;
+};
-SkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint)
- : INHERITED(device) {
- fShader = paint.getShader();
+SkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint,
+ SkShader::Context* shaderContext)
+ : INHERITED(device)
+ , fShader(paint.getShader())
+ , fShaderContext(shaderContext) {
SkASSERT(fShader);
- SkASSERT(fShader->setContextHasBeenCalled());
+ SkASSERT(fShaderContext);
fShader->ref();
- fShaderFlags = fShader->getFlags();
+ fShaderFlags = fShaderContext->getFlags();
}
SkShaderBlitter::~SkShaderBlitter() {
- SkASSERT(fShader->setContextHasBeenCalled());
- fShader->endContext();
fShader->unref();
}
+
+bool SkShaderBlitter::resetShaderContext(const SkShader::ContextRec& rec) {
+ // Only destroy the old context if we have a new one. We need to ensure to have a
+ // live context in fShaderContext because the storage is owned by an SkSmallAllocator
+ // outside of this class.
+ // The new context will be of the same size as the old one because we use the same
+ // shader to create it. It is therefore safe to re-use the storage.
+ fShaderContext->~Context();
+ SkShader::Context* ctx = fShader->createContext(rec, (void*)fShaderContext);
+ if (NULL == ctx) {
+ // Need a valid context in fShaderContext's storage, so we can later (or our caller) call
+ // the in-place destructor.
+ SkNEW_PLACEMENT_ARGS(fShaderContext, SkTransparentShaderContext, (*fShader, rec));
+ return false;
+ }
+ return true;
+}
diff --git a/chromium/third_party/skia/src/core/SkBlitter.h b/chromium/third_party/skia/src/core/SkBlitter.h
index b659fe47358..a3a2196122e 100644
--- a/chromium/third_party/skia/src/core/SkBlitter.h
+++ b/chromium/third_party/skia/src/core/SkBlitter.h
@@ -11,11 +11,14 @@
#define SkBlitter_DEFINED
#include "SkBitmap.h"
+#include "SkBitmapProcShader.h"
+#include "SkMask.h"
#include "SkMatrix.h"
#include "SkPaint.h"
#include "SkRefCnt.h"
#include "SkRegion.h"
-#include "SkMask.h"
+#include "SkShader.h"
+#include "SkSmallAllocator.h"
/** SkBlitter and its subclasses are responsible for actually writing pixels
into memory. Besides efficiency, they handle clipping and antialiasing.
@@ -58,6 +61,12 @@ public:
*/
virtual bool isNullBlitter() const;
+ /**
+ * Special methods for SkShaderBlitter. On all other classes this is a no-op.
+ */
+ virtual bool resetShaderContext(const SkShader::ContextRec&);
+ virtual SkShader::Context* getShaderContext() const;
+
///@name non-virtual helpers
void blitMaskRegion(const SkMask& mask, const SkRegion& clip);
void blitRectRegion(const SkIRect& rect, const SkRegion& clip);
@@ -69,21 +78,15 @@ public:
*/
static SkBlitter* Choose(const SkBitmap& device,
const SkMatrix& matrix,
- const SkPaint& paint) {
- return Choose(device, matrix, paint, NULL, 0);
- }
-
- static SkBlitter* Choose(const SkBitmap& device,
- const SkMatrix& matrix,
const SkPaint& paint,
- void* storage, size_t storageSize,
+ SkTBlitterAllocator*,
bool drawCoverage = false);
static SkBlitter* ChooseSprite(const SkBitmap& device,
const SkPaint&,
const SkBitmap& src,
int left, int top,
- void* storage, size_t storageSize);
+ SkTBlitterAllocator*);
///@}
private:
diff --git a/chromium/third_party/skia/src/core/SkBlitter_A8.cpp b/chromium/third_party/skia/src/core/SkBlitter_A8.cpp
index 983a226e346..11f425903b9 100644
--- a/chromium/third_party/skia/src/core/SkBlitter_A8.cpp
+++ b/chromium/third_party/skia/src/core/SkBlitter_A8.cpp
@@ -228,11 +228,12 @@ void SkA8_Blitter::blitRect(int x, int y, int width, int height) {
///////////////////////////////////////////////////////////////////////
-SkA8_Shader_Blitter::SkA8_Shader_Blitter(const SkBitmap& device, const SkPaint& paint)
- : INHERITED(device, paint) {
+SkA8_Shader_Blitter::SkA8_Shader_Blitter(const SkBitmap& device, const SkPaint& paint,
+ SkShader::Context* shaderContext)
+ : INHERITED(device, paint, shaderContext) {
if ((fXfermode = paint.getXfermode()) != NULL) {
fXfermode->ref();
- SkASSERT(fShader);
+ SkASSERT(fShaderContext);
}
int width = device.width();
@@ -250,13 +251,14 @@ void SkA8_Shader_Blitter::blitH(int x, int y, int width) {
(unsigned)(x + width) <= (unsigned)fDevice.width());
uint8_t* device = fDevice.getAddr8(x, y);
+ SkShader::Context* shaderContext = fShaderContext;
- if ((fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) && !fXfermode) {
+ if ((shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag) && !fXfermode) {
memset(device, 0xFF, width);
} else {
SkPMColor* span = fBuffer;
- fShader->shadeSpan(x, y, span, width);
+ shaderContext->shadeSpan(x, y, span, width);
if (fXfermode) {
fXfermode->xferA8(device, span, width, NULL);
} else {
@@ -282,12 +284,12 @@ static inline uint8_t aa_blend8(SkPMColor src, U8CPU da, int aa) {
void SkA8_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
const int16_t runs[]) {
- SkShader* shader = fShader;
- SkXfermode* mode = fXfermode;
- uint8_t* aaExpand = fAAExpand;
- SkPMColor* span = fBuffer;
- uint8_t* device = fDevice.getAddr8(x, y);
- int opaque = fShader->getFlags() & SkShader::kOpaqueAlpha_Flag;
+ SkShader::Context* shaderContext = fShaderContext;
+ SkXfermode* mode = fXfermode;
+ uint8_t* aaExpand = fAAExpand;
+ SkPMColor* span = fBuffer;
+ uint8_t* device = fDevice.getAddr8(x, y);
+ int opaque = shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag;
for (;;) {
int count = *runs;
@@ -299,7 +301,7 @@ void SkA8_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
if (opaque && aa == 255 && mode == NULL) {
memset(device, 0xFF, count);
} else {
- shader->shadeSpan(x, y, span, count);
+ shaderContext->shadeSpan(x, y, span, count);
if (mode) {
memset(aaExpand, aa, count);
mode->xferA8(device, span, count, aaExpand);
@@ -329,11 +331,12 @@ void SkA8_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
int height = clip.height();
uint8_t* device = fDevice.getAddr8(x, y);
const uint8_t* alpha = mask.getAddr8(x, y);
+ SkShader::Context* shaderContext = fShaderContext;
SkPMColor* span = fBuffer;
while (--height >= 0) {
- fShader->shadeSpan(x, y, span, width);
+ shaderContext->shadeSpan(x, y, span, width);
if (fXfermode) {
fXfermode->xferA8(device, span, width, alpha);
} else {
diff --git a/chromium/third_party/skia/src/core/SkBlitter_ARGB32.cpp b/chromium/third_party/skia/src/core/SkBlitter_ARGB32.cpp
index d4bec1bc086..f86bc47074b 100644
--- a/chromium/third_party/skia/src/core/SkBlitter_ARGB32.cpp
+++ b/chromium/third_party/skia/src/core/SkBlitter_ARGB32.cpp
@@ -275,14 +275,16 @@ static void blend_srcmode(SkPMColor* SK_RESTRICT device,
}
SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkBitmap& device,
- const SkPaint& paint) : INHERITED(device, paint) {
+ const SkPaint& paint, SkShader::Context* shaderContext)
+ : INHERITED(device, paint, shaderContext)
+{
fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor)));
fXfermode = paint.getXfermode();
SkSafeRef(fXfermode);
int flags = 0;
- if (!(fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
+ if (!(shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
flags |= SkBlitRow::kSrcPixelAlpha_Flag32;
}
// we call this on the output from the shader
@@ -292,7 +294,7 @@ SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkBitmap& device,
fShadeDirectlyIntoDevice = false;
if (fXfermode == NULL) {
- if (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) {
+ if (shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag) {
fShadeDirectlyIntoDevice = true;
}
} else {
@@ -305,7 +307,7 @@ SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkBitmap& device,
}
}
- fConstInY = SkToBool(fShader->getFlags() & SkShader::kConstInY32_Flag);
+ fConstInY = SkToBool(shaderContext->getFlags() & SkShader::kConstInY32_Flag);
}
SkARGB32_Shader_Blitter::~SkARGB32_Shader_Blitter() {
@@ -319,10 +321,10 @@ void SkARGB32_Shader_Blitter::blitH(int x, int y, int width) {
uint32_t* device = fDevice.getAddr32(x, y);
if (fShadeDirectlyIntoDevice) {
- fShader->shadeSpan(x, y, device, width);
+ fShaderContext->shadeSpan(x, y, device, width);
} else {
SkPMColor* span = fBuffer;
- fShader->shadeSpan(x, y, span, width);
+ fShaderContext->shadeSpan(x, y, span, width);
if (fXfermode) {
fXfermode->xfer32(device, span, width, NULL);
} else {
@@ -335,22 +337,22 @@ void SkARGB32_Shader_Blitter::blitRect(int x, int y, int width, int height) {
SkASSERT(x >= 0 && y >= 0 &&
x + width <= fDevice.width() && y + height <= fDevice.height());
- uint32_t* device = fDevice.getAddr32(x, y);
- size_t deviceRB = fDevice.rowBytes();
- SkShader* shader = fShader;
- SkPMColor* span = fBuffer;
+ uint32_t* device = fDevice.getAddr32(x, y);
+ size_t deviceRB = fDevice.rowBytes();
+ SkShader::Context* shaderContext = fShaderContext;
+ SkPMColor* span = fBuffer;
if (fConstInY) {
if (fShadeDirectlyIntoDevice) {
// shade the first row directly into the device
- fShader->shadeSpan(x, y, device, width);
+ shaderContext->shadeSpan(x, y, device, width);
span = device;
while (--height > 0) {
device = (uint32_t*)((char*)device + deviceRB);
memcpy(device, span, width << 2);
}
} else {
- fShader->shadeSpan(x, y, span, width);
+ shaderContext->shadeSpan(x, y, span, width);
SkXfermode* xfer = fXfermode;
if (xfer) {
do {
@@ -372,7 +374,7 @@ void SkARGB32_Shader_Blitter::blitRect(int x, int y, int width, int height) {
if (fShadeDirectlyIntoDevice) {
void* ctx;
- SkShader::ShadeProc shadeProc = fShader->asAShadeProc(&ctx);
+ SkShader::Context::ShadeProc shadeProc = shaderContext->asAShadeProc(&ctx);
if (shadeProc) {
do {
shadeProc(ctx, x, y, device, width);
@@ -381,7 +383,7 @@ void SkARGB32_Shader_Blitter::blitRect(int x, int y, int width, int height) {
} while (--height > 0);
} else {
do {
- shader->shadeSpan(x, y, device, width);
+ shaderContext->shadeSpan(x, y, device, width);
y += 1;
device = (uint32_t*)((char*)device + deviceRB);
} while (--height > 0);
@@ -390,7 +392,7 @@ void SkARGB32_Shader_Blitter::blitRect(int x, int y, int width, int height) {
SkXfermode* xfer = fXfermode;
if (xfer) {
do {
- shader->shadeSpan(x, y, span, width);
+ shaderContext->shadeSpan(x, y, span, width);
xfer->xfer32(device, span, width, NULL);
y += 1;
device = (uint32_t*)((char*)device + deviceRB);
@@ -398,7 +400,7 @@ void SkARGB32_Shader_Blitter::blitRect(int x, int y, int width, int height) {
} else {
SkBlitRow::Proc32 proc = fProc32;
do {
- shader->shadeSpan(x, y, span, width);
+ shaderContext->shadeSpan(x, y, span, width);
proc(device, span, width, 255);
y += 1;
device = (uint32_t*)((char*)device + deviceRB);
@@ -409,9 +411,9 @@ void SkARGB32_Shader_Blitter::blitRect(int x, int y, int width, int height) {
void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
const int16_t runs[]) {
- SkPMColor* span = fBuffer;
- uint32_t* device = fDevice.getAddr32(x, y);
- SkShader* shader = fShader;
+ SkPMColor* span = fBuffer;
+ uint32_t* device = fDevice.getAddr32(x, y);
+ SkShader::Context* shaderContext = fShaderContext;
if (fXfermode && !fShadeDirectlyIntoDevice) {
for (;;) {
@@ -422,7 +424,7 @@ void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
break;
int aa = *antialias;
if (aa) {
- shader->shadeSpan(x, y, span, count);
+ shaderContext->shadeSpan(x, y, span, count);
if (aa == 255) {
xfer->xfer32(device, span, count, NULL);
} else {
@@ -438,7 +440,7 @@ void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
x += count;
}
} else if (fShadeDirectlyIntoDevice ||
- (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
+ (shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
for (;;) {
int count = *runs;
if (count <= 0) {
@@ -448,9 +450,9 @@ void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
if (aa) {
if (aa == 255) {
// cool, have the shader draw right into the device
- shader->shadeSpan(x, y, device, count);
+ shaderContext->shadeSpan(x, y, device, count);
} else {
- shader->shadeSpan(x, y, span, count);
+ shaderContext->shadeSpan(x, y, span, count);
fProc32Blend(device, span, count, aa);
}
}
@@ -467,7 +469,7 @@ void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
}
int aa = *antialias;
if (aa) {
- fShader->shadeSpan(x, y, span, count);
+ shaderContext->shadeSpan(x, y, span, count);
if (aa == 255) {
fProc32(device, span, count, 255);
} else {
@@ -491,13 +493,14 @@ void SkARGB32_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip)
SkASSERT(mask.fBounds.contains(clip));
+ SkShader::Context* shaderContext = fShaderContext;
SkBlitMask::RowProc proc = NULL;
if (!fXfermode) {
unsigned flags = 0;
- if (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) {
+ if (shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag) {
flags |= SkBlitMask::kSrcIsOpaque_RowFlag;
}
- proc = SkBlitMask::RowFactory(SkBitmap::kARGB_8888_Config, mask.fFormat,
+ proc = SkBlitMask::RowFactory(kN32_SkColorType, mask.fFormat,
(SkBlitMask::RowFlags)flags);
if (NULL == proc) {
this->INHERITED::blitMask(mask, clip);
@@ -515,14 +518,13 @@ void SkARGB32_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip)
const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y);
const size_t maskRB = mask.fRowBytes;
- SkShader* shader = fShader;
SkPMColor* span = fBuffer;
if (fXfermode) {
SkASSERT(SkMask::kA8_Format == mask.fFormat);
SkXfermode* xfer = fXfermode;
do {
- shader->shadeSpan(x, y, span, width);
+ shaderContext->shadeSpan(x, y, span, width);
xfer->xfer32((SkPMColor*)dstRow, span, width, maskRow);
dstRow += dstRB;
maskRow += maskRB;
@@ -530,7 +532,7 @@ void SkARGB32_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip)
} while (--height > 0);
} else {
do {
- shader->shadeSpan(x, y, span, width);
+ shaderContext->shadeSpan(x, y, span, width);
proc(dstRow, maskRow, span, width);
dstRow += dstRB;
maskRow += maskRB;
@@ -542,13 +544,13 @@ void SkARGB32_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip)
void SkARGB32_Shader_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height());
- uint32_t* device = fDevice.getAddr32(x, y);
- size_t deviceRB = fDevice.rowBytes();
- SkShader* shader = fShader;
+ uint32_t* device = fDevice.getAddr32(x, y);
+ size_t deviceRB = fDevice.rowBytes();
+ SkShader::Context* shaderContext = fShaderContext;
if (fConstInY) {
SkPMColor c;
- fShader->shadeSpan(x, y, &c, 1);
+ shaderContext->shadeSpan(x, y, &c, 1);
if (fShadeDirectlyIntoDevice) {
if (255 == alpha) {
@@ -582,7 +584,7 @@ void SkARGB32_Shader_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
if (fShadeDirectlyIntoDevice) {
void* ctx;
- SkShader::ShadeProc shadeProc = fShader->asAShadeProc(&ctx);
+ SkShader::Context::ShadeProc shadeProc = shaderContext->asAShadeProc(&ctx);
if (255 == alpha) {
if (shadeProc) {
do {
@@ -592,7 +594,7 @@ void SkARGB32_Shader_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
} while (--height > 0);
} else {
do {
- shader->shadeSpan(x, y, device, 1);
+ shaderContext->shadeSpan(x, y, device, 1);
y += 1;
device = (uint32_t*)((char*)device + deviceRB);
} while (--height > 0);
@@ -608,7 +610,7 @@ void SkARGB32_Shader_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
} while (--height > 0);
} else {
do {
- shader->shadeSpan(x, y, &c, 1);
+ shaderContext->shadeSpan(x, y, &c, 1);
*device = SkFourByteInterp(c, *device, alpha);
y += 1;
device = (uint32_t*)((char*)device + deviceRB);
@@ -620,7 +622,7 @@ void SkARGB32_Shader_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
SkXfermode* xfer = fXfermode;
if (xfer) {
do {
- shader->shadeSpan(x, y, span, 1);
+ shaderContext->shadeSpan(x, y, span, 1);
xfer->xfer32(device, span, 1, &alpha);
y += 1;
device = (uint32_t*)((char*)device + deviceRB);
@@ -628,7 +630,7 @@ void SkARGB32_Shader_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
} else {
SkBlitRow::Proc32 proc = (255 == alpha) ? fProc32 : fProc32Blend;
do {
- shader->shadeSpan(x, y, span, 1);
+ shaderContext->shadeSpan(x, y, span, 1);
proc(device, span, 1, alpha);
y += 1;
device = (uint32_t*)((char*)device + deviceRB);
diff --git a/chromium/third_party/skia/src/core/SkBlitter_RGB16.cpp b/chromium/third_party/skia/src/core/SkBlitter_RGB16.cpp
index 256cbc6936f..4503a2ae792 100644
--- a/chromium/third_party/skia/src/core/SkBlitter_RGB16.cpp
+++ b/chromium/third_party/skia/src/core/SkBlitter_RGB16.cpp
@@ -12,12 +12,11 @@
#include "SkColorPriv.h"
#include "SkDither.h"
#include "SkShader.h"
-#include "SkTemplatesPriv.h"
#include "SkUtils.h"
+#include "SkUtilsArm.h"
#include "SkXfermode.h"
-#if defined(__ARM_HAVE_NEON) && defined(SK_CPU_LENDIAN)
- #define SK_USE_NEON
+#if SK_ARM_NEON_IS_ALWAYS && defined(SK_CPU_LENDIAN)
#include <arm_neon.h>
#else
// if we don't have neon, then our black blitter is worth the extra code
@@ -108,7 +107,8 @@ private:
class SkRGB16_Shader_Blitter : public SkShaderBlitter {
public:
- SkRGB16_Shader_Blitter(const SkBitmap& device, const SkPaint& paint);
+ SkRGB16_Shader_Blitter(const SkBitmap& device, const SkPaint& paint,
+ SkShader::Context* shaderContext);
virtual ~SkRGB16_Shader_Blitter();
virtual void blitH(int x, int y, int width);
virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
@@ -130,7 +130,8 @@ private:
// used only if the shader can perform shadSpan16
class SkRGB16_Shader16_Blitter : public SkRGB16_Shader_Blitter {
public:
- SkRGB16_Shader16_Blitter(const SkBitmap& device, const SkPaint& paint);
+ SkRGB16_Shader16_Blitter(const SkBitmap& device, const SkPaint& paint,
+ SkShader::Context* shaderContext);
virtual void blitH(int x, int y, int width);
virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
const int16_t* runs);
@@ -142,7 +143,8 @@ private:
class SkRGB16_Shader_Xfermode_Blitter : public SkShaderBlitter {
public:
- SkRGB16_Shader_Xfermode_Blitter(const SkBitmap& device, const SkPaint& paint);
+ SkRGB16_Shader_Xfermode_Blitter(const SkBitmap& device, const SkPaint& paint,
+ SkShader::Context* shaderContext);
virtual ~SkRGB16_Shader_Xfermode_Blitter();
virtual void blitH(int x, int y, int width);
virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
@@ -385,7 +387,7 @@ void SkRGB16_Opaque_Blitter::blitMask(const SkMask& mask,
unsigned maskRB = mask.fRowBytes - width;
uint32_t expanded32 = fExpandedRaw16;
-#ifdef SK_USE_NEON
+#if SK_ARM_NEON_IS_ALWAYS && defined(SK_CPU_LENDIAN)
#define UNROLL 8
do {
int w = width;
@@ -680,8 +682,9 @@ void SkRGB16_Blitter::blitRect(int x, int y, int width, int height) {
///////////////////////////////////////////////////////////////////////////////
SkRGB16_Shader16_Blitter::SkRGB16_Shader16_Blitter(const SkBitmap& device,
- const SkPaint& paint)
- : SkRGB16_Shader_Blitter(device, paint) {
+ const SkPaint& paint,
+ SkShader::Context* shaderContext)
+ : SkRGB16_Shader_Blitter(device, paint, shaderContext) {
SkASSERT(SkShader::CanCallShadeSpan16(fShaderFlags));
}
@@ -689,28 +692,28 @@ void SkRGB16_Shader16_Blitter::blitH(int x, int y, int width) {
SkASSERT(x + width <= fDevice.width());
uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
- SkShader* shader = fShader;
+ SkShader::Context* shaderContext = fShaderContext;
- int alpha = shader->getSpan16Alpha();
+ int alpha = shaderContext->getSpan16Alpha();
if (0xFF == alpha) {
- shader->shadeSpan16(x, y, device, width);
+ shaderContext->shadeSpan16(x, y, device, width);
} else {
uint16_t* span16 = (uint16_t*)fBuffer;
- shader->shadeSpan16(x, y, span16, width);
+ shaderContext->shadeSpan16(x, y, span16, width);
SkBlendRGB16(span16, device, SkAlpha255To256(alpha), width);
}
}
void SkRGB16_Shader16_Blitter::blitRect(int x, int y, int width, int height) {
- SkShader* shader = fShader;
- uint16_t* dst = fDevice.getAddr16(x, y);
- size_t dstRB = fDevice.rowBytes();
- int alpha = shader->getSpan16Alpha();
+ SkShader::Context* shaderContext = fShaderContext;
+ uint16_t* dst = fDevice.getAddr16(x, y);
+ size_t dstRB = fDevice.rowBytes();
+ int alpha = shaderContext->getSpan16Alpha();
if (0xFF == alpha) {
if (fShaderFlags & SkShader::kConstInY16_Flag) {
// have the shader blit directly into the device the first time
- shader->shadeSpan16(x, y, dst, width);
+ shaderContext->shadeSpan16(x, y, dst, width);
// and now just memcpy that line on the subsequent lines
if (--height > 0) {
const uint16_t* orig = dst;
@@ -721,7 +724,7 @@ void SkRGB16_Shader16_Blitter::blitRect(int x, int y, int width, int height) {
}
} else { // need to call shadeSpan16 for every line
do {
- shader->shadeSpan16(x, y, dst, width);
+ shaderContext->shadeSpan16(x, y, dst, width);
y += 1;
dst = (uint16_t*)((char*)dst + dstRB);
} while (--height);
@@ -730,14 +733,14 @@ void SkRGB16_Shader16_Blitter::blitRect(int x, int y, int width, int height) {
int scale = SkAlpha255To256(alpha);
uint16_t* span16 = (uint16_t*)fBuffer;
if (fShaderFlags & SkShader::kConstInY16_Flag) {
- shader->shadeSpan16(x, y, span16, width);
+ shaderContext->shadeSpan16(x, y, span16, width);
do {
SkBlendRGB16(span16, dst, scale, width);
dst = (uint16_t*)((char*)dst + dstRB);
} while (--height);
} else {
do {
- shader->shadeSpan16(x, y, span16, width);
+ shaderContext->shadeSpan16(x, y, span16, width);
SkBlendRGB16(span16, dst, scale, width);
y += 1;
dst = (uint16_t*)((char*)dst + dstRB);
@@ -749,11 +752,11 @@ void SkRGB16_Shader16_Blitter::blitRect(int x, int y, int width, int height) {
void SkRGB16_Shader16_Blitter::blitAntiH(int x, int y,
const SkAlpha* SK_RESTRICT antialias,
const int16_t* SK_RESTRICT runs) {
- SkShader* shader = fShader;
+ SkShader::Context* shaderContext = fShaderContext;
SkPMColor* SK_RESTRICT span = fBuffer;
- uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
+ uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
- int alpha = shader->getSpan16Alpha();
+ int alpha = shaderContext->getSpan16Alpha();
uint16_t* span16 = (uint16_t*)span;
if (0xFF == alpha) {
@@ -767,9 +770,9 @@ void SkRGB16_Shader16_Blitter::blitAntiH(int x, int y,
int aa = *antialias;
if (aa == 255) {
// go direct to the device!
- shader->shadeSpan16(x, y, device, count);
+ shaderContext->shadeSpan16(x, y, device, count);
} else if (aa) {
- shader->shadeSpan16(x, y, span16, count);
+ shaderContext->shadeSpan16(x, y, span16, count);
SkBlendRGB16(span16, device, SkAlpha255To256(aa), count);
}
device += count;
@@ -788,7 +791,7 @@ void SkRGB16_Shader16_Blitter::blitAntiH(int x, int y,
int aa = SkAlphaMul(*antialias, alpha);
if (aa) {
- shader->shadeSpan16(x, y, span16, count);
+ shaderContext->shadeSpan16(x, y, span16, count);
SkBlendRGB16(span16, device, SkAlpha255To256(aa), count);
}
@@ -803,8 +806,9 @@ void SkRGB16_Shader16_Blitter::blitAntiH(int x, int y,
///////////////////////////////////////////////////////////////////////////////
SkRGB16_Shader_Blitter::SkRGB16_Shader_Blitter(const SkBitmap& device,
- const SkPaint& paint)
-: INHERITED(device, paint) {
+ const SkPaint& paint,
+ SkShader::Context* shaderContext)
+: INHERITED(device, paint, shaderContext) {
SkASSERT(paint.getXfermode() == NULL);
fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * sizeof(SkPMColor));
@@ -822,10 +826,10 @@ SkRGB16_Shader_Blitter::SkRGB16_Shader_Blitter(const SkBitmap& device,
flags |= SkBlitRow::kDither_Flag;
}
// used when we know our global alpha is 0xFF
- fOpaqueProc = SkBlitRow::Factory(flags, SkBitmap::kRGB_565_Config);
+ fOpaqueProc = SkBlitRow::Factory(flags, kRGB_565_SkColorType);
// used when we know our global alpha is < 0xFF
fAlphaProc = SkBlitRow::Factory(flags | SkBlitRow::kGlobalAlpha_Flag,
- SkBitmap::kRGB_565_Config);
+ kRGB_565_SkColorType);
}
SkRGB16_Shader_Blitter::~SkRGB16_Shader_Blitter() {
@@ -835,20 +839,20 @@ SkRGB16_Shader_Blitter::~SkRGB16_Shader_Blitter() {
void SkRGB16_Shader_Blitter::blitH(int x, int y, int width) {
SkASSERT(x + width <= fDevice.width());
- fShader->shadeSpan(x, y, fBuffer, width);
+ fShaderContext->shadeSpan(x, y, fBuffer, width);
// shaders take care of global alpha, so we pass 0xFF (should be ignored)
fOpaqueProc(fDevice.getAddr16(x, y), fBuffer, width, 0xFF, x, y);
}
void SkRGB16_Shader_Blitter::blitRect(int x, int y, int width, int height) {
- SkShader* shader = fShader;
- SkBlitRow::Proc proc = fOpaqueProc;
- SkPMColor* buffer = fBuffer;
- uint16_t* dst = fDevice.getAddr16(x, y);
- size_t dstRB = fDevice.rowBytes();
+ SkShader::Context* shaderContext = fShaderContext;
+ SkBlitRow::Proc proc = fOpaqueProc;
+ SkPMColor* buffer = fBuffer;
+ uint16_t* dst = fDevice.getAddr16(x, y);
+ size_t dstRB = fDevice.rowBytes();
if (fShaderFlags & SkShader::kConstInY32_Flag) {
- shader->shadeSpan(x, y, buffer, width);
+ shaderContext->shadeSpan(x, y, buffer, width);
do {
proc(dst, buffer, width, 0xFF, x, y);
y += 1;
@@ -856,7 +860,7 @@ void SkRGB16_Shader_Blitter::blitRect(int x, int y, int width, int height) {
} while (--height);
} else {
do {
- shader->shadeSpan(x, y, buffer, width);
+ shaderContext->shadeSpan(x, y, buffer, width);
proc(dst, buffer, width, 0xFF, x, y);
y += 1;
dst = (uint16_t*)((char*)dst + dstRB);
@@ -881,9 +885,9 @@ static inline int count_nonzero_span(const int16_t runs[], const SkAlpha aa[]) {
void SkRGB16_Shader_Blitter::blitAntiH(int x, int y,
const SkAlpha* SK_RESTRICT antialias,
const int16_t* SK_RESTRICT runs) {
- SkShader* shader = fShader;
+ SkShader::Context* shaderContext = fShaderContext;
SkPMColor* SK_RESTRICT span = fBuffer;
- uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
+ uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
for (;;) {
int count = *runs;
@@ -902,7 +906,7 @@ void SkRGB16_Shader_Blitter::blitAntiH(int x, int y,
int nonZeroCount = count + count_nonzero_span(runs + count, antialias + count);
SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
- shader->shadeSpan(x, y, span, nonZeroCount);
+ shaderContext->shadeSpan(x, y, span, nonZeroCount);
SkPMColor* localSpan = span;
for (;;) {
@@ -929,8 +933,9 @@ void SkRGB16_Shader_Blitter::blitAntiH(int x, int y,
///////////////////////////////////////////////////////////////////////
SkRGB16_Shader_Xfermode_Blitter::SkRGB16_Shader_Xfermode_Blitter(
- const SkBitmap& device, const SkPaint& paint)
-: INHERITED(device, paint) {
+ const SkBitmap& device, const SkPaint& paint,
+ SkShader::Context* shaderContext)
+: INHERITED(device, paint, shaderContext) {
fXfermode = paint.getXfermode();
SkASSERT(fXfermode);
fXfermode->ref();
@@ -951,18 +956,18 @@ void SkRGB16_Shader_Xfermode_Blitter::blitH(int x, int y, int width) {
uint16_t* device = fDevice.getAddr16(x, y);
SkPMColor* span = fBuffer;
- fShader->shadeSpan(x, y, span, width);
+ fShaderContext->shadeSpan(x, y, span, width);
fXfermode->xfer16(device, span, width, NULL);
}
void SkRGB16_Shader_Xfermode_Blitter::blitAntiH(int x, int y,
const SkAlpha* SK_RESTRICT antialias,
const int16_t* SK_RESTRICT runs) {
- SkShader* shader = fShader;
- SkXfermode* mode = fXfermode;
+ SkShader::Context* shaderContext = fShaderContext;
+ SkXfermode* mode = fXfermode;
SkPMColor* SK_RESTRICT span = fBuffer;
- uint8_t* SK_RESTRICT aaExpand = fAAExpand;
- uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
+ uint8_t* SK_RESTRICT aaExpand = fAAExpand;
+ uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
for (;;) {
int count = *runs;
@@ -982,7 +987,7 @@ void SkRGB16_Shader_Xfermode_Blitter::blitAntiH(int x, int y,
antialias + count);
SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
- shader->shadeSpan(x, y, span, nonZeroCount);
+ shaderContext->shadeSpan(x, y, span, nonZeroCount);
x += nonZeroCount;
SkPMColor* localSpan = span;
@@ -1013,7 +1018,10 @@ void SkRGB16_Shader_Xfermode_Blitter::blitAntiH(int x, int y,
///////////////////////////////////////////////////////////////////////////////
SkBlitter* SkBlitter_ChooseD565(const SkBitmap& device, const SkPaint& paint,
- void* storage, size_t storageSize) {
+ SkShader::Context* shaderContext,
+ SkTBlitterAllocator* allocator) {
+ SkASSERT(allocator != NULL);
+
SkBlitter* blitter;
SkShader* shader = paint.getShader();
SkXfermode* mode = paint.getXfermode();
@@ -1022,32 +1030,28 @@ SkBlitter* SkBlitter_ChooseD565(const SkBitmap& device, const SkPaint& paint,
SkASSERT(NULL == mode || NULL != shader);
if (shader) {
+ SkASSERT(shaderContext != NULL);
if (mode) {
- SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader_Xfermode_Blitter,
- storage, storageSize, (device, paint));
- } else if (shader->canCallShadeSpan16()) {
- SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader16_Blitter,
- storage, storageSize, (device, paint));
+ blitter = allocator->createT<SkRGB16_Shader_Xfermode_Blitter>(device, paint,
+ shaderContext);
+ } else if (shaderContext->canCallShadeSpan16()) {
+ blitter = allocator->createT<SkRGB16_Shader16_Blitter>(device, paint, shaderContext);
} else {
- SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader_Blitter,
- storage, storageSize, (device, paint));
+ blitter = allocator->createT<SkRGB16_Shader_Blitter>(device, paint, shaderContext);
}
} else {
// no shader, no xfermode, (and we always ignore colorfilter)
SkColor color = paint.getColor();
if (0 == SkColorGetA(color)) {
- SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
+ blitter = allocator->createT<SkNullBlitter>();
#ifdef USE_BLACK_BLITTER
} else if (SK_ColorBLACK == color) {
- SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Black_Blitter, storage,
- storageSize, (device, paint));
+ blitter = allocator->createT<SkRGB16_Black_Blitter>(device, paint);
#endif
} else if (0xFF == SkColorGetA(color)) {
- SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Opaque_Blitter, storage,
- storageSize, (device, paint));
+ blitter = allocator->createT<SkRGB16_Opaque_Blitter>(device, paint);
} else {
- SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Blitter, storage,
- storageSize, (device, paint));
+ blitter = allocator->createT<SkRGB16_Blitter>(device, paint);
}
}
diff --git a/chromium/third_party/skia/src/core/SkBlitter_Sprite.cpp b/chromium/third_party/skia/src/core/SkBlitter_Sprite.cpp
index 9322e203967..91a3cd1fee1 100644
--- a/chromium/third_party/skia/src/core/SkBlitter_Sprite.cpp
+++ b/chromium/third_party/skia/src/core/SkBlitter_Sprite.cpp
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -6,7 +5,7 @@
* found in the LICENSE file.
*/
-
+#include "SkSmallAllocator.h"
#include "SkSpriteBlitter.h"
SkSpriteBlitter::SkSpriteBlitter(const SkBitmap& source)
@@ -49,11 +48,8 @@ void SkSpriteBlitter::blitMask(const SkMask&, const SkIRect& clip) {
// returning null means the caller will call SkBlitter::Choose() and
// have wrapped the source bitmap inside a shader
-SkBlitter* SkBlitter::ChooseSprite( const SkBitmap& device,
- const SkPaint& paint,
- const SkBitmap& source,
- int left, int top,
- void* storage, size_t storageSize) {
+SkBlitter* SkBlitter::ChooseSprite(const SkBitmap& device, const SkPaint& paint,
+ const SkBitmap& source, int left, int top, SkTBlitterAllocator* allocator) {
/* We currently ignore antialiasing and filtertype, meaning we will take our
special blitters regardless of these settings. Ignoring filtertype seems fine
since by definition there is no scale in the matrix. Ignoring antialiasing is
@@ -63,17 +59,16 @@ SkBlitter* SkBlitter::ChooseSprite( const SkBitmap& device,
paint and return null if it is set, forcing the client to take the slow shader case
(which does respect soft edges).
*/
+ SkASSERT(allocator != NULL);
SkSpriteBlitter* blitter;
- switch (device.config()) {
- case SkBitmap::kRGB_565_Config:
- blitter = SkSpriteBlitter::ChooseD16(source, paint, storage,
- storageSize);
+ switch (device.colorType()) {
+ case kRGB_565_SkColorType:
+ blitter = SkSpriteBlitter::ChooseD16(source, paint, allocator);
break;
- case SkBitmap::kARGB_8888_Config:
- blitter = SkSpriteBlitter::ChooseD32(source, paint, storage,
- storageSize);
+ case kN32_SkColorType:
+ blitter = SkSpriteBlitter::ChooseD32(source, paint, allocator);
break;
default:
blitter = NULL;
diff --git a/chromium/third_party/skia/src/core/SkCanvas.cpp b/chromium/third_party/skia/src/core/SkCanvas.cpp
index feeba758fa3..bdbcd3be740 100644
--- a/chromium/third_party/skia/src/core/SkCanvas.cpp
+++ b/chromium/third_party/skia/src/core/SkCanvas.cpp
@@ -1,4 +1,3 @@
-
/*
* Copyright 2008 The Android Open Source Project
*
@@ -9,7 +8,6 @@
#include "SkCanvas.h"
#include "SkBitmapDevice.h"
-#include "SkBounder.h"
#include "SkDeviceImageFilterProxy.h"
#include "SkDraw.h"
#include "SkDrawFilter.h"
@@ -19,6 +17,7 @@
#include "SkPicture.h"
#include "SkRasterClip.h"
#include "SkRRect.h"
+#include "SkSmallAllocator.h"
#include "SkSurface_Base.h"
#include "SkTemplates.h"
#include "SkTextFormatParams.h"
@@ -90,32 +89,10 @@ private:
};
#endif
-class AutoCheckNoSetContext {
-public:
- AutoCheckNoSetContext(const SkPaint& paint) : fPaint(paint) {
- this->assertNoSetContext(fPaint);
- }
- ~AutoCheckNoSetContext() {
- this->assertNoSetContext(fPaint);
- }
-
-private:
- const SkPaint& fPaint;
-
- void assertNoSetContext(const SkPaint& paint) {
- SkShader* s = paint.getShader();
- if (s) {
- SkASSERT(!s->setContextHasBeenCalled());
- }
- }
-};
-
#define CHECK_LOCKCOUNT_BALANCE(bitmap) AutoCheckLockCountBalance clcb(bitmap)
-#define CHECK_SHADER_NOSETCONTEXT(paint) AutoCheckNoSetContext cshsc(paint)
#else
#define CHECK_LOCKCOUNT_BALANCE(bitmap)
- #define CHECK_SHADER_NOSETCONTEXT(paint)
#endif
typedef SkTLazy<SkPaint> SkLazyPaint;
@@ -212,7 +189,6 @@ private:
*/
class SkCanvas::MCRec {
public:
- MCRec* fNext;
int fFlags;
SkMatrix* fMatrix; // points to either fMatrixStorage or prev MCRec
SkRasterClip* fRasterClip; // points to either fRegionStorage or prev MCRec
@@ -279,7 +255,6 @@ public:
canvas->updateDeviceCMCache();
fClipStack = &canvas->fClipStack;
- fBounder = canvas->getBounder();
fCurrLayer = canvas->fMCRec->fTopLayer;
fSkipEmptyClips = skipEmptyClips;
}
@@ -304,9 +279,6 @@ public:
SkDEBUGCODE(this->validate();)
fCurrLayer = rec->fNext;
- if (fBounder) {
- fBounder->setClip(fClip);
- }
// fCurrLayer may be NULL now
return true;
@@ -335,9 +307,9 @@ private:
class AutoDrawLooper {
public:
AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint,
- bool skipLayerForImageFilter = false) : fOrigPaint(paint) {
+ bool skipLayerForImageFilter = false,
+ const SkRect* bounds = NULL) : fOrigPaint(paint) {
fCanvas = canvas;
- fLooper = paint.getLooper();
fFilter = canvas->getDrawFilter();
fPaint = NULL;
fSaveCount = canvas->getSaveCount();
@@ -347,18 +319,20 @@ public:
if (!skipLayerForImageFilter && fOrigPaint.getImageFilter()) {
SkPaint tmp;
tmp.setImageFilter(fOrigPaint.getImageFilter());
- // it would be nice if we had a guess at the bounds, instead of null
- (void)canvas->internalSaveLayer(NULL, &tmp,
- SkCanvas::kARGB_ClipLayer_SaveFlag, true);
+ (void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLayer_SaveFlag,
+ true, SkCanvas::kFullLayer_SaveLayerStrategy);
// we'll clear the imageFilter for the actual draws in next(), so
// it will only be applied during the restore().
fDoClearImageFilter = true;
}
- if (fLooper) {
- fLooper->init(canvas);
+ if (SkDrawLooper* looper = paint.getLooper()) {
+ void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Context>(
+ looper->contextSize());
+ fLooperContext = looper->createContext(canvas, buffer);
fIsSimple = false;
} else {
+ fLooperContext = NULL;
// can we be marked as simple?
fIsSimple = !fFilter && !fDoClearImageFilter;
}
@@ -392,13 +366,14 @@ private:
SkLazyPaint fLazyPaint;
SkCanvas* fCanvas;
const SkPaint& fOrigPaint;
- SkDrawLooper* fLooper;
SkDrawFilter* fFilter;
const SkPaint* fPaint;
int fSaveCount;
bool fDoClearImageFilter;
bool fDone;
bool fIsSimple;
+ SkDrawLooper::Context* fLooperContext;
+ SkSmallAllocator<1, 32> fLooperContextAllocator;
bool doNext(SkDrawFilter::Type drawType);
};
@@ -406,7 +381,7 @@ private:
bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
fPaint = NULL;
SkASSERT(!fIsSimple);
- SkASSERT(fLooper || fFilter || fDoClearImageFilter);
+ SkASSERT(fLooperContext || fFilter || fDoClearImageFilter);
SkPaint* paint = fLazyPaint.set(fOrigPaint);
@@ -414,7 +389,7 @@ bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
paint->setImageFilter(NULL);
}
- if (fLooper && !fLooper->next(fCanvas, paint)) {
+ if (fLooperContext && !fLooperContext->next(fCanvas, paint)) {
fDone = true;
return false;
}
@@ -423,7 +398,7 @@ bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
fDone = true;
return false;
}
- if (NULL == fLooper) {
+ if (NULL == fLooperContext) {
// no looper means we only draw once
fDone = true;
}
@@ -431,7 +406,7 @@ bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
fPaint = paint;
// if we only came in here for the imagefilter, mark us as done
- if (!fLooper && !fFilter) {
+ if (!fLooperContext && !fFilter) {
fDone = true;
}
@@ -443,23 +418,6 @@ bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
return true;
}
-/* Stack helper for managing a SkBounder. In the destructor, if we were
- given a bounder, we call its commit() method, signifying that we are
- done accumulating bounds for that draw.
-*/
-class SkAutoBounderCommit {
-public:
- SkAutoBounderCommit(SkBounder* bounder) : fBounder(bounder) {}
- ~SkAutoBounderCommit() {
- if (NULL != fBounder) {
- fBounder->commit();
- }
- }
-private:
- SkBounder* fBounder;
-};
-#define SkAutoBounderCommit(...) SK_REQUIRE_LOCAL_VAR(SkAutoBounderCommit)
-
#include "SkColorPriv.h"
////////// macros to place around the internal draw calls //////////////////
@@ -468,14 +426,12 @@ private:
this->predrawNotify(); \
AutoDrawLooper looper(this, paint, true); \
while (looper.next(type)) { \
- SkAutoBounderCommit ac(fBounder); \
SkDrawIter iter(this);
-#define LOOPER_BEGIN(paint, type) \
+#define LOOPER_BEGIN(paint, type, bounds) \
this->predrawNotify(); \
- AutoDrawLooper looper(this, paint); \
+ AutoDrawLooper looper(this, paint, false, bounds); \
while (looper.next(type)) { \
- SkAutoBounderCommit ac(fBounder); \
SkDrawIter iter(this);
#define LOOPER_END }
@@ -483,13 +439,13 @@ private:
////////////////////////////////////////////////////////////////////////////
SkBaseDevice* SkCanvas::init(SkBaseDevice* device) {
- fBounder = NULL;
fCachedLocalClipBounds.setEmpty();
fCachedLocalClipBoundsDirty = true;
fAllowSoftClip = true;
fAllowSimplifyClip = false;
fDeviceCMDirty = false;
fSaveLayerCount = 0;
+ fCullCount = 0;
fMetaData = NULL;
fMCRec = (MCRec*)fMCStack.push_back();
@@ -497,29 +453,41 @@ SkBaseDevice* SkCanvas::init(SkBaseDevice* device) {
fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL));
fMCRec->fTopLayer = fMCRec->fLayer;
- fMCRec->fNext = NULL;
fSurfaceBase = NULL;
- return this->setDevice(device);
+ return this->setRootDevice(device);
}
SkCanvas::SkCanvas()
-: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
+ : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
+{
inc_canvas();
this->init(NULL);
}
+SkCanvas::SkCanvas(int width, int height)
+ : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
+{
+ inc_canvas();
+
+ SkBitmap bitmap;
+ bitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
+ this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)))->unref();
+}
+
SkCanvas::SkCanvas(SkBaseDevice* device)
- : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
+ : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
+{
inc_canvas();
this->init(device);
}
SkCanvas::SkCanvas(const SkBitmap& bitmap)
- : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
+ : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
+{
inc_canvas();
this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)))->unref();
@@ -532,17 +500,11 @@ SkCanvas::~SkCanvas() {
this->internalRestore(); // restore the last, since we're going away
- SkSafeUnref(fBounder);
SkDELETE(fMetaData);
dec_canvas();
}
-SkBounder* SkCanvas::setBounder(SkBounder* bounder) {
- SkRefCnt_SafeAssign(fBounder, bounder);
- return bounder;
-}
-
SkDrawFilter* SkCanvas::getDrawFilter() const {
return fMCRec->fFilter;
}
@@ -570,7 +532,17 @@ void SkCanvas::flush() {
}
}
-SkISize SkCanvas::getDeviceSize() const {
+SkISize SkCanvas::getTopLayerSize() const {
+ SkBaseDevice* d = this->getTopDevice();
+ return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
+}
+
+SkIPoint SkCanvas::getTopLayerOrigin() const {
+ SkBaseDevice* d = this->getTopDevice();
+ return d ? d->getOrigin() : SkIPoint::Make(0, 0);
+}
+
+SkISize SkCanvas::getBaseLayerSize() const {
SkBaseDevice* d = this->getDevice();
return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
}
@@ -589,7 +561,7 @@ SkBaseDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const {
return fMCRec->fTopLayer->fDevice;
}
-SkBaseDevice* SkCanvas::setDevice(SkBaseDevice* device) {
+SkBaseDevice* SkCanvas::setRootDevice(SkBaseDevice* device) {
// return root device
SkDeque::F2BIter iter(fMCStack);
MCRec* rec = (MCRec*)iter.next();
@@ -641,49 +613,148 @@ SkBaseDevice* SkCanvas::setDevice(SkBaseDevice* device) {
return device;
}
-bool SkCanvas::readPixels(SkBitmap* bitmap,
- int x, int y,
- Config8888 config8888) {
- SkBaseDevice* device = this->getDevice();
- if (!device) {
+bool SkCanvas::readPixels(SkBitmap* bitmap, int x, int y) {
+ if (kUnknown_SkColorType == bitmap->colorType() || bitmap->getTexture()) {
return false;
}
- return device->readPixels(bitmap, x, y, config8888);
+
+ bool weAllocated = false;
+ if (NULL == bitmap->pixelRef()) {
+ if (!bitmap->allocPixels()) {
+ return false;
+ }
+ weAllocated = true;
+ }
+
+ SkBitmap bm(*bitmap);
+ bm.lockPixels();
+ if (bm.getPixels() && this->readPixels(bm.info(), bm.getPixels(), bm.rowBytes(), x, y)) {
+ return true;
+ }
+
+ if (weAllocated) {
+ bitmap->setPixelRef(NULL);
+ }
+ return false;
}
bool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
+ SkIRect r = srcRect;
+ const SkISize size = this->getBaseLayerSize();
+ if (!r.intersect(0, 0, size.width(), size.height())) {
+ bitmap->reset();
+ return false;
+ }
+
+ if (!bitmap->allocN32Pixels(r.width(), r.height())) {
+ // bitmap will already be reset.
+ return false;
+ }
+ if (!this->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), r.x(), r.y())) {
+ bitmap->reset();
+ return false;
+ }
+ return true;
+}
+
+bool SkCanvas::readPixels(const SkImageInfo& origInfo, void* dstP, size_t rowBytes, int x, int y) {
+ switch (origInfo.colorType()) {
+ case kUnknown_SkColorType:
+ case kIndex_8_SkColorType:
+ return false;
+ default:
+ break;
+ }
+ if (NULL == dstP || rowBytes < origInfo.minRowBytes()) {
+ return false;
+ }
+ if (0 == origInfo.width() || 0 == origInfo.height()) {
+ return false;
+ }
+
SkBaseDevice* device = this->getDevice();
if (!device) {
return false;
}
- SkIRect bounds;
- bounds.set(0, 0, device->width(), device->height());
- if (!bounds.intersect(srcRect)) {
+ const SkISize size = this->getBaseLayerSize();
+ SkIRect srcR = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height());
+ if (!srcR.intersect(0, 0, size.width(), size.height())) {
return false;
}
- SkBitmap tmp;
- tmp.setConfig(SkBitmap::kARGB_8888_Config, bounds.width(),
- bounds.height());
- if (this->readPixels(&tmp, bounds.fLeft, bounds.fTop)) {
- bitmap->swap(tmp);
- return true;
- } else {
+ SkImageInfo info = origInfo;
+ // the intersect may have shrunk info's logical size
+ info.fWidth = srcR.width();
+ info.fHeight = srcR.height();
+
+ // if x or y are negative, then we have to adjust pixels
+ if (x > 0) {
+ x = 0;
+ }
+ if (y > 0) {
+ y = 0;
+ }
+ // here x,y are either 0 or negative
+ dstP = ((char*)dstP - y * rowBytes - x * info.bytesPerPixel());
+
+ // The device can assert that the requested area is always contained in its bounds
+ return device->readPixels(info, dstP, rowBytes, srcR.x(), srcR.y());
+}
+
+bool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) {
+ if (bitmap.getTexture()) {
return false;
}
+ SkBitmap bm(bitmap);
+ bm.lockPixels();
+ if (bm.getPixels()) {
+ return this->writePixels(bm.info(), bm.getPixels(), bm.rowBytes(), x, y);
+ }
+ return false;
}
-void SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y,
- Config8888 config8888) {
+bool SkCanvas::writePixels(const SkImageInfo& origInfo, const void* pixels, size_t rowBytes,
+ int x, int y) {
+ switch (origInfo.colorType()) {
+ case kUnknown_SkColorType:
+ case kIndex_8_SkColorType:
+ return false;
+ default:
+ break;
+ }
+ if (NULL == pixels || rowBytes < origInfo.minRowBytes()) {
+ return false;
+ }
+
+ const SkISize size = this->getBaseLayerSize();
+ SkIRect target = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height());
+ if (!target.intersect(0, 0, size.width(), size.height())) {
+ return false;
+ }
+
SkBaseDevice* device = this->getDevice();
- if (device) {
- if (SkIRect::Intersects(SkIRect::MakeSize(this->getDeviceSize()),
- SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height()))) {
- device->accessBitmap(true);
- device->writePixels(bitmap, x, y, config8888);
- }
+ if (!device) {
+ return false;
+ }
+
+ SkImageInfo info = origInfo;
+ // the intersect may have shrunk info's logical size
+ info.fWidth = target.width();
+ info.fHeight = target.height();
+
+ // if x or y are negative, then we have to adjust pixels
+ if (x > 0) {
+ x = 0;
}
+ if (y > 0) {
+ y = 0;
+ }
+ // here x,y are either 0 or negative
+ pixels = ((const char*)pixels - y * rowBytes - x * info.bytesPerPixel());
+
+ // The device can assert that the requested area is always contained in its bounds
+ return device->writePixels(info, pixels, rowBytes, target.x(), target.y());
}
SkCanvas* SkCanvas::canvasForDrawIter() {
@@ -718,7 +789,6 @@ int SkCanvas::internalSave(SaveFlags flags) {
MCRec* newTop = (MCRec*)fMCStack.push_back();
new (newTop) MCRec(fMCRec, flags); // balanced in restore()
- newTop->fNext = fMCRec;
fMCRec = newTop;
if (SkCanvas::kClip_SaveFlag & flags) {
@@ -728,61 +798,38 @@ int SkCanvas::internalSave(SaveFlags flags) {
return saveCount;
}
+int SkCanvas::save() {
+ this->willSave(kMatrixClip_SaveFlag);
+ return this->internalSave(kMatrixClip_SaveFlag);
+}
+
int SkCanvas::save(SaveFlags flags) {
+ this->willSave(flags);
// call shared impl
return this->internalSave(flags);
}
-#define C32MASK (1 << SkBitmap::kARGB_8888_Config)
-#define C16MASK (1 << SkBitmap::kRGB_565_Config)
-#define C8MASK (1 << SkBitmap::kA8_Config)
-
-static SkBitmap::Config resolve_config(SkCanvas* canvas,
- const SkIRect& bounds,
- SkCanvas::SaveFlags flags,
- bool* isOpaque) {
- *isOpaque = (flags & SkCanvas::kHasAlphaLayer_SaveFlag) == 0;
-
-#if 0
- // loop through and union all the configs we may draw into
- uint32_t configMask = 0;
- for (int i = canvas->countLayerDevices() - 1; i >= 0; --i)
- {
- SkBaseDevice* device = canvas->getLayerDevice(i);
- if (device->intersects(bounds))
- configMask |= 1 << device->config();
- }
-
- // if the caller wants alpha or fullcolor, we can't return 565
- if (flags & (SkCanvas::kFullColorLayer_SaveFlag |
- SkCanvas::kHasAlphaLayer_SaveFlag))
- configMask &= ~C16MASK;
-
- switch (configMask) {
- case C8MASK: // if we only have A8, return that
- return SkBitmap::kA8_Config;
-
- case C16MASK: // if we only have 565, return that
- return SkBitmap::kRGB_565_Config;
-
- default:
- return SkBitmap::kARGB_8888_Config; // default answer
- }
-#else
- return SkBitmap::kARGB_8888_Config; // default answer
-#endif
-}
-
static bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
+#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0;
+#else
+ return true;
+#endif
}
bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
- SkIRect* intersection) {
+ SkIRect* intersection, const SkImageFilter* imageFilter) {
SkIRect clipBounds;
+ SkRegion::Op op = SkRegion::kIntersect_Op;
if (!this->getClipDeviceBounds(&clipBounds)) {
return false;
}
+
+ if (imageFilter) {
+ imageFilter->filterBounds(clipBounds, *fMCRec->fMatrix, &clipBounds);
+ // Filters may grow the bounds beyond the device bounds.
+ op = SkRegion::kReplace_Op;
+ }
SkIRect ir;
if (NULL != bounds) {
SkRect r;
@@ -800,12 +847,12 @@ bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
ir = clipBounds;
}
- fClipStack.clipDevRect(ir, SkRegion::kIntersect_Op);
-
- // early exit if the clip is now empty
- if (bounds_affects_clip(flags) &&
- !fMCRec->fRasterClip->op(ir, SkRegion::kIntersect_Op)) {
- return false;
+ if (bounds_affects_clip(flags)) {
+ fClipStack.clipDevRect(ir, op);
+ // early exit if the clip is now empty
+ if (!fMCRec->fRasterClip->op(ir, op)) {
+ return false;
+ }
}
if (intersection) {
@@ -814,13 +861,29 @@ bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
return true;
}
+int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
+ SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag);
+ return this->internalSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag, false, strategy);
+}
+
int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
SaveFlags flags) {
- return this->internalSaveLayer(bounds, paint, flags, false);
+ SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, flags);
+ return this->internalSaveLayer(bounds, paint, flags, false, strategy);
+}
+
+static SkBaseDevice* create_compatible_device(SkCanvas* canvas,
+ const SkImageInfo& info) {
+ SkBaseDevice* device = canvas->getDevice();
+ return device ? device->createCompatibleDevice(info) : NULL;
}
-int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint,
- SaveFlags flags, bool justForImageFilter) {
+int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags,
+ bool justForImageFilter, SaveLayerStrategy strategy) {
+#ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
+ flags |= kClipToLayer_SaveFlag;
+#endif
+
// do this before we create the layer. We don't call the public save() since
// that would invoke a possibly overridden virtual
int count = this->internalSave(flags);
@@ -828,7 +891,13 @@ int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint,
fDeviceCMDirty = true;
SkIRect ir;
- if (!this->clipRectBounds(bounds, flags, &ir)) {
+ if (!this->clipRectBounds(bounds, flags, &ir, paint ? paint->getImageFilter() : NULL)) {
+ return count;
+ }
+
+ // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
+ // the clipRectBounds() call above?
+ if (kNoLayer_SaveLayerStrategy == strategy) {
return count;
}
@@ -846,16 +915,15 @@ int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint,
}
}
- bool isOpaque;
- SkBitmap::Config config = resolve_config(this, ir, flags, &isOpaque);
+ bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag);
+ SkImageInfo info = SkImageInfo::MakeN32(ir.width(), ir.height(),
+ isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
SkBaseDevice* device;
if (paint && paint->getImageFilter()) {
- device = this->createCompatibleDevice(config, ir.width(), ir.height(),
- isOpaque);
+ device = create_compatible_device(this, info);
} else {
- device = this->createLayerDevice(config, ir.width(), ir.height(),
- isOpaque);
+ device = this->createLayerDevice(info);
}
if (NULL == device) {
SkDebugf("Unable to create device for layer.");
@@ -874,6 +942,10 @@ int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint,
return count;
}
+int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
+ return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag);
+}
+
int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
SaveFlags flags) {
if (0xFF == alpha) {
@@ -888,6 +960,7 @@ int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
void SkCanvas::restore() {
// check for underflow
if (fMCStack.count() > 1) {
+ this->willRestore();
this->internalRestore();
}
}
@@ -951,16 +1024,138 @@ bool SkCanvas::isDrawingToLayer() const {
return fSaveLayerCount > 0;
}
+SkSurface* SkCanvas::newSurface(const SkImageInfo& info) {
+ return this->onNewSurface(info);
+}
+
+SkSurface* SkCanvas::onNewSurface(const SkImageInfo& info) {
+ SkBaseDevice* dev = this->getDevice();
+ return dev ? dev->newSurface(info) : NULL;
+}
+
+SkImageInfo SkCanvas::imageInfo() const {
+ SkBaseDevice* dev = this->getDevice();
+ if (dev) {
+ return dev->imageInfo();
+ } else {
+ return SkImageInfo::MakeUnknown(0, 0);
+ }
+}
+
+const void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) {
+ return this->onPeekPixels(info, rowBytes);
+}
+
+const void* SkCanvas::onPeekPixels(SkImageInfo* info, size_t* rowBytes) {
+ SkBaseDevice* dev = this->getDevice();
+ return dev ? dev->peekPixels(info, rowBytes) : NULL;
+}
+
+void* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
+ void* pixels = this->onAccessTopLayerPixels(info, rowBytes);
+ if (pixels && origin) {
+ *origin = this->getTopDevice(false)->getOrigin();
+ }
+ return pixels;
+}
+
+void* SkCanvas::onAccessTopLayerPixels(SkImageInfo* info, size_t* rowBytes) {
+ SkBaseDevice* dev = this->getTopDevice();
+ return dev ? dev->accessPixels(info, rowBytes) : NULL;
+}
+
+SkAutoROCanvasPixels::SkAutoROCanvasPixels(SkCanvas* canvas) {
+ fAddr = canvas->peekPixels(&fInfo, &fRowBytes);
+ if (NULL == fAddr) {
+ fInfo = canvas->imageInfo();
+ if (kUnknown_SkColorType == fInfo.colorType() || !fBitmap.allocPixels(fInfo)) {
+ return; // failure, fAddr is NULL
+ }
+ if (!canvas->readPixels(&fBitmap, 0, 0)) {
+ return; // failure, fAddr is NULL
+ }
+ fAddr = fBitmap.getPixels();
+ fRowBytes = fBitmap.rowBytes();
+ }
+ SkASSERT(fAddr); // success
+}
+
+bool SkAutoROCanvasPixels::asROBitmap(SkBitmap* bitmap) const {
+ if (fAddr) {
+ return bitmap->installPixels(fInfo, const_cast<void*>(fAddr), fRowBytes);
+ } else {
+ bitmap->reset();
+ return false;
+ }
+}
+
+void SkCanvas::onPushCull(const SkRect& cullRect) {
+ // do nothing. Subclasses may do something
+}
+
+void SkCanvas::onPopCull() {
+ // do nothing. Subclasses may do something
+}
+
/////////////////////////////////////////////////////////////////////////////
+#ifdef SK_DEBUG
+// Ensure that cull rects are monotonically nested in device space.
+void SkCanvas::validateCull(const SkIRect& devCull) {
+ if (fCullStack.isEmpty()
+ || devCull.isEmpty()
+ || fCullStack.top().contains(devCull)) {
+ return;
+ }
-// can't draw it if its empty, or its too big for a fixed-point width or height
-static bool reject_bitmap(const SkBitmap& bitmap) {
- return bitmap.width() <= 0 || bitmap.height() <= 0;
+ SkDEBUGF(("Invalid cull: [%d %d %d %d] (previous cull: [%d %d %d %d])\n",
+ devCull.x(), devCull.y(), devCull.right(), devCull.bottom(),
+ fCullStack.top().x(), fCullStack.top().y(),
+ fCullStack.top().right(), fCullStack.top().bottom()));
+
+#ifdef ASSERT_NESTED_CULLING
+ SkDEBUGFAIL("Invalid cull.");
+#endif
+}
+#endif
+
+void SkCanvas::pushCull(const SkRect& cullRect) {
+ ++fCullCount;
+ this->onPushCull(cullRect);
+
+#ifdef SK_DEBUG
+ // Map the cull rect into device space.
+ SkRect mappedCull;
+ this->getTotalMatrix().mapRect(&mappedCull, cullRect);
+
+ // Take clipping into account.
+ SkIRect devClip, devCull;
+ mappedCull.roundOut(&devCull);
+ this->getClipDeviceBounds(&devClip);
+ if (!devCull.intersect(devClip)) {
+ devCull.setEmpty();
+ }
+
+ this->validateCull(devCull);
+ fCullStack.push(devCull); // balanced in popCull
+#endif
}
+void SkCanvas::popCull() {
+ SkASSERT(fCullStack.count() == fCullCount);
+
+ if (fCullCount > 0) {
+ --fCullCount;
+ this->onPopCull();
+
+ SkDEBUGCODE(fCullStack.pop());
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap,
const SkMatrix& matrix, const SkPaint* paint) {
- if (reject_bitmap(bitmap)) {
+ if (bitmap.drawsNothing()) {
return;
}
@@ -972,7 +1167,15 @@ void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap,
SkDEBUGCODE(bitmap.validate();)
CHECK_LOCKCOUNT_BALANCE(bitmap);
- LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type)
+ SkRect storage;
+ const SkRect* bounds = NULL;
+ if (paint && paint->canComputeFastBounds()) {
+ bitmap.getBounds(&storage);
+ matrix.mapRect(&storage);
+ bounds = &paint->computeFastBounds(storage, &storage);
+ }
+
+ LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
while (iter.next()) {
iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint());
@@ -998,13 +1201,23 @@ void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y,
if (filter && !dstDev->canHandleImageFilter(filter)) {
SkDeviceImageFilterProxy proxy(dstDev);
SkBitmap dst;
+ SkIPoint offset = SkIPoint::Make(0, 0);
const SkBitmap& src = srcDev->accessBitmap(false);
SkMatrix matrix = *iter.fMatrix;
- matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y));
- if (filter->filterImage(&proxy, src, matrix, &dst, &pos)) {
+ matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
+ SkIRect clipBounds = SkIRect::MakeWH(srcDev->width(), srcDev->height());
+ SkImageFilter::Cache* cache = SkImageFilter::GetExternalCache();
+ SkAutoUnref aur(NULL);
+ if (!cache) {
+ cache = SkImageFilter::Cache::Create();
+ aur.reset(cache);
+ }
+ SkImageFilter::Context ctx(matrix, clipBounds, cache);
+ if (filter->filterImage(&proxy, src, ctx, &dst, &offset)) {
SkPaint tmpUnfiltered(*paint);
tmpUnfiltered.setImageFilter(NULL);
- dstDev->drawSprite(iter, dst, pos.x(), pos.y(), tmpUnfiltered);
+ dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
+ tmpUnfiltered);
}
} else {
dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
@@ -1015,12 +1228,11 @@ void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y,
void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
const SkPaint* paint) {
- SkDEBUGCODE(bitmap.validate();)
- CHECK_LOCKCOUNT_BALANCE(bitmap);
-
- if (reject_bitmap(bitmap)) {
+ if (bitmap.drawsNothing()) {
return;
}
+ SkDEBUGCODE(bitmap.validate();)
+ CHECK_LOCKCOUNT_BALANCE(bitmap);
SkPaint tmp;
if (NULL == paint) {
@@ -1036,12 +1248,21 @@ void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
if (filter && !iter.fDevice->canHandleImageFilter(filter)) {
SkDeviceImageFilterProxy proxy(iter.fDevice);
SkBitmap dst;
+ SkIPoint offset = SkIPoint::Make(0, 0);
SkMatrix matrix = *iter.fMatrix;
- matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y));
- if (filter->filterImage(&proxy, bitmap, matrix, &dst, &pos)) {
+ matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
+ SkIRect clipBounds = SkIRect::MakeWH(bitmap.width(), bitmap.height());
+ SkImageFilter::Cache* cache = SkImageFilter::GetExternalCache();
+ SkAutoUnref aur(NULL);
+ if (!cache) {
+ cache = SkImageFilter::Cache::Create();
+ aur.reset(cache);
+ }
+ SkImageFilter::Context ctx(matrix, clipBounds, cache);
+ if (filter->filterImage(&proxy, bitmap, ctx, &dst, &offset)) {
SkPaint tmpUnfiltered(*paint);
tmpUnfiltered.setImageFilter(NULL);
- iter.fDevice->drawSprite(iter, dst, pos.x(), pos.y(),
+ iter.fDevice->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
tmpUnfiltered);
}
} else {
@@ -1052,45 +1273,49 @@ void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
}
/////////////////////////////////////////////////////////////////////////////
-
-bool SkCanvas::translate(SkScalar dx, SkScalar dy) {
- fDeviceCMDirty = true;
- fCachedLocalClipBoundsDirty = true;
- return fMCRec->fMatrix->preTranslate(dx, dy);
+void SkCanvas::translate(SkScalar dx, SkScalar dy) {
+ SkMatrix m;
+ m.setTranslate(dx, dy);
+ this->concat(m);
}
-bool SkCanvas::scale(SkScalar sx, SkScalar sy) {
- fDeviceCMDirty = true;
- fCachedLocalClipBoundsDirty = true;
- return fMCRec->fMatrix->preScale(sx, sy);
+void SkCanvas::scale(SkScalar sx, SkScalar sy) {
+ SkMatrix m;
+ m.setScale(sx, sy);
+ this->concat(m);
}
-bool SkCanvas::rotate(SkScalar degrees) {
- fDeviceCMDirty = true;
- fCachedLocalClipBoundsDirty = true;
- return fMCRec->fMatrix->preRotate(degrees);
+void SkCanvas::rotate(SkScalar degrees) {
+ SkMatrix m;
+ m.setRotate(degrees);
+ this->concat(m);
}
-bool SkCanvas::skew(SkScalar sx, SkScalar sy) {
- fDeviceCMDirty = true;
- fCachedLocalClipBoundsDirty = true;
- return fMCRec->fMatrix->preSkew(sx, sy);
+void SkCanvas::skew(SkScalar sx, SkScalar sy) {
+ SkMatrix m;
+ m.setSkew(sx, sy);
+ this->concat(m);
}
-bool SkCanvas::concat(const SkMatrix& matrix) {
+void SkCanvas::concat(const SkMatrix& matrix) {
+ if (matrix.isIdentity()) {
+ return;
+ }
+
fDeviceCMDirty = true;
fCachedLocalClipBoundsDirty = true;
- return fMCRec->fMatrix->preConcat(matrix);
+ fMCRec->fMatrix->preConcat(matrix);
+
+ this->didConcat(matrix);
}
void SkCanvas::setMatrix(const SkMatrix& matrix) {
fDeviceCMDirty = true;
fCachedLocalClipBoundsDirty = true;
*fMCRec->fMatrix = matrix;
+ this->didSetMatrix(matrix);
}
-// this is not virtual, so it must call a virtual method so that subclasses
-// will see its action
void SkCanvas::resetMatrix() {
SkMatrix matrix;
@@ -1100,7 +1325,12 @@ void SkCanvas::resetMatrix() {
//////////////////////////////////////////////////////////////////////////////
-bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
+void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
+ ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
+ this->onClipRect(rect, op, edgeStyle);
+}
+
+void SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
#ifdef SK_ENABLE_CLIP_QUICKREJECT
if (SkRegion::kIntersect_Op == op) {
if (fMCRec->fRasterClip->isEmpty()) {
@@ -1121,7 +1351,9 @@ bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
fDeviceCMDirty = true;
fCachedLocalClipBoundsDirty = true;
- doAA &= fAllowSoftClip;
+ if (!fAllowSoftClip) {
+ edgeStyle = kHard_ClipEdgeStyle;
+ }
if (fMCRec->fMatrix->rectStaysRect()) {
// for these simpler matrices, we can stay a rect even after applying
@@ -1131,8 +1363,8 @@ bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
SkRect r;
fMCRec->fMatrix->mapRect(&r, rect);
- fClipStack.clipDevRect(r, op, doAA);
- return fMCRec->fRasterClip->op(r, op, doAA);
+ fClipStack.clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle);
+ fMCRec->fRasterClip->op(r, op, kSoft_ClipEdgeStyle == edgeStyle);
} else {
// since we're rotated or some such thing, we convert the rect to a path
// and clip against that, since it can handle any matrix. However, to
@@ -1141,12 +1373,12 @@ bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
SkPath path;
path.addRect(rect);
- return this->SkCanvas::clipPath(path, op, doAA);
+ this->SkCanvas::onClipPath(path, op, edgeStyle);
}
}
-static bool clipPathHelper(const SkCanvas* canvas, SkRasterClip* currClip,
- const SkPath& devPath, SkRegion::Op op, bool doAA) {
+static void clip_path_helper(const SkCanvas* canvas, SkRasterClip* currClip,
+ const SkPath& devPath, SkRegion::Op op, bool doAA) {
// base is used to limit the size (and therefore memory allocation) of the
// region that results from scan converting devPath.
SkRegion base;
@@ -1159,44 +1391,78 @@ static bool clipPathHelper(const SkCanvas* canvas, SkRasterClip* currClip,
// FIXME: we should also be able to do this when currClip->isBW(),
// but relaxing the test above triggers GM asserts in
// SkRgnBuilder::blitH(). We need to investigate what's going on.
- return currClip->setPath(devPath, currClip->bwRgn(), doAA);
+ currClip->setPath(devPath, currClip->bwRgn(), doAA);
} else {
base.setRect(currClip->getBounds());
SkRasterClip clip;
clip.setPath(devPath, base, doAA);
- return currClip->op(clip, op);
+ currClip->op(clip, op);
}
} else {
const SkBaseDevice* device = canvas->getDevice();
if (!device) {
- return currClip->setEmpty();
+ currClip->setEmpty();
+ return;
}
base.setRect(0, 0, device->width(), device->height());
if (SkRegion::kReplace_Op == op) {
- return currClip->setPath(devPath, base, doAA);
+ currClip->setPath(devPath, base, doAA);
} else {
SkRasterClip clip;
clip.setPath(devPath, base, doAA);
- return currClip->op(clip, op);
+ currClip->op(clip, op);
}
}
}
-bool SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
+void SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
+ ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
if (rrect.isRect()) {
- // call the non-virtual version
- return this->SkCanvas::clipRect(rrect.getBounds(), op, doAA);
+ this->onClipRect(rrect.getBounds(), op, edgeStyle);
} else {
- SkPath path;
- path.addRRect(rrect);
- // call the non-virtual version
- return this->SkCanvas::clipPath(path, op, doAA);
+ this->onClipRRect(rrect, op, edgeStyle);
+ }
+}
+
+void SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
+ SkRRect transformedRRect;
+ if (rrect.transform(*fMCRec->fMatrix, &transformedRRect)) {
+ AutoValidateClip avc(this);
+
+ fDeviceCMDirty = true;
+ fCachedLocalClipBoundsDirty = true;
+ if (!fAllowSoftClip) {
+ edgeStyle = kHard_ClipEdgeStyle;
+ }
+
+ fClipStack.clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle);
+
+ SkPath devPath;
+ devPath.addRRect(transformedRRect);
+
+ clip_path_helper(this, fMCRec->fRasterClip, devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
+ return;
+ }
+
+ SkPath path;
+ path.addRRect(rrect);
+ // call the non-virtual version
+ this->SkCanvas::onClipPath(path, op, edgeStyle);
+}
+
+void SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
+ ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
+ SkRect r;
+ if (!path.isInverseFillType() && path.isRect(&r)) {
+ this->onClipRect(r, op, edgeStyle);
+ } else {
+ this->onClipPath(path, op, edgeStyle);
}
}
-bool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
+void SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
#ifdef SK_ENABLE_CLIP_QUICKREJECT
if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
if (fMCRec->fRasterClip->isEmpty()) {
@@ -1217,7 +1483,9 @@ bool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
fDeviceCMDirty = true;
fCachedLocalClipBoundsDirty = true;
- doAA &= fAllowSoftClip;
+ if (!fAllowSoftClip) {
+ edgeStyle = kHard_ClipEdgeStyle;
+ }
SkPath devPath;
path.transform(*fMCRec->fMatrix, &devPath);
@@ -1233,7 +1501,7 @@ bool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
}
// if we called path.swap() we could avoid a deep copy of this path
- fClipStack.clipDevPath(devPath, op, doAA);
+ fClipStack.clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
if (fAllowSimplifyClip) {
devPath.reset();
@@ -1243,16 +1511,9 @@ bool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
const SkClipStack::Element* element;
while ((element = iter.next())) {
SkClipStack::Element::Type type = element->getType();
- if (type == SkClipStack::Element::kEmpty_Type) {
- continue;
- }
SkPath operand;
- if (type == SkClipStack::Element::kRect_Type) {
- operand.addRect(element->getRect());
- } else if (type == SkClipStack::Element::kPath_Type) {
- operand = element->getPath();
- } else {
- SkDEBUGFAIL("Unexpected type.");
+ if (type != SkClipStack::Element::kEmpty_Type) {
+ element->asPath(&operand);
}
SkRegion::Op elementOp = element->getOp();
if (elementOp == SkRegion::kReplace_Op) {
@@ -1263,15 +1524,17 @@ bool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
// if the prev and curr clips disagree about aa -vs- not, favor the aa request.
// perhaps we need an API change to avoid this sort of mixed-signals about
// clipping.
- doAA |= element->isAA();
+ if (element->isAA()) {
+ edgeStyle = kSoft_ClipEdgeStyle;
+ }
}
op = SkRegion::kReplace_Op;
}
- return clipPathHelper(this, fMCRec->fRasterClip, devPath, op, doAA);
+ clip_path_helper(this, fMCRec->fRasterClip, devPath, op, edgeStyle);
}
-bool SkCanvas::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegion::Op op,
+void SkCanvas::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegion::Op op,
bool inverseFilled) {
// This is for updating the clip conservatively using only bounds
// information.
@@ -1294,13 +1557,12 @@ bool SkCanvas::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegio
case SkRegion::kIntersect_Op:
case SkRegion::kDifference_Op:
// These ops can only shrink the current clip. So leaving
- // the clip unchanges conservatively respects the contract.
- return this->getClipDeviceBounds(NULL);
+ // the clip unchanged conservatively respects the contract.
+ break;
case SkRegion::kUnion_Op:
case SkRegion::kReplace_Op:
case SkRegion::kReverseDifference_Op:
- case SkRegion::kXOR_Op:
- {
+ case SkRegion::kXOR_Op: {
// These ops can grow the current clip up to the extents of
// the input clip, which is inverse filled, so we just set
// the current clip to the device bounds.
@@ -1308,14 +1570,15 @@ bool SkCanvas::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegio
SkIRect deviceIBounds;
this->getDevice()->getGlobalBounds(&deviceIBounds);
deviceBounds = SkRect::Make(deviceIBounds);
- this->SkCanvas::save(SkCanvas::kMatrix_SaveFlag);
+
// set the clip in device space
+ SkMatrix savedMatrix = this->getTotalMatrix();
this->SkCanvas::setMatrix(SkMatrix::I());
- bool result = this->SkCanvas::clipRect(deviceBounds,
- SkRegion::kReplace_Op, false);
- this->SkCanvas::restore(); //pop the matrix, but keep the clip
- return result;
- }
+ this->SkCanvas::onClipRect(deviceBounds, SkRegion::kReplace_Op,
+ kHard_ClipEdgeStyle);
+ this->setMatrix(savedMatrix);
+ break;
+ }
default:
SkASSERT(0); // unhandled op?
}
@@ -1325,27 +1588,33 @@ bool SkCanvas::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegio
case SkRegion::kIntersect_Op:
case SkRegion::kUnion_Op:
case SkRegion::kReplace_Op:
- return this->SkCanvas::clipRect(bounds, op, false);
+ this->SkCanvas::onClipRect(bounds, op, kHard_ClipEdgeStyle);
+ break;
case SkRegion::kDifference_Op:
// Difference can only shrink the current clip.
// Leaving clip unchanged conservatively fullfills the contract.
- return this->getClipDeviceBounds(NULL);
+ break;
case SkRegion::kReverseDifference_Op:
// To reverse, we swap in the bounds with a replace op.
// As with difference, leave it unchanged.
- return this->SkCanvas::clipRect(bounds, SkRegion::kReplace_Op, false);
+ this->SkCanvas::onClipRect(bounds, SkRegion::kReplace_Op, kHard_ClipEdgeStyle);
+ break;
case SkRegion::kXOR_Op:
// Be conservative, based on (A XOR B) always included in (A union B),
// which is always included in (bounds(A) union bounds(B))
- return this->SkCanvas::clipRect(bounds, SkRegion::kUnion_Op, false);
+ this->SkCanvas::onClipRect(bounds, SkRegion::kUnion_Op, kHard_ClipEdgeStyle);
+ break;
default:
SkASSERT(0); // unhandled op?
}
}
- return true;
}
-bool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
+void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
+ this->onClipRegion(rgn, op);
+}
+
+void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) {
AutoValidateClip avc(this);
fDeviceCMDirty = true;
@@ -1355,7 +1624,7 @@ bool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
// we have to ignore it, and use the region directly?
fClipStack.clipDevRect(rgn.getBounds(), op);
- return fMCRec->fRasterClip->op(rgn, op);
+ fMCRec->fRasterClip->op(rgn, op);
}
#ifdef SK_DEBUG
@@ -1363,7 +1632,7 @@ void SkCanvas::validateClip() const {
// construct clipRgn from the clipstack
const SkBaseDevice* device = this->getDevice();
if (!device) {
- SkASSERT(this->getTotalClip().isEmpty());
+ SkASSERT(this->isClipEmpty());
return;
}
@@ -1375,13 +1644,6 @@ void SkCanvas::validateClip() const {
const SkClipStack::Element* element;
while ((element = iter.next()) != NULL) {
switch (element->getType()) {
- case SkClipStack::Element::kPath_Type:
- clipPathHelper(this,
- &tmpClip,
- element->getPath(),
- element->getOp(),
- element->isAA());
- break;
case SkClipStack::Element::kRect_Type:
element->getRect().round(&ir);
tmpClip.op(ir, element->getOp());
@@ -1389,14 +1651,14 @@ void SkCanvas::validateClip() const {
case SkClipStack::Element::kEmpty_Type:
tmpClip.setEmpty();
break;
+ default: {
+ SkPath path;
+ element->asPath(&path);
+ clip_path_helper(this, &tmpClip, path, element->getOp(), element->isAA());
+ break;
+ }
}
}
-
-#if 0 // enable this locally for testing
- // now compare against the current rgn
- const SkRegion& rgn = this->getTotalClip();
- SkASSERT(rgn == tmpClip);
-#endif
}
#endif
@@ -1404,24 +1666,21 @@ void SkCanvas::replayClips(ClipVisitor* visitor) const {
SkClipStack::B2TIter iter(fClipStack);
const SkClipStack::Element* element;
- static const SkRect kEmpty = { 0, 0, 0, 0 };
while ((element = iter.next()) != NULL) {
- switch (element->getType()) {
- case SkClipStack::Element::kPath_Type:
- visitor->clipPath(element->getPath(), element->getOp(), element->isAA());
- break;
- case SkClipStack::Element::kRect_Type:
- visitor->clipRect(element->getRect(), element->getOp(), element->isAA());
- break;
- case SkClipStack::Element::kEmpty_Type:
- visitor->clipRect(kEmpty, SkRegion::kIntersect_Op, false);
- break;
- }
+ element->replay(visitor);
}
}
///////////////////////////////////////////////////////////////////////////////
+bool SkCanvas::isClipEmpty() const {
+ return fMCRec->fRasterClip->isEmpty();
+}
+
+bool SkCanvas::isClipRect() const {
+ return fMCRec->fRasterClip->isRect();
+}
+
bool SkCanvas::quickReject(const SkRect& rect) const {
if (!rect.isFinite())
@@ -1456,20 +1715,9 @@ bool SkCanvas::quickReject(const SkPath& path) const {
return path.isEmpty() || this->quickReject(path.getBounds());
}
-static inline int pinIntForScalar(int x) {
-#ifdef SK_SCALAR_IS_FIXED
- if (x < SK_MinS16) {
- x = SK_MinS16;
- } else if (x > SK_MaxS16) {
- x = SK_MaxS16;
- }
-#endif
- return x;
-}
-
bool SkCanvas::getClipBounds(SkRect* bounds) const {
SkIRect ibounds;
- if (!getClipDeviceBounds(&ibounds)) {
+ if (!this->getClipDeviceBounds(&ibounds)) {
return false;
}
@@ -1487,15 +1735,8 @@ bool SkCanvas::getClipBounds(SkRect* bounds) const {
// adjust it outwards in case we are antialiasing
const int inset = 1;
- // SkRect::iset() will correctly assert if we pass a value out of range
- // (when SkScalar==fixed), so we pin to legal values. This does not
- // really returnt the correct answer, but its the best we can do given
- // that we've promised to return SkRect (even though we support devices
- // that can be larger than 32K in width or height).
- r.iset(pinIntForScalar(ibounds.fLeft - inset),
- pinIntForScalar(ibounds.fTop - inset),
- pinIntForScalar(ibounds.fRight + inset),
- pinIntForScalar(ibounds.fBottom + inset));
+ r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
+ ibounds.fRight + inset, ibounds.fBottom + inset);
inverse.mapRect(bounds, r);
}
return true;
@@ -1520,37 +1761,46 @@ const SkMatrix& SkCanvas::getTotalMatrix() const {
return *fMCRec->fMatrix;
}
+#ifdef SK_SUPPORT_LEGACY_GETCLIPTYPE
SkCanvas::ClipType SkCanvas::getClipType() const {
- if (fMCRec->fRasterClip->isEmpty()) return kEmpty_ClipType;
- if (fMCRec->fRasterClip->isRect()) return kRect_ClipType;
+ if (fMCRec->fRasterClip->isEmpty()) {
+ return kEmpty_ClipType;
+ }
+ if (fMCRec->fRasterClip->isRect()) {
+ return kRect_ClipType;
+ }
return kComplex_ClipType;
}
+#endif
+#ifdef SK_SUPPORT_LEGACY_GETTOTALCLIP
const SkRegion& SkCanvas::getTotalClip() const {
return fMCRec->fRasterClip->forceGetBW();
}
+#endif
-SkBaseDevice* SkCanvas::createLayerDevice(SkBitmap::Config config,
- int width, int height,
- bool isOpaque) {
- SkBaseDevice* device = this->getTopDevice();
- if (device) {
- return device->createCompatibleDeviceForSaveLayer(config, width, height,
- isOpaque);
- } else {
- return NULL;
- }
+const SkRegion& SkCanvas::internal_private_getTotalClip() const {
+ return fMCRec->fRasterClip->forceGetBW();
}
-SkBaseDevice* SkCanvas::createCompatibleDevice(SkBitmap::Config config,
- int width, int height,
- bool isOpaque) {
- SkBaseDevice* device = this->getDevice();
- if (device) {
- return device->createCompatibleDevice(config, width, height, isOpaque);
- } else {
- return NULL;
+void SkCanvas::internal_private_getTotalClipAsPath(SkPath* path) const {
+ path->reset();
+
+ const SkRegion& rgn = fMCRec->fRasterClip->forceGetBW();
+ if (rgn.isEmpty()) {
+ return;
}
+ (void)rgn.getBoundaryPath(path);
+}
+
+GrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() {
+ SkBaseDevice* dev = this->getTopDevice();
+ return dev ? dev->accessRenderTarget() : NULL;
+}
+
+SkBaseDevice* SkCanvas::createLayerDevice(const SkImageInfo& info) {
+ SkBaseDevice* device = this->getTopDevice();
+ return device ? device->createCompatibleDeviceForSaveLayer(info) : NULL;
}
GrContext* SkCanvas::getGrContext() {
@@ -1568,6 +1818,26 @@ GrContext* SkCanvas::getGrContext() {
}
+void SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
+ const SkPaint& paint) {
+ if (outer.isEmpty()) {
+ return;
+ }
+ if (inner.isEmpty()) {
+ this->drawRRect(outer, paint);
+ return;
+ }
+
+ // We don't have this method (yet), but technically this is what we should
+ // be able to assert...
+ // SkASSERT(outer.contains(inner));
+ //
+ // For now at least check for containment of bounds
+ SkASSERT(outer.getBounds().contains(inner.getBounds()));
+
+ this->onDrawDRRect(outer, inner, paint);
+}
+
//////////////////////////////////////////////////////////////////////////////
// These are the virtual drawing methods
//////////////////////////////////////////////////////////////////////////////
@@ -1580,14 +1850,18 @@ void SkCanvas::clear(SkColor color) {
}
}
+void SkCanvas::onDiscard() {
+ if (NULL != fSurfaceBase) {
+ fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
+ }
+}
+
void SkCanvas::drawPaint(const SkPaint& paint) {
this->internalDrawPaint(paint);
}
void SkCanvas::internalDrawPaint(const SkPaint& paint) {
- CHECK_SHADER_NOSETCONTEXT(paint);
-
- LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type)
+ LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type, NULL)
while (iter.next()) {
iter.fDevice->drawPaint(iter, looper.paint());
@@ -1602,25 +1876,24 @@ void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
return;
}
- CHECK_SHADER_NOSETCONTEXT(paint);
-
+ SkRect r, storage;
+ const SkRect* bounds = NULL;
if (paint.canComputeFastBounds()) {
- SkRect r;
// special-case 2 points (common for drawing a single line)
if (2 == count) {
r.set(pts[0], pts[1]);
} else {
- r.set(pts, count);
+ r.set(pts, SkToInt(count));
}
- SkRect storage;
- if (this->quickReject(paint.computeFastStrokeBounds(r, &storage))) {
+ bounds = &paint.computeFastStrokeBounds(r, &storage);
+ if (this->quickReject(*bounds)) {
return;
}
}
SkASSERT(pts != NULL);
- LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type)
+ LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
while (iter.next()) {
iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
@@ -1630,16 +1903,16 @@ void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
}
void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
- CHECK_SHADER_NOSETCONTEXT(paint);
-
+ SkRect storage;
+ const SkRect* bounds = NULL;
if (paint.canComputeFastBounds()) {
- SkRect storage;
- if (this->quickReject(paint.computeFastBounds(r, &storage))) {
+ bounds = &paint.computeFastBounds(r, &storage);
+ if (this->quickReject(*bounds)) {
return;
}
}
- LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type)
+ LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds)
while (iter.next()) {
iter.fDevice->drawRect(iter, r, looper.paint());
@@ -1649,16 +1922,16 @@ void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
}
void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
- CHECK_SHADER_NOSETCONTEXT(paint);
-
+ SkRect storage;
+ const SkRect* bounds = NULL;
if (paint.canComputeFastBounds()) {
- SkRect storage;
- if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
+ bounds = &paint.computeFastBounds(oval, &storage);
+ if (this->quickReject(*bounds)) {
return;
}
}
- LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type)
+ LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
while (iter.next()) {
iter.fDevice->drawOval(iter, oval, looper.paint());
@@ -1668,11 +1941,11 @@ void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
}
void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
- CHECK_SHADER_NOSETCONTEXT(paint);
-
+ SkRect storage;
+ const SkRect* bounds = NULL;
if (paint.canComputeFastBounds()) {
- SkRect storage;
- if (this->quickReject(paint.computeFastBounds(rrect.getBounds(), &storage))) {
+ bounds = &paint.computeFastBounds(rrect.getBounds(), &storage);
+ if (this->quickReject(*bounds)) {
return;
}
}
@@ -1687,7 +1960,7 @@ void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
return;
}
- LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type)
+ LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
while (iter.next()) {
iter.fDevice->drawRRect(iter, rrect, looper.paint());
@@ -1696,29 +1969,50 @@ void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
LOOPER_END
}
+void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
+ const SkPaint& paint) {
+ SkRect storage;
+ const SkRect* bounds = NULL;
+ if (paint.canComputeFastBounds()) {
+ bounds = &paint.computeFastBounds(outer.getBounds(), &storage);
+ if (this->quickReject(*bounds)) {
+ return;
+ }
+ }
+
+ LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
-void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
- CHECK_SHADER_NOSETCONTEXT(paint);
+ while (iter.next()) {
+ iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
+ }
+ LOOPER_END
+}
+
+void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
if (!path.isFinite()) {
return;
}
+ SkRect storage;
+ const SkRect* bounds = NULL;
if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
- SkRect storage;
- const SkRect& bounds = path.getBounds();
- if (this->quickReject(paint.computeFastBounds(bounds, &storage))) {
+ const SkRect& pathBounds = path.getBounds();
+ bounds = &paint.computeFastBounds(pathBounds, &storage);
+ if (this->quickReject(*bounds)) {
return;
}
}
- if (path.isEmpty()) {
+
+ const SkRect& r = path.getBounds();
+ if (r.width() <= 0 && r.height() <= 0) {
if (path.isInverseFillType()) {
this->internalDrawPaint(paint);
}
return;
}
- LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type)
+ LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
while (iter.next()) {
iter.fDevice->drawPath(iter, path, looper.paint());
@@ -1754,15 +2048,15 @@ void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
const SkRect& dst, const SkPaint* paint,
DrawBitmapRectFlags flags) {
- if (bitmap.width() == 0 || bitmap.height() == 0 || dst.isEmpty()) {
+ if (bitmap.drawsNothing() || dst.isEmpty()) {
return;
}
CHECK_LOCKCOUNT_BALANCE(bitmap);
+ SkRect storage;
+ const SkRect* bounds = &dst;
if (NULL == paint || paint->canComputeFastBounds()) {
- SkRect storage;
- const SkRect* bounds = &dst;
if (paint) {
bounds = &paint->computeFastBounds(dst, &storage);
}
@@ -1776,7 +2070,7 @@ void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
paint = lazy.init();
}
- LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type)
+ LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds)
while (iter.next()) {
iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), flags);
@@ -1801,6 +2095,9 @@ void SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
void SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap,
const SkIRect& center, const SkRect& dst,
const SkPaint* paint) {
+ if (bitmap.drawsNothing()) {
+ return;
+ }
if (NULL == paint || paint->canComputeFastBounds()) {
SkRect storage;
const SkRect* bounds = &dst;
@@ -1966,11 +2263,9 @@ void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
}
}
-void SkCanvas::drawText(const void* text, size_t byteLength,
- SkScalar x, SkScalar y, const SkPaint& paint) {
- CHECK_SHADER_NOSETCONTEXT(paint);
-
- LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
+void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
+ const SkPaint& paint) {
+ LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
while (iter.next()) {
SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
@@ -1982,11 +2277,9 @@ void SkCanvas::drawText(const void* text, size_t byteLength,
LOOPER_END
}
-void SkCanvas::drawPosText(const void* text, size_t byteLength,
- const SkPoint pos[], const SkPaint& paint) {
- CHECK_SHADER_NOSETCONTEXT(paint);
-
- LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
+void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
+ const SkPaint& paint) {
+ LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
while (iter.next()) {
SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
@@ -1997,12 +2290,9 @@ void SkCanvas::drawPosText(const void* text, size_t byteLength,
LOOPER_END
}
-void SkCanvas::drawPosTextH(const void* text, size_t byteLength,
- const SkScalar xpos[], SkScalar constY,
- const SkPaint& paint) {
- CHECK_SHADER_NOSETCONTEXT(paint);
-
- LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
+void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
+ SkScalar constY, const SkPaint& paint) {
+ LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
while (iter.next()) {
SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
@@ -2013,12 +2303,9 @@ void SkCanvas::drawPosTextH(const void* text, size_t byteLength,
LOOPER_END
}
-void SkCanvas::drawTextOnPath(const void* text, size_t byteLength,
- const SkPath& path, const SkMatrix* matrix,
- const SkPaint& paint) {
- CHECK_SHADER_NOSETCONTEXT(paint);
-
- LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
+void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
+ const SkMatrix* matrix, const SkPaint& paint) {
+ LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
while (iter.next()) {
iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
@@ -2028,14 +2315,30 @@ void SkCanvas::drawTextOnPath(const void* text, size_t byteLength,
LOOPER_END
}
+// These will become non-virtual, so they always call the (virtual) onDraw... method
+void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
+ const SkPaint& paint) {
+ this->onDrawText(text, byteLength, x, y, paint);
+}
+void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
+ const SkPaint& paint) {
+ this->onDrawPosText(text, byteLength, pos, paint);
+}
+void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
+ SkScalar constY, const SkPaint& paint) {
+ this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
+}
+void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
+ const SkMatrix* matrix, const SkPaint& paint) {
+ this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
+}
+
void SkCanvas::drawVertices(VertexMode vmode, int vertexCount,
const SkPoint verts[], const SkPoint texs[],
const SkColor colors[], SkXfermode* xmode,
const uint16_t indices[], int indexCount,
const SkPaint& paint) {
- CHECK_SHADER_NOSETCONTEXT(paint);
-
- LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type)
+ LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL)
while (iter.next()) {
iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
@@ -2162,9 +2465,39 @@ void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
}
///////////////////////////////////////////////////////////////////////////////
+void SkCanvas::EXPERIMENTAL_optimize(const SkPicture* picture) {
+ SkBaseDevice* device = this->getDevice();
+ if (NULL != device) {
+ device->EXPERIMENTAL_optimize(picture);
+ }
+}
+
+void SkCanvas::EXPERIMENTAL_purge(const SkPicture* picture) {
+ SkBaseDevice* device = this->getTopDevice();
+ if (NULL != device) {
+ device->EXPERIMENTAL_purge(picture);
+ }
+}
+
+void SkCanvas::drawPicture(const SkPicture* picture) {
+ if (NULL != picture) {
+ this->onDrawPicture(picture);
+ }
+}
+
+void SkCanvas::onDrawPicture(const SkPicture* picture) {
+ SkASSERT(NULL != picture);
+
+ SkBaseDevice* device = this->getTopDevice();
+ if (NULL != device) {
+ // Canvas has to first give the device the opportunity to render
+ // the picture itself.
+ if (device->EXPERIMENTAL_drawPicture(this, picture)) {
+ return; // the device has rendered the entire picture
+ }
+ }
-void SkCanvas::drawPicture(SkPicture& picture) {
- picture.draw(this);
+ picture->draw(this);
}
///////////////////////////////////////////////////////////////////////////////
@@ -2209,4 +2542,56 @@ int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
///////////////////////////////////////////////////////////////////////////////
-SkCanvas::ClipVisitor::~ClipVisitor() { }
+SkCanvasClipVisitor::~SkCanvasClipVisitor() { }
+
+///////////////////////////////////////////////////////////////////////////////
+
+static bool supported_for_raster_canvas(const SkImageInfo& info) {
+ switch (info.alphaType()) {
+ case kPremul_SkAlphaType:
+ case kOpaque_SkAlphaType:
+ break;
+ default:
+ return false;
+ }
+
+ switch (info.colorType()) {
+ case kAlpha_8_SkColorType:
+ case kRGB_565_SkColorType:
+ case kN32_SkColorType:
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+SkCanvas* SkCanvas::NewRaster(const SkImageInfo& info) {
+ if (!supported_for_raster_canvas(info)) {
+ return NULL;
+ }
+
+ SkBitmap bitmap;
+ if (!bitmap.allocPixels(info)) {
+ return NULL;
+ }
+
+ // should this functionality be moved into allocPixels()?
+ if (!bitmap.info().isOpaque()) {
+ bitmap.eraseColor(0);
+ }
+ return SkNEW_ARGS(SkCanvas, (bitmap));
+}
+
+SkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
+ if (!supported_for_raster_canvas(info)) {
+ return NULL;
+ }
+
+ SkBitmap bitmap;
+ if (!bitmap.installPixels(info, pixels, rowBytes)) {
+ return NULL;
+ }
+ return SkNEW_ARGS(SkCanvas, (bitmap));
+}
diff --git a/chromium/third_party/skia/src/core/SkClipStack.cpp b/chromium/third_party/skia/src/core/SkClipStack.cpp
index 9e3f7c6b308..a965b1bae7b 100644
--- a/chromium/third_party/skia/src/core/SkClipStack.cpp
+++ b/chromium/third_party/skia/src/core/SkClipStack.cpp
@@ -1,10 +1,11 @@
-
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
+
+#include "SkCanvas.h"
#include "SkClipStack.h"
#include "SkPath.h"
#include "SkThread.h"
@@ -16,27 +17,154 @@
static const int32_t kFirstUnreservedGenID = 3;
int32_t SkClipStack::gGenID = kFirstUnreservedGenID;
+SkClipStack::Element::Element(const Element& that) {
+ switch (that.getType()) {
+ case kEmpty_Type:
+ fPath.reset();
+ break;
+ case kRect_Type: // Rect uses rrect
+ case kRRect_Type:
+ fPath.reset();
+ fRRect = that.fRRect;
+ break;
+ case kPath_Type:
+ fPath.set(that.getPath());
+ break;
+ }
+
+ fSaveCount = that.fSaveCount;
+ fOp = that.fOp;
+ fType = that.fType;
+ fDoAA = that.fDoAA;
+ fFiniteBoundType = that.fFiniteBoundType;
+ fFiniteBound = that.fFiniteBound;
+ fIsIntersectionOfRects = that.fIsIntersectionOfRects;
+ fGenID = that.fGenID;
+}
+
+bool SkClipStack::Element::operator== (const Element& element) const {
+ if (this == &element) {
+ return true;
+ }
+ if (fOp != element.fOp ||
+ fType != element.fType ||
+ fDoAA != element.fDoAA ||
+ fSaveCount != element.fSaveCount) {
+ return false;
+ }
+ switch (fType) {
+ case kPath_Type:
+ return this->getPath() == element.getPath();
+ case kRRect_Type:
+ return fRRect == element.fRRect;
+ case kRect_Type:
+ return this->getRect() == element.getRect();
+ case kEmpty_Type:
+ return true;
+ default:
+ SkDEBUGFAIL("Unexpected type.");
+ return false;
+ }
+}
+
+void SkClipStack::Element::replay(SkCanvasClipVisitor* visitor) const {
+ static const SkRect kEmptyRect = { 0, 0, 0, 0 };
+
+ switch (fType) {
+ case kPath_Type:
+ visitor->clipPath(this->getPath(), this->getOp(), this->isAA());
+ break;
+ case kRRect_Type:
+ visitor->clipRRect(this->getRRect(), this->getOp(), this->isAA());
+ break;
+ case kRect_Type:
+ visitor->clipRect(this->getRect(), this->getOp(), this->isAA());
+ break;
+ case kEmpty_Type:
+ visitor->clipRect(kEmptyRect, SkRegion::kIntersect_Op, false);
+ break;
+ }
+}
+
void SkClipStack::Element::invertShapeFillType() {
switch (fType) {
case kRect_Type:
- fPath.reset();
- fPath.addRect(fRect);
- fPath.setFillType(SkPath::kInverseWinding_FillType);
+ fPath.init();
+ fPath.get()->addRect(this->getRect());
+ fPath.get()->setFillType(SkPath::kInverseEvenOdd_FillType);
+ fType = kPath_Type;
+ break;
+ case kRRect_Type:
+ fPath.init();
+ fPath.get()->addRRect(fRRect);
+ fPath.get()->setFillType(SkPath::kInverseEvenOdd_FillType);
fType = kPath_Type;
break;
case kPath_Type:
- fPath.toggleInverseFillType();
+ fPath.get()->toggleInverseFillType();
+ break;
+ case kEmpty_Type:
+ // Should this set to an empty, inverse filled path?
+ break;
+ }
+}
+
+void SkClipStack::Element::initPath(int saveCount, const SkPath& path, SkRegion::Op op,
+ bool doAA) {
+ if (!path.isInverseFillType()) {
+ if (SkPath::kNone_PathAsRect != path.asRect()) {
+ this->initRect(saveCount, path.getBounds(), op, doAA);
+ return;
+ }
+ SkRect ovalRect;
+ if (path.isOval(&ovalRect)) {
+ SkRRect rrect;
+ rrect.setOval(ovalRect);
+ this->initRRect(saveCount, rrect, op, doAA);
+ return;
+ }
+ }
+ fPath.set(path);
+ fType = kPath_Type;
+ this->initCommon(saveCount, op, doAA);
+}
+
+void SkClipStack::Element::asPath(SkPath* path) const {
+ switch (fType) {
case kEmpty_Type:
+ path->reset();
+ break;
+ case kRect_Type:
+ path->reset();
+ path->addRect(this->getRect());
+ break;
+ case kRRect_Type:
+ path->reset();
+ path->addRRect(fRRect);
+ break;
+ case kPath_Type:
+ *path = *fPath.get();
break;
}
}
+void SkClipStack::Element::setEmpty() {
+ fType = kEmpty_Type;
+ fFiniteBound.setEmpty();
+ fFiniteBoundType = kNormal_BoundsType;
+ fIsIntersectionOfRects = false;
+ fRRect.setEmpty();
+ fPath.reset();
+ fGenID = kEmptyGenID;
+ SkDEBUGCODE(this->checkEmpty();)
+}
+
void SkClipStack::Element::checkEmpty() const {
SkASSERT(fFiniteBound.isEmpty());
SkASSERT(kNormal_BoundsType == fFiniteBoundType);
SkASSERT(!fIsIntersectionOfRects);
SkASSERT(kEmptyGenID == fGenID);
- SkASSERT(fPath.isEmpty());
+ SkASSERT(!fPath.isValid());
}
bool SkClipStack::Element::canBeIntersectedInPlace(int saveCount, SkRegion::Op op) const {
@@ -59,12 +187,12 @@ bool SkClipStack::Element::rectRectIntersectAllowed(const SkRect& newR, bool new
return true;
}
- if (!SkRect::Intersects(fRect, newR)) {
+ if (!SkRect::Intersects(this->getRect(), newR)) {
// The calling code will correctly set the result to the empty clip
return true;
}
- if (fRect.contains(newR)) {
+ if (this->getRect().contains(newR)) {
// if the new rect carves out a portion of the old one there is no
// issue
return true;
@@ -100,10 +228,10 @@ void SkClipStack::Element::combineBoundsDiff(FillCombo combination, const SkRect
// is erased, so the only pixels that can remain set
// occur w/in the intersection of the two finite bounds
if (!fFiniteBound.intersect(prevFinite)) {
- fFiniteBound.setEmpty();
- fGenID = kEmptyGenID;
+ this->setEmpty();
+ } else {
+ fFiniteBoundType = kNormal_BoundsType;
}
- fFiniteBoundType = kNormal_BoundsType;
break;
case kPrev_Cur_FillCombo:
// The most conservative result bound is that of the
@@ -205,8 +333,7 @@ void SkClipStack::Element::combineBoundsIntersection(int combination, const SkRe
break;
case kPrev_Cur_FillCombo:
if (!fFiniteBound.intersect(prevFinite)) {
- fFiniteBound.setEmpty();
- fGenID = kEmptyGenID;
+ this->setEmpty();
}
break;
default:
@@ -228,10 +355,10 @@ void SkClipStack::Element::combineBoundsRevDiff(int combination, const SkRect& p
break;
case kInvPrev_Cur_FillCombo:
if (!fFiniteBound.intersect(prevFinite)) {
- fFiniteBound.setEmpty();
- fGenID = kEmptyGenID;
+ this->setEmpty();
+ } else {
+ fFiniteBoundType = kNormal_BoundsType;
}
- fFiniteBoundType = kNormal_BoundsType;
break;
case kPrev_InvCur_FillCombo:
fFiniteBound.join(prevFinite);
@@ -258,27 +385,34 @@ void SkClipStack::Element::updateBoundAndGenID(const Element* prior) {
// First, optimistically update the current Element's bound information
// with the current clip's bound
fIsIntersectionOfRects = false;
- if (kRect_Type == fType) {
- fFiniteBound = fRect;
- fFiniteBoundType = kNormal_BoundsType;
-
- if (SkRegion::kReplace_Op == fOp ||
- (SkRegion::kIntersect_Op == fOp && NULL == prior) ||
- (SkRegion::kIntersect_Op == fOp && prior->fIsIntersectionOfRects &&
- prior->rectRectIntersectAllowed(fRect, fDoAA))) {
- fIsIntersectionOfRects = true;
- }
-
- } else {
- SkASSERT(kPath_Type == fType);
-
- fFiniteBound = fPath.getBounds();
+ switch (fType) {
+ case kRect_Type:
+ fFiniteBound = this->getRect();
+ fFiniteBoundType = kNormal_BoundsType;
- if (fPath.isInverseFillType()) {
- fFiniteBoundType = kInsideOut_BoundsType;
- } else {
+ if (SkRegion::kReplace_Op == fOp ||
+ (SkRegion::kIntersect_Op == fOp && NULL == prior) ||
+ (SkRegion::kIntersect_Op == fOp && prior->fIsIntersectionOfRects &&
+ prior->rectRectIntersectAllowed(this->getRect(), fDoAA))) {
+ fIsIntersectionOfRects = true;
+ }
+ break;
+ case kRRect_Type:
+ fFiniteBound = fRRect.getBounds();
fFiniteBoundType = kNormal_BoundsType;
- }
+ break;
+ case kPath_Type:
+ fFiniteBound = fPath.get()->getBounds();
+
+ if (fPath.get()->isInverseFillType()) {
+ fFiniteBoundType = kInsideOut_BoundsType;
+ } else {
+ fFiniteBoundType = kNormal_BoundsType;
+ }
+ break;
+ case kEmpty_Type:
+ SkDEBUGFAIL("We shouldn't get here with an empty element.");
+ break;
}
if (!fDoAA) {
@@ -288,10 +422,10 @@ void SkClipStack::Element::updateBoundAndGenID(const Element* prior) {
// Note: the left edge is handled slightly differently below. We
// are a bit more generous in the rounding since we don't want to
// risk missing the left pixels when fLeft is very close to .5
- fFiniteBound.set(SkIntToScalar(SkScalarFloorToInt(fFiniteBound.fLeft+0.45f)),
- SkIntToScalar(SkScalarRound(fFiniteBound.fTop)),
- SkIntToScalar(SkScalarRound(fFiniteBound.fRight)),
- SkIntToScalar(SkScalarRound(fFiniteBound.fBottom)));
+ fFiniteBound.set(SkScalarFloorToScalar(fFiniteBound.fLeft+0.45f),
+ SkScalarRoundToScalar(fFiniteBound.fTop),
+ SkScalarRoundToScalar(fFiniteBound.fRight),
+ SkScalarRoundToScalar(fFiniteBound.fBottom));
}
// Now determine the previous Element's bound information taking into
@@ -344,7 +478,7 @@ void SkClipStack::Element::updateBoundAndGenID(const Element* prior) {
// so nothing to do
break;
default:
- SkDebugf("SkRegion::Op error/n");
+ SkDebugf("SkRegion::Op error\n");
SkASSERT(0);
break;
}
@@ -406,6 +540,9 @@ SkClipStack& SkClipStack::operator=(const SkClipStack& b) {
}
bool SkClipStack::operator==(const SkClipStack& b) const {
+ if (this->getTopmostGenID() == b.getTopmostGenID()) {
+ return true;
+ }
if (fSaveCount != b.fSaveCount ||
fDeque.count() != b.fDeque.count()) {
return false;
@@ -525,97 +662,71 @@ bool SkClipStack::quickContains(const SkRect& rect) const {
return true;
}
-void SkClipStack::clipDevRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
-
+void SkClipStack::pushElement(const Element& element) {
// Use reverse iterator instead of back because Rect path may need previous
SkDeque::Iter iter(fDeque, SkDeque::Iter::kBack_IterStart);
- Element* element = (Element*) iter.prev();
+ Element* prior = (Element*) iter.prev();
- if (NULL != element) {
- if (element->canBeIntersectedInPlace(fSaveCount, op)) {
- switch (element->fType) {
+ if (NULL != prior) {
+ if (prior->canBeIntersectedInPlace(fSaveCount, element.getOp())) {
+ switch (prior->fType) {
case Element::kEmpty_Type:
- element->checkEmpty();
+ SkDEBUGCODE(prior->checkEmpty();)
return;
case Element::kRect_Type:
- if (element->rectRectIntersectAllowed(rect, doAA)) {
- if (!element->fRect.intersect(rect)) {
- element->setEmpty();
+ if (Element::kRect_Type == element.getType()) {
+ if (prior->rectRectIntersectAllowed(element.getRect(), element.isAA())) {
+ SkRect isectRect;
+ if (!isectRect.intersect(prior->getRect(), element.getRect())) {
+ prior->setEmpty();
+ return;
+ }
+
+ prior->fRRect.setRect(isectRect);
+ prior->fDoAA = element.isAA();
+ Element* priorPrior = (Element*) iter.prev();
+ prior->updateBoundAndGenID(priorPrior);
return;
}
-
- element->fDoAA = doAA;
- Element* prev = (Element*) iter.prev();
- element->updateBoundAndGenID(prev);
- return;
+ break;
}
- break;
- case Element::kPath_Type:
- if (!SkRect::Intersects(element->fPath.getBounds(), rect)) {
- element->setEmpty();
+ // fallthrough
+ default:
+ if (!SkRect::Intersects(prior->getBounds(), element.getBounds())) {
+ prior->setEmpty();
return;
}
break;
}
- } else if (SkRegion::kReplace_Op == op) {
+ } else if (SkRegion::kReplace_Op == element.getOp()) {
this->restoreTo(fSaveCount - 1);
- element = (Element*) fDeque.back();
+ prior = (Element*) fDeque.back();
}
}
- new (fDeque.push_back()) Element(fSaveCount, rect, op, doAA);
- ((Element*) fDeque.back())->updateBoundAndGenID(element);
+ Element* newElement = SkNEW_PLACEMENT_ARGS(fDeque.push_back(), Element, (element));
+ newElement->updateBoundAndGenID(prior);
}
-void SkClipStack::clipDevPath(const SkPath& path, SkRegion::Op op, bool doAA) {
- SkRect alt;
- if (path.isRect(&alt) && !path.isInverseFillType()) {
- return this->clipDevRect(alt, op, doAA);
- }
+void SkClipStack::clipDevRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
+ Element element(fSaveCount, rrect, op, doAA);
+ this->pushElement(element);
+}
- Element* element = (Element*)fDeque.back();
- if (NULL != element) {
- if (element->canBeIntersectedInPlace(fSaveCount, op)) {
- const SkRect& pathBounds = path.getBounds();
- switch (element->fType) {
- case Element::kEmpty_Type:
- element->checkEmpty();
- return;
- case Element::kRect_Type:
- if (!SkRect::Intersects(element->fRect, pathBounds)) {
- element->setEmpty();
- return;
- }
- break;
- case Element::kPath_Type:
- if (!SkRect::Intersects(element->fPath.getBounds(), pathBounds)) {
- element->setEmpty();
- return;
- }
- break;
- }
- } else if (SkRegion::kReplace_Op == op) {
- this->restoreTo(fSaveCount - 1);
- element = (Element*) fDeque.back();
- }
- }
- new (fDeque.push_back()) Element(fSaveCount, path, op, doAA);
- ((Element*) fDeque.back())->updateBoundAndGenID(element);
+void SkClipStack::clipDevRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
+ Element element(fSaveCount, rect, op, doAA);
+ this->pushElement(element);
}
-void SkClipStack::clipEmpty() {
+void SkClipStack::clipDevPath(const SkPath& path, SkRegion::Op op, bool doAA) {
+ Element element(fSaveCount, path, op, doAA);
+ this->pushElement(element);
+}
+void SkClipStack::clipEmpty() {
Element* element = (Element*) fDeque.back();
if (element && element->canBeIntersectedInPlace(fSaveCount, SkRegion::kIntersect_Op)) {
- switch (element->fType) {
- case Element::kEmpty_Type:
- element->checkEmpty();
- return;
- case Element::kRect_Type:
- case Element::kPath_Type:
- element->setEmpty();
- return;
- }
+ element->setEmpty();
}
new (fDeque.push_back()) Element(fSaveCount);
@@ -734,3 +845,63 @@ int32_t SkClipStack::getTopmostGenID() const {
return back->getGenID();
}
+
+#ifdef SK_DEVELOPER
+void SkClipStack::Element::dump() const {
+ static const char* kTypeStrings[] = {
+ "empty",
+ "rect",
+ "rrect",
+ "path"
+ };
+ SK_COMPILE_ASSERT(0 == kEmpty_Type, type_str);
+ SK_COMPILE_ASSERT(1 == kRect_Type, type_str);
+ SK_COMPILE_ASSERT(2 == kRRect_Type, type_str);
+ SK_COMPILE_ASSERT(3 == kPath_Type, type_str);
+ SK_COMPILE_ASSERT(SK_ARRAY_COUNT(kTypeStrings) == kTypeCnt, type_str);
+
+ static const char* kOpStrings[] = {
+ "difference",
+ "intersect",
+ "union",
+ "xor",
+ "reverse-difference",
+ "replace",
+ };
+ SK_COMPILE_ASSERT(0 == SkRegion::kDifference_Op, op_str);
+ SK_COMPILE_ASSERT(1 == SkRegion::kIntersect_Op, op_str);
+ SK_COMPILE_ASSERT(2 == SkRegion::kUnion_Op, op_str);
+ SK_COMPILE_ASSERT(3 == SkRegion::kXOR_Op, op_str);
+ SK_COMPILE_ASSERT(4 == SkRegion::kReverseDifference_Op, op_str);
+ SK_COMPILE_ASSERT(5 == SkRegion::kReplace_Op, op_str);
+ SK_COMPILE_ASSERT(SK_ARRAY_COUNT(kOpStrings) == SkRegion::kOpCnt, op_str);
+
+ SkDebugf("Type: %s, Op: %s, AA: %s, Save Count: %d\n", kTypeStrings[fType],
+ kOpStrings[fOp], (fDoAA ? "yes" : "no"), fSaveCount);
+ switch (fType) {
+ case kEmpty_Type:
+ SkDebugf("\n");
+ break;
+ case kRect_Type:
+ this->getRect().dump();
+ SkDebugf("\n");
+ break;
+ case kRRect_Type:
+ this->getRRect().dump();
+ SkDebugf("\n");
+ break;
+ case kPath_Type:
+ this->getPath().dump(true);
+ break;
+ }
+}
+
+void SkClipStack::dump() const {
+ B2TIter iter(*this);
+ const Element* e;
+ while ((e = iter.next())) {
+ e->dump();
+ SkDebugf("\n");
+ }
+}
+#endif
diff --git a/chromium/third_party/skia/src/core/SkColorFilter.cpp b/chromium/third_party/skia/src/core/SkColorFilter.cpp
index ef0bda74eef..8cf9fc010a1 100644
--- a/chromium/third_party/skia/src/core/SkColorFilter.cpp
+++ b/chromium/third_party/skia/src/core/SkColorFilter.cpp
@@ -7,7 +7,8 @@
#include "SkColorFilter.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkShader.h"
#include "SkUnPreMultiply.h"
#include "SkString.h"
diff --git a/chromium/third_party/skia/src/core/SkColorTable.cpp b/chromium/third_party/skia/src/core/SkColorTable.cpp
index c719defe869..b8e7b059e8f 100644
--- a/chromium/third_party/skia/src/core/SkColorTable.cpp
+++ b/chromium/third_party/skia/src/core/SkColorTable.cpp
@@ -8,7 +8,8 @@
#include "SkColorTable.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkStream.h"
#include "SkTemplates.h"
@@ -83,22 +84,29 @@ const uint16_t* SkColorTable::lock16BitCache() {
///////////////////////////////////////////////////////////////////////////////
-SkColorTable::SkColorTable(SkFlattenableReadBuffer& buffer) {
+SkColorTable::SkColorTable(SkReadBuffer& buffer) {
f16BitCache = NULL;
SkDEBUGCODE(fColorLockCount = 0;)
SkDEBUGCODE(f16BitCacheLockCount = 0;)
fAlphaType = SkToU8(buffer.readUInt());
fCount = buffer.getArrayCount();
- fColors = (SkPMColor*)sk_malloc_throw(fCount * sizeof(SkPMColor));
- SkDEBUGCODE(bool success =) buffer.readColorArray(fColors, fCount);
+ size_t allocSize = fCount * sizeof(SkPMColor);
+ SkDEBUGCODE(bool success = false;)
+ if (buffer.validateAvailable(allocSize)) {
+ fColors = (SkPMColor*)sk_malloc_throw(allocSize);
+ SkDEBUGCODE(success =) buffer.readColorArray(fColors, fCount);
+ } else {
+ fCount = 0;
+ fColors = NULL;
+ }
#ifdef SK_DEBUG
SkASSERT((unsigned)fCount <= 256);
SkASSERT(success);
#endif
}
-void SkColorTable::writeToBuffer(SkFlattenableWriteBuffer& buffer) const {
+void SkColorTable::writeToBuffer(SkWriteBuffer& buffer) const {
buffer.writeUInt(fAlphaType);
buffer.writeColorArray(fColors, fCount);
}
diff --git a/chromium/third_party/skia/src/core/SkComposeShader.cpp b/chromium/third_party/skia/src/core/SkComposeShader.cpp
index 0d2d68717f2..f7de73b205d 100644
--- a/chromium/third_party/skia/src/core/SkComposeShader.cpp
+++ b/chromium/third_party/skia/src/core/SkComposeShader.cpp
@@ -11,7 +11,8 @@
#include "SkColorFilter.h"
#include "SkColorPriv.h"
#include "SkColorShader.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkXfermode.h"
#include "SkString.h"
@@ -25,15 +26,15 @@ SkComposeShader::SkComposeShader(SkShader* sA, SkShader* sB, SkXfermode* mode) {
SkSafeRef(mode);
}
-SkComposeShader::SkComposeShader(SkFlattenableReadBuffer& buffer) :
+SkComposeShader::SkComposeShader(SkReadBuffer& buffer) :
INHERITED(buffer) {
fShaderA = buffer.readShader();
if (NULL == fShaderA) {
- fShaderA = SkNEW_ARGS(SkColorShader, (0));
+ fShaderA = SkNEW_ARGS(SkColorShader, ((SkColor)0));
}
fShaderB = buffer.readShader();
if (NULL == fShaderB) {
- fShaderB = SkNEW_ARGS(SkColorShader, (0));
+ fShaderB = SkNEW_ARGS(SkColorShader, ((SkColor)0));
}
fMode = buffer.readXfermode();
}
@@ -44,6 +45,10 @@ SkComposeShader::~SkComposeShader() {
fShaderA->unref();
}
+size_t SkComposeShader::contextSize() const {
+ return sizeof(ComposeShaderContext) + fShaderA->contextSize() + fShaderB->contextSize();
+}
+
class SkAutoAlphaRestore {
public:
SkAutoAlphaRestore(SkPaint* paint, uint8_t newAlpha) {
@@ -61,66 +66,84 @@ private:
};
#define SkAutoAlphaRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoAlphaRestore)
-void SkComposeShader::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkComposeShader::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeFlattenable(fShaderA);
buffer.writeFlattenable(fShaderB);
buffer.writeFlattenable(fMode);
}
-/* We call setContext on our two worker shaders. However, we
- always let them see opaque alpha, and if the paint really
- is translucent, then we apply that after the fact.
-
- We need to keep the calls to setContext/endContext balanced, since if we
- return false, our endContext() will not be called.
- */
-bool SkComposeShader::setContext(const SkBitmap& device,
- const SkPaint& paint,
- const SkMatrix& matrix) {
- if (!this->INHERITED::setContext(device, paint, matrix)) {
- return false;
+template <typename T> void safe_call_destructor(T* obj) {
+ if (obj) {
+ obj->~T();
}
+}
+
+SkShader::Context* SkComposeShader::onCreateContext(const ContextRec& rec, void* storage) const {
+ char* aStorage = (char*) storage + sizeof(ComposeShaderContext);
+ char* bStorage = aStorage + fShaderA->contextSize();
// we preconcat our localMatrix (if any) with the device matrix
// before calling our sub-shaders
-
SkMatrix tmpM;
+ tmpM.setConcat(*rec.fMatrix, this->getLocalMatrix());
+
+ // Our sub-shaders need to see opaque, so by combining them we don't double-alphatize the
+ // result. ComposeShader itself will respect the alpha, and post-apply it after calling the
+ // sub-shaders.
+ SkPaint opaquePaint(*rec.fPaint);
+ opaquePaint.setAlpha(0xFF);
+
+ ContextRec newRec(rec);
+ newRec.fMatrix = &tmpM;
+ newRec.fPaint = &opaquePaint;
+
+ SkShader::Context* contextA = fShaderA->createContext(newRec, aStorage);
+ SkShader::Context* contextB = fShaderB->createContext(newRec, bStorage);
+ if (!contextA || !contextB) {
+ safe_call_destructor(contextA);
+ safe_call_destructor(contextB);
+ return NULL;
+ }
- tmpM.setConcat(matrix, this->getLocalMatrix());
-
- SkAutoAlphaRestore restore(const_cast<SkPaint*>(&paint), 0xFF);
-
- bool setContextA = fShaderA->setContext(device, paint, tmpM);
- bool setContextB = fShaderB->setContext(device, paint, tmpM);
- if (!setContextA || !setContextB) {
- if (setContextB) {
- fShaderB->endContext();
- }
- else if (setContextA) {
- fShaderA->endContext();
- }
- this->INHERITED::endContext();
- return false;
+ return SkNEW_PLACEMENT_ARGS(storage, ComposeShaderContext, (*this, rec, contextA, contextB));
+}
+
+SkComposeShader::ComposeShaderContext::ComposeShaderContext(
+ const SkComposeShader& shader, const ContextRec& rec,
+ SkShader::Context* contextA, SkShader::Context* contextB)
+ : INHERITED(shader, rec)
+ , fShaderContextA(contextA)
+ , fShaderContextB(contextB) {}
+
+SkComposeShader::ComposeShaderContext::~ComposeShaderContext() {
+ fShaderContextA->~Context();
+ fShaderContextB->~Context();
+}
+
+bool SkComposeShader::asACompose(ComposeRec* rec) const {
+ if (rec) {
+ rec->fShaderA = fShaderA;
+ rec->fShaderB = fShaderB;
+ rec->fMode = fMode;
}
return true;
}
-void SkComposeShader::endContext() {
- fShaderB->endContext();
- fShaderA->endContext();
- this->INHERITED::endContext();
-}
// larger is better (fewer times we have to loop), but we shouldn't
// take up too much stack-space (each element is 4 bytes)
#define TMP_COLOR_COUNT 64
-void SkComposeShader::shadeSpan(int x, int y, SkPMColor result[], int count) {
- SkShader* shaderA = fShaderA;
- SkShader* shaderB = fShaderB;
- SkXfermode* mode = fMode;
- unsigned scale = SkAlpha255To256(this->getPaintAlpha());
+void SkComposeShader::ComposeShaderContext::shadeSpan(int x, int y, SkPMColor result[], int count) {
+ SkShader::Context* shaderContextA = fShaderContextA;
+ SkShader::Context* shaderContextB = fShaderContextB;
+ SkXfermode* mode = static_cast<const SkComposeShader&>(fShader).fMode;
+ unsigned scale = SkAlpha255To256(this->getPaintAlpha());
+
+#ifdef SK_BUILD_FOR_ANDROID
+ scale = 256; // ugh -- maintain old bug/behavior for now
+#endif
SkPMColor tmp[TMP_COLOR_COUNT];
@@ -133,8 +156,8 @@ void SkComposeShader::shadeSpan(int x, int y, SkPMColor result[], int count) {
n = TMP_COLOR_COUNT;
}
- shaderA->shadeSpan(x, y, result, n);
- shaderB->shadeSpan(x, y, tmp, n);
+ shaderContextA->shadeSpan(x, y, result, n);
+ shaderContextB->shadeSpan(x, y, tmp, n);
if (256 == scale) {
for (int i = 0; i < n; i++) {
@@ -158,11 +181,11 @@ void SkComposeShader::shadeSpan(int x, int y, SkPMColor result[], int count) {
n = TMP_COLOR_COUNT;
}
- shaderA->shadeSpan(x, y, result, n);
- shaderB->shadeSpan(x, y, tmp, n);
+ shaderContextA->shadeSpan(x, y, result, n);
+ shaderContextB->shadeSpan(x, y, tmp, n);
mode->xfer32(result, tmp, n, NULL);
- if (256 == scale) {
+ if (256 != scale) {
for (int i = 0; i < n; i++) {
result[i] = SkAlphaMulQ(result[i], scale);
}
@@ -175,7 +198,7 @@ void SkComposeShader::shadeSpan(int x, int y, SkPMColor result[], int count) {
}
}
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkComposeShader::toString(SkString* str) const {
str->append("SkComposeShader: (");
diff --git a/chromium/third_party/skia/src/core/SkConfig8888.cpp b/chromium/third_party/skia/src/core/SkConfig8888.cpp
index dd5cbc47240..189309dae6e 100644
--- a/chromium/third_party/skia/src/core/SkConfig8888.cpp
+++ b/chromium/third_party/skia/src/core/SkConfig8888.cpp
@@ -1,280 +1,117 @@
#include "SkConfig8888.h"
+#include "SkColorPriv.h"
#include "SkMathPriv.h"
#include "SkUnPreMultiply.h"
-namespace {
+enum AlphaVerb {
+ kNothing_AlphaVerb,
+ kPremul_AlphaVerb,
+ kUnpremul_AlphaVerb,
+};
-template <int A_IDX, int R_IDX, int G_IDX, int B_IDX>
-inline uint32_t pack_config8888(uint32_t a, uint32_t r,
- uint32_t g, uint32_t b) {
-#ifdef SK_CPU_LENDIAN
- return (a << (A_IDX * 8)) | (r << (R_IDX * 8)) |
- (g << (G_IDX * 8)) | (b << (B_IDX * 8));
-#else
- return (a << ((3-A_IDX) * 8)) | (r << ((3-R_IDX) * 8)) |
- (g << ((3-G_IDX) * 8)) | (b << ((3-B_IDX) * 8));
-#endif
-}
-
-template <int A_IDX, int R_IDX, int G_IDX, int B_IDX>
-inline void unpack_config8888(uint32_t color,
- uint32_t* a, uint32_t* r,
- uint32_t* g, uint32_t* b) {
-#ifdef SK_CPU_LENDIAN
- *a = (color >> (A_IDX * 8)) & 0xff;
- *r = (color >> (R_IDX * 8)) & 0xff;
- *g = (color >> (G_IDX * 8)) & 0xff;
- *b = (color >> (B_IDX * 8)) & 0xff;
-#else
- *a = (color >> ((3 - A_IDX) * 8)) & 0xff;
- *r = (color >> ((3 - R_IDX) * 8)) & 0xff;
- *g = (color >> ((3 - G_IDX) * 8)) & 0xff;
- *b = (color >> ((3 - B_IDX) * 8)) & 0xff;
-#endif
-}
-
-#ifdef SK_CPU_LENDIAN
- static const int SK_NATIVE_A_IDX = SK_A32_SHIFT / 8;
- static const int SK_NATIVE_R_IDX = SK_R32_SHIFT / 8;
- static const int SK_NATIVE_G_IDX = SK_G32_SHIFT / 8;
- static const int SK_NATIVE_B_IDX = SK_B32_SHIFT / 8;
-#else
- static const int SK_NATIVE_A_IDX = 3 - (SK_A32_SHIFT / 8);
- static const int SK_NATIVE_R_IDX = 3 - (SK_R32_SHIFT / 8);
- static const int SK_NATIVE_G_IDX = 3 - (SK_G32_SHIFT / 8);
- static const int SK_NATIVE_B_IDX = 3 - (SK_B32_SHIFT / 8);
-#endif
-
-/**
- * convert_pixel<OUT_CFG, IN_CFG converts a pixel value from one Config8888 to
- * another. It is implemented by first expanding OUT_CFG to r, g, b, a indices
- * and an is_premul bool as params to another template function. Then IN_CFG is
- * expanded via another function call.
- */
-
-template <bool OUT_PM, int OUT_A_IDX, int OUT_R_IDX, int OUT_G_IDX, int OUT_B_IDX,
- bool IN_PM, int IN_A_IDX, int IN_R_IDX, int IN_G_IDX, int IN_B_IDX>
-inline uint32_t convert_pixel(uint32_t pixel) {
- uint32_t a, r, g, b;
- unpack_config8888<IN_A_IDX, IN_R_IDX, IN_G_IDX, IN_B_IDX>(pixel, &a, &r, &g, &b);
- if (IN_PM && !OUT_PM) {
- // Using SkUnPreMultiply::ApplyScale is faster than (value * 0xff) / a.
- if (a) {
- SkUnPreMultiply::Scale scale = SkUnPreMultiply::GetScale(a);
- r = SkUnPreMultiply::ApplyScale(scale, r);
- g = SkUnPreMultiply::ApplyScale(scale, g);
- b = SkUnPreMultiply::ApplyScale(scale, b);
- } else {
- return 0;
- }
- } else if (!IN_PM && OUT_PM) {
- // This matches SkUnPreMultiply conversion which we are replacing.
- r = SkMulDiv255Round(r, a);
- g = SkMulDiv255Round(g, a);
- b = SkMulDiv255Round(b, a);
+template <bool doSwapRB, AlphaVerb doAlpha> uint32_t convert32(uint32_t c) {
+ if (doSwapRB) {
+ c = SkSwizzle_RB(c);
}
- return pack_config8888<OUT_A_IDX, OUT_R_IDX, OUT_G_IDX, OUT_B_IDX>(a, r, g, b);
-}
-template <bool OUT_PM, int OUT_A_IDX, int OUT_R_IDX, int OUT_G_IDX, int OUT_B_IDX, SkCanvas::Config8888 IN_CFG>
-inline uint32_t convert_pixel(uint32_t pixel) {
- switch(IN_CFG) {
- case SkCanvas::kNative_Premul_Config8888:
- return convert_pixel<OUT_PM, OUT_A_IDX, OUT_R_IDX, OUT_G_IDX, OUT_B_IDX,
- true, SK_NATIVE_A_IDX, SK_NATIVE_R_IDX, SK_NATIVE_G_IDX, SK_NATIVE_B_IDX>(pixel);
- break;
- case SkCanvas::kNative_Unpremul_Config8888:
- return convert_pixel<OUT_PM, OUT_A_IDX, OUT_R_IDX, OUT_G_IDX, OUT_B_IDX,
- false, SK_NATIVE_A_IDX, SK_NATIVE_R_IDX, SK_NATIVE_G_IDX, SK_NATIVE_B_IDX>(pixel);
- break;
- case SkCanvas::kBGRA_Premul_Config8888:
- return convert_pixel<OUT_PM, OUT_A_IDX, OUT_R_IDX, OUT_G_IDX, OUT_B_IDX,
- true, 3, 2, 1, 0>(pixel);
- break;
- case SkCanvas::kBGRA_Unpremul_Config8888:
- return convert_pixel<OUT_PM, OUT_A_IDX, OUT_R_IDX, OUT_G_IDX, OUT_B_IDX,
- false, 3, 2, 1, 0>(pixel);
- break;
- case SkCanvas::kRGBA_Premul_Config8888:
- return convert_pixel<OUT_PM, OUT_A_IDX, OUT_R_IDX, OUT_G_IDX, OUT_B_IDX,
- true, 3, 0, 1, 2>(pixel);
+ // Lucky for us, in both RGBA and BGRA, the alpha component is always in the same place, so
+ // we can perform premul or unpremul the same way without knowing the swizzles for RGB.
+ switch (doAlpha) {
+ case kNothing_AlphaVerb:
+ // no change
break;
- case SkCanvas::kRGBA_Unpremul_Config8888:
- return convert_pixel<OUT_PM, OUT_A_IDX, OUT_R_IDX, OUT_G_IDX, OUT_B_IDX,
- false, 3, 0, 1, 2>(pixel);
+ case kPremul_AlphaVerb:
+ c = SkPreMultiplyARGB(SkGetPackedA32(c), SkGetPackedR32(c),
+ SkGetPackedG32(c), SkGetPackedB32(c));
break;
- default:
- SkDEBUGFAIL("Unexpected config8888");
- return 0;
+ case kUnpremul_AlphaVerb:
+ c = SkUnPreMultiply::UnPreMultiplyPreservingByteOrder(c);
break;
}
+ return c;
}
-template <SkCanvas::Config8888 OUT_CFG, SkCanvas::Config8888 IN_CFG>
-inline uint32_t convert_pixel(uint32_t pixel) {
- switch(OUT_CFG) {
- case SkCanvas::kNative_Premul_Config8888:
- return convert_pixel<true, SK_NATIVE_A_IDX, SK_NATIVE_R_IDX, SK_NATIVE_G_IDX, SK_NATIVE_B_IDX, IN_CFG>(pixel);
- break;
- case SkCanvas::kNative_Unpremul_Config8888:
- return convert_pixel<false, SK_NATIVE_A_IDX, SK_NATIVE_R_IDX, SK_NATIVE_G_IDX, SK_NATIVE_B_IDX, IN_CFG>(pixel);
- break;
- case SkCanvas::kBGRA_Premul_Config8888:
- return convert_pixel<true, 3, 2, 1, 0, IN_CFG>(pixel);
- break;
- case SkCanvas::kBGRA_Unpremul_Config8888:
- return convert_pixel<false, 3, 2, 1, 0, IN_CFG>(pixel);
- break;
- case SkCanvas::kRGBA_Premul_Config8888:
- return convert_pixel<true, 3, 0, 1, 2, IN_CFG>(pixel);
- break;
- case SkCanvas::kRGBA_Unpremul_Config8888:
- return convert_pixel<false, 3, 0, 1, 2, IN_CFG>(pixel);
- break;
- default:
- SkDEBUGFAIL("Unexpected config8888");
- return 0;
- break;
+template <bool doSwapRB, AlphaVerb doAlpha>
+void convert32_row(uint32_t* dst, const uint32_t* src, int count) {
+ // This has to be correct if src == dst (but not partial overlap)
+ for (int i = 0; i < count; ++i) {
+ dst[i] = convert32<doSwapRB, doAlpha>(src[i]);
}
}
-/**
- * SkConvertConfig8888Pixels has 6 * 6 possible combinations of src and dst
- * configs. Each is implemented as an instantiation templated function. Two
- * levels of switch statements are used to select the correct instantiation, one
- * for the src config and one for the dst config.
- */
+static bool is_32bit_colortype(SkColorType ct) {
+ return kRGBA_8888_SkColorType == ct || kBGRA_8888_SkColorType == ct;
+}
-template <SkCanvas::Config8888 DST_CFG, SkCanvas::Config8888 SRC_CFG>
-inline void convert_config8888(uint32_t* dstPixels,
- size_t dstRowBytes,
- const uint32_t* srcPixels,
- size_t srcRowBytes,
- int width,
- int height) {
- intptr_t dstPix = reinterpret_cast<intptr_t>(dstPixels);
- intptr_t srcPix = reinterpret_cast<intptr_t>(srcPixels);
+static AlphaVerb compute_AlphaVerb(SkAlphaType src, SkAlphaType dst) {
+ SkASSERT(kIgnore_SkAlphaType != src);
+ SkASSERT(kIgnore_SkAlphaType != dst);
- for (int y = 0; y < height; ++y) {
- srcPixels = reinterpret_cast<const uint32_t*>(srcPix);
- dstPixels = reinterpret_cast<uint32_t*>(dstPix);
- for (int x = 0; x < width; ++x) {
- dstPixels[x] = convert_pixel<DST_CFG, SRC_CFG>(srcPixels[x]);
- }
- dstPix += dstRowBytes;
- srcPix += srcRowBytes;
+ if (kOpaque_SkAlphaType == src || kOpaque_SkAlphaType == dst || src == dst) {
+ return kNothing_AlphaVerb;
}
-}
-
-template <SkCanvas::Config8888 SRC_CFG>
-inline void convert_config8888(uint32_t* dstPixels,
- size_t dstRowBytes,
- SkCanvas::Config8888 dstConfig,
- const uint32_t* srcPixels,
- size_t srcRowBytes,
- int width,
- int height) {
- switch(dstConfig) {
- case SkCanvas::kNative_Premul_Config8888:
- convert_config8888<SkCanvas::kNative_Premul_Config8888, SRC_CFG>(dstPixels, dstRowBytes, srcPixels, srcRowBytes, width, height);
- break;
- case SkCanvas::kNative_Unpremul_Config8888:
- convert_config8888<SkCanvas::kNative_Unpremul_Config8888, SRC_CFG>(dstPixels, dstRowBytes, srcPixels, srcRowBytes, width, height);
- break;
- case SkCanvas::kBGRA_Premul_Config8888:
- convert_config8888<SkCanvas::kBGRA_Premul_Config8888, SRC_CFG>(dstPixels, dstRowBytes, srcPixels, srcRowBytes, width, height);
- break;
- case SkCanvas::kBGRA_Unpremul_Config8888:
- convert_config8888<SkCanvas::kBGRA_Unpremul_Config8888, SRC_CFG>(dstPixels, dstRowBytes, srcPixels, srcRowBytes, width, height);
- break;
- case SkCanvas::kRGBA_Premul_Config8888:
- convert_config8888<SkCanvas::kRGBA_Premul_Config8888, SRC_CFG>(dstPixels, dstRowBytes, srcPixels, srcRowBytes, width, height);
- break;
- case SkCanvas::kRGBA_Unpremul_Config8888:
- convert_config8888<SkCanvas::kRGBA_Unpremul_Config8888, SRC_CFG>(dstPixels, dstRowBytes, srcPixels, srcRowBytes, width, height);
- break;
- default:
- SkDEBUGFAIL("Unexpected config8888");
- break;
+ if (kPremul_SkAlphaType == dst) {
+ SkASSERT(kUnpremul_SkAlphaType == src);
+ return kPremul_AlphaVerb;
+ } else {
+ SkASSERT(kPremul_SkAlphaType == src);
+ SkASSERT(kUnpremul_SkAlphaType == dst);
+ return kUnpremul_AlphaVerb;
}
}
+static void memcpy32_row(uint32_t* dst, const uint32_t* src, int count) {
+ memcpy(dst, src, count * 4);
}
-void SkConvertConfig8888Pixels(uint32_t* dstPixels,
- size_t dstRowBytes,
- SkCanvas::Config8888 dstConfig,
- const uint32_t* srcPixels,
- size_t srcRowBytes,
- SkCanvas::Config8888 srcConfig,
- int width,
- int height) {
- if (srcConfig == dstConfig) {
- if (srcPixels == dstPixels) {
- return;
- }
- if (dstRowBytes == srcRowBytes &&
- 4U * width == srcRowBytes) {
- memcpy(dstPixels, srcPixels, srcRowBytes * height);
- return;
- } else {
- intptr_t srcPix = reinterpret_cast<intptr_t>(srcPixels);
- intptr_t dstPix = reinterpret_cast<intptr_t>(dstPixels);
- for (int y = 0; y < height; ++y) {
- srcPixels = reinterpret_cast<const uint32_t*>(srcPix);
- dstPixels = reinterpret_cast<uint32_t*>(dstPix);
- memcpy(dstPixels, srcPixels, 4 * width);
- srcPix += srcRowBytes;
- dstPix += dstRowBytes;
- }
- return;
- }
+bool SkSrcPixelInfo::convertPixelsTo(SkDstPixelInfo* dst, int width, int height) const {
+ if (width <= 0 || height <= 0) {
+ return false;
}
- switch(srcConfig) {
- case SkCanvas::kNative_Premul_Config8888:
- convert_config8888<SkCanvas::kNative_Premul_Config8888>(dstPixels, dstRowBytes, dstConfig, srcPixels, srcRowBytes, width, height);
- break;
- case SkCanvas::kNative_Unpremul_Config8888:
- convert_config8888<SkCanvas::kNative_Unpremul_Config8888>(dstPixels, dstRowBytes, dstConfig, srcPixels, srcRowBytes, width, height);
- break;
- case SkCanvas::kBGRA_Premul_Config8888:
- convert_config8888<SkCanvas::kBGRA_Premul_Config8888>(dstPixels, dstRowBytes, dstConfig, srcPixels, srcRowBytes, width, height);
- break;
- case SkCanvas::kBGRA_Unpremul_Config8888:
- convert_config8888<SkCanvas::kBGRA_Unpremul_Config8888>(dstPixels, dstRowBytes, dstConfig, srcPixels, srcRowBytes, width, height);
- break;
- case SkCanvas::kRGBA_Premul_Config8888:
- convert_config8888<SkCanvas::kRGBA_Premul_Config8888>(dstPixels, dstRowBytes, dstConfig, srcPixels, srcRowBytes, width, height);
+
+ if (!is_32bit_colortype(fColorType) || !is_32bit_colortype(dst->fColorType)) {
+ return false;
+ }
+
+ void (*proc)(uint32_t* dst, const uint32_t* src, int count);
+ AlphaVerb doAlpha = compute_AlphaVerb(fAlphaType, dst->fAlphaType);
+ bool doSwapRB = fColorType != dst->fColorType;
+
+ switch (doAlpha) {
+ case kNothing_AlphaVerb:
+ if (doSwapRB) {
+ proc = convert32_row<true, kNothing_AlphaVerb>;
+ } else {
+ if (fPixels == dst->fPixels) {
+ return true;
+ }
+ proc = memcpy32_row;
+ }
break;
- case SkCanvas::kRGBA_Unpremul_Config8888:
- convert_config8888<SkCanvas::kRGBA_Unpremul_Config8888>(dstPixels, dstRowBytes, dstConfig, srcPixels, srcRowBytes, width, height);
+ case kPremul_AlphaVerb:
+ if (doSwapRB) {
+ proc = convert32_row<true, kPremul_AlphaVerb>;
+ } else {
+ proc = convert32_row<false, kPremul_AlphaVerb>;
+ }
break;
- default:
- SkDEBUGFAIL("Unexpected config8888");
+ case kUnpremul_AlphaVerb:
+ if (doSwapRB) {
+ proc = convert32_row<true, kUnpremul_AlphaVerb>;
+ } else {
+ proc = convert32_row<false, kUnpremul_AlphaVerb>;
+ }
break;
}
-}
-uint32_t SkPackConfig8888(SkCanvas::Config8888 config,
- uint32_t a,
- uint32_t r,
- uint32_t g,
- uint32_t b) {
- switch (config) {
- case SkCanvas::kNative_Premul_Config8888:
- case SkCanvas::kNative_Unpremul_Config8888:
- return pack_config8888<SK_NATIVE_A_IDX,
- SK_NATIVE_R_IDX,
- SK_NATIVE_G_IDX,
- SK_NATIVE_B_IDX>(a, r, g, b);
- case SkCanvas::kBGRA_Premul_Config8888:
- case SkCanvas::kBGRA_Unpremul_Config8888:
- return pack_config8888<3, 2, 1, 0>(a, r, g, b);
- case SkCanvas::kRGBA_Premul_Config8888:
- case SkCanvas::kRGBA_Unpremul_Config8888:
- return pack_config8888<3, 0, 1, 2>(a, r, g, b);
- default:
- SkDEBUGFAIL("Unexpected config8888");
- return 0;
+ uint32_t* dstP = static_cast<uint32_t*>(dst->fPixels);
+ const uint32_t* srcP = static_cast<const uint32_t*>(fPixels);
+ size_t srcInc = fRowBytes >> 2;
+ size_t dstInc = dst->fRowBytes >> 2;
+ for (int y = 0; y < height; ++y) {
+ proc(dstP, srcP, width);
+ dstP += dstInc;
+ srcP += srcInc;
}
+ return true;
}
diff --git a/chromium/third_party/skia/src/core/SkConfig8888.h b/chromium/third_party/skia/src/core/SkConfig8888.h
index 96eaef2447f..97a3433ad24 100644
--- a/chromium/third_party/skia/src/core/SkConfig8888.h
+++ b/chromium/third_party/skia/src/core/SkConfig8888.h
@@ -1,4 +1,3 @@
-
/*
* Copyright 2011 Google Inc.
*
@@ -6,71 +5,27 @@
* found in the LICENSE file.
*/
+#ifndef SkPixelInfo_DEFINED
+#define SkPixelInfo_DEFINED
-#include "SkCanvas.h"
-#include "SkColorPriv.h"
-
-/**
- * Converts pixels from one Config8888 to another Config8888
- */
-void SkConvertConfig8888Pixels(uint32_t* dstPixels,
- size_t dstRowBytes,
- SkCanvas::Config8888 dstConfig,
- const uint32_t* srcPixels,
- size_t srcRowBytes,
- SkCanvas::Config8888 srcConfig,
- int width,
- int height);
-
-/**
- * Packs a, r, g, b, values into byte order specified by config.
- */
-uint32_t SkPackConfig8888(SkCanvas::Config8888 config,
- uint32_t a,
- uint32_t r,
- uint32_t g,
- uint32_t b);
-
-///////////////////////////////////////////////////////////////////////////////
-// Implementation
-
-namespace {
+#include "SkImageInfo.h"
-/**
- Copies all pixels from a bitmap to a dst ptr with a given rowBytes and
- Config8888. The bitmap must have kARGB_8888_Config.
- */
+struct SkPixelInfo {
+ SkColorType fColorType;
+ SkAlphaType fAlphaType;
+ size_t fRowBytes;
+};
-static inline void SkCopyBitmapToConfig8888(uint32_t* dstPixels,
- size_t dstRowBytes,
- SkCanvas::Config8888 dstConfig8888,
- const SkBitmap& srcBmp) {
- SkASSERT(SkBitmap::kARGB_8888_Config == srcBmp.config());
- SkAutoLockPixels alp(srcBmp);
- int w = srcBmp.width();
- int h = srcBmp.height();
- size_t srcRowBytes = srcBmp.rowBytes();
- const uint32_t* srcPixels = reinterpret_cast<uint32_t*>(srcBmp.getPixels());
+struct SkDstPixelInfo : SkPixelInfo {
+ void* fPixels;
+};
- SkConvertConfig8888Pixels(dstPixels, dstRowBytes, dstConfig8888, srcPixels, srcRowBytes, SkCanvas::kNative_Premul_Config8888, w, h);
-}
-
-/**
- Copies over all pixels in a bitmap from a src ptr with a given rowBytes and
- Config8888. The bitmap must have pixels and be kARGB_8888_Config.
- */
-static inline void SkCopyConfig8888ToBitmap(const SkBitmap& dstBmp,
- const uint32_t* srcPixels,
- size_t srcRowBytes,
- SkCanvas::Config8888 srcConfig8888) {
- SkASSERT(SkBitmap::kARGB_8888_Config == dstBmp.config());
- SkAutoLockPixels alp(dstBmp);
- int w = dstBmp.width();
- int h = dstBmp.height();
- size_t dstRowBytes = dstBmp.rowBytes();
- uint32_t* dstPixels = reinterpret_cast<uint32_t*>(dstBmp.getPixels());
+struct SkSrcPixelInfo : SkPixelInfo {
+ const void* fPixels;
- SkConvertConfig8888Pixels(dstPixels, dstRowBytes, SkCanvas::kNative_Premul_Config8888, srcPixels, srcRowBytes, srcConfig8888, w, h);
-}
+ // Guaranteed to work even if src.fPixels and dst.fPixels are the same
+ // (but not if they overlap partially)
+ bool convertPixelsTo(SkDstPixelInfo* dst, int width, int height) const;
+};
-}
+#endif
diff --git a/chromium/third_party/skia/src/core/SkConvolver.cpp b/chromium/third_party/skia/src/core/SkConvolver.cpp
index 7666e6fadc9..0f5cf9021b4 100644
--- a/chromium/third_party/skia/src/core/SkConvolver.cpp
+++ b/chromium/third_party/skia/src/core/SkConvolver.cpp
@@ -405,7 +405,7 @@ void BGRAConvolve2D(const unsigned char* sourceData,
const unsigned char* src[4];
unsigned char* outRow[4];
for (int i = 0; i < 4; ++i) {
- src[i] = &sourceData[(nextXRow + i) * sourceByteRowStride];
+ src[i] = &sourceData[(uint64_t)(nextXRow + i) * sourceByteRowStride];
outRow[i] = rowBuffer.advanceRow();
}
convolveProcs.fConvolve4RowsHorizontally(src, filterX, outRow);
@@ -416,16 +416,16 @@ void BGRAConvolve2D(const unsigned char* sourceData,
nextXRow < lastFilterOffset + lastFilterLength -
avoidSimdRows) {
convolveProcs.fConvolveHorizontally(
- &sourceData[nextXRow * sourceByteRowStride],
+ &sourceData[(uint64_t)nextXRow * sourceByteRowStride],
filterX, rowBuffer.advanceRow(), sourceHasAlpha);
} else {
if (sourceHasAlpha) {
ConvolveHorizontally<true>(
- &sourceData[nextXRow * sourceByteRowStride],
+ &sourceData[(uint64_t)nextXRow * sourceByteRowStride],
filterX, rowBuffer.advanceRow());
} else {
ConvolveHorizontally<false>(
- &sourceData[nextXRow * sourceByteRowStride],
+ &sourceData[(uint64_t)nextXRow * sourceByteRowStride],
filterX, rowBuffer.advanceRow());
}
}
@@ -434,7 +434,7 @@ void BGRAConvolve2D(const unsigned char* sourceData,
}
// Compute where in the output image this row of final data will go.
- unsigned char* curOutputRow = &output[outY * outputByteRowStride];
+ unsigned char* curOutputRow = &output[(uint64_t)outY * outputByteRowStride];
// Get the list of rows that the circular buffer has, in order.
int firstRowInCircularBuffer;
diff --git a/chromium/third_party/skia/src/core/SkConvolver.h b/chromium/third_party/skia/src/core/SkConvolver.h
index 94a5e915987..8e53da2d423 100644
--- a/chromium/third_party/skia/src/core/SkConvolver.h
+++ b/chromium/third_party/skia/src/core/SkConvolver.h
@@ -13,6 +13,8 @@
#if defined(__APPLE__)
#undef FloatToConvolutionFixed
#undef ConvolutionFixedToFloat
+#undef FloatToFixed
+#undef FixedToFloat
#endif
// Represents a filter in one dimension. Each output pixel has one entry in this
diff --git a/chromium/third_party/skia/src/core/SkCordic.cpp b/chromium/third_party/skia/src/core/SkCordic.cpp
deleted file mode 100644
index 3adc92faa10..00000000000
--- a/chromium/third_party/skia/src/core/SkCordic.cpp
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * Copyright 2006 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkCordic.h"
-#include "SkMathPriv.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
-
-#include "SkFloatingPoint.h"
-
-void SkCordic_UnitTest()
-{
-#if defined(SK_SUPPORT_UNITTEST)
- float val;
- for (float angle = -720; angle < 720; angle += 30) {
- float radian = angle * 3.1415925358f / 180.0f;
- SkFixed f_angle = SkFloatToFixed(radian);
- // 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 = SkFloatToFixed(val);
- // 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 = SkFloatToFixed(val);
- // 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 = SkFloatToFixed(val);
- SkFixed f_val2 = SkFloatToFixed(val2);
- 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 = SkFloatToFixed(val);
- // 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/chromium/third_party/skia/src/core/SkCordic.h b/chromium/third_party/skia/src/core/SkCordic.h
deleted file mode 100644
index fecf6456430..00000000000
--- a/chromium/third_party/skia/src/core/SkCordic.h
+++ /dev/null
@@ -1,28 +0,0 @@
-
-/*
- * Copyright 2006 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#ifndef 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/chromium/third_party/skia/src/core/SkCoreBlitters.h b/chromium/third_party/skia/src/core/SkCoreBlitters.h
index 1605a5273dc..20f9437ac8a 100644
--- a/chromium/third_party/skia/src/core/SkCoreBlitters.h
+++ b/chromium/third_party/skia/src/core/SkCoreBlitters.h
@@ -8,8 +8,11 @@
#ifndef SkCoreBlitters_DEFINED
#define SkCoreBlitters_DEFINED
+#include "SkBitmapProcShader.h"
#include "SkBlitter.h"
#include "SkBlitRow.h"
+#include "SkShader.h"
+#include "SkSmallAllocator.h"
class SkRasterBlitter : public SkBlitter {
public:
@@ -24,12 +27,28 @@ private:
class SkShaderBlitter : public SkRasterBlitter {
public:
- SkShaderBlitter(const SkBitmap& device, const SkPaint& paint);
+ /**
+ * The storage for shaderContext is owned by the caller, but the object itself is not.
+ * The blitter only ensures that the storage always holds a live object, but it may
+ * exchange that object.
+ */
+ SkShaderBlitter(const SkBitmap& device, const SkPaint& paint,
+ SkShader::Context* shaderContext);
virtual ~SkShaderBlitter();
+ /**
+ * Create a new shader context and uses it instead of the old one if successful.
+ * Will create the context at the same location as the old one (this is safe
+ * because the shader itself is unchanged).
+ */
+ virtual bool resetShaderContext(const SkShader::ContextRec&) SK_OVERRIDE;
+
+ virtual SkShader::Context* getShaderContext() const SK_OVERRIDE { return fShaderContext; }
+
protected:
- uint32_t fShaderFlags;
- SkShader* fShader;
+ uint32_t fShaderFlags;
+ const SkShader* fShader;
+ SkShader::Context* fShaderContext;
private:
// illegal
@@ -72,7 +91,8 @@ private:
class SkA8_Shader_Blitter : public SkShaderBlitter {
public:
- SkA8_Shader_Blitter(const SkBitmap& device, const SkPaint& paint);
+ SkA8_Shader_Blitter(const SkBitmap& device, const SkPaint& paint,
+ SkShader::Context* shaderContext);
virtual ~SkA8_Shader_Blitter();
virtual void blitH(int x, int y, int width);
virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]);
@@ -138,7 +158,8 @@ private:
class SkARGB32_Shader_Blitter : public SkShaderBlitter {
public:
- SkARGB32_Shader_Blitter(const SkBitmap& device, const SkPaint& paint);
+ SkARGB32_Shader_Blitter(const SkBitmap& device, const SkPaint& paint,
+ SkShader::Context* shaderContext);
virtual ~SkARGB32_Shader_Blitter();
virtual void blitH(int x, int y, int width) SK_OVERRIDE;
virtual void blitV(int x, int y, int height, SkAlpha alpha) SK_OVERRIDE;
@@ -175,8 +196,8 @@ private:
SkBlitter::Choose(...)
*/
-extern SkBlitter* SkBlitter_ChooseD565(const SkBitmap& device,
- const SkPaint& paint,
- void* storage, size_t storageSize);
+SkBlitter* SkBlitter_ChooseD565(const SkBitmap& device, const SkPaint& paint,
+ SkShader::Context* shaderContext,
+ SkTBlitterAllocator* allocator);
#endif
diff --git a/chromium/third_party/skia/src/core/SkCubicClipper.cpp b/chromium/third_party/skia/src/core/SkCubicClipper.cpp
index aed681b9f30..81ef18de7af 100644
--- a/chromium/third_party/skia/src/core/SkCubicClipper.cpp
+++ b/chromium/third_party/skia/src/core/SkCubicClipper.cpp
@@ -31,11 +31,7 @@ static bool chopMonoCubicAtY(SkPoint pts[4], SkScalar y, SkScalar* t) {
// Initial guess.
// TODO(turk): Check for zero denominator? Shouldn't happen unless the curve
// is not only monotonic but degenerate.
-#ifdef SK_SCALAR_IS_FLOAT
SkScalar t1 = ycrv[0] / (ycrv[0] - ycrv[3]);
-#else // !SK_SCALAR_IS_FLOAT
- SkScalar t1 = SkDivBits(ycrv[0], ycrv[0] - ycrv[3], 16);
-#endif // !SK_SCALAR_IS_FLOAT
// Newton's iterations.
const SkScalar tol = SK_Scalar1 / 16384; // This leaves 2 fixed noise bits.
@@ -53,11 +49,7 @@ static bool chopMonoCubicAtY(SkPoint pts[4], SkScalar y, SkScalar* t) {
SkScalar y0123 = SkScalarInterp(y012, y123, t0);
SkScalar yder = (y123 - y012) * 3;
// TODO(turk): check for yder==0: horizontal.
-#ifdef SK_SCALAR_IS_FLOAT
t1 -= y0123 / yder;
-#else // !SK_SCALAR_IS_FLOAT
- t1 -= SkDivBits(y0123, yder, 16);
-#endif // !SK_SCALAR_IS_FLOAT
converged = SkScalarAbs(t1 - t0) <= tol; // NaN-safe
++iters;
} while (!converged && (iters < maxiters));
diff --git a/chromium/third_party/skia/src/core/SkData.cpp b/chromium/third_party/skia/src/core/SkData.cpp
index fd963a9ff50..c65328720a7 100644
--- a/chromium/third_party/skia/src/core/SkData.cpp
+++ b/chromium/third_party/skia/src/core/SkData.cpp
@@ -6,9 +6,10 @@
*/
#include "SkData.h"
-#include "SkFlattenableBuffers.h"
+#include "SkLazyPtr.h"
#include "SkOSFile.h"
-#include "SkOnce.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
SkData::SkData(const void* ptr, size_t size, ReleaseProc proc, void* context) {
fPtr = ptr;
@@ -48,16 +49,14 @@ size_t SkData::copyRange(size_t offset, size_t length, void* buffer) const {
///////////////////////////////////////////////////////////////////////////////
-void SkData::NewEmptyImpl(SkData** empty) {
- *empty = new SkData(NULL, 0, NULL, NULL);
+SkData* SkData::NewEmptyImpl() {
+ return new SkData(NULL, 0, NULL, NULL);
}
+void SkData::DeleteEmpty(SkData* ptr) { SkDELETE(ptr); }
SkData* SkData::NewEmpty() {
- static SkData* gEmptyRef;
- SK_DECLARE_STATIC_ONCE(once);
- SkOnce(&once, SkData::NewEmptyImpl, &gEmptyRef);
- gEmptyRef->ref();
- return gEmptyRef;
+ SK_DECLARE_STATIC_LAZY_PTR(SkData, empty, NewEmptyImpl, DeleteEmpty);
+ return SkRef(empty.get());
}
// assumes fPtr was allocated via sk_malloc
diff --git a/chromium/third_party/skia/src/core/SkDebug.cpp b/chromium/third_party/skia/src/core/SkDebug.cpp
index 2a04b302ff6..b705a650ea2 100644
--- a/chromium/third_party/skia/src/core/SkDebug.cpp
+++ b/chromium/third_party/skia/src/core/SkDebug.cpp
@@ -41,4 +41,19 @@ uint32_t SkToU32(uintmax_t x) {
return (uint32_t)x;
}
+int SkToInt(intmax_t x) {
+ SkASSERT((int)x == x);
+ return (int)x;
+}
+
+unsigned SkToUInt(uintmax_t x) {
+ SkASSERT((unsigned)x == x);
+ return (unsigned)x;
+}
+
+size_t SkToSizeT(uintmax_t x) {
+ SkASSERT((size_t)x == x);
+ return (size_t)x;
+}
+
#endif
diff --git a/chromium/third_party/skia/src/core/SkDescriptor.h b/chromium/third_party/skia/src/core/SkDescriptor.h
index e71ff41b5c5..c526451af5e 100644
--- a/chromium/third_party/skia/src/core/SkDescriptor.h
+++ b/chromium/third_party/skia/src/core/SkDescriptor.h
@@ -37,14 +37,14 @@ public:
uint32_t getLength() const { return fLength; }
- void* addEntry(uint32_t tag, uint32_t length, const void* data = NULL) {
+ void* addEntry(uint32_t tag, size_t length, const void* data = NULL) {
SkASSERT(tag);
SkASSERT(SkAlign4(length) == length);
SkASSERT(this->findEntry(tag, NULL) == NULL);
Entry* entry = (Entry*)((char*)this + fLength);
entry->fTag = tag;
- entry->fLen = length;
+ entry->fLen = SkToU32(length);
if (data) {
memcpy(entry + 1, data, length);
}
diff --git a/chromium/third_party/skia/src/core/SkDevice.cpp b/chromium/third_party/skia/src/core/SkDevice.cpp
index 0c9e9d66b6b..6a09c0b9db8 100644
--- a/chromium/third_party/skia/src/core/SkDevice.cpp
+++ b/chromium/third_party/skia/src/core/SkDevice.cpp
@@ -1,4 +1,3 @@
-
/*
* Copyright 2011 Google Inc.
*
@@ -9,15 +8,6 @@
#include "SkDevice.h"
#include "SkMetaData.h"
-#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
- const SkCanvas::Config8888 SkBaseDevice::kPMColorAlias = SkCanvas::kBGRA_Premul_Config8888;
-#elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
- const SkCanvas::Config8888 SkBaseDevice::kPMColorAlias = SkCanvas::kRGBA_Premul_Config8888;
-#else
- const SkCanvas::Config8888 SkBaseDevice::kPMColorAlias = (SkCanvas::Config8888) -1;
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
SkBaseDevice::SkBaseDevice()
: fLeakyProperties(SkDeviceProperties::MakeDefault())
#ifdef SK_DEBUG
@@ -42,18 +32,12 @@ SkBaseDevice::~SkBaseDevice() {
delete fMetaData;
}
-SkBaseDevice* SkBaseDevice::createCompatibleDevice(SkBitmap::Config config,
- int width, int height,
- bool isOpaque) {
- return this->onCreateCompatibleDevice(config, width, height,
- isOpaque, kGeneral_Usage);
+SkBaseDevice* SkBaseDevice::createCompatibleDevice(const SkImageInfo& info) {
+ return this->onCreateDevice(info, kGeneral_Usage);
}
-SkBaseDevice* SkBaseDevice::createCompatibleDeviceForSaveLayer(SkBitmap::Config config,
- int width, int height,
- bool isOpaque) {
- return this->onCreateCompatibleDevice(config, width, height,
- isOpaque, kSaveLayer_Usage);
+SkBaseDevice* SkBaseDevice::createCompatibleDeviceForSaveLayer(const SkImageInfo& info) {
+ return this->onCreateDevice(info, kSaveLayer_Usage);
}
SkMetaData& SkBaseDevice::getMetaData() {
@@ -65,6 +49,10 @@ SkMetaData& SkBaseDevice::getMetaData() {
return *fMetaData;
}
+SkImageInfo SkBaseDevice::imageInfo() const {
+ return SkImageInfo::MakeUnknown();
+}
+
const SkBitmap& SkBaseDevice::accessBitmap(bool changePixels) {
const SkBitmap& bitmap = this->onAccessBitmap();
if (changePixels) {
@@ -73,46 +61,84 @@ const SkBitmap& SkBaseDevice::accessBitmap(bool changePixels) {
return bitmap;
}
-bool SkBaseDevice::readPixels(SkBitmap* bitmap, int x, int y,
- SkCanvas::Config8888 config8888) {
- if (SkBitmap::kARGB_8888_Config != bitmap->config() ||
- NULL != bitmap->getTexture()) {
- return false;
- }
+SkSurface* SkBaseDevice::newSurface(const SkImageInfo&) { return NULL; }
- const SkBitmap& src = this->accessBitmap(false);
+const void* SkBaseDevice::peekPixels(SkImageInfo*, size_t*) { return NULL; }
- SkIRect srcRect = SkIRect::MakeXYWH(x, y, bitmap->width(),
- bitmap->height());
- SkIRect devbounds = SkIRect::MakeWH(src.width(), src.height());
- if (!srcRect.intersect(devbounds)) {
- return false;
- }
+void SkBaseDevice::drawDRRect(const SkDraw& draw, const SkRRect& outer,
+ const SkRRect& inner, const SkPaint& paint) {
+ SkPath path;
+ path.addRRect(outer);
+ path.addRRect(inner);
+ path.setFillType(SkPath::kEvenOdd_FillType);
- SkBitmap tmp;
- SkBitmap* bmp;
- if (bitmap->isNull()) {
- tmp.setConfig(SkBitmap::kARGB_8888_Config, bitmap->width(),
- bitmap->height());
- if (!tmp.allocPixels()) {
- return false;
- }
- bmp = &tmp;
- } else {
- bmp = bitmap;
- }
+ const SkMatrix* preMatrix = NULL;
+ const bool pathIsMutable = true;
+ this->drawPath(draw, path, paint, preMatrix, pathIsMutable);
+}
+
+bool SkBaseDevice::readPixels(const SkImageInfo& info, void* dstP, size_t rowBytes, int x, int y) {
+#ifdef SK_DEBUG
+ SkASSERT(info.width() > 0 && info.height() > 0);
+ SkASSERT(dstP);
+ SkASSERT(rowBytes >= info.minRowBytes());
+ SkASSERT(x >= 0 && y >= 0);
+
+ const SkImageInfo& srcInfo = this->imageInfo();
+ SkASSERT(x + info.width() <= srcInfo.width());
+ SkASSERT(y + info.height() <= srcInfo.height());
+#endif
+ return this->onReadPixels(info, dstP, rowBytes, x, y);
+}
+
+bool SkBaseDevice::writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes,
+ int x, int y) {
+#ifdef SK_DEBUG
+ SkASSERT(info.width() > 0 && info.height() > 0);
+ SkASSERT(pixels);
+ SkASSERT(rowBytes >= info.minRowBytes());
+ SkASSERT(x >= 0 && y >= 0);
+
+ const SkImageInfo& dstInfo = this->imageInfo();
+ SkASSERT(x + info.width() <= dstInfo.width());
+ SkASSERT(y + info.height() <= dstInfo.height());
+#endif
+ return this->onWritePixels(info, pixels, rowBytes, x, y);
+}
+
+bool SkBaseDevice::onWritePixels(const SkImageInfo&, const void*, size_t, int, int) {
+ return false;
+}
- SkIRect subrect = srcRect;
- subrect.offset(-x, -y);
- SkBitmap bmpSubset;
- bmp->extractSubset(&bmpSubset, subrect);
-
- bool result = this->onReadPixels(bmpSubset,
- srcRect.fLeft,
- srcRect.fTop,
- config8888);
- if (result && bmp == &tmp) {
- tmp.swap(*bitmap);
+bool SkBaseDevice::onReadPixels(const SkImageInfo&, void*, size_t, int x, int y) {
+ return false;
+}
+
+void* SkBaseDevice::accessPixels(SkImageInfo* info, size_t* rowBytes) {
+ SkImageInfo tmpInfo;
+ size_t tmpRowBytes;
+ if (NULL == info) {
+ info = &tmpInfo;
}
- return result;
+ if (NULL == rowBytes) {
+ rowBytes = &tmpRowBytes;
+ }
+ return this->onAccessPixels(info, rowBytes);
+}
+
+void* SkBaseDevice::onAccessPixels(SkImageInfo* info, size_t* rowBytes) {
+ return NULL;
+}
+
+void SkBaseDevice::EXPERIMENTAL_optimize(const SkPicture* picture) {
+ // The base class doesn't perform any analysis but derived classes may
+}
+
+void SkBaseDevice::EXPERIMENTAL_purge(const SkPicture* picture) {
+ // Derived-classes may have data to purge but not the base class
+}
+
+bool SkBaseDevice::EXPERIMENTAL_drawPicture(SkCanvas* canvas, const SkPicture* picture) {
+ // The base class doesn't perform any accelerated picture rendering
+ return false;
}
diff --git a/chromium/third_party/skia/src/core/SkDeviceImageFilterProxy.h b/chromium/third_party/skia/src/core/SkDeviceImageFilterProxy.h
index 03fcb68125a..5ee563484ee 100644
--- a/chromium/third_party/skia/src/core/SkDeviceImageFilterProxy.h
+++ b/chromium/third_party/skia/src/core/SkDeviceImageFilterProxy.h
@@ -15,16 +15,15 @@ public:
SkDeviceImageFilterProxy(SkBaseDevice* device) : fDevice(device) {}
virtual SkBaseDevice* createDevice(int w, int h) SK_OVERRIDE {
- return fDevice->createCompatibleDevice(SkBitmap::kARGB_8888_Config,
- w, h, false);
+ return fDevice->createCompatibleDevice(SkImageInfo::MakeN32Premul(w, h));
}
- virtual bool canHandleImageFilter(SkImageFilter* filter) SK_OVERRIDE {
+ virtual bool canHandleImageFilter(const SkImageFilter* filter) SK_OVERRIDE {
return fDevice->canHandleImageFilter(filter);
}
- virtual bool filterImage(SkImageFilter* filter, const SkBitmap& src,
- const SkMatrix& ctm,
+ virtual bool filterImage(const SkImageFilter* filter, const SkBitmap& src,
+ const SkImageFilter::Context& ctx,
SkBitmap* result, SkIPoint* offset) SK_OVERRIDE {
- return fDevice->filterImage(filter, src, ctm, result, offset);
+ return fDevice->filterImage(filter, src, ctx, result, offset);
}
private:
diff --git a/chromium/third_party/skia/src/core/SkDistanceFieldGen.cpp b/chromium/third_party/skia/src/core/SkDistanceFieldGen.cpp
new file mode 100755
index 00000000000..ef0ee86d59c
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkDistanceFieldGen.cpp
@@ -0,0 +1,521 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkDistanceFieldGen.h"
+#include "SkPoint.h"
+
+struct DFData {
+ float fAlpha; // alpha value of source texel
+ float fDistSq; // distance squared to nearest (so far) edge texel
+ SkPoint fDistVector; // distance vector to nearest (so far) edge texel
+};
+
+enum NeighborFlags {
+ kLeft_NeighborFlag = 0x01,
+ kRight_NeighborFlag = 0x02,
+ kTopLeft_NeighborFlag = 0x04,
+ kTop_NeighborFlag = 0x08,
+ kTopRight_NeighborFlag = 0x10,
+ kBottomLeft_NeighborFlag = 0x20,
+ kBottom_NeighborFlag = 0x40,
+ kBottomRight_NeighborFlag = 0x80,
+ kAll_NeighborFlags = 0xff,
+
+ kNeighborFlagCount = 8
+};
+
+// We treat an "edge" as a place where we cross from >=128 to <128, or vice versa, or
+// where we have two non-zero pixels that are <128.
+// 'neighborFlags' is used to limit the directions in which we test to avoid indexing
+// outside of the image
+static bool found_edge(const unsigned char* imagePtr, int width, int neighborFlags) {
+ // the order of these should match the neighbor flags above
+ const int kNum8ConnectedNeighbors = 8;
+ const int offsets[8] = {-1, 1, -width-1, -width, -width+1, width-1, width, width+1 };
+ SkASSERT(kNum8ConnectedNeighbors == kNeighborFlagCount);
+
+ // search for an edge
+ unsigned char currVal = *imagePtr;
+ unsigned char currCheck = (currVal >> 7);
+ for (int i = 0; i < kNum8ConnectedNeighbors; ++i) {
+ unsigned char neighborVal;
+ if ((1 << i) & neighborFlags) {
+ const unsigned char* checkPtr = imagePtr + offsets[i];
+ neighborVal = *checkPtr;
+ } else {
+ neighborVal = 0;
+ }
+ unsigned char neighborCheck = (neighborVal >> 7);
+ SkASSERT(currCheck == 0 || currCheck == 1);
+ SkASSERT(neighborCheck == 0 || neighborCheck == 1);
+ // if sharp transition
+ if (currCheck != neighborCheck ||
+ // or both <128 and >0
+ (!currCheck && !neighborCheck && currVal && neighborVal)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static void init_glyph_data(DFData* data, unsigned char* edges, const unsigned char* image,
+ int dataWidth, int dataHeight,
+ int imageWidth, int imageHeight,
+ int pad) {
+ data += pad*dataWidth;
+ data += pad;
+ edges += (pad*dataWidth + pad);
+
+ for (int j = 0; j < imageHeight; ++j) {
+ for (int i = 0; i < imageWidth; ++i) {
+ if (255 == *image) {
+ data->fAlpha = 1.0f;
+ } else {
+ data->fAlpha = (*image)*0.00392156862f; // 1/255
+ }
+ int checkMask = kAll_NeighborFlags;
+ if (i == 0) {
+ checkMask &= ~(kLeft_NeighborFlag|kTopLeft_NeighborFlag|kBottomLeft_NeighborFlag);
+ }
+ if (i == imageWidth-1) {
+ checkMask &= ~(kRight_NeighborFlag|kTopRight_NeighborFlag|kBottomRight_NeighborFlag);
+ }
+ if (j == 0) {
+ checkMask &= ~(kTopLeft_NeighborFlag|kTop_NeighborFlag|kTopRight_NeighborFlag);
+ }
+ if (j == imageHeight-1) {
+ checkMask &= ~(kBottomLeft_NeighborFlag|kBottom_NeighborFlag|kBottomRight_NeighborFlag);
+ }
+ if (found_edge(image, imageWidth, checkMask)) {
+ *edges = 255; // using 255 makes for convenient debug rendering
+ }
+ ++data;
+ ++image;
+ ++edges;
+ }
+ data += 2*pad;
+ edges += 2*pad;
+ }
+}
+
+// from Gustavson (2011)
+// computes the distance to an edge given an edge normal vector and a pixel's alpha value
+// assumes that direction has been pre-normalized
+static float edge_distance(const SkPoint& direction, float alpha) {
+ float dx = direction.fX;
+ float dy = direction.fY;
+ float distance;
+ if (SkScalarNearlyZero(dx) || SkScalarNearlyZero(dy)) {
+ distance = 0.5f - alpha;
+ } else {
+ // this is easier if we treat the direction as being in the first octant
+ // (other octants are symmetrical)
+ dx = SkScalarAbs(dx);
+ dy = SkScalarAbs(dy);
+ if (dx < dy) {
+ SkTSwap(dx, dy);
+ }
+
+ // a1 = 0.5*dy/dx is the smaller fractional area chopped off by the edge
+ // to avoid the divide, we just consider the numerator
+ float a1num = 0.5f*dy;
+
+ // we now compute the approximate distance, depending where the alpha falls
+ // relative to the edge fractional area
+
+ // if 0 <= alpha < a1
+ if (alpha*dx < a1num) {
+ // TODO: find a way to do this without square roots?
+ distance = 0.5f*(dx + dy) - SkScalarSqrt(2.0f*dx*dy*alpha);
+ // if a1 <= alpha <= 1 - a1
+ } else if (alpha*dx < (dx - a1num)) {
+ distance = (0.5f - alpha)*dx;
+ // if 1 - a1 < alpha <= 1
+ } else {
+ // TODO: find a way to do this without square roots?
+ distance = -0.5f*(dx + dy) + SkScalarSqrt(2.0f*dx*dy*(1.0f - alpha));
+ }
+ }
+
+ return distance;
+}
+
+static void init_distances(DFData* data, unsigned char* edges, int width, int height) {
+ // skip one pixel border
+ DFData* currData = data;
+ DFData* prevData = data - width;
+ DFData* nextData = data + width;
+
+ for (int j = 0; j < height; ++j) {
+ for (int i = 0; i < width; ++i) {
+ if (*edges) {
+ // we should not be in the one-pixel outside band
+ SkASSERT(i > 0 && i < width-1 && j > 0 && j < height-1);
+ // gradient will point from low to high
+ // +y is down in this case
+ // i.e., if you're outside, gradient points towards edge
+ // if you're inside, gradient points away from edge
+ SkPoint currGrad;
+ currGrad.fX = (prevData+1)->fAlpha - (prevData-1)->fAlpha
+ + SK_ScalarSqrt2*(currData+1)->fAlpha
+ - SK_ScalarSqrt2*(currData-1)->fAlpha
+ + (nextData+1)->fAlpha - (nextData-1)->fAlpha;
+ currGrad.fY = (nextData-1)->fAlpha - (prevData-1)->fAlpha
+ + SK_ScalarSqrt2*nextData->fAlpha
+ - SK_ScalarSqrt2*prevData->fAlpha
+ + (nextData+1)->fAlpha - (prevData+1)->fAlpha;
+ currGrad.setLengthFast(1.0f);
+
+ // init squared distance to edge and distance vector
+ float dist = edge_distance(currGrad, currData->fAlpha);
+ currGrad.scale(dist, &currData->fDistVector);
+ currData->fDistSq = dist*dist;
+ } else {
+ // init distance to "far away"
+ currData->fDistSq = 2000000.f;
+ currData->fDistVector.fX = 1000.f;
+ currData->fDistVector.fY = 1000.f;
+ }
+ ++currData;
+ ++prevData;
+ ++nextData;
+ ++edges;
+ }
+ }
+}
+
+// Danielsson's 8SSEDT
+
+// first stage forward pass
+// (forward in Y, forward in X)
+static void F1(DFData* curr, int width) {
+ // upper left
+ DFData* check = curr - width-1;
+ SkPoint distVec = check->fDistVector;
+ float distSq = check->fDistSq - 2.0f*(distVec.fX + distVec.fY - 1.0f);
+ if (distSq < curr->fDistSq) {
+ distVec.fX -= 1.0f;
+ distVec.fY -= 1.0f;
+ curr->fDistSq = distSq;
+ curr->fDistVector = distVec;
+ }
+
+ // up
+ check = curr - width;
+ distVec = check->fDistVector;
+ distSq = check->fDistSq - 2.0f*distVec.fY + 1.0f;
+ if (distSq < curr->fDistSq) {
+ distVec.fY -= 1.0f;
+ curr->fDistSq = distSq;
+ curr->fDistVector = distVec;
+ }
+
+ // upper right
+ check = curr - width+1;
+ distVec = check->fDistVector;
+ distSq = check->fDistSq + 2.0f*(distVec.fX - distVec.fY + 1.0f);
+ if (distSq < curr->fDistSq) {
+ distVec.fX += 1.0f;
+ distVec.fY -= 1.0f;
+ curr->fDistSq = distSq;
+ curr->fDistVector = distVec;
+ }
+
+ // left
+ check = curr - 1;
+ distVec = check->fDistVector;
+ distSq = check->fDistSq - 2.0f*distVec.fX + 1.0f;
+ if (distSq < curr->fDistSq) {
+ distVec.fX -= 1.0f;
+ curr->fDistSq = distSq;
+ curr->fDistVector = distVec;
+ }
+}
+
+// second stage forward pass
+// (forward in Y, backward in X)
+static void F2(DFData* curr, int width) {
+ // right
+ DFData* check = curr + 1;
+ float distSq = check->fDistSq;
+ SkPoint distVec = check->fDistVector;
+ distSq = check->fDistSq + 2.0f*distVec.fX + 1.0f;
+ if (distSq < curr->fDistSq) {
+ distVec.fX += 1.0f;
+ curr->fDistSq = distSq;
+ curr->fDistVector = distVec;
+ }
+}
+
+// first stage backward pass
+// (backward in Y, forward in X)
+static void B1(DFData* curr, int width) {
+ // left
+ DFData* check = curr - 1;
+ SkPoint distVec = check->fDistVector;
+ float distSq = check->fDistSq - 2.0f*distVec.fX + 1.0f;
+ if (distSq < curr->fDistSq) {
+ distVec.fX -= 1.0f;
+ curr->fDistSq = distSq;
+ curr->fDistVector = distVec;
+ }
+}
+
+// second stage backward pass
+// (backward in Y, backwards in X)
+static void B2(DFData* curr, int width) {
+ // right
+ DFData* check = curr + 1;
+ SkPoint distVec = check->fDistVector;
+ float distSq = check->fDistSq + 2.0f*distVec.fX + 1.0f;
+ if (distSq < curr->fDistSq) {
+ distVec.fX += 1.0f;
+ curr->fDistSq = distSq;
+ curr->fDistVector = distVec;
+ }
+
+ // bottom left
+ check = curr + width-1;
+ distVec = check->fDistVector;
+ distSq = check->fDistSq - 2.0f*(distVec.fX - distVec.fY - 1.0f);
+ if (distSq < curr->fDistSq) {
+ distVec.fX -= 1.0f;
+ distVec.fY += 1.0f;
+ curr->fDistSq = distSq;
+ curr->fDistVector = distVec;
+ }
+
+ // bottom
+ check = curr + width;
+ distVec = check->fDistVector;
+ distSq = check->fDistSq + 2.0f*distVec.fY + 1.0f;
+ if (distSq < curr->fDistSq) {
+ distVec.fY += 1.0f;
+ curr->fDistSq = distSq;
+ curr->fDistVector = distVec;
+ }
+
+ // bottom right
+ check = curr + width+1;
+ distVec = check->fDistVector;
+ distSq = check->fDistSq + 2.0f*(distVec.fX + distVec.fY + 1.0f);
+ if (distSq < curr->fDistSq) {
+ distVec.fX += 1.0f;
+ distVec.fY += 1.0f;
+ curr->fDistSq = distSq;
+ curr->fDistVector = distVec;
+ }
+}
+
+// enable this to output edge data rather than the distance field
+#define DUMP_EDGE 0
+
+#if !DUMP_EDGE
+static unsigned char pack_distance_field_val(float dist, float distanceMagnitude) {
+ if (dist <= -distanceMagnitude) {
+ return 255;
+ } else if (dist > distanceMagnitude) {
+ return 0;
+ } else {
+ return (unsigned char)((distanceMagnitude-dist)*128.0f/distanceMagnitude);
+ }
+}
+#endif
+
+// assumes a padded 8-bit image and distance field
+// width and height are the original width and height of the image
+static bool generate_distance_field_from_image(unsigned char* distanceField,
+ const unsigned char* copyPtr,
+ int width, int height) {
+ SkASSERT(NULL != distanceField);
+ SkASSERT(NULL != copyPtr);
+
+ // we expand our temp data by one more on each side to simplify
+ // the scanning code -- will always be treated as infinitely far away
+ int pad = SK_DistanceFieldPad + 1;
+
+ // set params for distance field data
+ int dataWidth = width + 2*pad;
+ int dataHeight = height + 2*pad;
+
+ // create temp data
+ size_t dataSize = dataWidth*dataHeight*sizeof(DFData);
+ SkAutoSMalloc<1024> dfStorage(dataSize);
+ DFData* dataPtr = (DFData*) dfStorage.get();
+ sk_bzero(dataPtr, dataSize);
+
+ SkAutoSMalloc<1024> edgeStorage(dataWidth*dataHeight*sizeof(char));
+ unsigned char* edgePtr = (unsigned char*) edgeStorage.get();
+ sk_bzero(edgePtr, dataWidth*dataHeight*sizeof(char));
+
+ // copy glyph into distance field storage
+ init_glyph_data(dataPtr, edgePtr, copyPtr,
+ dataWidth, dataHeight,
+ width+2, height+2, SK_DistanceFieldPad);
+
+ // create initial distance data, particularly at edges
+ init_distances(dataPtr, edgePtr, dataWidth, dataHeight);
+
+ // now perform Euclidean distance transform to propagate distances
+
+ // forwards in y
+ DFData* currData = dataPtr+dataWidth+1; // skip outer buffer
+ unsigned char* currEdge = edgePtr+dataWidth+1;
+ for (int j = 1; j < dataHeight-1; ++j) {
+ // forwards in x
+ for (int i = 1; i < dataWidth-1; ++i) {
+ // don't need to calculate distance for edge pixels
+ if (!*currEdge) {
+ F1(currData, dataWidth);
+ }
+ ++currData;
+ ++currEdge;
+ }
+
+ // backwards in x
+ --currData; // reset to end
+ --currEdge;
+ for (int i = 1; i < dataWidth-1; ++i) {
+ // don't need to calculate distance for edge pixels
+ if (!*currEdge) {
+ F2(currData, dataWidth);
+ }
+ --currData;
+ --currEdge;
+ }
+
+ currData += dataWidth+1;
+ currEdge += dataWidth+1;
+ }
+
+ // backwards in y
+ currData = dataPtr+dataWidth*(dataHeight-2) - 1; // skip outer buffer
+ currEdge = edgePtr+dataWidth*(dataHeight-2) - 1;
+ for (int j = 1; j < dataHeight-1; ++j) {
+ // forwards in x
+ for (int i = 1; i < dataWidth-1; ++i) {
+ // don't need to calculate distance for edge pixels
+ if (!*currEdge) {
+ B1(currData, dataWidth);
+ }
+ ++currData;
+ ++currEdge;
+ }
+
+ // backwards in x
+ --currData; // reset to end
+ --currEdge;
+ for (int i = 1; i < dataWidth-1; ++i) {
+ // don't need to calculate distance for edge pixels
+ if (!*currEdge) {
+ B2(currData, dataWidth);
+ }
+ --currData;
+ --currEdge;
+ }
+
+ currData -= dataWidth-1;
+ currEdge -= dataWidth-1;
+ }
+
+ // copy results to final distance field data
+ currData = dataPtr + dataWidth+1;
+ currEdge = edgePtr + dataWidth+1;
+ unsigned char *dfPtr = distanceField;
+ for (int j = 1; j < dataHeight-1; ++j) {
+ for (int i = 1; i < dataWidth-1; ++i) {
+#if DUMP_EDGE
+ float alpha = currData->fAlpha;
+ float edge = 0.0f;
+ if (*currEdge) {
+ edge = 0.25f;
+ }
+ // blend with original image
+ float result = alpha + (1.0f-alpha)*edge;
+ unsigned char val = sk_float_round2int(255*result);
+ *dfPtr++ = val;
+#else
+ float dist;
+ if (currData->fAlpha > 0.5f) {
+ dist = -SkScalarSqrt(currData->fDistSq);
+ } else {
+ dist = SkScalarSqrt(currData->fDistSq);
+ }
+ *dfPtr++ = pack_distance_field_val(dist, (float)SK_DistanceFieldMagnitude);
+#endif
+ ++currData;
+ ++currEdge;
+ }
+ currData += 2;
+ currEdge += 2;
+ }
+
+ return true;
+}
+
+// assumes an 8-bit image and distance field
+bool SkGenerateDistanceFieldFromA8Image(unsigned char* distanceField,
+ const unsigned char* image,
+ int width, int height, int rowBytes) {
+ SkASSERT(NULL != distanceField);
+ SkASSERT(NULL != image);
+
+ // create temp data
+ SkAutoSMalloc<1024> copyStorage((width+2)*(height+2)*sizeof(char));
+ unsigned char* copyPtr = (unsigned char*) copyStorage.get();
+
+ // we copy our source image into a padded copy to ensure we catch edge transitions
+ // around the outside
+ const unsigned char* currSrcScanLine = image;
+ sk_bzero(copyPtr, (width+2)*sizeof(char));
+ unsigned char* currDestPtr = copyPtr + width + 2;
+ for (int i = 0; i < height; ++i) {
+ *currDestPtr++ = 0;
+ memcpy(currDestPtr, currSrcScanLine, rowBytes);
+ currSrcScanLine += rowBytes;
+ currDestPtr += width;
+ *currDestPtr++ = 0;
+ }
+ sk_bzero(currDestPtr, (width+2)*sizeof(char));
+
+ return generate_distance_field_from_image(distanceField, copyPtr, width, height);
+}
+
+// assumes a 1-bit image and 8-bit distance field
+bool SkGenerateDistanceFieldFromBWImage(unsigned char* distanceField,
+ const unsigned char* image,
+ int width, int height, int rowBytes) {
+ SkASSERT(NULL != distanceField);
+ SkASSERT(NULL != image);
+
+ // create temp data
+ SkAutoSMalloc<1024> copyStorage((width+2)*(height+2)*sizeof(char));
+ unsigned char* copyPtr = (unsigned char*) copyStorage.get();
+
+ // we copy our source image into a padded copy to ensure we catch edge transitions
+ // around the outside
+ const unsigned char* currSrcScanLine = image;
+ sk_bzero(copyPtr, (width+2)*sizeof(char));
+ unsigned char* currDestPtr = copyPtr + width + 2;
+ for (int i = 0; i < height; ++i) {
+ *currDestPtr++ = 0;
+ int rowWritesLeft = width;
+ const unsigned char *maskPtr = currSrcScanLine;
+ while (rowWritesLeft > 0) {
+ unsigned mask = *maskPtr++;
+ for (int i = 7; i >= 0 && rowWritesLeft; --i, --rowWritesLeft) {
+ *currDestPtr++ = (mask & (1 << i)) ? 0xff : 0;
+ }
+ }
+ currSrcScanLine += rowBytes;
+ *currDestPtr++ = 0;
+ }
+ sk_bzero(currDestPtr, (width+2)*sizeof(char));
+
+ return generate_distance_field_from_image(distanceField, copyPtr, width, height);
+}
diff --git a/chromium/third_party/skia/src/core/SkDistanceFieldGen.h b/chromium/third_party/skia/src/core/SkDistanceFieldGen.h
new file mode 100644
index 00000000000..0510907f8c8
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkDistanceFieldGen.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkDistanceFieldGen_DEFINED
+#define SkDistanceFieldGen_DEFINED
+
+#include "SkTypes.h"
+
+// the max magnitude for the distance field
+// distance values are limited to the range [-SK_DistanceFieldMagnitude, SK_DistanceFieldMagnitude)
+#define SK_DistanceFieldMagnitude 4
+// we need to pad around the original glyph to allow our maximum distance of
+// SK_DistanceFieldMagnitude texels away from any edge
+#define SK_DistanceFieldPad 4
+// the rect we render with is inset from the distance field glyph size to allow for bilerp
+#define SK_DistanceFieldInset 2
+
+// for the fragment shader
+// The distance field is constructed as unsigned char values, so that the zero value is at 128,
+// and the range is [-4, 4 - 1/255). Hence our multiplier is 8 - 1/32 and zero threshold is 128/255.
+#define SK_DistanceFieldMultiplier "7.96875"
+#define SK_DistanceFieldThreshold "0.50196078431"
+
+/** Given 8-bit mask data, generate the associated distance field
+
+ * @param distanceField The distance field to be generated. Should already be allocated
+ * by the client with the padding above.
+ * @param image 8-bit mask we're using to generate the distance field.
+ * @param w Width of the original image.
+ * @param h Height of the original image.
+ * @param rowBytes Size of each row in the image, in bytes
+ */
+bool SkGenerateDistanceFieldFromA8Image(unsigned char* distanceField,
+ const unsigned char* image,
+ int w, int h, int rowBytes);
+
+/** Given 1-bit mask data, generate the associated distance field
+
+ * @param distanceField The distance field to be generated. Should already be allocated
+ * by the client with the padding above.
+ * @param image 1-bit mask we're using to generate the distance field.
+ * @param w Width of the original image.
+ * @param h Height of the original image.
+ * @param rowBytes Size of each row in the image, in bytes
+ */
+bool SkGenerateDistanceFieldFromBWImage(unsigned char* distanceField,
+ const unsigned char* image,
+ int w, int h, int rowBytes);
+
+/** Given width and height of original image, return size (in bytes) of distance field
+ * @param w Width of the original image.
+ * @param h Height of the original image.
+ */
+inline size_t SkComputeDistanceFieldSize(int w, int h) {
+ return (w + 2*SK_DistanceFieldPad) * (h + 2*SK_DistanceFieldPad) * sizeof(unsigned char);
+}
+
+#endif
diff --git a/chromium/third_party/skia/src/core/SkDraw.cpp b/chromium/third_party/skia/src/core/SkDraw.cpp
index ccab56ca62a..b77eb430c7b 100644
--- a/chromium/third_party/skia/src/core/SkDraw.cpp
+++ b/chromium/third_party/skia/src/core/SkDraw.cpp
@@ -7,7 +7,6 @@
#include "SkDraw.h"
#include "SkBlitter.h"
-#include "SkBounder.h"
#include "SkCanvas.h"
#include "SkColorPriv.h"
#include "SkDevice.h"
@@ -21,36 +20,22 @@
#include "SkRRect.h"
#include "SkScan.h"
#include "SkShader.h"
+#include "SkSmallAllocator.h"
#include "SkString.h"
#include "SkStroke.h"
-#include "SkTemplatesPriv.h"
+#include "SkTextMapStateProc.h"
#include "SkTLazy.h"
#include "SkUtils.h"
+#include "SkVertState.h"
#include "SkAutoKern.h"
#include "SkBitmapProcShader.h"
#include "SkDrawProcs.h"
#include "SkMatrixUtils.h"
-bool SkDraw::ShouldDrawTextAsPaths(const SkPaint& paint, const SkMatrix& ctm) {
- // we don't cache hairlines in the cache
- if (SkPaint::kStroke_Style == paint.getStyle() &&
- 0 == paint.getStrokeWidth()) {
- return true;
- }
-
- // we don't cache perspective
- if (ctm.hasPerspective()) {
- return true;
- }
-
- SkMatrix textM;
- return SkPaint::TooBigToUseCache(ctm, *paint.setTextMatrix(&textM));
-}
//#define TRACE_BITMAP_DRAWS
-#define kBlitterStorageLongCount (sizeof(SkBitmapProcShader) >> 2)
/** Helper for allocating small blitters on the stack.
*/
@@ -61,16 +46,8 @@ public:
}
SkAutoBlitterChoose(const SkBitmap& device, const SkMatrix& matrix,
const SkPaint& paint, bool drawCoverage = false) {
- fBlitter = SkBlitter::Choose(device, matrix, paint,
- fStorage, sizeof(fStorage), drawCoverage);
- }
-
- ~SkAutoBlitterChoose() {
- if ((void*)fBlitter == (void*)fStorage) {
- fBlitter->~SkBlitter();
- } else {
- SkDELETE(fBlitter);
- }
+ fBlitter = SkBlitter::Choose(device, matrix, paint, &fAllocator,
+ drawCoverage);
}
SkBlitter* operator->() { return fBlitter; }
@@ -79,13 +56,13 @@ public:
void choose(const SkBitmap& device, const SkMatrix& matrix,
const SkPaint& paint) {
SkASSERT(!fBlitter);
- fBlitter = SkBlitter::Choose(device, matrix, paint,
- fStorage, sizeof(fStorage));
+ fBlitter = SkBlitter::Choose(device, matrix, paint, &fAllocator);
}
private:
- SkBlitter* fBlitter;
- uint32_t fStorage[kBlitterStorageLongCount];
+ // Owned by fAllocator, which will handle the delete.
+ SkBlitter* fBlitter;
+ SkTBlitterAllocator fAllocator;
};
#define SkAutoBlitterChoose(...) SK_REQUIRE_LOCAL_VAR(SkAutoBlitterChoose)
@@ -96,36 +73,32 @@ private:
*/
class SkAutoBitmapShaderInstall : SkNoncopyable {
public:
- SkAutoBitmapShaderInstall(const SkBitmap& src, const SkPaint& paint)
+ SkAutoBitmapShaderInstall(const SkBitmap& src, const SkPaint& paint,
+ const SkMatrix* localMatrix = NULL)
: fPaint(paint) /* makes a copy of the paint */ {
- fPaint.setShader(SkShader::CreateBitmapShader(src,
- SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
- fStorage, sizeof(fStorage)));
+ fPaint.setShader(CreateBitmapShader(src, SkShader::kClamp_TileMode,
+ SkShader::kClamp_TileMode,
+ localMatrix, &fAllocator));
// we deliberately left the shader with an owner-count of 2
SkASSERT(2 == fPaint.getShader()->getRefCnt());
}
~SkAutoBitmapShaderInstall() {
- SkShader* shader = fPaint.getShader();
- // since we manually destroy shader, we insist that owners == 2
- SkASSERT(2 == shader->getRefCnt());
+ // since fAllocator will destroy shader, we insist that owners == 2
+ SkASSERT(2 == fPaint.getShader()->getRefCnt());
fPaint.setShader(NULL); // unref the shader by 1
- // now destroy to take care of the 2nd owner-count
- if ((void*)shader == (void*)fStorage) {
- shader->~SkShader();
- } else {
- SkDELETE(shader);
- }
}
// return the new paint that has the shader applied
const SkPaint& paintWithShader() const { return fPaint; }
private:
- SkPaint fPaint; // copy of caller's paint (which we then modify)
- uint32_t fStorage[kBlitterStorageLongCount];
+ // copy of caller's paint (which we then modify)
+ SkPaint fPaint;
+ // Stores the shader.
+ SkTBlitterAllocator fAllocator;
};
#define SkAutoBitmapShaderInstall(...) SK_REQUIRE_LOCAL_VAR(SkAutoBitmapShaderInstall)
@@ -167,11 +140,11 @@ static void D_Clear_BitmapXferProc(void* pixels, size_t bytes, uint32_t) {
static void D_Dst_BitmapXferProc(void*, size_t, uint32_t data) {}
static void D32_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) {
- sk_memset32((uint32_t*)pixels, data, bytes >> 2);
+ sk_memset32((uint32_t*)pixels, data, SkToInt(bytes >> 2));
}
static void D16_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) {
- sk_memset16((uint16_t*)pixels, data, bytes >> 1);
+ sk_memset16((uint16_t*)pixels, data, SkToInt(bytes >> 1));
}
static void DA8_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) {
@@ -216,20 +189,20 @@ static BitmapXferProc ChooseBitmapXferProc(const SkBitmap& bitmap,
should I worry about dithering for the lower depths?
*/
SkPMColor pmc = SkPreMultiplyColor(color);
- switch (bitmap.config()) {
- case SkBitmap::kARGB_8888_Config:
+ switch (bitmap.colorType()) {
+ case kN32_SkColorType:
if (data) {
*data = pmc;
}
// SkDebugf("--- D32_Src_BitmapXferProc\n");
return D32_Src_BitmapXferProc;
- case SkBitmap::kRGB_565_Config:
+ case kRGB_565_SkColorType:
if (data) {
*data = SkPixel32ToPixel16(pmc);
}
// SkDebugf("--- D16_Src_BitmapXferProc\n");
return D16_Src_BitmapXferProc;
- case SkBitmap::kA8_Config:
+ case kAlpha_8_SkColorType:
if (data) {
*data = SkGetPackedA32(pmc);
}
@@ -249,14 +222,14 @@ static BitmapXferProc ChooseBitmapXferProc(const SkBitmap& bitmap,
static void CallBitmapXferProc(const SkBitmap& bitmap, const SkIRect& rect,
BitmapXferProc proc, uint32_t procData) {
int shiftPerPixel;
- switch (bitmap.config()) {
- case SkBitmap::kARGB_8888_Config:
+ switch (bitmap.colorType()) {
+ case kN32_SkColorType:
shiftPerPixel = 2;
break;
- case SkBitmap::kRGB_565_Config:
+ case kRGB_565_SkColorType:
shiftPerPixel = 1;
break;
- case SkBitmap::kA8_Config:
+ case kAlpha_8_SkColorType:
shiftPerPixel = 0;
break;
default:
@@ -286,9 +259,6 @@ void SkDraw::drawPaint(const SkPaint& paint) const {
SkIRect devRect;
devRect.set(0, 0, fBitmap->width(), fBitmap->height());
- if (fBounder && !fBounder->doIRect(devRect)) {
- return;
- }
if (fRC->isBW()) {
/* If we don't have a shader (i.e. we're just a solid color) we may
@@ -399,8 +369,8 @@ static void bw_pt_rect_32_hair_proc(const PtProcRec& rec,
static void bw_pt_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
int count, SkBlitter* blitter) {
for (int i = 0; i < count; i++) {
- int x = SkScalarFloor(devPts[i].fX);
- int y = SkScalarFloor(devPts[i].fY);
+ int x = SkScalarFloorToInt(devPts[i].fX);
+ int y = SkScalarFloorToInt(devPts[i].fY);
if (rec.fClip->contains(x, y)) {
blitter->blitH(x, y, 1);
}
@@ -542,9 +512,9 @@ PtProcRec::Proc PtProcRec::chooseProc(SkBlitter** blitterPtr) {
if (SkCanvas::kPoints_PointMode == fMode && fClip->isRect()) {
uint32_t value;
const SkBitmap* bm = blitter->justAnOpaqueColor(&value);
- if (bm && SkBitmap::kRGB_565_Config == bm->config()) {
+ if (bm && kRGB_565_SkColorType == bm->colorType()) {
proc = bw_pt_rect_16_hair_proc;
- } else if (bm && SkBitmap::kARGB_8888_Config == bm->config()) {
+ } else if (bm && kN32_SkColorType == bm->colorType()) {
proc = bw_pt_rect_32_hair_proc;
} else {
proc = bw_pt_rect_hair_proc;
@@ -562,21 +532,6 @@ PtProcRec::Proc PtProcRec::chooseProc(SkBlitter** blitterPtr) {
return proc;
}
-static bool bounder_points(SkBounder* bounder, SkCanvas::PointMode mode,
- size_t count, const SkPoint pts[],
- const SkPaint& paint, const SkMatrix& matrix) {
- SkIRect ibounds;
- SkRect bounds;
- SkScalar inset = paint.getStrokeWidth();
-
- bounds.set(pts, count);
- bounds.inset(-inset, -inset);
- matrix.mapRect(&bounds);
-
- bounds.roundOut(&ibounds);
- return bounder->doIRect(ibounds);
-}
-
// each of these costs 8-bytes of stack space, so don't make it too large
// must be even for lines/polygon to work
#define MAX_DEV_PTS 32
@@ -601,19 +556,6 @@ void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count,
return;
}
- if (fBounder) {
- if (!bounder_points(fBounder, mode, count, pts, paint, *fMatrix)) {
- return;
- }
-
- // clear the bounder and call this again, so we don't invoke the bounder
- // later if we happen to call ourselves for drawRect, drawPath, etc.
- SkDraw noBounder(*this);
- noBounder.fBounder = NULL;
- noBounder.drawPoints(mode, count, pts, paint, forceUseDevice);
- return;
- }
-
PtProcRec rec;
if (!forceUseDevice && rec.init(mode, paint, fMatrix, fRC)) {
SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
@@ -626,14 +568,14 @@ void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count,
const size_t backup = (SkCanvas::kPolygon_PointMode == mode);
do {
- size_t n = count;
+ int n = SkToInt(count);
if (n > MAX_DEV_PTS) {
n = MAX_DEV_PTS;
}
matrix->mapPoints(devPts, pts, n);
proc(rec, devPts, n, bltr);
pts += n - backup;
- SkASSERT(count >= n);
+ SkASSERT(SkToInt(count) >= n);
count -= n;
if (count > 0) {
count += backup;
@@ -869,10 +811,6 @@ void SkDraw::drawRect(const SkRect& rect, const SkPaint& paint) const {
matrix.mapPoints(rect_points(devRect), rect_points(rect), 2);
devRect.sort();
- if (fBounder && !fBounder->doRect(devRect, paint)) {
- return;
- }
-
// look for the quick exit, before we build a blitter
SkIRect ir;
devRect.roundOut(&ir);
@@ -943,10 +881,6 @@ void SkDraw::drawDevMask(const SkMask& srcM, const SkPaint& paint) const {
}
SkAutoMaskFreeImage ami(dstM.fImage);
- if (fBounder && !fBounder->doIRect(mask->fBounds)) {
- return;
- }
-
SkAutoBlitterChoose blitterChooser(*fBitmap, *fMatrix, paint);
SkBlitter* blitter = blitterChooser.get();
@@ -1042,8 +976,7 @@ void SkDraw::drawRRect(const SkRRect& rrect, const SkPaint& paint) const {
SkRRect devRRect;
if (rrect.transform(*fMatrix, &devRRect)) {
SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
- if (paint.getMaskFilter()->filterRRect(devRRect, *fMatrix, *fRC,
- fBounder, blitter.get(),
+ if (paint.getMaskFilter()->filterRRect(devRRect, *fMatrix, *fRC, blitter.get(),
SkPaint::kFill_Style)) {
return; // filterRRect() called the blitter, so we're done
}
@@ -1085,10 +1018,7 @@ void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint,
pathPtr->transform(*prePathMatrix, result);
pathPtr = result;
} else {
- if (!tmpMatrix.setConcat(*matrix, *prePathMatrix)) {
- // overflow
- return;
- }
+ tmpMatrix.setConcat(*matrix, *prePathMatrix);
matrix = &tmpMatrix;
}
}
@@ -1153,17 +1083,11 @@ void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint,
if (paint->getMaskFilter()) {
SkPaint::Style style = doFill ? SkPaint::kFill_Style :
SkPaint::kStroke_Style;
- if (paint->getMaskFilter()->filterPath(*devPathPtr, *fMatrix, *fRC,
- fBounder, blitter.get(),
- style)) {
+ if (paint->getMaskFilter()->filterPath(*devPathPtr, *fMatrix, *fRC, blitter.get(), style)) {
return; // filterPath() called the blitter, so we're done
}
}
- if (fBounder && !fBounder->doPath(*devPathPtr, *paint, doFill)) {
- return;
- }
-
void (*proc)(const SkPath&, const SkRasterClip&, SkBlitter*);
if (doFill) {
if (paint->isAntiAlias()) {
@@ -1192,11 +1116,11 @@ static bool just_translate(const SkMatrix& matrix, const SkBitmap& bitmap) {
void SkDraw::drawBitmapAsMask(const SkBitmap& bitmap,
const SkPaint& paint) const {
- SkASSERT(bitmap.config() == SkBitmap::kA8_Config);
+ SkASSERT(bitmap.colorType() == kAlpha_8_SkColorType);
if (just_translate(*fMatrix, bitmap)) {
- int ix = SkScalarRound(fMatrix->getTranslateX());
- int iy = SkScalarRound(fMatrix->getTranslateY());
+ int ix = SkScalarRoundToInt(fMatrix->getTranslateX());
+ int iy = SkScalarRoundToInt(fMatrix->getTranslateY());
SkAutoLockPixels alp(bitmap);
if (!bitmap.readyToDraw()) {
@@ -1246,9 +1170,8 @@ void SkDraw::drawBitmapAsMask(const SkBitmap& bitmap,
// now draw our bitmap(src) into mask(dst), transformed by the matrix
{
SkBitmap device;
- device.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(),
- mask.fBounds.height(), mask.fRowBytes);
- device.setPixels(mask.fImage);
+ device.installPixels(SkImageInfo::MakeA8(mask.fBounds.width(), mask.fBounds.height()),
+ mask.fImage, mask.fRowBytes);
SkCanvas c(device);
// need the unclipped top/left for the translate
@@ -1300,7 +1223,7 @@ void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
// nothing to draw
if (fRC->isEmpty() ||
bitmap.width() == 0 || bitmap.height() == 0 ||
- bitmap.config() == SkBitmap::kNo_Config) {
+ bitmap.colorType() == kUnknown_SkColorType) {
return;
}
@@ -1308,26 +1231,13 @@ void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
paint.setStyle(SkPaint::kFill_Style);
SkMatrix matrix;
- if (!matrix.setConcat(*fMatrix, prematrix)) {
- return;
- }
+ matrix.setConcat(*fMatrix, prematrix);
if (clipped_out(matrix, *fRC, bitmap.width(), bitmap.height())) {
return;
}
- if (fBounder && just_translate(matrix, bitmap)) {
- SkIRect ir;
- int32_t ix = SkScalarRound(matrix.getTranslateX());
- int32_t iy = SkScalarRound(matrix.getTranslateY());
- ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
- if (!fBounder->doIRect(ir)) {
- return;
- }
- }
-
- if (bitmap.config() != SkBitmap::kA8_Config &&
- just_translate(matrix, bitmap)) {
+ if (bitmap.colorType() != kAlpha_8_SkColorType && just_translate(matrix, bitmap)) {
//
// It is safe to call lock pixels now, since we know the matrix is
// (more or less) identity.
@@ -1336,15 +1246,14 @@ void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
if (!bitmap.readyToDraw()) {
return;
}
- int ix = SkScalarRound(matrix.getTranslateX());
- int iy = SkScalarRound(matrix.getTranslateY());
+ int ix = SkScalarRoundToInt(matrix.getTranslateX());
+ int iy = SkScalarRoundToInt(matrix.getTranslateY());
if (clipHandlesSprite(*fRC, ix, iy, bitmap)) {
- uint32_t storage[kBlitterStorageLongCount];
- SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
- ix, iy, storage, sizeof(storage));
+ SkTBlitterAllocator allocator;
+ // blitter will be owned by the allocator.
+ SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
+ ix, iy, &allocator);
if (blitter) {
- SkAutoTPlacementDelete<SkBlitter> ad(blitter, storage);
-
SkIRect ir;
ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
@@ -1359,7 +1268,7 @@ void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
SkDraw draw(*this);
draw.fMatrix = &matrix;
- if (bitmap.config() == SkBitmap::kA8_Config) {
+ if (bitmap.colorType() == kAlpha_8_SkColorType) {
draw.drawBitmapAsMask(bitmap, paint);
} else {
SkAutoBitmapShaderInstall install(bitmap, paint);
@@ -1379,7 +1288,7 @@ void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y,
// nothing to draw
if (fRC->isEmpty() ||
bitmap.width() == 0 || bitmap.height() == 0 ||
- bitmap.config() == SkBitmap::kNo_Config) {
+ bitmap.colorType() == kUnknown_SkColorType) {
return;
}
@@ -1394,34 +1303,27 @@ void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y,
paint.setStyle(SkPaint::kFill_Style);
if (NULL == paint.getColorFilter() && clipHandlesSprite(*fRC, x, y, bitmap)) {
- uint32_t storage[kBlitterStorageLongCount];
- SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
- x, y, storage, sizeof(storage));
+ SkTBlitterAllocator allocator;
+ // blitter will be owned by the allocator.
+ SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
+ x, y, &allocator);
if (blitter) {
- SkAutoTPlacementDelete<SkBlitter> ad(blitter, storage);
-
- if (fBounder && !fBounder->doIRect(bounds)) {
- return;
- }
-
SkScan::FillIRect(bounds, *fRC, blitter);
return;
}
}
- SkAutoBitmapShaderInstall install(bitmap, paint);
- const SkPaint& shaderPaint = install.paintWithShader();
-
SkMatrix matrix;
SkRect r;
// get a scalar version of our rect
r.set(bounds);
- // tell the shader our offset
+ // create shader with offset
matrix.setTranslate(r.fLeft, r.fTop);
- shaderPaint.getShader()->setLocalMatrix(matrix);
+ SkAutoBitmapShaderInstall install(bitmap, paint, &matrix);
+ const SkPaint& shaderPaint = install.paintWithShader();
SkDraw draw(*this);
matrix.reset();
@@ -1458,6 +1360,21 @@ static void measure_text(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
SkASSERT(text == stop);
}
+bool SkDraw::ShouldDrawTextAsPaths(const SkPaint& paint, const SkMatrix& ctm) {
+ // hairline glyphs are fast enough so we don't need to cache them
+ if (SkPaint::kStroke_Style == paint.getStyle() && 0 == paint.getStrokeWidth()) {
+ return true;
+ }
+
+ // we don't cache perspective
+ if (ctm.hasPerspective()) {
+ return true;
+ }
+
+ SkMatrix textM;
+ return SkPaint::TooBigToUseCache(ctm, *paint.setTextMatrix(&textM));
+}
+
void SkDraw::drawText_asPaths(const char text[], size_t byteLength,
SkScalar x, SkScalar y,
const SkPaint& paint) const {
@@ -1494,13 +1411,10 @@ void SkDraw::drawText_asPaths(const char text[], size_t byteLength,
//////////////////////////////////////////////////////////////////////////////
-static void D1G_NoBounder_RectClip(const SkDraw1Glyph& state,
- SkFixed fx, SkFixed fy,
- const SkGlyph& glyph) {
- int left = SkFixedFloor(fx);
- int top = SkFixedFloor(fy);
+static void D1G_RectClip(const SkDraw1Glyph& state, SkFixed fx, SkFixed fy, const SkGlyph& glyph) {
+ int left = SkFixedFloorToInt(fx);
+ int top = SkFixedFloorToInt(fy);
SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
- SkASSERT(NULL == state.fBounder);
SkASSERT((NULL == state.fClip && state.fAAClip) ||
(state.fClip && NULL == state.fAAClip && state.fClip->isRect()));
@@ -1538,14 +1452,11 @@ static void D1G_NoBounder_RectClip(const SkDraw1Glyph& state,
state.blitMask(mask, *bounds);
}
-static void D1G_NoBounder_RgnClip(const SkDraw1Glyph& state,
- SkFixed fx, SkFixed fy,
- const SkGlyph& glyph) {
- int left = SkFixedFloor(fx);
- int top = SkFixedFloor(fy);
+static void D1G_RgnClip(const SkDraw1Glyph& state, SkFixed fx, SkFixed fy, const SkGlyph& glyph) {
+ int left = SkFixedFloorToInt(fx);
+ int top = SkFixedFloorToInt(fy);
SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
SkASSERT(!state.fClip->isRect());
- SkASSERT(NULL == state.fBounder);
SkMask mask;
@@ -1575,60 +1486,6 @@ static void D1G_NoBounder_RgnClip(const SkDraw1Glyph& state,
}
}
-static void D1G_Bounder(const SkDraw1Glyph& state,
- SkFixed fx, SkFixed fy,
- const SkGlyph& glyph) {
- int left = SkFixedFloor(fx);
- int top = SkFixedFloor(fy);
- SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
-
- SkMask mask;
-
- left += glyph.fLeft;
- top += glyph.fTop;
-
- mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
- SkRegion::Cliperator clipper(*state.fClip, mask.fBounds);
-
- if (!clipper.done()) {
- const SkIRect& cr = clipper.rect();
- const uint8_t* aa = (const uint8_t*)glyph.fImage;
- if (NULL == aa) {
- aa = (uint8_t*)state.fCache->findImage(glyph);
- if (NULL == aa) {
- return;
- }
- }
-
- // we need to pass the origin, which we approximate with our
- // (unadjusted) left,top coordinates (the caller called fixedfloor)
- if (state.fBounder->doIRectGlyph(cr,
- left - glyph.fLeft,
- top - glyph.fTop, glyph)) {
- mask.fRowBytes = glyph.rowBytes();
- mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
- mask.fImage = (uint8_t*)aa;
- do {
- state.blitMask(mask, cr);
- clipper.next();
- } while (!clipper.done());
- }
- }
-}
-
-static void D1G_Bounder_AAClip(const SkDraw1Glyph& state,
- SkFixed fx, SkFixed fy,
- const SkGlyph& glyph) {
- int left = SkFixedFloor(fx);
- int top = SkFixedFloor(fy);
- SkIRect bounds;
- bounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
-
- if (state.fBounder->doIRectGlyph(bounds, left, top, glyph)) {
- D1G_NoBounder_RectClip(state, fx, fy, glyph);
- }
-}
-
static bool hasCustomD1GProc(const SkDraw& draw) {
return draw.fProcs && draw.fProcs->fD1GProc;
}
@@ -1637,10 +1494,9 @@ static bool needsRasterTextBlit(const SkDraw& draw) {
return !hasCustomD1GProc(draw);
}
-SkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter,
- SkGlyphCache* cache, const SkPaint& pnt) {
+SkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter, SkGlyphCache* cache,
+ const SkPaint& pnt) {
fDraw = draw;
- fBounder = draw->fBounder;
fBlitter = blitter;
fCache = cache;
fPaint = &pnt;
@@ -1662,24 +1518,16 @@ SkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter,
fAAClip = NULL;
fClip = &draw->fRC->bwRgn();
fClipBounds = fClip->getBounds();
- if (NULL == fBounder) {
- if (fClip->isRect()) {
- return D1G_NoBounder_RectClip;
- } else {
- return D1G_NoBounder_RgnClip;
- }
+ if (fClip->isRect()) {
+ return D1G_RectClip;
} else {
- return D1G_Bounder;
+ return D1G_RgnClip;
}
} else { // aaclip
fAAClip = &draw->fRC->aaRgn();
fClip = NULL;
fClipBounds = fAAClip->getBounds();
- if (NULL == fBounder) {
- return D1G_NoBounder_RectClip;
- } else {
- return D1G_Bounder_AAClip;
- }
+ return D1G_RectClip;
}
}
@@ -1687,9 +1535,8 @@ void SkDraw1Glyph::blitMaskAsSprite(const SkMask& mask) const {
SkASSERT(SkMask::kARGB32_Format == mask.fFormat);
SkBitmap bm;
- bm.setConfig(SkBitmap::kARGB_8888_Config,
- mask.fBounds.width(), mask.fBounds.height(), mask.fRowBytes);
- bm.setPixels((SkPMColor*)mask.fImage);
+ bm.installPixels(SkImageInfo::MakeN32Premul(mask.fBounds.width(), mask.fBounds.height()),
+ (SkPMColor*)mask.fImage, mask.fRowBytes);
fDraw->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), *fPaint);
}
@@ -1716,30 +1563,10 @@ void SkDraw::drawText(const char text[], size_t byteLength,
SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc();
-#if SK_DISTANCEFIELD_FONTS
- const SkMatrix* ctm = fMatrix;
- const SkPaint* paintRef = &paint;
- SkPaint paintCopy;
- uint32_t procFlags = fProcs ? fProcs->fFlags : 0;
- if (procFlags & SkDrawProcs::kUseScaledGlyphs_Flag) {
- paintCopy = paint;
- paintCopy.setTextSize(SkDrawProcs::kBaseDFFontSize);
- paintCopy.setLCDRenderText(false);
- paintRef = &paintCopy;
- }
- if (procFlags & SkDrawProcs::kSkipBakedGlyphTransform_Flag) {
- ctm = NULL;
- }
- SkAutoGlyphCache autoCache(*paintRef, &fDevice->fLeakyProperties, ctm);
-#else
SkAutoGlyphCache autoCache(paint, &fDevice->fLeakyProperties, fMatrix);
-#endif
SkGlyphCache* cache = autoCache.getCache();
// transform our starting point
-#if SK_DISTANCEFIELD_FONTS
- if (!(procFlags & SkDrawProcs::kSkipBakedGlyphTransform_Flag))
-#endif
{
SkPoint loc;
fMatrix->mapXY(x, y, &loc);
@@ -1798,154 +1625,17 @@ void SkDraw::drawText(const char text[], size_t byteLength,
SkFixed fx = SkScalarToFixed(x) + d1g.fHalfSampleX;
SkFixed fy = SkScalarToFixed(y) + d1g.fHalfSampleY;
-#if SK_DISTANCEFIELD_FONTS
- SkFixed fixedScale;
- if (procFlags & SkDrawProcs::kUseScaledGlyphs_Flag) {
- fixedScale = SkScalarToFixed(paint.getTextSize()/(float)SkDrawProcs::kBaseDFFontSize);
- }
-#endif
while (text < stop) {
const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
-#if SK_DISTANCEFIELD_FONTS
- if (procFlags & SkDrawProcs::kUseScaledGlyphs_Flag) {
- fx += SkFixedMul_portable(autokern.adjust(glyph), fixedScale);
- } else {
- fx += autokern.adjust(glyph);
- }
-#else
fx += autokern.adjust(glyph);
-#endif
if (glyph.fWidth) {
proc(d1g, fx, fy, glyph);
}
-#if SK_DISTANCEFIELD_FONTS
- if (procFlags & SkDrawProcs::kUseScaledGlyphs_Flag) {
- fx += SkFixedMul_portable(glyph.fAdvanceX, fixedScale);
- fy += SkFixedMul_portable(glyph.fAdvanceY, fixedScale);
- } else {
- fx += glyph.fAdvanceX;
- fy += glyph.fAdvanceY;
- }
-#else
fx += glyph.fAdvanceX;
fy += glyph.fAdvanceY;
-#endif
- }
-}
-
-// last parameter is interpreted as SkFixed [x, y]
-// return the fixed position, which may be rounded or not by the caller
-// e.g. subpixel doesn't round
-typedef void (*AlignProc)(const SkPoint&, const SkGlyph&, SkIPoint*);
-
-static void leftAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
- dst->set(SkScalarToFixed(loc.fX), SkScalarToFixed(loc.fY));
-}
-
-static void centerAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
- dst->set(SkScalarToFixed(loc.fX) - (glyph.fAdvanceX >> 1),
- SkScalarToFixed(loc.fY) - (glyph.fAdvanceY >> 1));
-}
-
-static void rightAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
- dst->set(SkScalarToFixed(loc.fX) - glyph.fAdvanceX,
- SkScalarToFixed(loc.fY) - glyph.fAdvanceY);
-}
-
-static AlignProc pick_align_proc(SkPaint::Align align) {
- static const AlignProc gProcs[] = {
- leftAlignProc, centerAlignProc, rightAlignProc
- };
-
- SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs));
-
- return gProcs[align];
-}
-
-typedef void (*AlignProc_scalar)(const SkPoint&, const SkGlyph&, SkPoint*);
-
-static void leftAlignProc_scalar(const SkPoint& loc, const SkGlyph& glyph, SkPoint* dst) {
- dst->set(loc.fX, loc.fY);
-}
-
-static void centerAlignProc_scalar(const SkPoint& loc, const SkGlyph& glyph, SkPoint* dst) {
- dst->set(loc.fX - SkFixedToScalar(glyph.fAdvanceX >> 1),
- loc.fY - SkFixedToScalar(glyph.fAdvanceY >> 1));
-}
-
-static void rightAlignProc_scalar(const SkPoint& loc, const SkGlyph& glyph, SkPoint* dst) {
- dst->set(loc.fX - SkFixedToScalar(glyph.fAdvanceX),
- loc.fY - SkFixedToScalar(glyph.fAdvanceY));
-}
-
-static AlignProc_scalar pick_align_proc_scalar(SkPaint::Align align) {
- static const AlignProc_scalar gProcs[] = {
- leftAlignProc_scalar, centerAlignProc_scalar, rightAlignProc_scalar
- };
-
- SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs));
-
- return gProcs[align];
-}
-
-class TextMapState {
-public:
- mutable SkPoint fLoc;
-
- TextMapState(const SkMatrix& matrix, SkScalar y)
- : fMatrix(matrix), fProc(matrix.getMapXYProc()), fY(y) {}
-
- typedef void (*Proc)(const TextMapState&, const SkScalar pos[]);
-
- Proc pickProc(int scalarsPerPosition);
-
-private:
- const SkMatrix& fMatrix;
- SkMatrix::MapXYProc fProc;
- SkScalar fY; // ignored by MapXYProc
- // these are only used by Only... procs
- SkScalar fScaleX, fTransX, fTransformedY;
-
- static void MapXProc(const TextMapState& state, const SkScalar pos[]) {
- state.fProc(state.fMatrix, *pos, state.fY, &state.fLoc);
- }
-
- static void MapXYProc(const TextMapState& state, const SkScalar pos[]) {
- state.fProc(state.fMatrix, pos[0], pos[1], &state.fLoc);
- }
-
- static void MapOnlyScaleXProc(const TextMapState& state,
- const SkScalar pos[]) {
- state.fLoc.set(SkScalarMul(state.fScaleX, *pos) + state.fTransX,
- state.fTransformedY);
- }
-
- static void MapOnlyTransXProc(const TextMapState& state,
- const SkScalar pos[]) {
- state.fLoc.set(*pos + state.fTransX, state.fTransformedY);
- }
-};
-
-TextMapState::Proc TextMapState::pickProc(int scalarsPerPosition) {
- SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
-
- if (1 == scalarsPerPosition) {
- unsigned mtype = fMatrix.getType();
- if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) {
- return MapXProc;
- } else {
- fScaleX = fMatrix.getScaleX();
- fTransX = fMatrix.getTranslateX();
- fTransformedY = SkScalarMul(fY, fMatrix.getScaleY()) +
- fMatrix.getTranslateY();
- return (mtype & SkMatrix::kScale_Mask) ?
- MapOnlyScaleXProc : MapOnlyTransXProc;
- }
- } else {
- return MapXYProc;
}
}
@@ -1962,23 +1652,31 @@ void SkDraw::drawPosText_asPaths(const char text[], size_t byteLength,
SkMatrix matrix;
matrix.setScale(matrixScale, matrixScale);
+ // Temporarily jam in kFill, so we only ever ask for the raw outline from the cache.
+ paint.setStyle(SkPaint::kFill_Style);
+ paint.setPathEffect(NULL);
+
SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc();
SkAutoGlyphCache autoCache(paint, NULL, NULL);
SkGlyphCache* cache = autoCache.getCache();
const char* stop = text + byteLength;
- AlignProc_scalar alignProc = pick_align_proc_scalar(paint.getTextAlign());
- TextMapState tms(SkMatrix::I(), constY);
- TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition);
+ SkTextAlignProcScalar alignProc(paint.getTextAlign());
+ SkTextMapStateProc tmsProc(SkMatrix::I(), constY, scalarsPerPosition);
+
+ // Now restore the original settings, so we "draw" with whatever style/stroking.
+ paint.setStyle(origPaint.getStyle());
+ paint.setPathEffect(origPaint.getPathEffect());
while (text < stop) {
const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
if (glyph.fWidth) {
const SkPath* path = cache->findPath(glyph);
if (path) {
- tmsProc(tms, pos);
+ SkPoint tmsLoc;
+ tmsProc(pos, &tmsLoc);
SkPoint loc;
- alignProc(tms.fLoc, glyph, &loc);
+ alignProc(tmsLoc, glyph, &loc);
matrix[SkMatrix::kMTransX] = loc.fX;
matrix[SkMatrix::kMTransY] = loc.fY;
@@ -2013,23 +1711,7 @@ void SkDraw::drawPosText(const char text[], size_t byteLength,
}
SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc();
-#if SK_DISTANCEFIELD_FONTS
- const SkMatrix* ctm = fMatrix;
- const SkPaint* paintRef = &paint;
- SkPaint paintCopy;
- uint32_t procFlags = fProcs ? fProcs->fFlags : 0;
- if (procFlags & SkDrawProcs::kUseScaledGlyphs_Flag) {
- paintCopy = paint;
- paintCopy.setTextSize(SkDrawProcs::kBaseDFFontSize);
- paintRef = &paintCopy;
- }
- if (procFlags & SkDrawProcs::kSkipBakedGlyphTransform_Flag) {
- ctm = &SkMatrix::I();
- }
- SkAutoGlyphCache autoCache(*paintRef, &fDevice->fLeakyProperties, ctm);
-#else
SkAutoGlyphCache autoCache(paint, &fDevice->fLeakyProperties, fMatrix);
-#endif
SkGlyphCache* cache = autoCache.getCache();
SkAAClipBlitterWrapper wrapper;
@@ -2045,15 +1727,10 @@ void SkDraw::drawPosText(const char text[], size_t byteLength,
}
const char* stop = text + byteLength;
- AlignProc alignProc = pick_align_proc(paint.getTextAlign());
+ SkTextAlignProc alignProc(paint.getTextAlign());
SkDraw1Glyph d1g;
SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint);
-#if SK_DISTANCEFIELD_FONTS
- TextMapState tms(*ctm, constY);
-#else
- TextMapState tms(*fMatrix, constY);
-#endif
- TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition);
+ SkTextMapStateProc tmsProc(*fMatrix, constY, scalarsPerPosition);
if (cache->isSubpixel()) {
// maybe we should skip the rounding if linearText is set
@@ -2075,18 +1752,10 @@ void SkDraw::drawPosText(const char text[], size_t byteLength,
if (SkPaint::kLeft_Align == paint.getTextAlign()) {
while (text < stop) {
-#if SK_DISTANCEFIELD_FONTS
- if (procFlags & SkDrawProcs::kSkipBakedGlyphTransform_Flag) {
- tms.fLoc.fX = *pos;
- tms.fLoc.fY = *(pos+1);
- } else {
- tmsProc(tms, pos);
- }
-#else
- tmsProc(tms, pos);
-#endif
- SkFixed fx = SkScalarToFixed(tms.fLoc.fX) + d1g.fHalfSampleX;
- SkFixed fy = SkScalarToFixed(tms.fLoc.fY) + d1g.fHalfSampleY;
+ SkPoint tmsLoc;
+ tmsProc(pos, &tmsLoc);
+ SkFixed fx = SkScalarToFixed(tmsLoc.fX) + d1g.fHalfSampleX;
+ SkFixed fy = SkScalarToFixed(tmsLoc.fY) + d1g.fHalfSampleY;
const SkGlyph& glyph = glyphCacheProc(cache, &text,
fx & fxMask, fy & fyMask);
@@ -2104,10 +1773,10 @@ void SkDraw::drawPosText(const char text[], size_t byteLength,
if (metricGlyph.fWidth) {
SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;)
SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;)
-
- tmsProc(tms, pos);
+ SkPoint tmsLoc;
+ tmsProc(pos, &tmsLoc);
SkIPoint fixedLoc;
- alignProc(tms.fLoc, metricGlyph, &fixedLoc);
+ alignProc(tmsLoc, metricGlyph, &fixedLoc);
SkFixed fx = fixedLoc.fX + d1g.fHalfSampleX;
SkFixed fy = fixedLoc.fY + d1g.fHalfSampleY;
@@ -2132,11 +1801,12 @@ void SkDraw::drawPosText(const char text[], size_t byteLength,
const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
if (glyph.fWidth) {
- tmsProc(tms, pos);
+ SkPoint tmsLoc;
+ tmsProc(pos, &tmsLoc);
proc(d1g,
- SkScalarToFixed(tms.fLoc.fX) + SK_FixedHalf, //d1g.fHalfSampleX,
- SkScalarToFixed(tms.fLoc.fY) + SK_FixedHalf, //d1g.fHalfSampleY,
+ SkScalarToFixed(tmsLoc.fX) + SK_FixedHalf, //d1g.fHalfSampleX,
+ SkScalarToFixed(tmsLoc.fY) + SK_FixedHalf, //d1g.fHalfSampleY,
glyph);
}
pos += scalarsPerPosition;
@@ -2147,10 +1817,11 @@ void SkDraw::drawPosText(const char text[], size_t byteLength,
const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
if (glyph.fWidth) {
- tmsProc(tms, pos);
+ SkPoint tmsLoc;
+ tmsProc(pos, &tmsLoc);
SkIPoint fixedLoc;
- alignProc(tms.fLoc, glyph, &fixedLoc);
+ alignProc(tmsLoc, glyph, &fixedLoc);
proc(d1g,
fixedLoc.fX + SK_FixedHalf, //d1g.fHalfSampleX,
@@ -2297,133 +1968,6 @@ void SkDraw::drawTextOnPath(const char text[], size_t byteLength,
///////////////////////////////////////////////////////////////////////////////
-struct VertState {
- int f0, f1, f2;
-
- VertState(int vCount, const uint16_t indices[], int indexCount)
- : fIndices(indices) {
- fCurrIndex = 0;
- if (indices) {
- fCount = indexCount;
- } else {
- fCount = vCount;
- }
- }
-
- typedef bool (*Proc)(VertState*);
- Proc chooseProc(SkCanvas::VertexMode mode);
-
-private:
- int fCount;
- int fCurrIndex;
- const uint16_t* fIndices;
-
- static bool Triangles(VertState*);
- static bool TrianglesX(VertState*);
- static bool TriangleStrip(VertState*);
- static bool TriangleStripX(VertState*);
- static bool TriangleFan(VertState*);
- static bool TriangleFanX(VertState*);
-};
-
-bool VertState::Triangles(VertState* state) {
- int index = state->fCurrIndex;
- if (index + 3 > state->fCount) {
- return false;
- }
- state->f0 = index + 0;
- state->f1 = index + 1;
- state->f2 = index + 2;
- state->fCurrIndex = index + 3;
- return true;
-}
-
-bool VertState::TrianglesX(VertState* state) {
- const uint16_t* indices = state->fIndices;
- int index = state->fCurrIndex;
- if (index + 3 > state->fCount) {
- return false;
- }
- state->f0 = indices[index + 0];
- state->f1 = indices[index + 1];
- state->f2 = indices[index + 2];
- state->fCurrIndex = index + 3;
- return true;
-}
-
-bool VertState::TriangleStrip(VertState* state) {
- int index = state->fCurrIndex;
- if (index + 3 > state->fCount) {
- return false;
- }
- state->f2 = index + 2;
- if (index & 1) {
- state->f0 = index + 1;
- state->f1 = index + 0;
- } else {
- state->f0 = index + 0;
- state->f1 = index + 1;
- }
- state->fCurrIndex = index + 1;
- return true;
-}
-
-bool VertState::TriangleStripX(VertState* state) {
- const uint16_t* indices = state->fIndices;
- int index = state->fCurrIndex;
- if (index + 3 > state->fCount) {
- return false;
- }
- state->f2 = indices[index + 2];
- if (index & 1) {
- state->f0 = indices[index + 1];
- state->f1 = indices[index + 0];
- } else {
- state->f0 = indices[index + 0];
- state->f1 = indices[index + 1];
- }
- state->fCurrIndex = index + 1;
- return true;
-}
-
-bool VertState::TriangleFan(VertState* state) {
- int index = state->fCurrIndex;
- if (index + 3 > state->fCount) {
- return false;
- }
- state->f0 = 0;
- state->f1 = index + 1;
- state->f2 = index + 2;
- state->fCurrIndex = index + 1;
- return true;
-}
-
-bool VertState::TriangleFanX(VertState* state) {
- const uint16_t* indices = state->fIndices;
- int index = state->fCurrIndex;
- if (index + 3 > state->fCount) {
- return false;
- }
- state->f0 = indices[0];
- state->f1 = indices[index + 1];
- state->f2 = indices[index + 2];
- state->fCurrIndex = index + 1;
- return true;
-}
-
-VertState::Proc VertState::chooseProc(SkCanvas::VertexMode mode) {
- switch (mode) {
- case SkCanvas::kTriangles_VertexMode:
- return fIndices ? TrianglesX : Triangles;
- case SkCanvas::kTriangleStrip_VertexMode:
- return fIndices ? TriangleStripX : TriangleStrip;
- case SkCanvas::kTriangleFan_VertexMode:
- return fIndices ? TriangleFanX : TriangleFan;
- default:
- return NULL;
- }
-}
-
typedef void (*HairProc)(const SkPoint&, const SkPoint&, const SkRasterClip&,
SkBlitter*);
@@ -2448,25 +1992,40 @@ class SkTriColorShader : public SkShader {
public:
SkTriColorShader() {}
- bool setup(const SkPoint pts[], const SkColor colors[], int, int, int);
+ virtual size_t contextSize() const SK_OVERRIDE;
+
+ class TriColorShaderContext : public SkShader::Context {
+ public:
+ TriColorShaderContext(const SkTriColorShader& shader, const ContextRec&);
+ virtual ~TriColorShaderContext();
+
+ bool setup(const SkPoint pts[], const SkColor colors[], int, int, int);
+
+ virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE;
- virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE;
+ private:
+ SkMatrix fDstToUnit;
+ SkPMColor fColors[3];
- SK_DEVELOPER_TO_STRING()
+ typedef SkShader::Context INHERITED;
+ };
+
+ SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTriColorShader)
protected:
- SkTriColorShader(SkFlattenableReadBuffer& buffer) : SkShader(buffer) {}
+ SkTriColorShader(SkReadBuffer& buffer) : SkShader(buffer) {}
-private:
- SkMatrix fDstToUnit;
- SkPMColor fColors[3];
+ virtual Context* onCreateContext(const ContextRec& rec, void* storage) const SK_OVERRIDE {
+ return SkNEW_PLACEMENT_ARGS(storage, TriColorShaderContext, (*this, rec));
+ }
+private:
typedef SkShader INHERITED;
};
-bool SkTriColorShader::setup(const SkPoint pts[], const SkColor colors[],
- int index0, int index1, int index2) {
+bool SkTriColorShader::TriColorShaderContext::setup(const SkPoint pts[], const SkColor colors[],
+ int index0, int index1, int index2) {
fColors[0] = SkPreMultiplyColor(colors[index0]);
fColors[1] = SkPreMultiplyColor(colors[index1]);
@@ -2483,7 +2042,14 @@ bool SkTriColorShader::setup(const SkPoint pts[], const SkColor colors[],
if (!m.invert(&im)) {
return false;
}
- return fDstToUnit.setConcat(im, this->getTotalInverse());
+ // We can't call getTotalInverse(), because we explicitly don't want to look at the localmatrix
+ // as our interators are intrinsically tied to the vertices, and nothing else.
+ SkMatrix ctmInv;
+ if (!this->getCTM().invert(&ctmInv)) {
+ return false;
+ }
+ fDstToUnit.setConcat(im, ctmInv);
+ return true;
}
#include "SkColorPriv.h"
@@ -2500,7 +2066,19 @@ static int ScalarTo256(SkScalar v) {
return SkAlpha255To256(scale);
}
-void SkTriColorShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
+
+SkTriColorShader::TriColorShaderContext::TriColorShaderContext(const SkTriColorShader& shader,
+ const ContextRec& rec)
+ : INHERITED(shader, rec) {}
+
+SkTriColorShader::TriColorShaderContext::~TriColorShaderContext() {}
+
+size_t SkTriColorShader::contextSize() const {
+ return sizeof(TriColorShaderContext);
+}
+void SkTriColorShader::TriColorShaderContext::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
+ const int alphaScale = Sk255To256(this->getPaintAlpha());
+
SkPoint src;
for (int i = 0; i < count; i++) {
@@ -2519,13 +2097,19 @@ void SkTriColorShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
scale0 = 0;
}
+ if (256 != alphaScale) {
+ scale0 = SkAlphaMul(scale0, alphaScale);
+ scale1 = SkAlphaMul(scale1, alphaScale);
+ scale2 = SkAlphaMul(scale2, alphaScale);
+ }
+
dstC[i] = SkAlphaMulQ(fColors[0], scale0) +
- SkAlphaMulQ(fColors[1], scale1) +
- SkAlphaMulQ(fColors[2], scale2);
+ SkAlphaMulQ(fColors[1], scale1) +
+ SkAlphaMulQ(fColors[2], scale2);
}
}
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkTriColorShader::toString(SkString* str) const {
str->append("SkTriColorShader: (");
@@ -2552,14 +2136,6 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
SkPoint* devVerts = storage.get();
fMatrix->mapPoints(devVerts, vertices, count);
- if (fBounder) {
- SkRect bounds;
- bounds.set(devVerts, count);
- if (!fBounder->doRect(bounds, paint)) {
- return;
- }
- }
-
/*
We can draw the vertices in 1 of 4 ways:
@@ -2585,6 +2161,7 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
}
// setup the custom shader (if needed)
+ SkAutoTUnref<SkComposeShader> composeShader;
if (NULL != colors) {
if (NULL == textures) {
// just colors (no texture)
@@ -2597,20 +2174,16 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
xmode = SkXfermode::Create(SkXfermode::kModulate_Mode);
releaseMode = true;
}
- SkShader* compose = SkNEW_ARGS(SkComposeShader,
- (&triShader, shader, xmode));
- p.setShader(compose)->unref();
+ composeShader.reset(SkNEW_ARGS(SkComposeShader, (&triShader, shader, xmode)));
+ p.setShader(composeShader);
if (releaseMode) {
xmode->unref();
}
- shader = compose;
}
}
SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, p);
- // important that we abort early, as below we may manipulate the shader
- // and that is only valid if the shader returned true from setContext.
- // If it returned false, then our blitter will be the NullBlitter.
+ // Abort early if we failed to create a shader context.
if (blitter->isNullBlitter()) {
return;
}
@@ -2620,36 +2193,39 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
VertState::Proc vertProc = state.chooseProc(vmode);
if (NULL != textures || NULL != colors) {
- SkMatrix tempM;
- SkMatrix savedLocalM;
- if (shader) {
- savedLocalM = shader->getLocalMatrix();
- }
-
- // setContext has already been called and verified to return true
- // by the constructor of SkAutoBlitterChoose
- bool prevContextSuccess = true;
while (vertProc(&state)) {
if (NULL != textures) {
+ SkMatrix tempM;
if (texture_to_matrix(state, vertices, textures, &tempM)) {
- tempM.postConcat(savedLocalM);
- shader->setLocalMatrix(tempM);
- // Need to recall setContext since we changed the local matrix.
- // However, we also need to balance the calls this with a
- // call to endContext which requires tracking the result of
- // the previous call to setContext.
- if (prevContextSuccess) {
- shader->endContext();
- }
- prevContextSuccess = shader->setContext(*fBitmap, p, *fMatrix);
- if (!prevContextSuccess) {
+ SkShader::ContextRec rec(*fBitmap, p, *fMatrix);
+ rec.fLocalMatrix = &tempM;
+ if (!blitter->resetShaderContext(rec)) {
continue;
}
}
}
if (NULL != colors) {
- if (!triShader.setup(vertices, colors,
- state.f0, state.f1, state.f2)) {
+ // Find the context for triShader.
+ SkTriColorShader::TriColorShaderContext* triColorShaderContext;
+
+ SkShader::Context* shaderContext = blitter->getShaderContext();
+ SkASSERT(shaderContext);
+ if (p.getShader() == &triShader) {
+ triColorShaderContext =
+ static_cast<SkTriColorShader::TriColorShaderContext*>(shaderContext);
+ } else {
+ // The shader is a compose shader and triShader is its first shader.
+ SkASSERT(p.getShader() == composeShader);
+ SkASSERT(composeShader->getShaderA() == &triShader);
+ SkComposeShader::ComposeShaderContext* composeShaderContext =
+ static_cast<SkComposeShader::ComposeShaderContext*>(shaderContext);
+ SkShader::Context* shaderContextA = composeShaderContext->getShaderContextA();
+ triColorShaderContext =
+ static_cast<SkTriColorShader::TriColorShaderContext*>(shaderContextA);
+ }
+
+ if (!triColorShaderContext->setup(vertices, colors,
+ state.f0, state.f1, state.f2)) {
continue;
}
}
@@ -2659,20 +2235,8 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
};
SkScan::FillTriangle(tmp, *fRC, blitter.get());
}
-
- // now restore the shader's original local matrix
- if (NULL != shader) {
- shader->setLocalMatrix(savedLocalM);
- }
-
- // If the final call to setContext fails we must make it suceed so that the
- // call to endContext in the destructor for SkAutoBlitterChoose is balanced.
- if (!prevContextSuccess) {
- prevContextSuccess = shader->setContext(*fBitmap, paint, SkMatrix::I());
- SkASSERT(prevContextSuccess);
- }
} else {
- // no colors[] and no texture
+ // no colors[] and no texture, stroke hairlines with paint's color.
HairProc hairProc = ChooseHairProc(paint.isAntiAlias());
const SkRasterClip& clip = *fRC;
while (vertProc(&state)) {
@@ -2703,97 +2267,6 @@ void SkDraw::validate() const {
#endif
-///////////////////////////////////////////////////////////////////////////////
-
-SkBounder::SkBounder() {
- // initialize up front. This gets reset by SkCanvas before each draw call.
- fClip = &SkRegion::GetEmptyRegion();
-}
-
-bool SkBounder::doIRect(const SkIRect& r) {
- SkIRect rr;
- return rr.intersect(fClip->getBounds(), r) && this->onIRect(rr);
-}
-
-// TODO: change the prototype to take fixed, and update the callers
-bool SkBounder::doIRectGlyph(const SkIRect& r, int x, int y,
- const SkGlyph& glyph) {
- SkIRect rr;
- if (!rr.intersect(fClip->getBounds(), r)) {
- return false;
- }
- GlyphRec rec;
- rec.fLSB.set(SkIntToFixed(x), SkIntToFixed(y));
- rec.fRSB.set(rec.fLSB.fX + glyph.fAdvanceX,
- rec.fLSB.fY + glyph.fAdvanceY);
- rec.fGlyphID = glyph.getGlyphID();
- rec.fFlags = 0;
- return this->onIRectGlyph(rr, rec);
-}
-
-bool SkBounder::doHairline(const SkPoint& pt0, const SkPoint& pt1,
- const SkPaint& paint) {
- SkIRect r;
- SkScalar v0, v1;
-
- v0 = pt0.fX;
- v1 = pt1.fX;
- if (v0 > v1) {
- SkTSwap<SkScalar>(v0, v1);
- }
- r.fLeft = SkScalarFloor(v0);
- r.fRight = SkScalarCeil(v1);
-
- v0 = pt0.fY;
- v1 = pt1.fY;
- if (v0 > v1) {
- SkTSwap<SkScalar>(v0, v1);
- }
- r.fTop = SkScalarFloor(v0);
- r.fBottom = SkScalarCeil(v1);
-
- if (paint.isAntiAlias()) {
- r.inset(-1, -1);
- }
- return this->doIRect(r);
-}
-
-bool SkBounder::doRect(const SkRect& rect, const SkPaint& paint) {
- SkIRect r;
-
- if (paint.getStyle() == SkPaint::kFill_Style) {
- rect.round(&r);
- } else {
- int rad = -1;
- rect.roundOut(&r);
- if (paint.isAntiAlias()) {
- rad = -2;
- }
- r.inset(rad, rad);
- }
- return this->doIRect(r);
-}
-
-bool SkBounder::doPath(const SkPath& path, const SkPaint& paint, bool doFill) {
- SkIRect r;
- const SkRect& bounds = path.getBounds();
-
- if (doFill) {
- bounds.round(&r);
- } else { // hairline
- bounds.roundOut(&r);
- }
-
- if (paint.isAntiAlias()) {
- r.inset(-1, -1);
- }
- return this->doIRect(r);
-}
-
-void SkBounder::commit() {
- // override in subclass
-}
-
////////////////////////////////////////////////////////////////////////////////////////////////
#include "SkPath.h"
@@ -2858,8 +2331,8 @@ static void draw_into_mask(const SkMask& mask, const SkPath& devPath,
SkMatrix matrix;
SkPaint paint;
- bm.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(), mask.fBounds.height(), mask.fRowBytes);
- bm.setPixels(mask.fImage);
+ bm.installPixels(SkImageInfo::MakeA8(mask.fBounds.width(), mask.fBounds.height()),
+ mask.fImage, mask.fRowBytes);
clip.setRect(SkIRect::MakeWH(mask.fBounds.width(), mask.fBounds.height()));
matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft),
@@ -2869,7 +2342,6 @@ static void draw_into_mask(const SkMask& mask, const SkPath& devPath,
draw.fRC = &clip;
draw.fClip = &clip.bwRgn();
draw.fMatrix = &matrix;
- draw.fBounder = NULL;
paint.setAntiAlias(true);
paint.setStyle(style);
draw.drawPath(devPath, paint);
diff --git a/chromium/third_party/skia/src/core/SkDrawLooper.cpp b/chromium/third_party/skia/src/core/SkDrawLooper.cpp
index bac2d969c05..d18d12710ab 100644
--- a/chromium/third_party/skia/src/core/SkDrawLooper.cpp
+++ b/chromium/third_party/skia/src/core/SkDrawLooper.cpp
@@ -10,14 +10,17 @@
#include "SkMatrix.h"
#include "SkPaint.h"
#include "SkRect.h"
+#include "SkSmallAllocator.h"
-bool SkDrawLooper::canComputeFastBounds(const SkPaint& paint) {
+bool SkDrawLooper::canComputeFastBounds(const SkPaint& paint) const {
SkCanvas canvas;
+ SkSmallAllocator<1, 32> allocator;
+ void* buffer = allocator.reserveT<SkDrawLooper::Context>(this->contextSize());
- this->init(&canvas);
+ SkDrawLooper::Context* context = this->createContext(&canvas, buffer);
for (;;) {
SkPaint p(paint);
- if (this->next(&canvas, &p)) {
+ if (context->next(&canvas, &p)) {
p.setLooper(NULL);
if (!p.canComputeFastBounds()) {
return false;
@@ -30,14 +33,16 @@ bool SkDrawLooper::canComputeFastBounds(const SkPaint& paint) {
}
void SkDrawLooper::computeFastBounds(const SkPaint& paint, const SkRect& src,
- SkRect* dst) {
+ SkRect* dst) const {
SkCanvas canvas;
+ SkSmallAllocator<1, 32> allocator;
+ void* buffer = allocator.reserveT<SkDrawLooper::Context>(this->contextSize());
*dst = src; // catch case where there are no loops
- this->init(&canvas);
+ SkDrawLooper::Context* context = this->createContext(&canvas, buffer);
for (bool firstTime = true;; firstTime = false) {
SkPaint p(paint);
- if (this->next(&canvas, &p)) {
+ if (context->next(&canvas, &p)) {
SkRect r(src);
p.setLooper(NULL);
@@ -54,3 +59,7 @@ void SkDrawLooper::computeFastBounds(const SkPaint& paint, const SkRect& src,
}
}
}
+
+bool SkDrawLooper::asABlurShadow(BlurShadowRec*) const {
+ return false;
+}
diff --git a/chromium/third_party/skia/src/core/SkDrawProcs.h b/chromium/third_party/skia/src/core/SkDrawProcs.h
index 6911e5b0176..d059c674701 100644
--- a/chromium/third_party/skia/src/core/SkDrawProcs.h
+++ b/chromium/third_party/skia/src/core/SkDrawProcs.h
@@ -1,22 +1,22 @@
-
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
+
#ifndef SkDrawProcs_DEFINED
#define SkDrawProcs_DEFINED
#include "SkBlitter.h"
#include "SkDraw.h"
+#include "SkGlyph.h"
class SkAAClip;
class SkBlitter;
struct SkDraw1Glyph {
const SkDraw* fDraw;
- SkBounder* fBounder;
const SkRegion* fClip;
const SkAAClip* fAAClip;
SkBlitter* fBlitter;
@@ -57,22 +57,6 @@ struct SkDraw1Glyph {
struct SkDrawProcs {
SkDraw1Glyph::Proc fD1GProc;
-#if SK_DISTANCEFIELD_FONTS
- uint32_t fFlags;
-
- enum Flags {
- /**
- * Disable baked glyph transforms
- */
- kSkipBakedGlyphTransform_Flag = 0x1,
- /**
- * Scale glyphs to get different point sizes
- */
- kUseScaledGlyphs_Flag = 0x2,
- };
-
- static const int kBaseDFFontSize = 32;
-#endif
};
bool SkDrawTreatAAStrokeAsHairline(SkScalar strokeWidth, const SkMatrix&,
@@ -103,4 +87,53 @@ inline bool SkDrawTreatAsHairline(const SkPaint& paint, const SkMatrix& matrix,
return SkDrawTreatAAStrokeAsHairline(strokeWidth, matrix, coverage);
}
+class SkTextAlignProc {
+public:
+ SkTextAlignProc(SkPaint::Align align)
+ : fAlign(align) {
+ }
+
+ // Returns the position of the glyph in fixed point, which may be rounded or not
+ // by the caller e.g. subpixel doesn't round.
+ // @param point interpreted as SkFixed [x, y].
+ void operator()(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
+ if (SkPaint::kLeft_Align == fAlign) {
+ dst->set(SkScalarToFixed(loc.fX), SkScalarToFixed(loc.fY));
+ } else if (SkPaint::kCenter_Align == fAlign) {
+ dst->set(SkScalarToFixed(loc.fX) - (glyph.fAdvanceX >> 1),
+ SkScalarToFixed(loc.fY) - (glyph.fAdvanceY >> 1));
+ } else {
+ SkASSERT(SkPaint::kRight_Align == fAlign);
+ dst->set(SkScalarToFixed(loc.fX) - glyph.fAdvanceX,
+ SkScalarToFixed(loc.fY) - glyph.fAdvanceY);
+ }
+ }
+private:
+ const SkPaint::Align fAlign;
+};
+
+class SkTextAlignProcScalar {
+public:
+ SkTextAlignProcScalar(SkPaint::Align align)
+ : fAlign(align) {
+ }
+
+ // Returns the glyph position, which may be rounded or not by the caller
+ // e.g. subpixel doesn't round.
+ void operator()(const SkPoint& loc, const SkGlyph& glyph, SkPoint* dst) {
+ if (SkPaint::kLeft_Align == fAlign) {
+ dst->set(loc.fX, loc.fY);
+ } else if (SkPaint::kCenter_Align == fAlign) {
+ dst->set(loc.fX - SkFixedToScalar(glyph.fAdvanceX >> 1),
+ loc.fY - SkFixedToScalar(glyph.fAdvanceY >> 1));
+ } else {
+ SkASSERT(SkPaint::kRight_Align == fAlign);
+ dst->set(loc.fX - SkFixedToScalar(glyph.fAdvanceX),
+ loc.fY - SkFixedToScalar(glyph.fAdvanceY));
+ }
+ }
+private:
+ const SkPaint::Align fAlign;
+};
+
#endif
diff --git a/chromium/third_party/skia/src/core/SkEdge.cpp b/chromium/third_party/skia/src/core/SkEdge.cpp
index 8904ca727b9..9ce255843f6 100644
--- a/chromium/third_party/skia/src/core/SkEdge.cpp
+++ b/chromium/third_party/skia/src/core/SkEdge.cpp
@@ -36,19 +36,11 @@ int SkEdge::setLine(const SkPoint& p0, const SkPoint& p1, const SkIRect* clip,
SkFDot6 x0, y0, x1, y1;
{
-#ifdef SK_SCALAR_IS_FLOAT
float scale = float(1 << (shift + 6));
x0 = int(p0.fX * scale);
y0 = int(p0.fY * scale);
x1 = int(p1.fX * scale);
y1 = int(p1.fY * scale);
-#else
- shift = 10 - shift;
- x0 = p0.fX >> shift;
- y0 = p0.fY >> shift;
- x1 = p1.fX >> shift;
- y1 = p1.fY >> shift;
-#endif
}
int winding = 1;
@@ -179,7 +171,6 @@ int SkQuadraticEdge::setQuadratic(const SkPoint pts[3], int shift)
SkFDot6 x0, y0, x1, y1, x2, y2;
{
-#ifdef SK_SCALAR_IS_FLOAT
float scale = float(1 << (shift + 6));
x0 = int(pts[0].fX * scale);
y0 = int(pts[0].fY * scale);
@@ -187,15 +178,6 @@ int SkQuadraticEdge::setQuadratic(const SkPoint pts[3], int shift)
y1 = int(pts[1].fY * scale);
x2 = int(pts[2].fX * scale);
y2 = int(pts[2].fY * scale);
-#else
- shift = 10 - shift;
- x0 = pts[0].fX >> shift;
- y0 = pts[0].fY >> shift;
- x1 = pts[1].fX >> shift;
- y1 = pts[1].fY >> shift;
- x2 = pts[2].fX >> shift;
- y2 = pts[2].fY >> shift;
-#endif
}
int winding = 1;
@@ -339,7 +321,6 @@ int SkCubicEdge::setCubic(const SkPoint pts[4], const SkIRect* clip, int shift)
SkFDot6 x0, y0, x1, y1, x2, y2, x3, y3;
{
-#ifdef SK_SCALAR_IS_FLOAT
float scale = float(1 << (shift + 6));
x0 = int(pts[0].fX * scale);
y0 = int(pts[0].fY * scale);
@@ -349,17 +330,6 @@ int SkCubicEdge::setCubic(const SkPoint pts[4], const SkIRect* clip, int shift)
y2 = int(pts[2].fY * scale);
x3 = int(pts[3].fX * scale);
y3 = int(pts[3].fY * scale);
-#else
- shift = 10 - shift;
- x0 = pts[0].fX >> shift;
- y0 = pts[0].fY >> shift;
- x1 = pts[1].fX >> shift;
- y1 = pts[1].fY >> shift;
- x2 = pts[2].fX >> shift;
- y2 = pts[2].fY >> shift;
- x3 = pts[3].fX >> shift;
- y3 = pts[3].fY >> shift;
-#endif
}
int winding = 1;
diff --git a/chromium/third_party/skia/src/core/SkEdge.h b/chromium/third_party/skia/src/core/SkEdge.h
index ea7c84f78d2..091223631fe 100644
--- a/chromium/third_party/skia/src/core/SkEdge.h
+++ b/chromium/third_party/skia/src/core/SkEdge.h
@@ -89,19 +89,11 @@ int SkEdge::setLine(const SkPoint& p0, const SkPoint& p1, int shift) {
SkFDot6 x0, y0, x1, y1;
{
-#ifdef SK_SCALAR_IS_FLOAT
float scale = float(1 << (shift + 6));
x0 = int(p0.fX * scale);
y0 = int(p0.fY * scale);
x1 = int(p1.fX * scale);
y1 = int(p1.fY * scale);
-#else
- shift = 10 - shift;
- x0 = p0.fX >> shift;
- y0 = p0.fY >> shift;
- x1 = p1.fX >> shift;
- y1 = p1.fY >> shift;
-#endif
}
int winding = 1;
diff --git a/chromium/third_party/skia/src/core/SkEdgeBuilder.cpp b/chromium/third_party/skia/src/core/SkEdgeBuilder.cpp
index 799c6762d92..c3f5dafe8d7 100644
--- a/chromium/third_party/skia/src/core/SkEdgeBuilder.cpp
+++ b/chromium/third_party/skia/src/core/SkEdgeBuilder.cpp
@@ -150,7 +150,7 @@ int SkEdgeBuilder::buildPoly(const SkPath& path, const SkIRect* iclip,
}
SkASSERT((char*)edge <= (char*)fEdgeList);
SkASSERT(edgePtr - fEdgeList <= maxEdgeCount);
- return edgePtr - fEdgeList;
+ return SkToInt(edgePtr - fEdgeList);
}
static void handle_quad(SkEdgeBuilder* builder, const SkPoint pts[3]) {
diff --git a/chromium/third_party/skia/src/core/SkError.cpp b/chromium/third_party/skia/src/core/SkError.cpp
index f5d233c6daf..9e8ff2ddef0 100644
--- a/chromium/third_party/skia/src/core/SkError.cpp
+++ b/chromium/third_party/skia/src/core/SkError.cpp
@@ -130,7 +130,7 @@ void SkErrorInternals::SetError(SkError code, const char *fmt, ...) {
}
sprintf( str, "%s: ", error_name );
- int string_left = ERROR_STRING_LENGTH - strlen( str );
+ int string_left = SkToInt(ERROR_STRING_LENGTH - strlen(str));
str += strlen(str);
va_start( args, fmt );
diff --git a/chromium/third_party/skia/src/core/SkFDot6.h b/chromium/third_party/skia/src/core/SkFDot6.h
index afb369e9b27..5a0ec57f595 100644
--- a/chromium/third_party/skia/src/core/SkFDot6.h
+++ b/chromium/third_party/skia/src/core/SkFDot6.h
@@ -39,13 +39,8 @@ inline SkFixed SkFDot6ToFixed(SkFDot6 x) {
return x << 10;
}
-#ifdef SK_SCALAR_IS_FLOAT
- #define SkScalarToFDot6(x) (SkFDot6)((x) * 64)
- #define SkFDot6ToScalar(x) ((SkScalar)(x) * 0.015625f)
-#else
- #define SkScalarToFDot6(x) ((x) >> 10)
- #define SkFDot6ToScalar(x) ((x) << 10)
-#endif
+#define SkScalarToFDot6(x) (SkFDot6)((x) * 64)
+#define SkFDot6ToScalar(x) ((SkScalar)(x) * 0.015625f)
inline SkFixed SkFDot6Div(SkFDot6 a, SkFDot6 b) {
SkASSERT(b != 0);
diff --git a/chromium/third_party/skia/src/core/SkFP.h b/chromium/third_party/skia/src/core/SkFP.h
deleted file mode 100644
index 1d1507a3697..00000000000
--- a/chromium/third_party/skia/src/core/SkFP.h
+++ /dev/null
@@ -1,79 +0,0 @@
-
-/*
- * Copyright 2006 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#ifndef SkFP_DEFINED
-#define SkFP_DEFINED
-
-#include "SkMath.h"
-
-#ifdef SK_SCALAR_IS_FLOAT
-
- typedef float SkFP;
-
- #define SkScalarToFP(n) (n)
- #define SkFPToScalar(n) (n)
- #define SkIntToFP(n) SkIntToScalar(n)
- #define SkFPRound(x) SkScalarRound(n)
- #define SkFPCeil(x) SkScalarCeil(n)
- #define SkFPFloor(x) SkScalarFloor(n)
-
- #define SkFPNeg(x) (-(x))
- #define SkFPAbs(x) SkScalarAbs(x)
- #define SkFPAdd(a, b) ((a) + (b))
- #define SkFPSub(a, b) ((a) - (b))
- #define SkFPMul(a, b) ((a) * (b))
- #define SkFPMulInt(a, n) ((a) * (n))
- #define SkFPDiv(a, b) ((a) / (b))
- #define SkFPDivInt(a, n) ((a) / (n))
- #define SkFPInvert(x) SkScalarInvert(x)
- #define SkFPSqrt(x) SkScalarSqrt(x)
- #define SkFPCubeRoot(x) sk_float_pow(x, 0.3333333f)
-
- #define SkFPLT(a, b) ((a) < (b))
- #define SkFPLE(a, b) ((a) <= (b))
- #define SkFPGT(a, b) ((a) > (b))
- #define SkFPGE(a, b) ((a) >= (b))
-
-#else // scalar is fixed
-
- #include "SkFloat.h"
-
- typedef int32_t SkFP;
-
- #define SkScalarToFP(n) SkFloat::SetShift(n, -16)
- #define SkFPToScalar(n) SkFloat::GetShift(n, -16)
- #define SkIntToFP(n) SkFloat::SetShift(n, 0)
- #define SkFPRound(x) SkFloat::Round(x);
- #define SkFPCeil(x) SkFloat::Ceil();
- #define SkFPFloor(x) SkFloat::Floor();
-
- #define SkFPNeg(x) SkFloat::Neg(x)
- #define SkFPAbs(x) SkFloat::Abs(x)
- #define SkFPAdd(a, b) SkFloat::Add(a, b)
- #define SkFPSub(a, b) SkFloat::Add(a, SkFloat::Neg(b))
- #define SkFPMul(a, b) SkFloat::Mul(a, b)
- #define SkFPMulInt(a, n) SkFloat::MulInt(a, n)
- #define SkFPDiv(a, b) SkFloat::Div(a, b)
- #define SkFPDivInt(a, n) SkFloat::DivInt(a, n)
- #define SkFPInvert(x) SkFloat::Invert(x)
- #define SkFPSqrt(x) SkFloat::Sqrt(x)
- #define SkFPCubeRoot(x) SkFloat::CubeRoot(x)
-
- #define SkFPLT(a, b) (SkFloat::Cmp(a, b) < 0)
- #define SkFPLE(a, b) (SkFloat::Cmp(a, b) <= 0)
- #define SkFPGT(a, b) (SkFloat::Cmp(a, b) > 0)
- #define SkFPGE(a, b) (SkFloat::Cmp(a, b) >= 0)
-
-#endif
-
-#ifdef SK_DEBUG
- void SkFP_UnitTest();
-#endif
-
-#endif
diff --git a/chromium/third_party/skia/src/core/SkFilterShader.cpp b/chromium/third_party/skia/src/core/SkFilterShader.cpp
index 1e590cb66ff..0c92d4c3e3f 100644
--- a/chromium/third_party/skia/src/core/SkFilterShader.cpp
+++ b/chromium/third_party/skia/src/core/SkFilterShader.cpp
@@ -8,7 +8,8 @@
#include "SkFilterShader.h"
#include "SkColorFilter.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkShader.h"
#include "SkString.h"
@@ -20,7 +21,7 @@ SkFilterShader::SkFilterShader(SkShader* shader, SkColorFilter* filter) {
filter->ref();
}
-SkFilterShader::SkFilterShader(SkFlattenableReadBuffer& buffer)
+SkFilterShader::SkFilterShader(SkReadBuffer& buffer)
: INHERITED(buffer) {
fShader = buffer.readShader();
fFilter = buffer.readColorFilter();
@@ -31,15 +32,17 @@ SkFilterShader::~SkFilterShader() {
fShader->unref();
}
-void SkFilterShader::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkFilterShader::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeFlattenable(fShader);
buffer.writeFlattenable(fFilter);
}
-uint32_t SkFilterShader::getFlags() {
- uint32_t shaderF = fShader->getFlags();
- uint32_t filterF = fFilter->getFlags();
+uint32_t SkFilterShader::FilterShaderContext::getFlags() const {
+ const SkFilterShader& filterShader = static_cast<const SkFilterShader&>(fShader);
+
+ uint32_t shaderF = fShaderContext->getFlags();
+ uint32_t filterF = filterShader.fFilter->getFlags();
// if the filter doesn't support 16bit, clear the matching bit in the shader
if (!(filterF & SkColorFilter::kHasFilter16_Flag)) {
@@ -52,41 +55,47 @@ uint32_t SkFilterShader::getFlags() {
return shaderF;
}
-bool SkFilterShader::setContext(const SkBitmap& device,
- const SkPaint& paint,
- const SkMatrix& matrix) {
- // we need to keep the setContext/endContext calls balanced. If we return
- // false, our endContext() will not be called.
-
- if (!this->INHERITED::setContext(device, paint, matrix)) {
- return false;
+SkShader::Context* SkFilterShader::onCreateContext(const ContextRec& rec, void* storage) const {
+ char* shaderContextStorage = (char*)storage + sizeof(FilterShaderContext);
+ SkShader::Context* shaderContext = fShader->createContext(rec, shaderContextStorage);
+ if (NULL == shaderContext) {
+ return NULL;
}
- if (!fShader->setContext(device, paint, matrix)) {
- this->INHERITED::endContext();
- return false;
- }
- return true;
+ return SkNEW_PLACEMENT_ARGS(storage, FilterShaderContext, (*this, shaderContext, rec));
+}
+
+size_t SkFilterShader::contextSize() const {
+ return sizeof(FilterShaderContext) + fShader->contextSize();
}
-void SkFilterShader::endContext() {
- fShader->endContext();
- this->INHERITED::endContext();
+SkFilterShader::FilterShaderContext::FilterShaderContext(const SkFilterShader& filterShader,
+ SkShader::Context* shaderContext,
+ const ContextRec& rec)
+ : INHERITED(filterShader, rec)
+ , fShaderContext(shaderContext) {}
+
+SkFilterShader::FilterShaderContext::~FilterShaderContext() {
+ fShaderContext->~Context();
}
-void SkFilterShader::shadeSpan(int x, int y, SkPMColor result[], int count) {
- fShader->shadeSpan(x, y, result, count);
- fFilter->filterSpan(result, count, result);
+void SkFilterShader::FilterShaderContext::shadeSpan(int x, int y, SkPMColor result[], int count) {
+ const SkFilterShader& filterShader = static_cast<const SkFilterShader&>(fShader);
+
+ fShaderContext->shadeSpan(x, y, result, count);
+ filterShader.fFilter->filterSpan(result, count, result);
}
-void SkFilterShader::shadeSpan16(int x, int y, uint16_t result[], int count) {
- SkASSERT(fShader->getFlags() & SkShader::kHasSpan16_Flag);
- SkASSERT(fFilter->getFlags() & SkColorFilter::kHasFilter16_Flag);
+void SkFilterShader::FilterShaderContext::shadeSpan16(int x, int y, uint16_t result[], int count) {
+ const SkFilterShader& filterShader = static_cast<const SkFilterShader&>(fShader);
+
+ SkASSERT(fShaderContext->getFlags() & SkShader::kHasSpan16_Flag);
+ SkASSERT(filterShader.fFilter->getFlags() & SkColorFilter::kHasFilter16_Flag);
- fShader->shadeSpan16(x, y, result, count);
- fFilter->filterSpan16(result, count, result);
+ fShaderContext->shadeSpan16(x, y, result, count);
+ filterShader.fFilter->filterSpan16(result, count, result);
}
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkFilterShader::toString(SkString* str) const {
str->append("SkFilterShader: (");
diff --git a/chromium/third_party/skia/src/core/SkFilterShader.h b/chromium/third_party/skia/src/core/SkFilterShader.h
index be19640d0e2..1a4b71fe469 100644
--- a/chromium/third_party/skia/src/core/SkFilterShader.h
+++ b/chromium/third_party/skia/src/core/SkFilterShader.h
@@ -17,19 +17,33 @@ public:
SkFilterShader(SkShader* shader, SkColorFilter* filter);
virtual ~SkFilterShader();
- virtual uint32_t getFlags() SK_OVERRIDE;
- virtual bool setContext(const SkBitmap&, const SkPaint&,
- const SkMatrix&) SK_OVERRIDE;
- virtual void endContext() SK_OVERRIDE;
- virtual void shadeSpan(int x, int y, SkPMColor[], int count) SK_OVERRIDE;
- virtual void shadeSpan16(int x, int y, uint16_t[], int count) SK_OVERRIDE;
-
- SK_DEVELOPER_TO_STRING()
+ virtual size_t contextSize() const SK_OVERRIDE;
+
+ class FilterShaderContext : public SkShader::Context {
+ public:
+ // Takes ownership of shaderContext and calls its destructor.
+ FilterShaderContext(const SkFilterShader&, SkShader::Context*, const ContextRec&);
+ virtual ~FilterShaderContext();
+
+ virtual uint32_t getFlags() const SK_OVERRIDE;
+
+ virtual void shadeSpan(int x, int y, SkPMColor[], int count) SK_OVERRIDE;
+ virtual void shadeSpan16(int x, int y, uint16_t[], int count) SK_OVERRIDE;
+
+ private:
+ SkShader::Context* fShaderContext;
+
+ typedef SkShader::Context INHERITED;
+ };
+
+ SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkFilterShader)
protected:
- SkFilterShader(SkFlattenableReadBuffer& );
- virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+ SkFilterShader(SkReadBuffer& );
+ virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
+ virtual Context* onCreateContext(const ContextRec&, void* storage) const SK_OVERRIDE;
+
private:
SkShader* fShader;
diff --git a/chromium/third_party/skia/src/core/SkFlate.cpp b/chromium/third_party/skia/src/core/SkFlate.cpp
index 8258cdcd1d5..2b4e36d7271 100644
--- a/chromium/third_party/skia/src/core/SkFlate.cpp
+++ b/chromium/third_party/skia/src/core/SkFlate.cpp
@@ -61,7 +61,7 @@ bool doFlate(bool compress, SkStream* src, SkWStream* dst) {
flateData.avail_in = 0;
} else {
flateData.next_in = input;
- flateData.avail_in = inputLength;
+ flateData.avail_in = SkToUInt(inputLength);
}
rc = Z_OK;
@@ -83,7 +83,7 @@ bool doFlate(bool compress, SkStream* src, SkWStream* dst) {
if (read == 0)
break;
flateData.next_in = inputBuffer;
- flateData.avail_in = read;
+ flateData.avail_in = SkToUInt(read);
}
if (compress)
rc = deflate(&flateData, Z_NO_FLUSH);
diff --git a/chromium/third_party/skia/src/core/SkFlate.h b/chromium/third_party/skia/src/core/SkFlate.h
new file mode 100644
index 00000000000..e4c1417d910
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkFlate.h
@@ -0,0 +1,52 @@
+
+/*
+ * Copyright 2010 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkFlate_DEFINED
+#define SkFlate_DEFINED
+
+#include "SkTypes.h"
+
+class SkData;
+class SkWStream;
+class SkStream;
+
+/** \class SkFlate
+ A class to provide access to the flate compression algorithm.
+*/
+class SkFlate {
+public:
+ /** Indicates if the flate algorithm is available.
+ */
+ static bool HaveFlate();
+
+ /**
+ * Use the flate compression algorithm to compress the data in src,
+ * putting the result into dst. Returns false if an error occurs.
+ */
+ static bool Deflate(SkStream* src, SkWStream* dst);
+
+ /**
+ * Use the flate compression algorithm to compress the data in src,
+ * putting the result into dst. Returns false if an error occurs.
+ */
+ static bool Deflate(const void* src, size_t len, SkWStream* dst);
+
+ /**
+ * Use the flate compression algorithm to compress the data,
+ * putting the result into dst. Returns false if an error occurs.
+ */
+ static bool Deflate(const SkData*, SkWStream* dst);
+
+ /** Use the flate compression algorithm to decompress the data in src,
+ putting the result into dst. Returns false if an error occurs.
+ */
+ static bool Inflate(SkStream* src, SkWStream* dst);
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/core/SkFlattenable.cpp b/chromium/third_party/skia/src/core/SkFlattenable.cpp
index 877fa0a85ff..410fe0d9749 100644
--- a/chromium/third_party/skia/src/core/SkFlattenable.cpp
+++ b/chromium/third_party/skia/src/core/SkFlattenable.cpp
@@ -10,7 +10,7 @@
///////////////////////////////////////////////////////////////////////////////
-void SkFlattenable::flatten(SkFlattenableWriteBuffer&) const
+void SkFlattenable::flatten(SkWriteBuffer&) const
{
/* we don't write anything at the moment, but this allows our subclasses
to not know that, since we want them to always call INHERITED::flatten()
diff --git a/chromium/third_party/skia/src/core/SkFlattenableBuffers.cpp b/chromium/third_party/skia/src/core/SkFlattenableBuffers.cpp
deleted file mode 100644
index 9da4dd9ee48..00000000000
--- a/chromium/third_party/skia/src/core/SkFlattenableBuffers.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "SkFlattenableBuffers.h"
-#include "SkPaint.h"
-#include "SkTypeface.h"
-
-#include "SkColorFilter.h"
-#include "SkDrawLooper.h"
-#include "SkImageFilter.h"
-#include "SkMaskFilter.h"
-#include "SkPathEffect.h"
-#include "SkPixelRef.h"
-#include "SkRasterizer.h"
-#include "SkShader.h"
-#include "SkUnitMapper.h"
-#include "SkXfermode.h"
-
-SkFlattenableReadBuffer::SkFlattenableReadBuffer() {
- // Set default values. These should be explicitly set by our client
- // via setFlags() if the buffer came from serialization.
- fFlags = 0;
-#ifdef SK_SCALAR_IS_FLOAT
- fFlags |= kScalarIsFloat_Flag;
-#endif
- if (8 == sizeof(void*)) {
- fFlags |= kPtrIs64Bit_Flag;
- }
-}
-
-SkFlattenableReadBuffer::~SkFlattenableReadBuffer() { }
-
-void* SkFlattenableReadBuffer::readFunctionPtr() {
- void* proc;
- SkASSERT(sizeof(void*) == this->getArrayCount());
- this->readByteArray(&proc, sizeof(void*));
- return proc;
-}
-
-void SkFlattenableReadBuffer::readPaint(SkPaint* paint) {
- paint->unflatten(*this);
-}
-
-template <typename T> T* SkFlattenableReadBuffer::readFlattenableT() {
- return static_cast<T*>(this->readFlattenable(T::GetFlattenableType()));
-}
-
-SkColorFilter* SkFlattenableReadBuffer::readColorFilter() {
- return this->readFlattenableT<SkColorFilter>();
-}
-
-SkDrawLooper* SkFlattenableReadBuffer::readDrawLooper() {
- return this->readFlattenableT<SkDrawLooper>();
-}
-
-SkImageFilter* SkFlattenableReadBuffer::readImageFilter() {
- return this->readFlattenableT<SkImageFilter>();
-}
-
-SkMaskFilter* SkFlattenableReadBuffer::readMaskFilter() {
- return this->readFlattenableT<SkMaskFilter>();
-}
-
-SkPathEffect* SkFlattenableReadBuffer::readPathEffect() {
- return this->readFlattenableT<SkPathEffect>();
-}
-
-SkPixelRef* SkFlattenableReadBuffer::readPixelRef() {
- return this->readFlattenableT<SkPixelRef>();
-}
-
-SkRasterizer* SkFlattenableReadBuffer::readRasterizer() {
- return this->readFlattenableT<SkRasterizer>();
-}
-
-SkShader* SkFlattenableReadBuffer::readShader() {
- return this->readFlattenableT<SkShader>();
-}
-
-SkUnitMapper* SkFlattenableReadBuffer::readUnitMapper() {
- return this->readFlattenableT<SkUnitMapper>();
-}
-
-SkXfermode* SkFlattenableReadBuffer::readXfermode() {
- return this->readFlattenableT<SkXfermode>();
-}
-
-bool SkFlattenableReadBuffer::validate(bool isValid) {
- return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-SkFlattenableWriteBuffer::SkFlattenableWriteBuffer() {
- fFlags = (Flags)0;
-}
-
-SkFlattenableWriteBuffer::~SkFlattenableWriteBuffer() { }
-
-void SkFlattenableWriteBuffer::writeFunctionPtr(void* ptr) {
- void* ptrStorage[] = { ptr };
- this->writeByteArray(ptrStorage, sizeof(void*));
-}
-
-void SkFlattenableWriteBuffer::writePaint(const SkPaint& paint) {
- paint.flatten(*this);
-}
-
-void SkFlattenableWriteBuffer::flattenObject(const SkFlattenable* obj,
- SkFlattenableWriteBuffer& buffer) {
- obj->flatten(buffer);
-}
diff --git a/chromium/third_party/skia/src/core/SkFlattenableSerialization.cpp b/chromium/third_party/skia/src/core/SkFlattenableSerialization.cpp
index b98d935ca7d..b33bca6dbbe 100644
--- a/chromium/third_party/skia/src/core/SkFlattenableSerialization.cpp
+++ b/chromium/third_party/skia/src/core/SkFlattenableSerialization.cpp
@@ -9,13 +9,12 @@
#include "SkData.h"
#include "SkValidatingReadBuffer.h"
-#include "SkOrderedWriteBuffer.h"
+#include "SkWriteBuffer.h"
SkData* SkValidatingSerializeFlattenable(SkFlattenable* flattenable) {
- SkOrderedWriteBuffer writer(1024);
- writer.setFlags(SkOrderedWriteBuffer::kValidation_Flag);
+ SkWriteBuffer writer(SkWriteBuffer::kValidation_Flag);
writer.writeFlattenable(flattenable);
- uint32_t size = writer.bytesWritten();
+ size_t size = writer.bytesWritten();
void* data = sk_malloc_throw(size);
writer.writeToMemory(data);
return SkData::NewFromMalloc(data, size);
diff --git a/chromium/third_party/skia/src/core/SkFloat.cpp b/chromium/third_party/skia/src/core/SkFloat.cpp
index b5cc4f18e7d..9ec0a7a081b 100644
--- a/chromium/third_party/skia/src/core/SkFloat.cpp
+++ b/chromium/third_party/skia/src/core/SkFloat.cpp
@@ -156,15 +156,9 @@ int32_t SkFloat::Add(int32_t packed_a, int32_t packed_b)
return SkFloat::SetShift(value_a + value_b, exp - EXP_BIAS);
}
-#include "Sk64.h"
-
-static inline int32_t mul24(int32_t a, int32_t b)
-{
- Sk64 tmp;
-
- tmp.setMul(a, b);
- tmp.roundRight(24);
- return tmp.get32();
+static inline int32_t mul24(int32_t a, int32_t b) {
+ int64_t tmp = (sk_64_mul(a, b) + (1 << 23)) >> 24;
+ return sk_64_asS32(tmp);
}
int32_t SkFloat::Mul(int32_t packed_a, int32_t packed_b)
@@ -272,7 +266,7 @@ int SkFloat::Cmp(int32_t packed_a, int32_t packed_b)
void SkFloat::UnitTest()
{
-#ifdef SK_SUPPORT_UNITTEST
+#if 0 // def SK_SUPPORT_UNITTEST
SkFloat a, b, c, d;
int n;
diff --git a/chromium/third_party/skia/src/core/SkFloat.h b/chromium/third_party/skia/src/core/SkFloat.h
index 74cd19e542f..0d4f9b41a74 100644
--- a/chromium/third_party/skia/src/core/SkFloat.h
+++ b/chromium/third_party/skia/src/core/SkFloat.h
@@ -20,12 +20,10 @@ public:
// 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); }
diff --git a/chromium/third_party/skia/src/core/SkFont.cpp b/chromium/third_party/skia/src/core/SkFont.cpp
new file mode 100644
index 00000000000..dcc2f0bf67b
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkFont.cpp
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkFont.h"
+#include "SkTypeface.h"
+#include "SkUtils.h"
+
+static SkTypeface* ref_or_default(SkTypeface* face) {
+ return face ? SkRef(face) : SkTypeface::RefDefault();
+}
+
+SkFont::SkFont(SkTypeface* face, SkScalar size, SkScalar scaleX, SkScalar skewX, MaskType mt,
+ uint32_t flags)
+ : fTypeface(ref_or_default(face))
+ , fSize(size)
+ , fScaleX(scaleX)
+ , fSkewX(skewX)
+ , fFlags(flags)
+ , fMaskType(SkToU8(mt))
+{
+ SkASSERT(size > 0);
+ SkASSERT(scaleX > 0);
+ SkASSERT(SkScalarIsFinite(skewX));
+ SkASSERT(0 == (flags & ~kAllFlags));
+}
+
+SkFont* SkFont::Create(SkTypeface* face, SkScalar size, SkScalar scaleX, SkScalar skewX,
+ MaskType mt, uint32_t flags) {
+ if (size <= 0 || !SkScalarIsFinite(size)) {
+ return NULL;
+ }
+ if (scaleX <= 0 || !SkScalarIsFinite(scaleX)) {
+ return NULL;
+ }
+ if (!SkScalarIsFinite(skewX)) {
+ return NULL;
+ }
+ flags &= kAllFlags;
+ return SkNEW_ARGS(SkFont, (face, size, scaleX, skewX, mt, flags));
+}
+
+SkFont* SkFont::Create(SkTypeface* face, SkScalar size, MaskType mt, uint32_t flags) {
+ return SkFont::Create(face, size, 1, 0, mt, flags);
+}
+
+SkFont* SkFont::cloneWithSize(SkScalar newSize) const {
+ return SkFont::Create(this->getTypeface(), newSize, this->getScaleX(), this->getSkewX(),
+ this->getMaskType(), this->getFlags());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+SkFont::~SkFont() {
+ SkSafeUnref(fTypeface);
+}
+
+int SkFont::textToGlyphs(const void* text, size_t byteLength, SkTextEncoding encoding,
+ uint16_t glyphs[], int maxGlyphCount) const {
+ if (0 == byteLength) {
+ return 0;
+ }
+
+ SkASSERT(text);
+
+ int count = 0; // fix uninitialized warning (even though the switch is complete!)
+
+ switch (encoding) {
+ case kUTF8_SkTextEncoding:
+ count = SkUTF8_CountUnichars((const char*)text, byteLength);
+ break;
+ case kUTF16_SkTextEncoding:
+ count = SkUTF16_CountUnichars((const uint16_t*)text, SkToInt(byteLength >> 1));
+ break;
+ case kUTF32_SkTextEncoding:
+ count = SkToInt(byteLength >> 2);
+ break;
+ case kGlyphID_SkTextEncoding:
+ count = SkToInt(byteLength >> 1);
+ break;
+ }
+ if (NULL == glyphs) {
+ return count;
+ }
+
+ // TODO: unify/eliminate SkTypeface::Encoding with SkTextEncoding
+ SkTypeface::Encoding typeface_encoding;
+ switch (encoding) {
+ case kUTF8_SkTextEncoding:
+ typeface_encoding = SkTypeface::kUTF8_Encoding;
+ break;
+ case kUTF16_SkTextEncoding:
+ typeface_encoding = SkTypeface::kUTF16_Encoding;
+ break;
+ case kUTF32_SkTextEncoding:
+ typeface_encoding = SkTypeface::kUTF32_Encoding;
+ break;
+ default:
+ SkASSERT(kGlyphID_SkTextEncoding == encoding);
+ // we can early exit, since we already have glyphIDs
+ memcpy(glyphs, text, count << 1);
+ return count;
+ }
+
+ (void)fTypeface->charsToGlyphs(text, typeface_encoding, glyphs, count);
+ return count;
+}
+
+SkScalar SkFont::measureText(const void* text, size_t byteLength, SkTextEncoding encoding) const {
+ // TODO: need access to the cache
+ return -1;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+#include "SkPaint.h"
+
+SkFont* SkFont::Testing_CreateFromPaint(const SkPaint& paint) {
+ uint32_t flags = 0;
+ if (paint.isVerticalText()) {
+ flags |= kVertical_Flag;
+ }
+ if (paint.isEmbeddedBitmapText()) {
+ flags |= kEmbeddedBitmaps_Flag;
+ }
+ if (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) {
+ flags |= kGenA8FromLCD_Flag;
+ }
+ if (paint.isFakeBoldText()) {
+ flags |= kEmbolden_Flag;
+ }
+
+ if (SkPaint::kFull_Hinting == paint.getHinting()) {
+ flags |= kEnableByteCodeHints_Flag;
+ }
+ if (paint.isAutohinted()) {
+ flags |= kEnableAutoHints_Flag;
+ }
+ if (paint.isSubpixelText() || paint.isLinearText()) {
+ // this is our default
+ } else {
+ flags |= kUseNonlinearMetrics_Flag;
+ }
+
+ MaskType maskType = SkFont::kBW_MaskType;
+ if (paint.isAntiAlias()) {
+ maskType = paint.isLCDRenderText() ? kLCD_MaskType : kA8_MaskType;
+ }
+
+ return Create(paint.getTypeface(),
+ paint.getTextSize(), paint.getTextScaleX(), paint.getTextSkewX(),
+ maskType, flags);
+}
diff --git a/chromium/third_party/skia/src/core/SkFontDescriptor.cpp b/chromium/third_party/skia/src/core/SkFontDescriptor.cpp
index 7679d92a146..5088ed7687b 100644
--- a/chromium/third_party/skia/src/core/SkFontDescriptor.cpp
+++ b/chromium/third_party/skia/src/core/SkFontDescriptor.cpp
@@ -25,7 +25,7 @@ SkFontDescriptor::SkFontDescriptor(SkTypeface::Style style) {
}
static void read_string(SkStream* stream, SkString* string) {
- const uint32_t length = stream->readPackedUInt();
+ const uint32_t length = SkToU32(stream->readPackedUInt());
if (length > 0) {
string->resize(length);
stream->read(string->writable_str(), length);
diff --git a/chromium/third_party/skia/src/core/SkFontHost.cpp b/chromium/third_party/skia/src/core/SkFontHost.cpp
index a209b970278..a16a8c42e02 100644
--- a/chromium/third_party/skia/src/core/SkFontHost.cpp
+++ b/chromium/third_party/skia/src/core/SkFontHost.cpp
@@ -6,7 +6,7 @@
*/
#include "SkFontLCDConfig.h"
-#include "SkOnce.h"
+#include "SkLazyPtr.h"
static SkFontLCDConfig::LCDOrientation gLCDOrientation = SkFontLCDConfig::kHorizontal_LCDOrientation;
static SkFontLCDConfig::LCDOrder gLCDOrder = SkFontLCDConfig::kRGB_LCDOrder;
@@ -92,38 +92,44 @@ SkFontStyleSet* SkFontStyleSet::CreateEmpty() {
class SkEmptyFontMgr : public SkFontMgr {
protected:
- virtual int onCountFamilies() SK_OVERRIDE {
+ virtual int onCountFamilies() const SK_OVERRIDE {
return 0;
}
- virtual void onGetFamilyName(int index, SkString* familyName) SK_OVERRIDE {
+ virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE {
SkDEBUGFAIL("onGetFamilyName called with bad index");
}
- virtual SkFontStyleSet* onCreateStyleSet(int index) SK_OVERRIDE {
+ virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE {
SkDEBUGFAIL("onCreateStyleSet called with bad index");
return NULL;
}
- virtual SkFontStyleSet* onMatchFamily(const char[]) SK_OVERRIDE {
+ virtual SkFontStyleSet* onMatchFamily(const char[]) const SK_OVERRIDE {
return SkFontStyleSet::CreateEmpty();
}
virtual SkTypeface* onMatchFamilyStyle(const char[],
- const SkFontStyle&) SK_OVERRIDE {
+ const SkFontStyle&) const SK_OVERRIDE {
+ return NULL;
+ }
+ virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
+ const SkFontStyle& style,
+ const char bpc47[],
+ uint32_t character) const SK_OVERRIDE {
return NULL;
}
virtual SkTypeface* onMatchFaceStyle(const SkTypeface*,
- const SkFontStyle&) SK_OVERRIDE {
+ const SkFontStyle&) const SK_OVERRIDE {
return NULL;
}
- virtual SkTypeface* onCreateFromData(SkData*, int) SK_OVERRIDE {
+ virtual SkTypeface* onCreateFromData(SkData*, int) const SK_OVERRIDE {
return NULL;
}
- virtual SkTypeface* onCreateFromStream(SkStream*, int) SK_OVERRIDE {
+ virtual SkTypeface* onCreateFromStream(SkStream*, int) const SK_OVERRIDE {
return NULL;
}
- virtual SkTypeface* onCreateFromFile(const char[], int) SK_OVERRIDE {
+ virtual SkTypeface* onCreateFromFile(const char[], int) const SK_OVERRIDE {
return NULL;
}
- virtual SkTypeface* onLegacyCreateTypeface(const char [], unsigned) SK_OVERRIDE {
+ virtual SkTypeface* onLegacyCreateTypeface(const char [], unsigned) const SK_OVERRIDE {
return NULL;
}
};
@@ -135,47 +141,52 @@ static SkFontStyleSet* emptyOnNull(SkFontStyleSet* fsset) {
return fsset;
}
-int SkFontMgr::countFamilies() {
+int SkFontMgr::countFamilies() const {
return this->onCountFamilies();
}
-void SkFontMgr::getFamilyName(int index, SkString* familyName) {
+void SkFontMgr::getFamilyName(int index, SkString* familyName) const {
this->onGetFamilyName(index, familyName);
}
-SkFontStyleSet* SkFontMgr::createStyleSet(int index) {
+SkFontStyleSet* SkFontMgr::createStyleSet(int index) const {
return emptyOnNull(this->onCreateStyleSet(index));
}
-SkFontStyleSet* SkFontMgr::matchFamily(const char familyName[]) {
+SkFontStyleSet* SkFontMgr::matchFamily(const char familyName[]) const {
return emptyOnNull(this->onMatchFamily(familyName));
}
SkTypeface* SkFontMgr::matchFamilyStyle(const char familyName[],
- const SkFontStyle& fs) {
+ const SkFontStyle& fs) const {
return this->onMatchFamilyStyle(familyName, fs);
}
+SkTypeface* SkFontMgr::matchFamilyStyleCharacter(const char familyName[], const SkFontStyle& style,
+ const char bpc47[], uint32_t character) const {
+ return this->onMatchFamilyStyleCharacter(familyName, style, bpc47, character);
+}
+
SkTypeface* SkFontMgr::matchFaceStyle(const SkTypeface* face,
- const SkFontStyle& fs) {
+ const SkFontStyle& fs) const {
return this->onMatchFaceStyle(face, fs);
}
-SkTypeface* SkFontMgr::createFromData(SkData* data, int ttcIndex) {
+SkTypeface* SkFontMgr::createFromData(SkData* data, int ttcIndex) const {
if (NULL == data) {
return NULL;
}
return this->onCreateFromData(data, ttcIndex);
}
-SkTypeface* SkFontMgr::createFromStream(SkStream* stream, int ttcIndex) {
+SkTypeface* SkFontMgr::createFromStream(SkStream* stream, int ttcIndex) const {
if (NULL == stream) {
return NULL;
}
return this->onCreateFromStream(stream, ttcIndex);
}
-SkTypeface* SkFontMgr::createFromFile(const char path[], int ttcIndex) {
+SkTypeface* SkFontMgr::createFromFile(const char path[], int ttcIndex) const {
if (NULL == path) {
return NULL;
}
@@ -183,23 +194,18 @@ SkTypeface* SkFontMgr::createFromFile(const char path[], int ttcIndex) {
}
SkTypeface* SkFontMgr::legacyCreateTypeface(const char familyName[],
- unsigned styleBits) {
+ unsigned styleBits) const {
return this->onLegacyCreateTypeface(familyName, styleBits);
}
-void set_up_default(SkFontMgr** singleton) {
- *singleton = SkFontMgr::Factory();
- // we never want to return NULL
- if (NULL == *singleton) {
- *singleton = SkNEW(SkEmptyFontMgr);
- }
+SkFontMgr* SkFontMgr::CreateDefault() {
+ SkFontMgr* fm = SkFontMgr::Factory();
+ return fm ? fm : SkNEW(SkEmptyFontMgr);
}
SkFontMgr* SkFontMgr::RefDefault() {
- static SkFontMgr* gFM = NULL;
- SK_DECLARE_STATIC_ONCE(once);
- SkOnce(&once, set_up_default, &gFM);
- return SkRef(gFM);
+ SK_DECLARE_STATIC_LAZY_PTR(SkFontMgr, singleton, CreateDefault);
+ return SkRef(singleton.get());
}
//////////////////////////////////////////////////////////////////////////
diff --git a/chromium/third_party/skia/src/core/SkGeometry.cpp b/chromium/third_party/skia/src/core/SkGeometry.cpp
index 11d52b594e3..646dfb05b9d 100644
--- a/chromium/third_party/skia/src/core/SkGeometry.cpp
+++ b/chromium/third_party/skia/src/core/SkGeometry.cpp
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -6,12 +5,12 @@
* found in the LICENSE file.
*/
-
#include "SkGeometry.h"
-#include "Sk64.h"
#include "SkMatrix.h"
-bool SkXRayCrossesLine(const SkXRay& pt, const SkPoint pts[2], bool* ambiguous) {
+bool SkXRayCrossesLine(const SkXRay& pt,
+ const SkPoint pts[2],
+ bool* ambiguous) {
if (ambiguous) {
*ambiguous = false;
}
@@ -68,60 +67,45 @@ bool SkXRayCrossesLine(const SkXRay& pt, const SkPoint pts[2], bool* ambiguous)
involving integer multiplies by 2 or 3, but fewer calls to SkScalarMul.
May also introduce overflow of fixed when we compute our setup.
*/
-#ifdef SK_SCALAR_IS_FIXED
- #define DIRECT_EVAL_OF_POLYNOMIALS
-#endif
+// #define DIRECT_EVAL_OF_POLYNOMIALS
////////////////////////////////////////////////////////////////////////
-#ifdef SK_SCALAR_IS_FIXED
- static int is_not_monotonic(int a, int b, int c, int d)
- {
- return (((a - b) | (b - c) | (c - d)) & ((b - a) | (c - b) | (d - c))) >> 31;
- }
-
- static int is_not_monotonic(int a, int b, int c)
- {
- return (((a - b) | (b - c)) & ((b - a) | (c - b))) >> 31;
- }
-#else
- static int is_not_monotonic(float a, float b, float c)
- {
- float ab = a - b;
- float bc = b - c;
- if (ab < 0)
- bc = -bc;
- return ab == 0 || bc < 0;
+static int is_not_monotonic(SkScalar a, SkScalar b, SkScalar c) {
+ SkScalar ab = a - b;
+ SkScalar bc = b - c;
+ if (ab < 0) {
+ bc = -bc;
}
-#endif
+ return ab == 0 || bc < 0;
+}
////////////////////////////////////////////////////////////////////////
-static bool is_unit_interval(SkScalar x)
-{
+static bool is_unit_interval(SkScalar x) {
return x > 0 && x < SK_Scalar1;
}
-static int valid_unit_divide(SkScalar numer, SkScalar denom, SkScalar* ratio)
-{
+static int valid_unit_divide(SkScalar numer, SkScalar denom, SkScalar* ratio) {
SkASSERT(ratio);
- if (numer < 0)
- {
+ if (numer < 0) {
numer = -numer;
denom = -denom;
}
- if (denom == 0 || numer == 0 || numer >= denom)
+ if (denom == 0 || numer == 0 || numer >= denom) {
return 0;
+ }
SkScalar r = SkScalarDiv(numer, denom);
if (SkScalarIsNaN(r)) {
return 0;
}
SkASSERT(r >= 0 && r < SK_Scalar1);
- if (r == 0) // catch underflow if numer <<<< denom
+ if (r == 0) { // catch underflow if numer <<<< denom
return 0;
+ }
*ratio = r;
return 1;
}
@@ -132,38 +116,25 @@ static int valid_unit_divide(SkScalar numer, SkScalar denom, SkScalar* ratio)
x1 = Q / A
x2 = C / Q
*/
-int SkFindUnitQuadRoots(SkScalar A, SkScalar B, SkScalar C, SkScalar roots[2])
-{
+int SkFindUnitQuadRoots(SkScalar A, SkScalar B, SkScalar C, SkScalar roots[2]) {
SkASSERT(roots);
- if (A == 0)
+ if (A == 0) {
return valid_unit_divide(-C, B, roots);
+ }
SkScalar* r = roots;
-#ifdef SK_SCALAR_IS_FLOAT
- float R = B*B - 4*A*C;
+ SkScalar R = B*B - 4*A*C;
if (R < 0 || SkScalarIsNaN(R)) { // complex roots
return 0;
}
- R = sk_float_sqrt(R);
-#else
- Sk64 RR, tmp;
-
- RR.setMul(B,B);
- tmp.setMul(A,C);
- tmp.shiftLeft(2);
- RR.sub(tmp);
- if (RR.isNeg())
- return 0;
- SkFixed R = RR.getSqrt();
-#endif
+ R = SkScalarSqrt(R);
SkScalar Q = (B < 0) ? -(B-R)/2 : -(B+R)/2;
r += valid_unit_divide(Q, A, r);
r += valid_unit_divide(C, Q, r);
- if (r - roots == 2)
- {
+ if (r - roots == 2) {
if (roots[0] > roots[1])
SkTSwap<SkScalar>(roots[0], roots[1]);
else if (roots[0] == roots[1]) // nearly-equal?
@@ -172,28 +143,10 @@ int SkFindUnitQuadRoots(SkScalar A, SkScalar B, SkScalar C, SkScalar roots[2])
return (int)(r - roots);
}
-#ifdef SK_SCALAR_IS_FIXED
-/** Trim A/B/C down so that they are all <= 32bits
- and then call SkFindUnitQuadRoots()
-*/
-static int Sk64FindFixedQuadRoots(const Sk64& A, const Sk64& B, const Sk64& C, SkFixed roots[2])
-{
- int na = A.shiftToMake32();
- int nb = B.shiftToMake32();
- int nc = C.shiftToMake32();
-
- int shift = SkMax32(na, SkMax32(nb, nc));
- SkASSERT(shift >= 0);
-
- return SkFindUnitQuadRoots(A.getShiftRight(shift), B.getShiftRight(shift), C.getShiftRight(shift), roots);
-}
-#endif
-
-/////////////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
-static SkScalar eval_quad(const SkScalar src[], SkScalar t)
-{
+static SkScalar eval_quad(const SkScalar src[], SkScalar t) {
SkASSERT(src);
SkASSERT(t >= 0 && t <= SK_Scalar1);
@@ -209,52 +162,50 @@ static SkScalar eval_quad(const SkScalar src[], SkScalar t)
#endif
}
-static SkScalar eval_quad_derivative(const SkScalar src[], SkScalar t)
-{
+static SkScalar eval_quad_derivative(const SkScalar src[], SkScalar t) {
SkScalar A = src[4] - 2 * src[2] + src[0];
SkScalar B = src[2] - src[0];
return 2 * SkScalarMulAdd(A, t, B);
}
-static SkScalar eval_quad_derivative_at_half(const SkScalar src[])
-{
+static SkScalar eval_quad_derivative_at_half(const SkScalar src[]) {
SkScalar A = src[4] - 2 * src[2] + src[0];
SkScalar B = src[2] - src[0];
return A + 2 * B;
}
-void SkEvalQuadAt(const SkPoint src[3], SkScalar t, SkPoint* pt, SkVector* tangent)
-{
+void SkEvalQuadAt(const SkPoint src[3], SkScalar t, SkPoint* pt,
+ SkVector* tangent) {
SkASSERT(src);
SkASSERT(t >= 0 && t <= SK_Scalar1);
- if (pt)
+ if (pt) {
pt->set(eval_quad(&src[0].fX, t), eval_quad(&src[0].fY, t));
- if (tangent)
+ }
+ if (tangent) {
tangent->set(eval_quad_derivative(&src[0].fX, t),
eval_quad_derivative(&src[0].fY, t));
+ }
}
-void SkEvalQuadAtHalf(const SkPoint src[3], SkPoint* pt, SkVector* tangent)
-{
+void SkEvalQuadAtHalf(const SkPoint src[3], SkPoint* pt, SkVector* tangent) {
SkASSERT(src);
- if (pt)
- {
+ if (pt) {
SkScalar x01 = SkScalarAve(src[0].fX, src[1].fX);
SkScalar y01 = SkScalarAve(src[0].fY, src[1].fY);
SkScalar x12 = SkScalarAve(src[1].fX, src[2].fX);
SkScalar y12 = SkScalarAve(src[1].fY, src[2].fY);
pt->set(SkScalarAve(x01, x12), SkScalarAve(y01, y12));
}
- if (tangent)
+ if (tangent) {
tangent->set(eval_quad_derivative_at_half(&src[0].fX),
eval_quad_derivative_at_half(&src[0].fY));
+ }
}
-static void interp_quad_coords(const SkScalar* src, SkScalar* dst, SkScalar t)
-{
+static void interp_quad_coords(const SkScalar* src, SkScalar* dst, SkScalar t) {
SkScalar ab = SkScalarInterp(src[0], src[2], t);
SkScalar bc = SkScalarInterp(src[2], src[4], t);
@@ -265,16 +216,14 @@ static void interp_quad_coords(const SkScalar* src, SkScalar* dst, SkScalar t)
dst[8] = src[4];
}
-void SkChopQuadAt(const SkPoint src[3], SkPoint dst[5], SkScalar t)
-{
+void SkChopQuadAt(const SkPoint src[3], SkPoint dst[5], SkScalar t) {
SkASSERT(t > 0 && t < SK_Scalar1);
interp_quad_coords(&src[0].fX, &dst[0].fX, t);
interp_quad_coords(&src[0].fY, &dst[0].fY, t);
}
-void SkChopQuadAtHalf(const SkPoint src[3], SkPoint dst[5])
-{
+void SkChopQuadAtHalf(const SkPoint src[3], SkPoint dst[5]) {
SkScalar x01 = SkScalarAve(src[0].fX, src[1].fX);
SkScalar y01 = SkScalarAve(src[0].fY, src[1].fY);
SkScalar x12 = SkScalarAve(src[1].fX, src[2].fX);
@@ -292,53 +241,31 @@ void SkChopQuadAtHalf(const SkPoint src[3], SkPoint dst[5])
B = 2(b - a)
Solve for t, only if it fits between 0 < t < 1
*/
-int SkFindQuadExtrema(SkScalar a, SkScalar b, SkScalar c, SkScalar tValue[1])
-{
+int SkFindQuadExtrema(SkScalar a, SkScalar b, SkScalar c, SkScalar tValue[1]) {
/* At + B == 0
t = -B / A
*/
-#ifdef SK_SCALAR_IS_FIXED
- return is_not_monotonic(a, b, c) && valid_unit_divide(a - b, a - b - b + c, tValue);
-#else
return valid_unit_divide(a - b, a - b - b + c, tValue);
-#endif
}
-static inline void flatten_double_quad_extrema(SkScalar coords[14])
-{
+static inline void flatten_double_quad_extrema(SkScalar coords[14]) {
coords[2] = coords[6] = coords[4];
}
/* Returns 0 for 1 quad, and 1 for two quads, either way the answer is
stored in dst[]. Guarantees that the 1/2 quads will be monotonic.
*/
-int SkChopQuadAtYExtrema(const SkPoint src[3], SkPoint dst[5])
-{
+int SkChopQuadAtYExtrema(const SkPoint src[3], SkPoint dst[5]) {
SkASSERT(src);
SkASSERT(dst);
-#if 0
- static bool once = true;
- if (once)
- {
- once = false;
- SkPoint s[3] = { 0, 26398, 0, 26331, 0, 20621428 };
- SkPoint d[6];
-
- int n = SkChopQuadAtYExtrema(s, d);
- SkDebugf("chop=%d, Y=[%x %x %x %x %x %x]\n", n, d[0].fY, d[1].fY, d[2].fY, d[3].fY, d[4].fY, d[5].fY);
- }
-#endif
-
SkScalar a = src[0].fY;
SkScalar b = src[1].fY;
SkScalar c = src[2].fY;
- if (is_not_monotonic(a, b, c))
- {
+ if (is_not_monotonic(a, b, c)) {
SkScalar tValue;
- if (valid_unit_divide(a - b, a - b - b + c, &tValue))
- {
+ if (valid_unit_divide(a - b, a - b - b + c, &tValue)) {
SkChopQuadAt(src, dst, tValue);
flatten_double_quad_extrema(&dst[0].fY);
return 1;
@@ -356,8 +283,7 @@ int SkChopQuadAtYExtrema(const SkPoint src[3], SkPoint dst[5])
/* Returns 0 for 1 quad, and 1 for two quads, either way the answer is
stored in dst[]. Guarantees that the 1/2 quads will be monotonic.
*/
-int SkChopQuadAtXExtrema(const SkPoint src[3], SkPoint dst[5])
-{
+int SkChopQuadAtXExtrema(const SkPoint src[3], SkPoint dst[5]) {
SkASSERT(src);
SkASSERT(dst);
@@ -394,43 +320,18 @@ int SkChopQuadAtXExtrema(const SkPoint src[3], SkPoint dst[5])
//
// t = - (Ax Bx + Ay By) / (Bx ^ 2 + By ^ 2)
//
-float SkFindQuadMaxCurvature(const SkPoint src[3]) {
+SkScalar SkFindQuadMaxCurvature(const SkPoint src[3]) {
SkScalar Ax = src[1].fX - src[0].fX;
SkScalar Ay = src[1].fY - src[0].fY;
SkScalar Bx = src[0].fX - src[1].fX - src[1].fX + src[2].fX;
SkScalar By = src[0].fY - src[1].fY - src[1].fY + src[2].fY;
SkScalar t = 0; // 0 means don't chop
-#ifdef SK_SCALAR_IS_FLOAT
(void)valid_unit_divide(-(Ax * Bx + Ay * By), Bx * Bx + By * By, &t);
-#else
- // !!! should I use SkFloat here? seems like it
- Sk64 numer, denom, tmp;
-
- numer.setMul(Ax, -Bx);
- tmp.setMul(Ay, -By);
- numer.add(tmp);
-
- if (numer.isPos()) // do nothing if numer <= 0
- {
- denom.setMul(Bx, Bx);
- tmp.setMul(By, By);
- denom.add(tmp);
- SkASSERT(!denom.isNeg());
- if (numer < denom)
- {
- t = numer.getFixedDiv(denom);
- SkASSERT(t >= 0 && t <= SK_Fixed1); // assert that we're numerically stable (ha!)
- if ((unsigned)t >= SK_Fixed1) // runtime check for numerical stability
- t = 0; // ignore the chop
- }
- }
-#endif
return t;
}
-int SkChopQuadAtMaxCurvature(const SkPoint src[3], SkPoint dst[5])
-{
+int SkChopQuadAtMaxCurvature(const SkPoint src[3], SkPoint dst[5]) {
SkScalar t = SkFindQuadMaxCurvature(src);
if (t == 0) {
memcpy(dst, src, 3 * sizeof(SkPoint));
@@ -441,11 +342,7 @@ int SkChopQuadAtMaxCurvature(const SkPoint src[3], SkPoint dst[5])
}
}
-#ifdef SK_SCALAR_IS_FLOAT
- #define SK_ScalarTwoThirds (0.666666666f)
-#else
- #define SK_ScalarTwoThirds ((SkFixed)(43691))
-#endif
+#define SK_ScalarTwoThirds (0.666666666f)
void SkConvertQuadToCubic(const SkPoint src[3], SkPoint dst[4]) {
const SkScalar scale = SK_ScalarTwoThirds;
@@ -457,35 +354,35 @@ void SkConvertQuadToCubic(const SkPoint src[3], SkPoint dst[4]) {
dst[3] = src[2];
}
-////////////////////////////////////////////////////////////////////////////////////////
-///// CUBICS // CUBICS // CUBICS // CUBICS // CUBICS // CUBICS // CUBICS // CUBICS /////
-////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+///// CUBICS // CUBICS // CUBICS // CUBICS // CUBICS // CUBICS // CUBICS /////
+//////////////////////////////////////////////////////////////////////////////
-static void get_cubic_coeff(const SkScalar pt[], SkScalar coeff[4])
-{
+static void get_cubic_coeff(const SkScalar pt[], SkScalar coeff[4]) {
coeff[0] = pt[6] + 3*(pt[2] - pt[4]) - pt[0];
coeff[1] = 3*(pt[4] - pt[2] - pt[2] + pt[0]);
coeff[2] = 3*(pt[2] - pt[0]);
coeff[3] = pt[0];
}
-void SkGetCubicCoeff(const SkPoint pts[4], SkScalar cx[4], SkScalar cy[4])
-{
+void SkGetCubicCoeff(const SkPoint pts[4], SkScalar cx[4], SkScalar cy[4]) {
SkASSERT(pts);
- if (cx)
+ if (cx) {
get_cubic_coeff(&pts[0].fX, cx);
- if (cy)
+ }
+ if (cy) {
get_cubic_coeff(&pts[0].fY, cy);
+ }
}
-static SkScalar eval_cubic(const SkScalar src[], SkScalar t)
-{
+static SkScalar eval_cubic(const SkScalar src[], SkScalar t) {
SkASSERT(src);
SkASSERT(t >= 0 && t <= SK_Scalar1);
- if (t == 0)
+ if (t == 0) {
return src[0];
+ }
#ifdef DIRECT_EVAL_OF_POLYNOMIALS
SkScalar D = src[0];
@@ -506,15 +403,13 @@ static SkScalar eval_cubic(const SkScalar src[], SkScalar t)
/** return At^2 + Bt + C
*/
-static SkScalar eval_quadratic(SkScalar A, SkScalar B, SkScalar C, SkScalar t)
-{
+static SkScalar eval_quadratic(SkScalar A, SkScalar B, SkScalar C, SkScalar t) {
SkASSERT(t >= 0 && t <= SK_Scalar1);
return SkScalarMulAdd(SkScalarMulAdd(A, t, B), t, C);
}
-static SkScalar eval_cubic_derivative(const SkScalar src[], SkScalar t)
-{
+static SkScalar eval_cubic_derivative(const SkScalar src[], SkScalar t) {
SkScalar A = src[6] + 3*(src[2] - src[4]) - src[0];
SkScalar B = 2*(src[4] - 2 * src[2] + src[0]);
SkScalar C = src[2] - src[0];
@@ -522,27 +417,29 @@ static SkScalar eval_cubic_derivative(const SkScalar src[], SkScalar t)
return eval_quadratic(A, B, C, t);
}
-static SkScalar eval_cubic_2ndDerivative(const SkScalar src[], SkScalar t)
-{
+static SkScalar eval_cubic_2ndDerivative(const SkScalar src[], SkScalar t) {
SkScalar A = src[6] + 3*(src[2] - src[4]) - src[0];
SkScalar B = src[4] - 2 * src[2] + src[0];
return SkScalarMulAdd(A, t, B);
}
-void SkEvalCubicAt(const SkPoint src[4], SkScalar t, SkPoint* loc, SkVector* tangent, SkVector* curvature)
-{
+void SkEvalCubicAt(const SkPoint src[4], SkScalar t, SkPoint* loc,
+ SkVector* tangent, SkVector* curvature) {
SkASSERT(src);
SkASSERT(t >= 0 && t <= SK_Scalar1);
- if (loc)
+ if (loc) {
loc->set(eval_cubic(&src[0].fX, t), eval_cubic(&src[0].fY, t));
- if (tangent)
+ }
+ if (tangent) {
tangent->set(eval_cubic_derivative(&src[0].fX, t),
eval_cubic_derivative(&src[0].fY, t));
- if (curvature)
+ }
+ if (curvature) {
curvature->set(eval_cubic_2ndDerivative(&src[0].fX, t),
eval_cubic_2ndDerivative(&src[0].fY, t));
+ }
}
/** Cubic'(t) = At^2 + Bt + C, where
@@ -551,13 +448,8 @@ void SkEvalCubicAt(const SkPoint src[4], SkScalar t, SkPoint* loc, SkVector* tan
C = 3(b - a)
Solve for t, keeping only those that fit betwee 0 < t < 1
*/
-int SkFindCubicExtrema(SkScalar a, SkScalar b, SkScalar c, SkScalar d, SkScalar tValues[2])
-{
-#ifdef SK_SCALAR_IS_FIXED
- if (!is_not_monotonic(a, b, c, d))
- return 0;
-#endif
-
+int SkFindCubicExtrema(SkScalar a, SkScalar b, SkScalar c, SkScalar d,
+ SkScalar tValues[2]) {
// we divide A,B,C by 3 to simplify
SkScalar A = d - a + 3*(b - c);
SkScalar B = 2*(a - b - b + c);
@@ -566,8 +458,8 @@ int SkFindCubicExtrema(SkScalar a, SkScalar b, SkScalar c, SkScalar d, SkScalar
return SkFindUnitQuadRoots(A, B, C, tValues);
}
-static void interp_cubic_coords(const SkScalar* src, SkScalar* dst, SkScalar t)
-{
+static void interp_cubic_coords(const SkScalar* src, SkScalar* dst,
+ SkScalar t) {
SkScalar ab = SkScalarInterp(src[0], src[2], t);
SkScalar bc = SkScalarInterp(src[2], src[4], t);
SkScalar cd = SkScalarInterp(src[4], src[6], t);
@@ -584,8 +476,7 @@ static void interp_cubic_coords(const SkScalar* src, SkScalar* dst, SkScalar t)
dst[12] = src[6];
}
-void SkChopCubicAt(const SkPoint src[4], SkPoint dst[7], SkScalar t)
-{
+void SkChopCubicAt(const SkPoint src[4], SkPoint dst[7], SkScalar t) {
SkASSERT(t > 0 && t < SK_Scalar1);
interp_cubic_coords(&src[0].fX, &dst[0].fX, t);
@@ -615,8 +506,8 @@ void SkChopCubicAt(const SkPoint src[4], SkPoint dst[7], SkScalar t)
}
*/
-void SkChopCubicAt(const SkPoint src[4], SkPoint dst[], const SkScalar tValues[], int roots)
-{
+void SkChopCubicAt(const SkPoint src[4], SkPoint dst[],
+ const SkScalar tValues[], int roots) {
#ifdef SK_DEBUG
{
for (int i = 0; i < roots - 1; i++)
@@ -628,20 +519,18 @@ void SkChopCubicAt(const SkPoint src[4], SkPoint dst[], const SkScalar tValues[]
}
#endif
- if (dst)
- {
- if (roots == 0) // nothing to chop
+ if (dst) {
+ if (roots == 0) { // nothing to chop
memcpy(dst, src, 4*sizeof(SkPoint));
- else
- {
+ } else {
SkScalar t = tValues[0];
SkPoint tmp[4];
- for (int i = 0; i < roots; i++)
- {
+ for (int i = 0; i < roots; i++) {
SkChopCubicAt(src, dst, t);
- if (i == roots - 1)
+ if (i == roots - 1) {
break;
+ }
dst += 3;
// have src point to the remaining cubic (after the chop)
@@ -660,8 +549,7 @@ void SkChopCubicAt(const SkPoint src[4], SkPoint dst[], const SkScalar tValues[]
}
}
-void SkChopCubicAtHalf(const SkPoint src[4], SkPoint dst[7])
-{
+void SkChopCubicAtHalf(const SkPoint src[4], SkPoint dst[7]) {
SkScalar x01 = SkScalarAve(src[0].fX, src[1].fX);
SkScalar y01 = SkScalarAve(src[0].fY, src[1].fY);
SkScalar x12 = SkScalarAve(src[1].fX, src[2].fX);
@@ -683,14 +571,13 @@ void SkChopCubicAtHalf(const SkPoint src[4], SkPoint dst[7])
dst[6] = src[3];
}
-static void flatten_double_cubic_extrema(SkScalar coords[14])
-{
+static void flatten_double_cubic_extrema(SkScalar coords[14]) {
coords[4] = coords[8] = coords[6];
}
/** Given 4 points on a cubic bezier, chop it into 1, 2, 3 beziers such that
- the resulting beziers are monotonic in Y. This is called by the scan converter.
- Depending on what is returned, dst[] is treated as follows
+ the resulting beziers are monotonic in Y. This is called by the scan
+ converter. Depending on what is returned, dst[] is treated as follows:
0 dst[0..3] is the original cubic
1 dst[0..3] and dst[3..6] are the two new cubics
2 dst[0..3], dst[3..6], dst[6..9] are the three new cubics
@@ -739,56 +626,35 @@ int SkChopCubicAtXExtrema(const SkPoint src[4], SkPoint dst[10]) {
C = d - 3c + 3b - a
(BxCy - ByCx)t^2 + (AxCy - AyCx)t + AxBy - AyBx == 0
*/
-int SkFindCubicInflections(const SkPoint src[4], SkScalar tValues[])
-{
+int SkFindCubicInflections(const SkPoint src[4], SkScalar tValues[]) {
SkScalar Ax = src[1].fX - src[0].fX;
SkScalar Ay = src[1].fY - src[0].fY;
SkScalar Bx = src[2].fX - 2 * src[1].fX + src[0].fX;
SkScalar By = src[2].fY - 2 * src[1].fY + src[0].fY;
SkScalar Cx = src[3].fX + 3 * (src[1].fX - src[2].fX) - src[0].fX;
SkScalar Cy = src[3].fY + 3 * (src[1].fY - src[2].fY) - src[0].fY;
- int count;
-#ifdef SK_SCALAR_IS_FLOAT
- count = SkFindUnitQuadRoots(Bx*Cy - By*Cx, Ax*Cy - Ay*Cx, Ax*By - Ay*Bx, tValues);
-#else
- Sk64 A, B, C, tmp;
-
- A.setMul(Bx, Cy);
- tmp.setMul(By, Cx);
- A.sub(tmp);
-
- B.setMul(Ax, Cy);
- tmp.setMul(Ay, Cx);
- B.sub(tmp);
-
- C.setMul(Ax, By);
- tmp.setMul(Ay, Bx);
- C.sub(tmp);
-
- count = Sk64FindFixedQuadRoots(A, B, C, tValues);
-#endif
-
- return count;
+ return SkFindUnitQuadRoots(Bx*Cy - By*Cx,
+ Ax*Cy - Ay*Cx,
+ Ax*By - Ay*Bx,
+ tValues);
}
-int SkChopCubicAtInflections(const SkPoint src[], SkPoint dst[10])
-{
+int SkChopCubicAtInflections(const SkPoint src[], SkPoint dst[10]) {
SkScalar tValues[2];
int count = SkFindCubicInflections(src, tValues);
- if (dst)
- {
- if (count == 0)
+ if (dst) {
+ if (count == 0) {
memcpy(dst, src, 4 * sizeof(SkPoint));
- else
+ } else {
SkChopCubicAt(src, dst, tValues, count);
+ }
}
return count + 1;
}
-template <typename T> void bubble_sort(T array[], int count)
-{
+template <typename T> void bubble_sort(T array[], int count) {
for (int i = count - 1; i > 0; --i)
for (int j = i; j > 0; --j)
if (array[j] < array[j-1])
@@ -799,47 +665,11 @@ template <typename T> void bubble_sort(T array[], int count)
}
}
-#include "SkFP.h"
-
-// newton refinement
-#if 0
-static SkScalar refine_cubic_root(const SkFP coeff[4], SkScalar root)
-{
- // x1 = x0 - f(t) / f'(t)
-
- SkFP T = SkScalarToFloat(root);
- SkFP N, D;
-
- // f' = 3*coeff[0]*T^2 + 2*coeff[1]*T + coeff[2]
- D = SkFPMul(SkFPMul(coeff[0], SkFPMul(T,T)), 3);
- D = SkFPAdd(D, SkFPMulInt(SkFPMul(coeff[1], T), 2));
- D = SkFPAdd(D, coeff[2]);
-
- if (D == 0)
- return root;
-
- // f = coeff[0]*T^3 + coeff[1]*T^2 + coeff[2]*T + coeff[3]
- N = SkFPMul(SkFPMul(SkFPMul(T, T), T), coeff[0]);
- N = SkFPAdd(N, SkFPMul(SkFPMul(T, T), coeff[1]));
- N = SkFPAdd(N, SkFPMul(T, coeff[2]));
- N = SkFPAdd(N, coeff[3]);
-
- if (N)
- {
- SkScalar delta = SkFPToScalar(SkFPDiv(N, D));
-
- if (delta)
- root -= delta;
- }
- return root;
-}
-#endif
-
/**
* Given an array and count, remove all pair-wise duplicates from the array,
* keeping the existing sorting, and return the new count
*/
-static int collaps_duplicates(float array[], int count) {
+static int collaps_duplicates(SkScalar array[], int count) {
for (int n = count; n > 1; --n) {
if (array[0] == array[1]) {
for (int i = 1; i < n; ++i) {
@@ -861,15 +691,15 @@ static void test_collaps_duplicates() {
static bool gOnce;
if (gOnce) { return; }
gOnce = true;
- const float src0[] = { 0 };
- const float src1[] = { 0, 0 };
- const float src2[] = { 0, 1 };
- const float src3[] = { 0, 0, 0 };
- const float src4[] = { 0, 0, 1 };
- const float src5[] = { 0, 1, 1 };
- const float src6[] = { 0, 1, 2 };
+ const SkScalar src0[] = { 0 };
+ const SkScalar src1[] = { 0, 0 };
+ const SkScalar src2[] = { 0, 1 };
+ const SkScalar src3[] = { 0, 0, 0 };
+ const SkScalar src4[] = { 0, 0, 1 };
+ const SkScalar src5[] = { 0, 1, 1 };
+ const SkScalar src6[] = { 0, 1, 2 };
const struct {
- const float* fData;
+ const SkScalar* fData;
int fCount;
int fCollapsedCount;
} data[] = {
@@ -882,7 +712,7 @@ static void test_collaps_duplicates() {
{ TEST_COLLAPS_ENTRY(src6), 3 },
};
for (size_t i = 0; i < SK_ARRAY_COUNT(data); ++i) {
- float dst[3];
+ SkScalar dst[3];
memcpy(dst, data[i].fData, data[i].fCount * sizeof(dst[0]));
int count = collaps_duplicates(dst, data[i].fCount);
SkASSERT(data[i].fCollapsedCount == count);
@@ -893,9 +723,9 @@ static void test_collaps_duplicates() {
}
#endif
-#if defined _WIN32 && _MSC_VER >= 1300 && defined SK_SCALAR_IS_FIXED // disable warning : unreachable code if building fixed point for windows desktop
-#pragma warning ( disable : 4702 )
-#endif
+static SkScalar SkScalarCubeRoot(SkScalar x) {
+ return SkScalarPow(x, 0.3333333f);
+}
/* Solve coeff(t) == 0, returning the number of roots that
lie withing 0 < t < 1.
@@ -904,59 +734,47 @@ static void test_collaps_duplicates() {
Eliminates repeated roots (so that all tValues are distinct, and are always
in increasing order.
*/
-static int solve_cubic_polynomial(const SkFP coeff[4], SkScalar tValues[3])
-{
-#ifndef SK_SCALAR_IS_FLOAT
- return 0; // this is not yet implemented for software float
-#endif
-
- if (SkScalarNearlyZero(coeff[0])) // we're just a quadratic
- {
+static int solve_cubic_poly(const SkScalar coeff[4], SkScalar tValues[3]) {
+ if (SkScalarNearlyZero(coeff[0])) { // we're just a quadratic
return SkFindUnitQuadRoots(coeff[1], coeff[2], coeff[3], tValues);
}
- SkFP a, b, c, Q, R;
+ SkScalar a, b, c, Q, R;
{
SkASSERT(coeff[0] != 0);
- SkFP inva = SkFPInvert(coeff[0]);
- a = SkFPMul(coeff[1], inva);
- b = SkFPMul(coeff[2], inva);
- c = SkFPMul(coeff[3], inva);
+ SkScalar inva = SkScalarInvert(coeff[0]);
+ a = coeff[1] * inva;
+ b = coeff[2] * inva;
+ c = coeff[3] * inva;
}
- Q = SkFPDivInt(SkFPSub(SkFPMul(a,a), SkFPMulInt(b, 3)), 9);
-// R = (2*a*a*a - 9*a*b + 27*c) / 54;
- R = SkFPMulInt(SkFPMul(SkFPMul(a, a), a), 2);
- R = SkFPSub(R, SkFPMulInt(SkFPMul(a, b), 9));
- R = SkFPAdd(R, SkFPMulInt(c, 27));
- R = SkFPDivInt(R, 54);
+ Q = (a*a - b*3) / 9;
+ R = (2*a*a*a - 9*a*b + 27*c) / 54;
- SkFP Q3 = SkFPMul(SkFPMul(Q, Q), Q);
- SkFP R2MinusQ3 = SkFPSub(SkFPMul(R,R), Q3);
- SkFP adiv3 = SkFPDivInt(a, 3);
+ SkScalar Q3 = Q * Q * Q;
+ SkScalar R2MinusQ3 = R * R - Q3;
+ SkScalar adiv3 = a / 3;
SkScalar* roots = tValues;
SkScalar r;
- if (SkFPLT(R2MinusQ3, 0)) // we have 3 real roots
- {
-#ifdef SK_SCALAR_IS_FLOAT
- float theta = sk_float_acos(R / sk_float_sqrt(Q3));
- float neg2RootQ = -2 * sk_float_sqrt(Q);
+ if (R2MinusQ3 < 0) { // we have 3 real roots
+ SkScalar theta = SkScalarACos(R / SkScalarSqrt(Q3));
+ SkScalar neg2RootQ = -2 * SkScalarSqrt(Q);
- r = neg2RootQ * sk_float_cos(theta/3) - adiv3;
- if (is_unit_interval(r))
+ r = neg2RootQ * SkScalarCos(theta/3) - adiv3;
+ if (is_unit_interval(r)) {
*roots++ = r;
-
- r = neg2RootQ * sk_float_cos((theta + 2*SK_ScalarPI)/3) - adiv3;
- if (is_unit_interval(r))
+ }
+ r = neg2RootQ * SkScalarCos((theta + 2*SK_ScalarPI)/3) - adiv3;
+ if (is_unit_interval(r)) {
*roots++ = r;
-
- r = neg2RootQ * sk_float_cos((theta - 2*SK_ScalarPI)/3) - adiv3;
- if (is_unit_interval(r))
+ }
+ r = neg2RootQ * SkScalarCos((theta - 2*SK_ScalarPI)/3) - adiv3;
+ if (is_unit_interval(r)) {
*roots++ = r;
-
+ }
SkDEBUGCODE(test_collaps_duplicates();)
// now sort the roots
@@ -965,20 +783,19 @@ static int solve_cubic_polynomial(const SkFP coeff[4], SkScalar tValues[3])
bubble_sort(tValues, count);
count = collaps_duplicates(tValues, count);
roots = tValues + count; // so we compute the proper count below
-#endif
- }
- else // we have 1 real root
- {
- SkFP A = SkFPAdd(SkFPAbs(R), SkFPSqrt(R2MinusQ3));
- A = SkFPCubeRoot(A);
- if (SkFPGT(R, 0))
- A = SkFPNeg(A);
-
- if (A != 0)
- A = SkFPAdd(A, SkFPDiv(Q, A));
- r = SkFPToScalar(SkFPSub(A, adiv3));
- if (is_unit_interval(r))
+ } else { // we have 1 real root
+ SkScalar A = SkScalarAbs(R) + SkScalarSqrt(R2MinusQ3);
+ A = SkScalarCubeRoot(A);
+ if (R > 0) {
+ A = -A;
+ }
+ if (A != 0) {
+ A += Q / A;
+ }
+ r = A - adiv3;
+ if (is_unit_interval(r)) {
*roots++ = r;
+ }
}
return (int)(roots - tValues);
@@ -995,27 +812,17 @@ static int solve_cubic_polynomial(const SkFP coeff[4], SkScalar tValues[3])
F' dot F'' -> CCt^3 + 3BCt^2 + (2BB + CA)t + AB
*/
-static void formulate_F1DotF2(const SkScalar src[], SkFP coeff[4])
-{
+static void formulate_F1DotF2(const SkScalar src[], SkScalar coeff[4]) {
SkScalar a = src[2] - src[0];
SkScalar b = src[4] - 2 * src[2] + src[0];
SkScalar c = src[6] + 3 * (src[2] - src[4]) - src[0];
- SkFP A = SkScalarToFP(a);
- SkFP B = SkScalarToFP(b);
- SkFP C = SkScalarToFP(c);
-
- coeff[0] = SkFPMul(C, C);
- coeff[1] = SkFPMulInt(SkFPMul(B, C), 3);
- coeff[2] = SkFPMulInt(SkFPMul(B, B), 2);
- coeff[2] = SkFPAdd(coeff[2], SkFPMul(C, A));
- coeff[3] = SkFPMul(A, B);
+ coeff[0] = c * c;
+ coeff[1] = 3 * b * c;
+ coeff[2] = 2 * b * b + c * a;
+ coeff[3] = a * b;
}
-// EXPERIMENTAL: can set this to zero to accept all t-values 0 < t < 1
-//#define kMinTValueForChopping (SK_Scalar1 / 256)
-#define kMinTValueForChopping 0
-
/* Looking for F' dot F'' == 0
A = b - a
@@ -1027,51 +834,54 @@ static void formulate_F1DotF2(const SkScalar src[], SkFP coeff[4])
F' dot F'' -> CCt^3 + 3BCt^2 + (2BB + CA)t + AB
*/
-int SkFindCubicMaxCurvature(const SkPoint src[4], SkScalar tValues[3])
-{
- SkFP coeffX[4], coeffY[4];
- int i;
+int SkFindCubicMaxCurvature(const SkPoint src[4], SkScalar tValues[3]) {
+ SkScalar coeffX[4], coeffY[4];
+ int i;
formulate_F1DotF2(&src[0].fX, coeffX);
formulate_F1DotF2(&src[0].fY, coeffY);
- for (i = 0; i < 4; i++)
- coeffX[i] = SkFPAdd(coeffX[i],coeffY[i]);
+ for (i = 0; i < 4; i++) {
+ coeffX[i] += coeffY[i];
+ }
SkScalar t[3];
- int count = solve_cubic_polynomial(coeffX, t);
+ int count = solve_cubic_poly(coeffX, t);
int maxCount = 0;
// now remove extrema where the curvature is zero (mins)
// !!!! need a test for this !!!!
- for (i = 0; i < count; i++)
- {
+ for (i = 0; i < count; i++) {
// if (not_min_curvature())
- if (t[i] > kMinTValueForChopping && t[i] < SK_Scalar1 - kMinTValueForChopping)
+ if (t[i] > 0 && t[i] < SK_Scalar1) {
tValues[maxCount++] = t[i];
+ }
}
return maxCount;
}
-int SkChopCubicAtMaxCurvature(const SkPoint src[4], SkPoint dst[13], SkScalar tValues[3])
-{
+int SkChopCubicAtMaxCurvature(const SkPoint src[4], SkPoint dst[13],
+ SkScalar tValues[3]) {
SkScalar t_storage[3];
- if (tValues == NULL)
+ if (tValues == NULL) {
tValues = t_storage;
+ }
int count = SkFindCubicMaxCurvature(src, tValues);
if (dst) {
- if (count == 0)
+ if (count == 0) {
memcpy(dst, src, 4 * sizeof(SkPoint));
- else
+ } else {
SkChopCubicAt(src, dst, tValues, count);
+ }
}
return count + 1;
}
-bool SkXRayCrossesMonotonicCubic(const SkXRay& pt, const SkPoint cubic[4], bool* ambiguous) {
+bool SkXRayCrossesMonotonicCubic(const SkXRay& pt, const SkPoint cubic[4],
+ bool* ambiguous) {
if (ambiguous) {
*ambiguous = false;
}
@@ -1158,7 +968,9 @@ bool SkXRayCrossesMonotonicCubic(const SkXRay& pt, const SkPoint cubic[4], bool*
return false;
}
-int SkNumXRayCrossingsForCubic(const SkXRay& pt, const SkPoint cubic[4], bool* ambiguous) {
+int SkNumXRayCrossingsForCubic(const SkXRay& pt,
+ const SkPoint cubic[4],
+ bool* ambiguous) {
int num_crossings = 0;
SkPoint monotonic_cubics[10];
int num_monotonic_cubics = SkChopCubicAtYExtrema(cubic, monotonic_cubics);
@@ -1166,32 +978,38 @@ int SkNumXRayCrossingsForCubic(const SkXRay& pt, const SkPoint cubic[4], bool* a
*ambiguous = false;
}
bool locally_ambiguous;
- if (SkXRayCrossesMonotonicCubic(pt, &monotonic_cubics[0], &locally_ambiguous))
+ if (SkXRayCrossesMonotonicCubic(pt,
+ &monotonic_cubics[0],
+ &locally_ambiguous))
++num_crossings;
if (ambiguous) {
*ambiguous |= locally_ambiguous;
}
if (num_monotonic_cubics > 0)
- if (SkXRayCrossesMonotonicCubic(pt, &monotonic_cubics[3], &locally_ambiguous))
+ if (SkXRayCrossesMonotonicCubic(pt,
+ &monotonic_cubics[3],
+ &locally_ambiguous))
++num_crossings;
if (ambiguous) {
*ambiguous |= locally_ambiguous;
}
if (num_monotonic_cubics > 1)
- if (SkXRayCrossesMonotonicCubic(pt, &monotonic_cubics[6], &locally_ambiguous))
+ if (SkXRayCrossesMonotonicCubic(pt,
+ &monotonic_cubics[6],
+ &locally_ambiguous))
++num_crossings;
if (ambiguous) {
*ambiguous |= locally_ambiguous;
}
return num_crossings;
}
-////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
/* Find t value for quadratic [a, b, c] = d.
Return 0 if there is no solution within [0, 1)
*/
-static SkScalar quad_solve(SkScalar a, SkScalar b, SkScalar c, SkScalar d)
-{
+static SkScalar quad_solve(SkScalar a, SkScalar b, SkScalar c, SkScalar d) {
// At^2 + Bt + C = d
SkScalar A = a - 2 * b + c;
SkScalar B = 2 * (b - a);
@@ -1209,8 +1027,8 @@ static SkScalar quad_solve(SkScalar a, SkScalar b, SkScalar c, SkScalar d)
Should only return false if the computed pos is the start of the curve
(i.e. root == 0)
*/
-static bool truncate_last_curve(const SkPoint quad[3], SkScalar x, SkScalar y, SkPoint* dest)
-{
+static bool truncate_last_curve(const SkPoint quad[3], SkScalar x, SkScalar y,
+ SkPoint* dest) {
const SkScalar* base;
SkScalar value;
@@ -1226,8 +1044,7 @@ static bool truncate_last_curve(const SkPoint quad[3], SkScalar x, SkScalar y, S
// root might return something outside of [0, 1)
SkScalar t = quad_solve(base[0], base[2], base[4], value);
- if (t > 0)
- {
+ if (t > 0) {
SkPoint tmp[5];
SkChopQuadAt(quad, tmp, t);
dest[0] = tmp[1];
@@ -1259,9 +1076,10 @@ static bool truncate_last_curve(const SkPoint quad[3], SkScalar x, SkScalar y, S
static const SkPoint gQuadCirclePts[kSkBuildQuadArcStorage] = {
// The mid point of the quadratic arc approximation is half way between the two
// control points. The float epsilon adjustment moves the on curve point out by
-// two bits, distributing the convex test error between the round rect approximation
-// and the convex cross product sign equality test.
-#define SK_MID_RRECT_OFFSET (SK_Scalar1 + SK_ScalarTanPIOver8 + FLT_EPSILON * 4) / 2
+// two bits, distributing the convex test error between the round rect
+// approximation and the convex cross product sign equality test.
+#define SK_MID_RRECT_OFFSET \
+ (SK_Scalar1 + SK_ScalarTanPIOver8 + FLT_EPSILON * 4) / 2
{ SK_Scalar1, 0 },
{ SK_Scalar1, SK_ScalarTanPIOver8 },
{ SK_MID_RRECT_OFFSET, SK_MID_RRECT_OFFSET },
@@ -1288,8 +1106,7 @@ static const SkPoint gQuadCirclePts[kSkBuildQuadArcStorage] = {
int SkBuildQuadArc(const SkVector& uStart, const SkVector& uStop,
SkRotationDirection dir, const SkMatrix* userMatrix,
- SkPoint quadPoints[])
-{
+ SkPoint quadPoints[]) {
// rotate by x,y so that uStart is (1.0)
SkScalar x = SkPoint::DotProduct(uStart, uStop);
SkScalar y = SkPoint::CrossProduct(uStart, uStop);
@@ -1310,45 +1127,37 @@ int SkBuildQuadArc(const SkVector& uStart, const SkVector& uStop,
quadPoints[0].set(SK_Scalar1, 0);
pointCount = 1;
} else {
- if (dir == kCCW_SkRotationDirection)
+ if (dir == kCCW_SkRotationDirection) {
y = -y;
-
+ }
// what octant (quadratic curve) is [xy] in?
int oct = 0;
bool sameSign = true;
- if (0 == y)
- {
+ if (0 == y) {
oct = 4; // 180
SkASSERT(SkScalarAbs(x + SK_Scalar1) <= SK_ScalarNearlyZero);
- }
- else if (0 == x)
- {
+ } else if (0 == x) {
SkASSERT(absY - SK_Scalar1 <= SK_ScalarNearlyZero);
- if (y > 0)
- oct = 2; // 90
- else
- oct = 6; // 270
- }
- else
- {
- if (y < 0)
+ oct = y > 0 ? 2 : 6; // 90 : 270
+ } else {
+ if (y < 0) {
oct += 4;
- if ((x < 0) != (y < 0))
- {
+ }
+ if ((x < 0) != (y < 0)) {
oct += 2;
sameSign = false;
}
- if ((absX < absY) == sameSign)
+ if ((absX < absY) == sameSign) {
oct += 1;
+ }
}
int wholeCount = oct << 1;
memcpy(quadPoints, gQuadCirclePts, (wholeCount + 1) * sizeof(SkPoint));
const SkPoint* arc = &gQuadCirclePts[wholeCount];
- if (truncate_last_curve(arc, x, y, &quadPoints[wholeCount + 1]))
- {
+ if (truncate_last_curve(arc, x, y, &quadPoints[wholeCount + 1])) {
wholeCount += 2;
}
pointCount = wholeCount + 1;
@@ -1367,8 +1176,16 @@ int SkBuildQuadArc(const SkVector& uStart, const SkVector& uStop,
return pointCount;
}
-///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+//
+// NURB representation for conics. Helpful explanations at:
+//
+// http://citeseerx.ist.psu.edu/viewdoc/
+// download?doi=10.1.1.44.5740&rep=rep1&type=ps
+// and
+// http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/NURBS/RB-conics.html
+//
// F = (A (1 - t)^2 + C t^2 + 2 B (1 - t) t w)
// ------------------------------------------
// ((1 - t)^2 + t^2 + 2 (1 - t) t w)
@@ -1378,12 +1195,6 @@ int SkBuildQuadArc(const SkVector& uStart, const SkVector& uStop,
// {t^2 (2 - 2 w), t (-2 + 2 w), 1}
//
-// Take the parametric specification for the conic (either X or Y) and return
-// in coeff[] the coefficients for the simple quadratic polynomial
-// coeff[0] for t^2
-// coeff[1] for t
-// coeff[2] for constant term
-//
static SkScalar conic_eval_pos(const SkScalar src[], SkScalar w, SkScalar t) {
SkASSERT(src);
SkASSERT(t >= 0 && t <= SK_Scalar1);
@@ -1415,7 +1226,9 @@ static SkScalar conic_eval_pos(const SkScalar src[], SkScalar w, SkScalar t) {
// coeff[1] for t^1
// coeff[2] for t^0
//
-static void conic_deriv_coeff(const SkScalar src[], SkScalar w, SkScalar coeff[3]) {
+static void conic_deriv_coeff(const SkScalar src[],
+ SkScalar w,
+ SkScalar coeff[3]) {
const SkScalar P20 = src[4] - src[0];
const SkScalar P10 = src[2] - src[0];
const SkScalar wP10 = w * P10;
@@ -1457,9 +1270,8 @@ struct SkP3D {
}
};
-// we just return the middle 3 points, since the first and last are dups of src
-//
-static void p3d_interp(const SkScalar src[3], SkScalar dst[3], SkScalar t) {
+// We only interpolate one dimension at a time (the first, at +0, +3, +6).
+static void p3d_interp(const SkScalar src[7], SkScalar dst[7], SkScalar t) {
SkScalar ab = SkScalarInterp(src[0], src[3], t);
SkScalar bc = SkScalarInterp(src[3], src[6], t);
dst[0] = ab;
@@ -1506,7 +1318,8 @@ void SkConic::chopAt(SkScalar t, SkConic dst[2]) const {
// or
// w1 /= sqrt(w0*w2)
//
- // However, in our case, we know that for dst[0], w0 == 1, and for dst[1], w2 == 1
+ // However, in our case, we know that for dst[0]:
+ // w0 == 1, and for dst[1], w2 == 1
//
SkScalar root = SkScalarSqrt(tmp2[1].fZ);
dst[0].fW = tmp2[0].fZ / root;
@@ -1648,3 +1461,8 @@ void SkConic::computeTightBounds(SkRect* bounds) const {
void SkConic::computeFastBounds(SkRect* bounds) const {
bounds->set(fPts, 3);
}
+
+bool SkConic::findMaxCurvature(SkScalar* t) const {
+ // TODO: Implement me
+ return false;
+}
diff --git a/chromium/third_party/skia/src/core/SkGeometry.h b/chromium/third_party/skia/src/core/SkGeometry.h
new file mode 100644
index 00000000000..119cfc68db5
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkGeometry.h
@@ -0,0 +1,316 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkGeometry_DEFINED
+#define SkGeometry_DEFINED
+
+#include "SkMatrix.h"
+
+/** An XRay is a half-line that runs from the specific point/origin to
+ +infinity in the X direction. e.g. XRay(3,5) is the half-line
+ (3,5)....(infinity, 5)
+ */
+typedef SkPoint SkXRay;
+
+/** Given a line segment from pts[0] to pts[1], and an xray, return true if
+ they intersect. Optional outgoing "ambiguous" argument indicates
+ whether the answer is ambiguous because the query occurred exactly at
+ one of the endpoints' y coordinates, indicating that another query y
+ coordinate is preferred for robustness.
+*/
+bool SkXRayCrossesLine(const SkXRay& pt, const SkPoint pts[2],
+ bool* ambiguous = NULL);
+
+/** Given a quadratic equation Ax^2 + Bx + C = 0, return 0, 1, 2 roots for the
+ equation.
+*/
+int SkFindUnitQuadRoots(SkScalar A, SkScalar B, SkScalar C, SkScalar roots[2]);
+
+///////////////////////////////////////////////////////////////////////////////
+
+/** Set pt to the point on the src quadratic specified by t. t must be
+ 0 <= t <= 1.0
+*/
+void SkEvalQuadAt(const SkPoint src[3], SkScalar t, SkPoint* pt,
+ SkVector* tangent = NULL);
+void SkEvalQuadAtHalf(const SkPoint src[3], SkPoint* pt,
+ SkVector* tangent = NULL);
+
+/** Given a src quadratic bezier, chop it at the specified t value,
+ where 0 < t < 1, and return the two new quadratics in dst:
+ dst[0..2] and dst[2..4]
+*/
+void SkChopQuadAt(const SkPoint src[3], SkPoint dst[5], SkScalar t);
+
+/** Given a src quadratic bezier, chop it at the specified t == 1/2,
+ The new quads are returned in dst[0..2] and dst[2..4]
+*/
+void SkChopQuadAtHalf(const SkPoint src[3], SkPoint dst[5]);
+
+/** Given the 3 coefficients for a quadratic bezier (either X or Y values), look
+ for extrema, and return the number of t-values that are found that represent
+ these extrema. If the quadratic has no extrema betwee (0..1) exclusive, the
+ function returns 0.
+ Returned count tValues[]
+ 0 ignored
+ 1 0 < tValues[0] < 1
+*/
+int SkFindQuadExtrema(SkScalar a, SkScalar b, SkScalar c, SkScalar tValues[1]);
+
+/** Given 3 points on a quadratic bezier, chop it into 1, 2 beziers such that
+ the resulting beziers are monotonic in Y. This is called by the scan converter.
+ Depending on what is returned, dst[] is treated as follows
+ 0 dst[0..2] is the original quad
+ 1 dst[0..2] and dst[2..4] are the two new quads
+*/
+int SkChopQuadAtYExtrema(const SkPoint src[3], SkPoint dst[5]);
+int SkChopQuadAtXExtrema(const SkPoint src[3], SkPoint dst[5]);
+
+/** Given 3 points on a quadratic bezier, if the point of maximum
+ curvature exists on the segment, returns the t value for this
+ point along the curve. Otherwise it will return a value of 0.
+*/
+float SkFindQuadMaxCurvature(const SkPoint src[3]);
+
+/** Given 3 points on a quadratic bezier, divide it into 2 quadratics
+ if the point of maximum curvature exists on the quad segment.
+ Depending on what is returned, dst[] is treated as follows
+ 1 dst[0..2] is the original quad
+ 2 dst[0..2] and dst[2..4] are the two new quads
+ If dst == null, it is ignored and only the count is returned.
+*/
+int SkChopQuadAtMaxCurvature(const SkPoint src[3], SkPoint dst[5]);
+
+/** Given 3 points on a quadratic bezier, use degree elevation to
+ convert it into the cubic fitting the same curve. The new cubic
+ curve is returned in dst[0..3].
+*/
+SK_API void SkConvertQuadToCubic(const SkPoint src[3], SkPoint dst[4]);
+
+///////////////////////////////////////////////////////////////////////////////
+
+/** Convert from parametric from (pts) to polynomial coefficients
+ coeff[0]*T^3 + coeff[1]*T^2 + coeff[2]*T + coeff[3]
+*/
+void SkGetCubicCoeff(const SkPoint pts[4], SkScalar cx[4], SkScalar cy[4]);
+
+/** Set pt to the point on the src cubic specified by t. t must be
+ 0 <= t <= 1.0
+*/
+void SkEvalCubicAt(const SkPoint src[4], SkScalar t, SkPoint* locOrNull,
+ SkVector* tangentOrNull, SkVector* curvatureOrNull);
+
+/** Given a src cubic bezier, chop it at the specified t value,
+ where 0 < t < 1, and return the two new cubics in dst:
+ dst[0..3] and dst[3..6]
+*/
+void SkChopCubicAt(const SkPoint src[4], SkPoint dst[7], SkScalar t);
+/** Given a src cubic bezier, chop it at the specified t values,
+ where 0 < t < 1, and return the new cubics in dst:
+ dst[0..3],dst[3..6],...,dst[3*t_count..3*(t_count+1)]
+*/
+void SkChopCubicAt(const SkPoint src[4], SkPoint dst[], const SkScalar t[],
+ int t_count);
+
+/** Given a src cubic bezier, chop it at the specified t == 1/2,
+ The new cubics are returned in dst[0..3] and dst[3..6]
+*/
+void SkChopCubicAtHalf(const SkPoint src[4], SkPoint dst[7]);
+
+/** Given the 4 coefficients for a cubic bezier (either X or Y values), look
+ for extrema, and return the number of t-values that are found that represent
+ these extrema. If the cubic has no extrema betwee (0..1) exclusive, the
+ function returns 0.
+ Returned count tValues[]
+ 0 ignored
+ 1 0 < tValues[0] < 1
+ 2 0 < tValues[0] < tValues[1] < 1
+*/
+int SkFindCubicExtrema(SkScalar a, SkScalar b, SkScalar c, SkScalar d,
+ SkScalar tValues[2]);
+
+/** Given 4 points on a cubic bezier, chop it into 1, 2, 3 beziers such that
+ the resulting beziers are monotonic in Y. This is called by the scan converter.
+ Depending on what is returned, dst[] is treated as follows
+ 0 dst[0..3] is the original cubic
+ 1 dst[0..3] and dst[3..6] are the two new cubics
+ 2 dst[0..3], dst[3..6], dst[6..9] are the three new cubics
+ If dst == null, it is ignored and only the count is returned.
+*/
+int SkChopCubicAtYExtrema(const SkPoint src[4], SkPoint dst[10]);
+int SkChopCubicAtXExtrema(const SkPoint src[4], SkPoint dst[10]);
+
+/** Given a cubic bezier, return 0, 1, or 2 t-values that represent the
+ inflection points.
+*/
+int SkFindCubicInflections(const SkPoint src[4], SkScalar tValues[2]);
+
+/** Return 1 for no chop, 2 for having chopped the cubic at a single
+ inflection point, 3 for having chopped at 2 inflection points.
+ dst will hold the resulting 1, 2, or 3 cubics.
+*/
+int SkChopCubicAtInflections(const SkPoint src[4], SkPoint dst[10]);
+
+int SkFindCubicMaxCurvature(const SkPoint src[4], SkScalar tValues[3]);
+int SkChopCubicAtMaxCurvature(const SkPoint src[4], SkPoint dst[13],
+ SkScalar tValues[3] = NULL);
+
+/** Given a monotonic cubic bezier, determine whether an xray intersects the
+ cubic.
+ By definition the cubic is open at the starting point; in other
+ words, if pt.fY is equivalent to cubic[0].fY, and pt.fX is to the
+ left of the curve, the line is not considered to cross the curve,
+ but if it is equal to cubic[3].fY then it is considered to
+ cross.
+ Optional outgoing "ambiguous" argument indicates whether the answer is
+ ambiguous because the query occurred exactly at one of the endpoints' y
+ coordinates, indicating that another query y coordinate is preferred
+ for robustness.
+ */
+bool SkXRayCrossesMonotonicCubic(const SkXRay& pt, const SkPoint cubic[4],
+ bool* ambiguous = NULL);
+
+/** Given an arbitrary cubic bezier, return the number of times an xray crosses
+ the cubic. Valid return values are [0..3]
+ By definition the cubic is open at the starting point; in other
+ words, if pt.fY is equivalent to cubic[0].fY, and pt.fX is to the
+ left of the curve, the line is not considered to cross the curve,
+ but if it is equal to cubic[3].fY then it is considered to
+ cross.
+ Optional outgoing "ambiguous" argument indicates whether the answer is
+ ambiguous because the query occurred exactly at one of the endpoints' y
+ coordinates or at a tangent point, indicating that another query y
+ coordinate is preferred for robustness.
+ */
+int SkNumXRayCrossingsForCubic(const SkXRay& pt, const SkPoint cubic[4],
+ bool* ambiguous = NULL);
+
+///////////////////////////////////////////////////////////////////////////////
+
+enum SkRotationDirection {
+ kCW_SkRotationDirection,
+ kCCW_SkRotationDirection
+};
+
+/** Maximum number of points needed in the quadPoints[] parameter for
+ SkBuildQuadArc()
+*/
+#define kSkBuildQuadArcStorage 17
+
+/** Given 2 unit vectors and a rotation direction, fill out the specified
+ array of points with quadratic segments. Return is the number of points
+ written to, which will be { 0, 3, 5, 7, ... kSkBuildQuadArcStorage }
+
+ matrix, if not null, is appled to the points before they are returned.
+*/
+int SkBuildQuadArc(const SkVector& unitStart, const SkVector& unitStop,
+ SkRotationDirection, const SkMatrix*, SkPoint quadPoints[]);
+
+// experimental
+struct SkConic {
+ SkPoint fPts[3];
+ SkScalar fW;
+
+ void set(const SkPoint pts[3], SkScalar w) {
+ memcpy(fPts, pts, 3 * sizeof(SkPoint));
+ fW = w;
+ }
+
+ /**
+ * Given a t-value [0...1] return its position and/or tangent.
+ * If pos is not null, return its position at the t-value.
+ * If tangent is not null, return its tangent at the t-value. NOTE the
+ * tangent value's length is arbitrary, and only its direction should
+ * be used.
+ */
+ void evalAt(SkScalar t, SkPoint* pos, SkVector* tangent = NULL) const;
+ void chopAt(SkScalar t, SkConic dst[2]) const;
+ void chop(SkConic dst[2]) const;
+
+ void computeAsQuadError(SkVector* err) const;
+ bool asQuadTol(SkScalar tol) const;
+
+ /**
+ * return the power-of-2 number of quads needed to approximate this conic
+ * with a sequence of quads. Will be >= 0.
+ */
+ int computeQuadPOW2(SkScalar tol) const;
+
+ /**
+ * Chop this conic into N quads, stored continguously in pts[], where
+ * N = 1 << pow2. The amount of storage needed is (1 + 2 * N)
+ */
+ int chopIntoQuadsPOW2(SkPoint pts[], int pow2) const;
+
+ bool findXExtrema(SkScalar* t) const;
+ bool findYExtrema(SkScalar* t) const;
+ bool chopAtXExtrema(SkConic dst[2]) const;
+ bool chopAtYExtrema(SkConic dst[2]) const;
+
+ void computeTightBounds(SkRect* bounds) const;
+ void computeFastBounds(SkRect* bounds) const;
+
+ /** Find the parameter value where the conic takes on its maximum curvature.
+ *
+ * @param t output scalar for max curvature. Will be unchanged if
+ * max curvature outside 0..1 range.
+ *
+ * @return true if max curvature found inside 0..1 range, false otherwise
+ */
+ bool findMaxCurvature(SkScalar* t) const;
+};
+
+#include "SkTemplates.h"
+
+/**
+ * Help class to allocate storage for approximating a conic with N quads.
+ */
+class SkAutoConicToQuads {
+public:
+ SkAutoConicToQuads() : fQuadCount(0) {}
+
+ /**
+ * Given a conic and a tolerance, return the array of points for the
+ * approximating quad(s). Call countQuads() to know the number of quads
+ * represented in these points.
+ *
+ * The quads are allocated to share end-points. e.g. if there are 4 quads,
+ * there will be 9 points allocated as follows
+ * quad[0] == pts[0..2]
+ * quad[1] == pts[2..4]
+ * quad[2] == pts[4..6]
+ * quad[3] == pts[6..8]
+ */
+ const SkPoint* computeQuads(const SkConic& conic, SkScalar tol) {
+ int pow2 = conic.computeQuadPOW2(tol);
+ fQuadCount = 1 << pow2;
+ SkPoint* pts = fStorage.reset(1 + 2 * fQuadCount);
+ conic.chopIntoQuadsPOW2(pts, pow2);
+ return pts;
+ }
+
+ const SkPoint* computeQuads(const SkPoint pts[3], SkScalar weight,
+ SkScalar tol) {
+ SkConic conic;
+ conic.set(pts, weight);
+ return computeQuads(conic, tol);
+ }
+
+ int countQuads() const { return fQuadCount; }
+
+private:
+ enum {
+ kQuadCount = 8, // should handle most conics
+ kPointCount = 1 + 2 * kQuadCount,
+ };
+ SkAutoSTMalloc<kPointCount, SkPoint> fStorage;
+ int fQuadCount; // #quads for current usage
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/core/SkGlyph.h b/chromium/third_party/skia/src/core/SkGlyph.h
index 649fa7dd5db..73afb132d64 100644
--- a/chromium/third_party/skia/src/core/SkGlyph.h
+++ b/chromium/third_party/skia/src/core/SkGlyph.h
@@ -29,6 +29,7 @@ struct SkGlyph {
uint16_t fWidth, fHeight;
int16_t fTop, fLeft;
+ void* fDistanceField;
uint8_t fMaskFormat;
int8_t fRsbDelta, fLsbDelta; // used by auto-kerning
@@ -36,6 +37,7 @@ struct SkGlyph {
fID = id;
fImage = NULL;
fPath = NULL;
+ fDistanceField = NULL;
fMaskFormat = MASK_FORMAT_UNKNOWN;
}
diff --git a/chromium/third_party/skia/src/core/SkGlyphCache.cpp b/chromium/third_party/skia/src/core/SkGlyphCache.cpp
index a78b197a552..2ab721aab46 100644..100755
--- a/chromium/third_party/skia/src/core/SkGlyphCache.cpp
+++ b/chromium/third_party/skia/src/core/SkGlyphCache.cpp
@@ -9,7 +9,9 @@
#include "SkGlyphCache.h"
#include "SkGlyphCache_Globals.h"
+#include "SkDistanceFieldGen.h"
#include "SkGraphics.h"
+#include "SkLazyPtr.h"
#include "SkPaint.h"
#include "SkPath.h"
#include "SkTemplates.h"
@@ -19,14 +21,18 @@
//#define SPEW_PURGE_STATUS
//#define RECORD_HASH_EFFICIENCY
-bool gSkSuppressFontCachePurgeSpew;
+namespace {
+
+SkGlyphCache_Globals* create_globals() {
+ return SkNEW_ARGS(SkGlyphCache_Globals, (SkGlyphCache_Globals::kYes_UseMutex));
+}
+
+} // namespace
// Returns the shared globals
static SkGlyphCache_Globals& getSharedGlobals() {
- // we leak this, so we don't incur any shutdown cost of the destructor
- static SkGlyphCache_Globals* gGlobals = SkNEW_ARGS(SkGlyphCache_Globals,
- (SkGlyphCache_Globals::kYes_UseMutex));
- return *gGlobals;
+ SK_DECLARE_STATIC_LAZY_PTR(SkGlyphCache_Globals, globals, create_globals);
+ return *globals.get();
}
// Returns the TLS globals (if set), or the shared globals
@@ -328,12 +334,12 @@ SkGlyph* SkGlyphCache::lookupMetrics(uint32_t id, MetricsType mtype) {
const void* SkGlyphCache::findImage(const SkGlyph& glyph) {
if (glyph.fWidth > 0 && glyph.fWidth < kMaxGlyphWidth) {
- if (glyph.fImage == NULL) {
+ if (NULL == glyph.fImage) {
size_t size = glyph.computeImageSize();
const_cast<SkGlyph&>(glyph).fImage = fGlyphAlloc.alloc(size,
SkChunkAlloc::kReturnNil_AllocFailType);
// check that alloc() actually succeeded
- if (glyph.fImage) {
+ if (NULL != glyph.fImage) {
fScalerContext->getImage(glyph);
// TODO: the scaler may have changed the maskformat during
// getImage (e.g. from AA or LCD to BW) which means we may have
@@ -358,6 +364,45 @@ const SkPath* SkGlyphCache::findPath(const SkGlyph& glyph) {
return glyph.fPath;
}
+const void* SkGlyphCache::findDistanceField(const SkGlyph& glyph) {
+ if (glyph.fWidth > 0 && glyph.fWidth < kMaxGlyphWidth) {
+ if (NULL == glyph.fDistanceField) {
+ size_t size = SkComputeDistanceFieldSize(glyph.fWidth, glyph.fHeight);
+ if (size == 0) {
+ return NULL;
+ }
+ const void* image = this->findImage(glyph);
+ // now generate the distance field
+ if (NULL != image) {
+ const_cast<SkGlyph&>(glyph).fDistanceField = fGlyphAlloc.alloc(size,
+ SkChunkAlloc::kReturnNil_AllocFailType);
+ if (NULL != glyph.fDistanceField) {
+ SkMask::Format maskFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
+ if (SkMask::kA8_Format == maskFormat) {
+ // make the distance field from the image
+ SkGenerateDistanceFieldFromA8Image((unsigned char*)glyph.fDistanceField,
+ (unsigned char*)glyph.fImage,
+ glyph.fWidth, glyph.fHeight,
+ glyph.rowBytes());
+ fMemoryUsed += size;
+ } else if (SkMask::kBW_Format == maskFormat) {
+ // make the distance field from the image
+ SkGenerateDistanceFieldFromBWImage((unsigned char*)glyph.fDistanceField,
+ (unsigned char*)glyph.fImage,
+ glyph.fWidth, glyph.fHeight,
+ glyph.rowBytes());
+ fMemoryUsed += size;
+ } else {
+ fGlyphAlloc.unalloc(glyph.fDistanceField);
+ const_cast<SkGlyph&>(glyph).fDistanceField = NULL;
+ }
+ }
+ }
+ }
+ }
+ return glyph.fDistanceField;
+}
+
///////////////////////////////////////////////////////////////////////////////
bool SkGlyphCache::getAuxProcData(void (*proc)(void*), void** dataPtr) const {
@@ -560,10 +605,10 @@ size_t SkGlyphCache_Globals::internalPurge(size_t minBytesNeeded) {
if (fTotalMemoryUsed > fCacheSizeLimit) {
bytesNeeded = fTotalMemoryUsed - fCacheSizeLimit;
}
- bytesNeeded = SkMax32(bytesNeeded, minBytesNeeded);
+ bytesNeeded = SkTMax(bytesNeeded, minBytesNeeded);
if (bytesNeeded) {
// no small purges!
- bytesNeeded = SkMax32(bytesNeeded, fTotalMemoryUsed >> 2);
+ bytesNeeded = SkTMax(bytesNeeded, fTotalMemoryUsed >> 2);
}
int countNeeded = 0;
@@ -598,7 +643,7 @@ size_t SkGlyphCache_Globals::internalPurge(size_t minBytesNeeded) {
this->validate();
#ifdef SPEW_PURGE_STATUS
- if (countFreed && !gSkSuppressFontCachePurgeSpew) {
+ if (countFreed) {
SkDebugf("purging %dK from font cache [%d entries]\n",
(int)(bytesFreed >> 10), countFreed);
}
@@ -649,6 +694,9 @@ void SkGlyphCache::validate() const {
if (glyph->fImage) {
SkASSERT(fGlyphAlloc.contains(glyph->fImage));
}
+ if (glyph->fDistanceField) {
+ SkASSERT(fGlyphAlloc.contains(glyph->fDistanceField));
+ }
}
#endif
}
diff --git a/chromium/third_party/skia/src/core/SkGlyphCache.h b/chromium/third_party/skia/src/core/SkGlyphCache.h
index 7b2ebb844e2..4daf6b06b6c 100644
--- a/chromium/third_party/skia/src/core/SkGlyphCache.h
+++ b/chromium/third_party/skia/src/core/SkGlyphCache.h
@@ -28,7 +28,7 @@ class SkGlyphCache_Globals;
This class represents a strike: a specific combination of typeface, size,
matrix, etc., and holds the glyphs for that strike. Calling any of the
getUnichar.../getGlyphID... methods will return the requested glyph,
- either instantly if it is already cahced, or by first generating it and then
+ either instantly if it is already cached, or by first generating it and then
adding it to the strike.
The strikes are held in a global list, available to all threads. To interact
@@ -92,6 +92,10 @@ public:
this will trigger that.
*/
const SkPath* findPath(const SkGlyph&);
+ /** Return the distance field associated with the glyph. If it has not been generated
+ this will trigger that.
+ */
+ const void* findDistanceField(const SkGlyph&);
/** Return the vertical metrics for this strike.
*/
@@ -240,37 +244,74 @@ private:
friend class SkGlyphCache_Globals;
};
-class SkAutoGlyphCache {
+class SkAutoGlyphCacheBase {
public:
- SkAutoGlyphCache(SkGlyphCache* cache) : fCache(cache) {}
- SkAutoGlyphCache(SkTypeface* typeface, const SkDescriptor* desc) {
- fCache = SkGlyphCache::DetachCache(typeface, desc);
- }
- SkAutoGlyphCache(const SkPaint& paint,
- const SkDeviceProperties* deviceProperties,
- const SkMatrix* matrix) {
- fCache = paint.detachCache(deviceProperties, matrix);
- }
- ~SkAutoGlyphCache() {
+ SkGlyphCache* getCache() const { return fCache; }
+
+ void release() {
if (fCache) {
SkGlyphCache::AttachCache(fCache);
+ fCache = NULL;
}
}
- SkGlyphCache* getCache() const { return fCache; }
-
- void release() {
+protected:
+ // Hide the constructors so we can't create one of these directly.
+ // Create SkAutoGlyphCache or SkAutoGlyphCacheNoCache instead.
+ SkAutoGlyphCacheBase(SkGlyphCache* cache) : fCache(cache) {}
+ SkAutoGlyphCacheBase(SkTypeface* typeface, const SkDescriptor* desc) {
+ fCache = SkGlyphCache::DetachCache(typeface, desc);
+ }
+ SkAutoGlyphCacheBase(const SkPaint& paint,
+ const SkDeviceProperties* deviceProperties,
+ const SkMatrix* matrix) {
+ fCache = NULL;
+ }
+ SkAutoGlyphCacheBase() {
+ fCache = NULL;
+ }
+ ~SkAutoGlyphCacheBase() {
if (fCache) {
SkGlyphCache::AttachCache(fCache);
- fCache = NULL;
}
}
-private:
SkGlyphCache* fCache;
+private:
static bool DetachProc(const SkGlyphCache*, void*);
};
+
+class SkAutoGlyphCache : public SkAutoGlyphCacheBase {
+public:
+ SkAutoGlyphCache(SkGlyphCache* cache) : SkAutoGlyphCacheBase(cache) {}
+ SkAutoGlyphCache(SkTypeface* typeface, const SkDescriptor* desc) :
+ SkAutoGlyphCacheBase(typeface, desc) {}
+ SkAutoGlyphCache(const SkPaint& paint,
+ const SkDeviceProperties* deviceProperties,
+ const SkMatrix* matrix) {
+ fCache = paint.detachCache(deviceProperties, matrix, false);
+ }
+
+private:
+ SkAutoGlyphCache() : SkAutoGlyphCacheBase() {}
+};
#define SkAutoGlyphCache(...) SK_REQUIRE_LOCAL_VAR(SkAutoGlyphCache)
+class SkAutoGlyphCacheNoGamma : public SkAutoGlyphCacheBase {
+public:
+ SkAutoGlyphCacheNoGamma(SkGlyphCache* cache) : SkAutoGlyphCacheBase(cache) {}
+ SkAutoGlyphCacheNoGamma(SkTypeface* typeface, const SkDescriptor* desc) :
+ SkAutoGlyphCacheBase(typeface, desc) {}
+ SkAutoGlyphCacheNoGamma(const SkPaint& paint,
+ const SkDeviceProperties* deviceProperties,
+ const SkMatrix* matrix) {
+ fCache = paint.detachCache(deviceProperties, matrix, true);
+ }
+
+private:
+ SkAutoGlyphCacheNoGamma() : SkAutoGlyphCacheBase() {}
+};
+#define SkAutoGlyphCacheNoGamma(...) SK_REQUIRE_LOCAL_VAR(SkAutoGlyphCacheNoGamma)
+
#endif
diff --git a/chromium/third_party/skia/src/core/SkGraphics.cpp b/chromium/third_party/skia/src/core/SkGraphics.cpp
index 51521e42b1e..a89237fcff6 100644
--- a/chromium/third_party/skia/src/core/SkGraphics.cpp
+++ b/chromium/third_party/skia/src/core/SkGraphics.cpp
@@ -9,7 +9,6 @@
#include "SkGraphics.h"
-#include "Sk64.h"
#include "SkBlitter.h"
#include "SkCanvas.h"
#include "SkFloat.h"
@@ -55,8 +54,10 @@ void SkGraphics::Init() {
#ifdef SK_DEVELOPER
skRTConfRegistry().possiblyDumpFile();
skRTConfRegistry().validate();
- SkDebugf("Non-default runtime configuration options:\n");
- skRTConfRegistry().printNonDefault( );
+ if (skRTConfRegistry().hasNonDefault()) {
+ SkDebugf("Non-default runtime configuration options:\n");
+ skRTConfRegistry().printNonDefault();
+ }
#endif
#ifdef BUILD_EMBOSS_TABLE
@@ -128,7 +129,6 @@ void SkGraphics::Init() {
void SkGraphics::Term() {
PurgeFontCache();
SkPaint::Term();
- SkXfermode::Term();
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/third_party/skia/src/core/SkImageFilter.cpp b/chromium/third_party/skia/src/core/SkImageFilter.cpp
index cda635b4fbf..4c4b56beace 100644
--- a/chromium/third_party/skia/src/core/SkImageFilter.cpp
+++ b/chromium/third_party/skia/src/core/SkImageFilter.cpp
@@ -8,15 +8,20 @@
#include "SkImageFilter.h"
#include "SkBitmap.h"
-#include "SkFlattenableBuffers.h"
+#include "SkDevice.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkRect.h"
+#include "SkTDynamicHash.h"
#include "SkValidationUtils.h"
#if SK_SUPPORT_GPU
#include "GrContext.h"
-#include "GrTexture.h"
-#include "SkImageFilterUtils.h"
+#include "SkGrPixelRef.h"
+#include "SkGr.h"
#endif
+SkImageFilter::Cache* gExternalCache;
+
SkImageFilter::SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect)
: fInputCount(inputCount),
fInputs(new SkImageFilter*[inputCount]),
@@ -51,7 +56,7 @@ SkImageFilter::~SkImageFilter() {
delete[] fInputs;
}
-SkImageFilter::SkImageFilter(int inputCount, SkFlattenableReadBuffer& buffer) {
+SkImageFilter::SkImageFilter(int inputCount, SkReadBuffer& buffer) {
fInputCount = buffer.readInt();
if (buffer.validate((fInputCount >= 0) && ((inputCount < 0) || (fInputCount == inputCount)))) {
fInputs = new SkImageFilter*[fInputCount];
@@ -78,7 +83,7 @@ SkImageFilter::SkImageFilter(int inputCount, SkFlattenableReadBuffer& buffer) {
}
}
-void SkImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkImageFilter::flatten(SkWriteBuffer& buffer) const {
buffer.writeInt(fInputCount);
for (int i = 0; i < fInputCount; i++) {
SkImageFilter* input = getInput(i);
@@ -92,27 +97,68 @@ void SkImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
}
bool SkImageFilter::filterImage(Proxy* proxy, const SkBitmap& src,
- const SkMatrix& ctm,
- SkBitmap* result, SkIPoint* loc) {
+ const Context& context,
+ SkBitmap* result, SkIPoint* offset) const {
+ Cache* cache = context.cache();
SkASSERT(result);
- SkASSERT(loc);
+ SkASSERT(offset);
+ SkASSERT(cache);
+ if (cache->get(this, result, offset)) {
+ return true;
+ }
/*
* Give the proxy first shot at the filter. If it returns false, ask
* the filter to do it.
*/
- return (proxy && proxy->filterImage(this, src, ctm, result, loc)) ||
- this->onFilterImage(proxy, src, ctm, result, loc);
+ if ((proxy && proxy->filterImage(this, src, context, result, offset)) ||
+ this->onFilterImage(proxy, src, context, result, offset)) {
+ cache->set(this, *result, *offset);
+ return true;
+ }
+ return false;
}
bool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm,
- SkIRect* dst) {
+ SkIRect* dst) const {
SkASSERT(&src);
SkASSERT(dst);
+ if (SkImageFilter::GetExternalCache()) {
+ /*
+ * When the external cache is active, do not intersect the saveLayer
+ * bounds with the clip bounds. This is so that the cached result
+ * is always the full size of the primitive's bounds,
+ * regardless of the clip active on first draw.
+ */
+ *dst = SkIRect::MakeLargest();
+ return true;
+ }
return this->onFilterBounds(src, ctm, dst);
}
-bool SkImageFilter::onFilterImage(Proxy*, const SkBitmap&, const SkMatrix&,
- SkBitmap*, SkIPoint*) {
+void SkImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
+ if (0 == fInputCount) {
+ *dst = src;
+ return;
+ }
+ if (this->getInput(0)) {
+ this->getInput(0)->computeFastBounds(src, dst);
+ } else {
+ *dst = src;
+ }
+ for (int i = 1; i < fInputCount; i++) {
+ SkImageFilter* input = this->getInput(i);
+ if (input) {
+ SkRect bounds;
+ input->computeFastBounds(src, &bounds);
+ dst->join(bounds);
+ } else {
+ dst->join(src);
+ }
+ }
+}
+
+bool SkImageFilter::onFilterImage(Proxy*, const SkBitmap&, const Context&,
+ SkBitmap*, SkIPoint*) const {
return false;
}
@@ -120,18 +166,19 @@ bool SkImageFilter::canFilterImageGPU() const {
return this->asNewEffect(NULL, NULL, SkMatrix::I(), SkIRect());
}
-bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
- SkBitmap* result, SkIPoint* offset) {
+bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx,
+ SkBitmap* result, SkIPoint* offset) const {
#if SK_SUPPORT_GPU
- SkBitmap input;
+ SkBitmap input = src;
SkASSERT(fInputCount == 1);
- if (!SkImageFilterUtils::GetInputResultGPU(this->getInput(0), proxy, src, ctm, &input, offset)) {
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
+ if (this->getInput(0) &&
+ !this->getInput(0)->getInputResultGPU(proxy, src, ctx, &input, &srcOffset)) {
return false;
}
GrTexture* srcTexture = input.getTexture();
SkIRect bounds;
- src.getBounds(&bounds);
- if (!this->applyCropRect(&bounds, ctm)) {
+ if (!this->applyCropRect(ctx, proxy, input, &srcOffset, &bounds, &input)) {
return false;
}
SkRect srcRect = SkRect::Make(bounds);
@@ -150,7 +197,10 @@ bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMa
GrContext::AutoRenderTarget art(context, dst.texture()->asRenderTarget());
GrContext::AutoClip acs(context, dstRect);
GrEffectRef* effect;
- SkMatrix matrix(ctm);
+ offset->fX = bounds.left();
+ offset->fY = bounds.top();
+ bounds.offset(-srcOffset);
+ SkMatrix matrix(ctx.ctm());
matrix.postTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
this->asNewEffect(&effect, srcTexture, matrix, bounds);
SkASSERT(effect);
@@ -160,32 +210,92 @@ bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMa
context->drawRectToRect(paint, dstRect, srcRect);
SkAutoTUnref<GrTexture> resultTex(dst.detach());
- SkImageFilterUtils::WrapTexture(resultTex, bounds.width(), bounds.height(), result);
- offset->fX += bounds.left();
- offset->fY += bounds.top();
+ WrapTexture(resultTex, bounds.width(), bounds.height(), result);
return true;
#else
return false;
#endif
}
-bool SkImageFilter::applyCropRect(SkIRect* rect, const SkMatrix& matrix) const {
+bool SkImageFilter::applyCropRect(const Context& ctx, const SkBitmap& src,
+ const SkIPoint& srcOffset, SkIRect* bounds) const {
+ SkIRect srcBounds;
+ src.getBounds(&srcBounds);
+ srcBounds.offset(srcOffset);
+ SkRect cropRect;
+ ctx.ctm().mapRect(&cropRect, fCropRect.rect());
+ SkIRect cropRectI;
+ cropRect.roundOut(&cropRectI);
+ uint32_t flags = fCropRect.flags();
+ if (flags & CropRect::kHasLeft_CropEdge) srcBounds.fLeft = cropRectI.fLeft;
+ if (flags & CropRect::kHasTop_CropEdge) srcBounds.fTop = cropRectI.fTop;
+ if (flags & CropRect::kHasRight_CropEdge) srcBounds.fRight = cropRectI.fRight;
+ if (flags & CropRect::kHasBottom_CropEdge) srcBounds.fBottom = cropRectI.fBottom;
+ if (!srcBounds.intersect(ctx.clipBounds())) {
+ return false;
+ }
+ *bounds = srcBounds;
+ return true;
+}
+
+bool SkImageFilter::applyCropRect(const Context& ctx, Proxy* proxy, const SkBitmap& src,
+ SkIPoint* srcOffset, SkIRect* bounds, SkBitmap* dst) const {
+ SkIRect srcBounds;
+ src.getBounds(&srcBounds);
+ srcBounds.offset(*srcOffset);
SkRect cropRect;
- matrix.mapRect(&cropRect, fCropRect.rect());
+ ctx.ctm().mapRect(&cropRect, fCropRect.rect());
SkIRect cropRectI;
cropRect.roundOut(&cropRectI);
uint32_t flags = fCropRect.flags();
- // If the original crop rect edges were unset, max out the new crop edges
- if (!(flags & CropRect::kHasLeft_CropEdge)) cropRectI.fLeft = SK_MinS32;
- if (!(flags & CropRect::kHasTop_CropEdge)) cropRectI.fTop = SK_MinS32;
- if (!(flags & CropRect::kHasRight_CropEdge)) cropRectI.fRight = SK_MaxS32;
- if (!(flags & CropRect::kHasBottom_CropEdge)) cropRectI.fBottom = SK_MaxS32;
- return rect->intersect(cropRectI);
+ *bounds = srcBounds;
+ if (flags & CropRect::kHasLeft_CropEdge) bounds->fLeft = cropRectI.fLeft;
+ if (flags & CropRect::kHasTop_CropEdge) bounds->fTop = cropRectI.fTop;
+ if (flags & CropRect::kHasRight_CropEdge) bounds->fRight = cropRectI.fRight;
+ if (flags & CropRect::kHasBottom_CropEdge) bounds->fBottom = cropRectI.fBottom;
+ if (!bounds->intersect(ctx.clipBounds())) {
+ return false;
+ }
+ if (srcBounds.contains(*bounds)) {
+ *dst = src;
+ return true;
+ } else {
+ SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds->width(), bounds->height()));
+ if (!device) {
+ return false;
+ }
+ SkCanvas canvas(device);
+ canvas.clear(0x00000000);
+ canvas.drawBitmap(src, srcOffset->x() - bounds->x(), srcOffset->y() - bounds->y());
+ *srcOffset = SkIPoint::Make(bounds->x(), bounds->y());
+ *dst = device->accessBitmap(false);
+ return true;
+ }
}
bool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
- SkIRect* dst) {
- *dst = src;
+ SkIRect* dst) const {
+ if (fInputCount < 1) {
+ return false;
+ }
+
+ SkIRect bounds;
+ for (int i = 0; i < fInputCount; ++i) {
+ SkImageFilter* filter = this->getInput(i);
+ SkIRect rect = src;
+ if (filter && !filter->filterBounds(src, ctm, &rect)) {
+ return false;
+ }
+ if (0 == i) {
+ bounds = rect;
+ } else {
+ bounds.join(rect);
+ }
+ }
+
+ // don't modify dst until now, so we don't accidentally change it in the
+ // loop, but then return false on the next filter.
+ *dst = bounds;
return true;
}
@@ -196,3 +306,137 @@ bool SkImageFilter::asNewEffect(GrEffectRef**, GrTexture*, const SkMatrix&, cons
bool SkImageFilter::asColorFilter(SkColorFilter**) const {
return false;
}
+
+void SkImageFilter::SetExternalCache(Cache* cache) {
+ SkRefCnt_SafeAssign(gExternalCache, cache);
+}
+
+SkImageFilter::Cache* SkImageFilter::GetExternalCache() {
+ return gExternalCache;
+}
+
+#if SK_SUPPORT_GPU
+
+void SkImageFilter::WrapTexture(GrTexture* texture, int width, int height, SkBitmap* result) {
+ SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
+ result->setInfo(info);
+ result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref();
+}
+
+bool SkImageFilter::getInputResultGPU(SkImageFilter::Proxy* proxy,
+ const SkBitmap& src, const Context& ctx,
+ SkBitmap* result, SkIPoint* offset) const {
+ // Ensure that GrContext calls under filterImage and filterImageGPU below will see an identity
+ // matrix with no clip and that the matrix, clip, and render target set before this function was
+ // called are restored before we return to the caller.
+ GrContext* context = src.getTexture()->getContext();
+ GrContext::AutoWideOpenIdentityDraw awoid(context, NULL);
+ if (this->canFilterImageGPU()) {
+ return this->filterImageGPU(proxy, src, ctx, result, offset);
+ } else {
+ if (this->filterImage(proxy, src, ctx, result, offset)) {
+ if (!result->getTexture()) {
+ const SkImageInfo info = result->info();
+ if (kUnknown_SkColorType == info.colorType()) {
+ return false;
+ }
+ GrTexture* resultTex = GrLockAndRefCachedBitmapTexture(context, *result, NULL);
+ result->setPixelRef(new SkGrPixelRef(info, resultTex))->unref();
+ GrUnlockAndUnrefCachedBitmapTexture(resultTex);
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
+#endif
+
+static uint32_t compute_hash(const uint32_t* data, int count) {
+ uint32_t hash = 0;
+
+ for (int i = 0; i < count; ++i) {
+ uint32_t k = data[i];
+ k *= 0xcc9e2d51;
+ k = (k << 15) | (k >> 17);
+ k *= 0x1b873593;
+
+ hash ^= k;
+ hash = (hash << 13) | (hash >> 19);
+ hash *= 5;
+ hash += 0xe6546b64;
+ }
+
+ // hash ^= size;
+ hash ^= hash >> 16;
+ hash *= 0x85ebca6b;
+ hash ^= hash >> 13;
+ hash *= 0xc2b2ae35;
+ hash ^= hash >> 16;
+
+ return hash;
+}
+
+class CacheImpl : public SkImageFilter::Cache {
+public:
+ explicit CacheImpl(int minChildren) : fMinChildren(minChildren) {}
+ virtual ~CacheImpl();
+ bool get(const SkImageFilter* key, SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
+ void set(const SkImageFilter* key, const SkBitmap& result, const SkIPoint& offset) SK_OVERRIDE;
+ void remove(const SkImageFilter* key) SK_OVERRIDE;
+private:
+ typedef const SkImageFilter* Key;
+ struct Value {
+ Value(Key key, const SkBitmap& bitmap, const SkIPoint& offset)
+ : fKey(key), fBitmap(bitmap), fOffset(offset) {}
+ Key fKey;
+ SkBitmap fBitmap;
+ SkIPoint fOffset;
+ static const Key& GetKey(const Value& v) {
+ return v.fKey;
+ }
+ static uint32_t Hash(Key key) {
+ return compute_hash(reinterpret_cast<const uint32_t*>(&key), sizeof(Key) / sizeof(uint32_t));
+ }
+ };
+ SkTDynamicHash<Value, Key> fData;
+ int fMinChildren;
+};
+
+bool CacheImpl::get(const SkImageFilter* key, SkBitmap* result, SkIPoint* offset) {
+ Value* v = fData.find(key);
+ if (v) {
+ *result = v->fBitmap;
+ *offset = v->fOffset;
+ return true;
+ }
+ return false;
+}
+
+void CacheImpl::remove(const SkImageFilter* key) {
+ Value* v = fData.find(key);
+ if (v) {
+ fData.remove(key);
+ delete v;
+ }
+}
+
+void CacheImpl::set(const SkImageFilter* key, const SkBitmap& result, const SkIPoint& offset) {
+ if (key->getRefCnt() >= fMinChildren) {
+ fData.add(new Value(key, result, offset));
+ }
+}
+
+SkImageFilter::Cache* SkImageFilter::Cache::Create(int minChildren) {
+ return new CacheImpl(minChildren);
+}
+
+CacheImpl::~CacheImpl() {
+ SkTDynamicHash<Value, Key>::Iter iter(&fData);
+
+ while (!iter.done()) {
+ Value* v = &*iter;
+ ++iter;
+ delete v;
+ }
+}
diff --git a/chromium/third_party/skia/src/core/SkImageFilterUtils.cpp b/chromium/third_party/skia/src/core/SkImageFilterUtils.cpp
deleted file mode 100644
index a59cf7bbbdb..00000000000
--- a/chromium/third_party/skia/src/core/SkImageFilterUtils.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2013 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkMatrix.h"
-
-#if SK_SUPPORT_GPU
-#include "GrTexture.h"
-#include "SkImageFilterUtils.h"
-#include "SkBitmap.h"
-#include "SkGrPixelRef.h"
-#include "SkGr.h"
-
-bool SkImageFilterUtils::WrapTexture(GrTexture* texture, int width, int height, SkBitmap* result) {
- SkImageInfo info = {
- width,
- height,
- kPMColor_SkColorType,
- kPremul_SkAlphaType,
- };
- result->setConfig(info);
- result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref();
- return true;
-}
-
-bool SkImageFilterUtils::GetInputResultGPU(SkImageFilter* filter, SkImageFilter::Proxy* proxy,
- const SkBitmap& src, const SkMatrix& ctm,
- SkBitmap* result, SkIPoint* offset) {
- // Ensure that GrContext calls under filterImage and filterImageGPU below will see an identity
- // matrix with no clip and that the matrix, clip, and render target set before this function was
- // called are restored before we return to the caller.
- GrContext* context = src.getTexture()->getContext();
- GrContext::AutoWideOpenIdentityDraw awoid(context, NULL);
- if (!filter) {
- *result = src;
- return true;
- } else if (filter->canFilterImageGPU()) {
- return filter->filterImageGPU(proxy, src, ctm, result, offset);
- } else {
- if (filter->filterImage(proxy, src, ctm, result, offset)) {
- if (!result->getTexture()) {
- SkImageInfo info;
- if (!result->asImageInfo(&info)) {
- return false;
- }
- GrTexture* resultTex = GrLockAndRefCachedBitmapTexture(context, *result, NULL);
- result->setPixelRef(new SkGrPixelRef(info, resultTex))->unref();
- GrUnlockAndUnrefCachedBitmapTexture(resultTex);
- }
- return true;
- } else {
- return false;
- }
- }
-}
-#endif
diff --git a/chromium/third_party/skia/src/core/SkImageGenerator.cpp b/chromium/third_party/skia/src/core/SkImageGenerator.cpp
new file mode 100644
index 00000000000..daa55a3a4dc
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkImageGenerator.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkImageGenerator.h"
+
+#ifndef SK_SUPPORT_LEGACY_IMAGEGENERATORAPI
+bool SkImageGenerator::getInfo(SkImageInfo* info) {
+ SkImageInfo dummy;
+ if (NULL == info) {
+ info = &dummy;
+ }
+ return this->onGetInfo(info);
+}
+
+bool SkImageGenerator::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
+ SkPMColor ctable[], int* ctableCount) {
+ if (kUnknown_SkColorType == info.colorType()) {
+ return false;
+ }
+ if (NULL == pixels) {
+ return false;
+ }
+ if (rowBytes < info.minRowBytes()) {
+ return false;
+ }
+
+ if (kIndex_8_SkColorType == info.colorType()) {
+ if (NULL == ctable || NULL == ctableCount) {
+ return false;
+ }
+ } else {
+ if (ctableCount) {
+ *ctableCount = 0;
+ }
+ ctableCount = NULL;
+ ctable = NULL;
+ }
+
+ bool success = this->onGetPixels(info, pixels, rowBytes, ctable, ctableCount);
+
+ if (success && ctableCount) {
+ SkASSERT(*ctableCount >= 0 && *ctableCount <= 256);
+ }
+ return success;
+}
+
+bool SkImageGenerator::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {
+ SkASSERT(kIndex_8_SkColorType != info.colorType());
+ if (kIndex_8_SkColorType == info.colorType()) {
+ return false;
+ }
+ return this->getPixels(info, pixels, rowBytes, NULL, NULL);
+}
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+SkData* SkImageGenerator::onRefEncodedData() {
+ return NULL;
+}
+
+bool SkImageGenerator::onGetInfo(SkImageInfo*) {
+ return false;
+}
+
+bool SkImageGenerator::onGetPixels(const SkImageInfo&, void*, size_t, SkPMColor*, int*) {
+ return false;
+}
diff --git a/chromium/third_party/skia/src/core/SkImageGeneratorPriv.h b/chromium/third_party/skia/src/core/SkImageGeneratorPriv.h
new file mode 100644
index 00000000000..e03294d3fa0
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkImageGeneratorPriv.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkImageGeneratorPriv_DEFINED
+#define SkImageGeneratorPriv_DEFINED
+
+#include "SkImageGenerator.h"
+#include "SkDiscardableMemory.h"
+
+/**
+ * Takes ownership of SkImageGenerator. If this method fails for
+ * whatever reason, it will return false and immediatetely delete
+ * the generator. If it succeeds, it will modify destination
+ * bitmap.
+ *
+ * If generator is NULL, will safely return false.
+ *
+ * If this fails or when the SkDiscardablePixelRef that is
+ * installed into destination is destroyed, it will call
+ * SkDELETE() on the generator. Therefore, generator should be
+ * allocated with SkNEW() or SkNEW_ARGS().
+ *
+ * @param destination Upon success, this bitmap will be
+ * configured and have a pixelref installed.
+ *
+ * @param factory If not NULL, this object will be used as a
+ * source of discardable memory when decoding. If NULL, then
+ * SkDiscardableMemory::Create() will be called.
+ *
+ * @return true iff successful.
+ */
+bool SkInstallDiscardablePixelRef(SkImageGenerator*, SkBitmap* destination,
+ SkDiscardableMemory::Factory* factory);
+
+#endif
diff --git a/chromium/third_party/skia/src/core/SkImageInfo.cpp b/chromium/third_party/skia/src/core/SkImageInfo.cpp
index 967b4f6f08c..27c457391f1 100644
--- a/chromium/third_party/skia/src/core/SkImageInfo.cpp
+++ b/chromium/third_party/skia/src/core/SkImageInfo.cpp
@@ -6,7 +6,8 @@
*/
#include "SkImageInfo.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
static bool alpha_type_is_valid(SkAlphaType alphaType) {
return (alphaType >= 0) && (alphaType <= kLastEnum_SkAlphaType);
@@ -16,7 +17,7 @@ static bool color_type_is_valid(SkColorType colorType) {
return (colorType >= 0) && (colorType <= kLastEnum_SkColorType);
}
-void SkImageInfo::unflatten(SkFlattenableReadBuffer& buffer) {
+void SkImageInfo::unflatten(SkReadBuffer& buffer) {
fWidth = buffer.read32();
fHeight = buffer.read32();
@@ -28,7 +29,7 @@ void SkImageInfo::unflatten(SkFlattenableReadBuffer& buffer) {
color_type_is_valid(fColorType));
}
-void SkImageInfo::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkImageInfo::flatten(SkWriteBuffer& buffer) const {
buffer.write32(fWidth);
buffer.write32(fHeight);
diff --git a/chromium/third_party/skia/src/core/SkLazyFnPtr.h b/chromium/third_party/skia/src/core/SkLazyFnPtr.h
new file mode 100644
index 00000000000..464e061a131
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkLazyFnPtr.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkLazyFnPtr_DEFINED
+#define SkLazyFnPtr_DEFINED
+
+/** Declare a lazily-chosen static function pointer of type F.
+ *
+ * Example usage:
+ *
+ * typedef int (*FooImpl)(int, int);
+ *
+ * static FooImpl choose_foo() { return ... };
+ *
+ * int Foo(int a, int b) {
+ * SK_DECLARE_STATIC_LAZY_FN_PTR(FooImpl, foo, choose_foo);
+ * return foo.get()(a, b);
+ * }
+ *
+ * You can think of SK_DECLARE_STATIC_LAZY_FN_PTR as a cheaper specialization of SkOnce.
+ * There is no mutex, and in the fast path, no memory barriers are issued.
+ *
+ * This must be used in a global or function scope, not as a class member.
+ */
+#define SK_DECLARE_STATIC_LAZY_FN_PTR(F, name, Choose) static Private::SkLazyFnPtr<F, Choose> name
+
+
+// Everything below here is private implementation details. Don't touch, don't even look.
+
+#include "SkDynamicAnnotations.h"
+#include "SkThreadPriv.h"
+
+namespace Private {
+
+// This has no constructor and must be zero-initialized (the macro above does this).
+template <typename F, F (*Choose)()>
+class SkLazyFnPtr {
+public:
+ F get() {
+ // First, try reading to see if it's already set.
+ F fn = (F)SK_ANNOTATE_UNPROTECTED_READ(fPtr);
+ if (fn != NULL) {
+ return fn;
+ }
+
+ // We think it's not already set.
+ fn = Choose();
+
+ // No particular memory barriers needed; we're not guarding anything but the pointer itself.
+ F prev = (F)sk_atomic_cas(&fPtr, NULL, (void*)fn);
+
+ // If prev != NULL, someone snuck in and set fPtr concurrently.
+ // If prev == NULL, we did write fn to fPtr.
+ return prev != NULL ? prev : fn;
+ }
+
+private:
+ void* fPtr;
+};
+
+} // namespace Private
+
+#endif//SkLazyFnPtr_DEFINED
diff --git a/chromium/third_party/skia/src/core/SkLazyPtr.h b/chromium/third_party/skia/src/core/SkLazyPtr.h
new file mode 100644
index 00000000000..c25d3c81202
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkLazyPtr.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkLazyPtr_DEFINED
+#define SkLazyPtr_DEFINED
+
+/** Declare a lazily-chosen static pointer (or array of pointers) of type F.
+ *
+ * Example usage:
+ *
+ * Foo* GetSingletonFoo() {
+ * SK_DECLARE_STATIC_LAZY_PTR(Foo, singleton); // Created with SkNEW, destroyed with SkDELETE.
+ * return singleton.get();
+ * }
+ *
+ * These macros take an optional T* (*Create)() and void (*Destroy)(T*) at the end.
+ * If not given, we'll use SkNEW and SkDELETE.
+ * These options are most useful when T doesn't have a public constructor or destructor.
+ * Create comes first, so you may use a custom Create with a default Destroy, but not vice versa.
+ *
+ * Foo* CustomCreate() { return ...; }
+ * void CustomDestroy(Foo* ptr) { ... }
+ * Foo* GetSingletonFooWithCustomCleanup() {
+ * SK_DECLARE_STATIC_LAZY_PTR(Foo, singleton, CustomCreate, CustomDestroy);
+ * return singleton.get();
+ * }
+ *
+ * If you have a bunch of related static pointers of the same type, you can
+ * declare an array of lazy pointers together, and we'll pass the index to Create().
+ *
+ * Foo* CreateFoo(int i) { return ...; }
+ * Foo* GetCachedFoo(Foo::Enum enumVal) {
+ * SK_DECLARE_STATIC_LAZY_PTR_ARRAY(Foo, Foo::kEnumCount, cachedFoos, CreateFoo);
+ * return cachedFoos[enumVal];
+ * }
+ *
+ *
+ * You can think of SK_DECLARE_STATIC_LAZY_PTR as a cheaper specialization of
+ * SkOnce. There is no mutex or extra storage used past the pointer itself.
+ * In debug mode, each lazy pointer will be cleaned up at process exit so we
+ * can check that we've not leaked or freed them early.
+ *
+ * We may call Create more than once, but all threads will see the same pointer
+ * returned from get(). Any extra calls to Create will be cleaned up.
+ *
+ * These macros must be used in a global or function scope, not as a class member.
+ */
+
+#define SK_DECLARE_STATIC_LAZY_PTR(T, name, ...) \
+ static Private::SkLazyPtr<T, ##__VA_ARGS__> name
+
+#define SK_DECLARE_STATIC_LAZY_PTR_ARRAY(T, name, N, ...) \
+ static Private::SkLazyPtrArray<T, N, ##__VA_ARGS__> name
+
+
+
+// Everything below here is private implementation details. Don't touch, don't even look.
+
+#include "SkDynamicAnnotations.h"
+#include "SkThread.h"
+#include "SkThreadPriv.h"
+
+// See FIXME below.
+class SkFontConfigInterfaceDirect;
+
+namespace Private {
+
+// Set *dst to ptr if *dst is NULL. Returns value of *dst, destroying ptr if not swapped in.
+// Issues the same memory barriers as sk_atomic_cas: acquire on failure, release on success.
+template <typename P, void (*Destroy)(P)>
+static P try_cas(void** dst, P ptr) {
+ P prev = (P)sk_atomic_cas(dst, NULL, ptr);
+
+ if (prev) {
+ // We need an acquire barrier before returning prev, which sk_atomic_cas provided.
+ Destroy(ptr);
+ return prev;
+ } else {
+ // We need a release barrier before returning ptr, which sk_atomic_cas provided.
+ return ptr;
+ }
+}
+
+template <typename T> T* sk_new() { return SkNEW(T); }
+template <typename T> void sk_delete(T* ptr) { SkDELETE(ptr); }
+
+// This has no constructor and must be zero-initalized (the macro above does this).
+template <typename T, T* (*Create)() = sk_new<T>, void (*Destroy)(T*) = sk_delete<T> >
+class SkLazyPtr {
+public:
+ T* get() {
+ // If fPtr has already been filled, we need an acquire barrier when loading it.
+ // If not, we need a release barrier when setting it. try_cas will do that.
+ T* ptr = (T*)sk_acquire_load(&fPtr);
+ return ptr ? ptr : try_cas<T*, Destroy>(&fPtr, Create());
+ }
+
+#ifdef SK_DEVELOPER
+ // FIXME: We know we leak refs on some classes. For now, let them leak.
+ void cleanup(SkFontConfigInterfaceDirect*) {}
+ template <typename U> void cleanup(U* ptr) { Destroy(ptr); }
+
+ ~SkLazyPtr() {
+ this->cleanup((T*)fPtr);
+ fPtr = NULL;
+ }
+#endif
+
+private:
+ void* fPtr;
+};
+
+template <typename T> T* sk_new_arg(int i) { return SkNEW_ARGS(T, (i)); }
+
+// This has no constructor and must be zero-initalized (the macro above does this).
+template <typename T, int N, T* (*Create)(int) = sk_new_arg<T>, void (*Destroy)(T*) = sk_delete<T> >
+class SkLazyPtrArray {
+public:
+ T* operator[](int i) {
+ SkASSERT(i >= 0 && i < N);
+ // If fPtr has already been filled, we need an acquire barrier when loading it.
+ // If not, we need a release barrier when setting it. try_cas will do that.
+ T* ptr = (T*)sk_acquire_load(&fArray[i]);
+ return ptr ? ptr : try_cas<T*, Destroy>(&fArray[i], Create(i));
+ }
+
+#ifdef SK_DEVELOPER
+ ~SkLazyPtrArray() {
+ for (int i = 0; i < N; i++) {
+ Destroy((T*)fArray[i]);
+ fArray[i] = NULL;
+ }
+ }
+#endif
+
+private:
+ void* fArray[N];
+};
+
+} // namespace Private
+
+#endif//SkLazyPtr_DEFINED
diff --git a/chromium/third_party/skia/src/core/SkLineClipper.cpp b/chromium/third_party/skia/src/core/SkLineClipper.cpp
index 911cd974da5..1645917d70f 100644
--- a/chromium/third_party/skia/src/core/SkLineClipper.cpp
+++ b/chromium/third_party/skia/src/core/SkLineClipper.cpp
@@ -28,7 +28,6 @@ static SkScalar sect_with_horizontal(const SkPoint src[2], SkScalar Y) {
if (SkScalarNearlyZero(dy)) {
return SkScalarAve(src[0].fX, src[1].fX);
} else {
-#ifdef SK_SCALAR_IS_FLOAT
// need the extra precision so we don't compute a value that exceeds
// our original limits
double X0 = src[0].fX;
@@ -41,10 +40,6 @@ static SkScalar sect_with_horizontal(const SkPoint src[2], SkScalar Y) {
// when the doubles were added and subtracted, so we have to pin the
// answer :(
return (float)pin_unsorted(result, X0, X1);
-#else
- return src[0].fX + SkScalarMulDiv(Y - src[0].fY, src[1].fX - src[0].fX,
- dy);
-#endif
}
}
@@ -54,7 +49,6 @@ static SkScalar sect_with_vertical(const SkPoint src[2], SkScalar X) {
if (SkScalarNearlyZero(dx)) {
return SkScalarAve(src[0].fY, src[1].fY);
} else {
-#ifdef SK_SCALAR_IS_FLOAT
// need the extra precision so we don't compute a value that exceeds
// our original limits
double X0 = src[0].fX;
@@ -63,10 +57,6 @@ static SkScalar sect_with_vertical(const SkPoint src[2], SkScalar X) {
double Y1 = src[1].fY;
double result = Y0 + ((double)X - X0) * (Y1 - Y0) / (X1 - X0);
return (float)result;
-#else
- return src[0].fY + SkScalarMulDiv(X - src[0].fX, src[1].fY - src[0].fY,
- dx);
-#endif
}
}
@@ -167,7 +157,6 @@ static bool is_between_unsorted(SkScalar value,
}
#endif
-#ifdef SK_SCALAR_IS_FLOAT
#ifdef SK_DEBUG
// This is an example of why we need to pin the result computed in
// sect_with_horizontal. If we didn't explicitly pin, is_between_unsorted would
@@ -182,11 +171,9 @@ static void sect_with_horizontal_test_for_pin_results() {
SkASSERT(is_between_unsorted(x, pts[0].fX, pts[1].fX));
}
#endif
-#endif
int SkLineClipper::ClipLine(const SkPoint pts[], const SkRect& clip,
SkPoint lines[]) {
-#ifdef SK_SCALAR_IS_FLOAT
#ifdef SK_DEBUG
{
static bool gOnce;
@@ -196,7 +183,6 @@ int SkLineClipper::ClipLine(const SkPoint pts[], const SkRect& clip,
}
}
#endif
-#endif
int index0, index1;
@@ -281,7 +267,7 @@ int SkLineClipper::ClipLine(const SkPoint pts[], const SkRect& clip,
*r = tmp[index1];
}
- lineCount = r - result;
+ lineCount = SkToInt(r - result);
}
// Now copy the results into the caller's lines[] parameter
diff --git a/chromium/third_party/skia/src/core/SkLineClipper.h b/chromium/third_party/skia/src/core/SkLineClipper.h
new file mode 100644
index 00000000000..8026890b8d0
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkLineClipper.h
@@ -0,0 +1,47 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkLineClipper_DEFINED
+#define SkLineClipper_DEFINED
+
+#include "SkRect.h"
+#include "SkPoint.h"
+
+class SkLineClipper {
+public:
+ enum {
+ kMaxPoints = 4,
+ kMaxClippedLineSegments = kMaxPoints - 1
+ };
+
+ /* Clip the line pts[0]...pts[1] against clip, ignoring segments that
+ lie completely above or below the clip. For portions to the left or
+ right, turn those into vertical line segments that are aligned to the
+ edge of the clip.
+
+ Return the number of line segments that result, and store the end-points
+ of those segments sequentially in lines as follows:
+ 1st segment: lines[0]..lines[1]
+ 2nd segment: lines[1]..lines[2]
+ 3rd segment: lines[2]..lines[3]
+ */
+ static int ClipLine(const SkPoint pts[2], const SkRect& clip,
+ SkPoint lines[kMaxPoints]);
+
+ /* Intersect the line segment against the rect. If there is a non-empty
+ resulting segment, return true and set dst[] to that segment. If not,
+ return false and ignore dst[].
+
+ ClipLine is specialized for scan-conversion, as it adds vertical
+ segments on the sides to show where the line extended beyond the
+ left or right sides. IntersectLine does not.
+ */
+ static bool IntersectLine(const SkPoint src[2], const SkRect& clip,
+ SkPoint dst[2]);
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/core/SkLocalMatrixShader.cpp b/chromium/third_party/skia/src/core/SkLocalMatrixShader.cpp
new file mode 100644
index 00000000000..53580e6ac95
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkLocalMatrixShader.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkLocalMatrixShader.h"
+
+SkLocalMatrixShader::SkLocalMatrixShader(SkReadBuffer& buffer) : INHERITED(buffer) {
+ buffer.readMatrix(&fProxyLocalMatrix);
+ fProxyShader.reset(buffer.readShader());
+ if (NULL == fProxyShader.get()) {
+ sk_throw();
+ }
+}
+
+void SkLocalMatrixShader::flatten(SkWriteBuffer& buffer) const {
+ this->INHERITED::flatten(buffer);
+ buffer.writeMatrix(fProxyLocalMatrix);
+ buffer.writeFlattenable(fProxyShader.get());
+}
+
+SkShader::Context* SkLocalMatrixShader::onCreateContext(const ContextRec& rec,
+ void* storage) const {
+ ContextRec newRec(rec);
+ SkMatrix tmp;
+ if (rec.fLocalMatrix) {
+ tmp.setConcat(fProxyLocalMatrix, *rec.fLocalMatrix);
+ newRec.fLocalMatrix = &tmp;
+ } else {
+ newRec.fLocalMatrix = &fProxyLocalMatrix;
+ }
+ return fProxyShader->createContext(newRec, storage);
+}
+
+#ifndef SK_IGNORE_TO_STRING
+void SkLocalMatrixShader::toString(SkString* str) const {
+ str->append("SkLocalMatrixShader: (");
+
+ fProxyShader->toString(str);
+
+ this->INHERITED::toString(str);
+
+ str->append(")");
+}
+#endif
+
+SkShader* SkShader::CreateLocalMatrixShader(SkShader* proxy, const SkMatrix& localMatrix) {
+ if (localMatrix.isIdentity()) {
+ return SkRef(proxy);
+ }
+
+ const SkMatrix* lm = &localMatrix;
+
+ SkMatrix otherLocalMatrix;
+ SkAutoTUnref<SkShader> otherProxy(proxy->refAsALocalMatrixShader(&otherLocalMatrix));
+ if (otherProxy.get()) {
+ otherLocalMatrix.preConcat(localMatrix);
+ lm = &otherLocalMatrix;
+ proxy = otherProxy.get();
+ }
+
+ return SkNEW_ARGS(SkLocalMatrixShader, (proxy, *lm));
+}
diff --git a/chromium/third_party/skia/src/core/SkLocalMatrixShader.h b/chromium/third_party/skia/src/core/SkLocalMatrixShader.h
new file mode 100644
index 00000000000..1143f062d38
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkLocalMatrixShader.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkLocalMatrixShader_DEFINED
+#define SkLocalMatrixShader_DEFINED
+
+#include "SkShader.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
+
+class SkLocalMatrixShader : public SkShader {
+public:
+ SkLocalMatrixShader(SkShader* proxy, const SkMatrix& localMatrix)
+ : fProxyShader(SkRef(proxy))
+ , fProxyLocalMatrix(localMatrix)
+ {}
+
+ virtual size_t contextSize() const SK_OVERRIDE {
+ return fProxyShader->contextSize();
+ }
+
+ virtual BitmapType asABitmap(SkBitmap* bitmap, SkMatrix* matrix,
+ TileMode* mode) const SK_OVERRIDE {
+ return fProxyShader->asABitmap(bitmap, matrix, mode);
+ }
+
+ virtual GradientType asAGradient(GradientInfo* info) const SK_OVERRIDE {
+ return fProxyShader->asAGradient(info);
+ }
+
+#if SK_SUPPORT_GPU
+
+ virtual bool asNewEffect(GrContext* context, const SkPaint& paint, const SkMatrix* localMatrix,
+ GrColor* grColor, GrEffectRef** grEffect) const SK_OVERRIDE {
+ SkMatrix tmp = fProxyLocalMatrix;
+ if (localMatrix) {
+ tmp.preConcat(*localMatrix);
+ }
+ return fProxyShader->asNewEffect(context, paint, &tmp, grColor, grEffect);
+ }
+
+#else
+
+ virtual bool asNewEffect(GrContext* context, const SkPaint& paint, const SkMatrix* localMatrix,
+ GrColor* grColor, GrEffectRef** grEffect) const SK_OVERRIDE {
+ SkDEBUGFAIL("Should not call in GPU-less build");
+ return false;
+ }
+
+#endif
+
+ virtual SkShader* refAsALocalMatrixShader(SkMatrix* localMatrix) const SK_OVERRIDE {
+ if (localMatrix) {
+ *localMatrix = fProxyLocalMatrix;
+ }
+ return SkRef(fProxyShader.get());
+ }
+
+ SK_TO_STRING_OVERRIDE()
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLocalMatrixShader)
+
+protected:
+ SkLocalMatrixShader(SkReadBuffer&);
+ virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
+ virtual Context* onCreateContext(const ContextRec&, void*) const SK_OVERRIDE;
+
+private:
+ SkAutoTUnref<SkShader> fProxyShader;
+ SkMatrix fProxyLocalMatrix;
+
+ typedef SkShader INHERITED;
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/core/SkMallocPixelRef.cpp b/chromium/third_party/skia/src/core/SkMallocPixelRef.cpp
index d3bf9d1870c..12cb05bd729 100644
--- a/chromium/third_party/skia/src/core/SkMallocPixelRef.cpp
+++ b/chromium/third_party/skia/src/core/SkMallocPixelRef.cpp
@@ -7,7 +7,13 @@
#include "SkMallocPixelRef.h"
#include "SkBitmap.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
+
+// assumes ptr was allocated via sk_malloc
+static void sk_free_releaseproc(void* ptr, void*) {
+ sk_free(ptr);
+}
static bool is_valid(const SkImageInfo& info, SkColorTable* ctable) {
if (info.fWidth < 0 ||
@@ -17,7 +23,7 @@ static bool is_valid(const SkImageInfo& info, SkColorTable* ctable) {
{
return false;
}
-
+
// these seem like good checks, but currently we have (at least) tests
// that expect the pixelref to succeed even when there is a mismatch
// with colortables. fix?
@@ -39,9 +45,11 @@ SkMallocPixelRef* SkMallocPixelRef::NewDirect(const SkImageInfo& info,
if (!is_valid(info, ctable)) {
return NULL;
}
- return SkNEW_ARGS(SkMallocPixelRef, (info, addr, rowBytes, ctable, false));
+ return SkNEW_ARGS(SkMallocPixelRef,
+ (info, addr, rowBytes, ctable, NULL, NULL));
}
+
SkMallocPixelRef* SkMallocPixelRef::NewAllocate(const SkImageInfo& info,
size_t requestedRowBytes,
SkColorTable* ctable) {
@@ -49,7 +57,7 @@ SkMallocPixelRef* SkMallocPixelRef::NewAllocate(const SkImageInfo& info,
return NULL;
}
- int32_t minRB = info.minRowBytes();
+ int32_t minRB = SkToS32(info.minRowBytes());
if (minRB < 0) {
return NULL; // allocation will be too large
}
@@ -59,24 +67,67 @@ SkMallocPixelRef* SkMallocPixelRef::NewAllocate(const SkImageInfo& info,
int32_t rowBytes;
if (requestedRowBytes) {
- rowBytes = requestedRowBytes;
+ rowBytes = SkToS32(requestedRowBytes);
} else {
rowBytes = minRB;
}
- Sk64 bigSize;
- bigSize.setMul(info.fHeight, rowBytes);
- if (!bigSize.is32()) {
+ int64_t bigSize = (int64_t)info.fHeight * rowBytes;
+ if (!sk_64_isS32(bigSize)) {
return NULL;
}
- size_t size = bigSize.get32();
+ size_t size = sk_64_asS32(bigSize);
+ SkASSERT(size >= info.getSafeSize(rowBytes));
void* addr = sk_malloc_flags(size, 0);
if (NULL == addr) {
return NULL;
}
- return SkNEW_ARGS(SkMallocPixelRef, (info, addr, rowBytes, ctable, true));
+ return SkNEW_ARGS(SkMallocPixelRef,
+ (info, addr, rowBytes, ctable,
+ sk_free_releaseproc, NULL));
+}
+
+SkMallocPixelRef* SkMallocPixelRef::NewWithProc(const SkImageInfo& info,
+ size_t rowBytes,
+ SkColorTable* ctable,
+ void* addr,
+ SkMallocPixelRef::ReleaseProc proc,
+ void* context) {
+ if (!is_valid(info, ctable)) {
+ return NULL;
+ }
+ return SkNEW_ARGS(SkMallocPixelRef,
+ (info, addr, rowBytes, ctable, proc, context));
+}
+
+static void sk_data_releaseproc(void*, void* dataPtr) {
+ (static_cast<SkData*>(dataPtr))->unref();
+}
+
+SkMallocPixelRef* SkMallocPixelRef::NewWithData(const SkImageInfo& info,
+ size_t rowBytes,
+ SkColorTable* ctable,
+ SkData* data) {
+ SkASSERT(data != NULL);
+ if (!is_valid(info, ctable)) {
+ return NULL;
+ }
+ if ((rowBytes < info.minRowBytes())
+ || (data->size() < info.getSafeSize(rowBytes))) {
+ return NULL;
+ }
+ data->ref();
+ SkMallocPixelRef* pr
+ = SkNEW_ARGS(SkMallocPixelRef,
+ (info, const_cast<void*>(data->data()), rowBytes, ctable,
+ sk_data_releaseproc, static_cast<void*>(data)));
+ SkASSERT(pr != NULL);
+ // We rely on the immutability of the pixels to make the
+ // const_cast okay.
+ pr->setImmutable();
+ return pr;
}
///////////////////////////////////////////////////////////////////////////////
@@ -85,7 +136,31 @@ SkMallocPixelRef::SkMallocPixelRef(const SkImageInfo& info, void* storage,
size_t rowBytes, SkColorTable* ctable,
bool ownsPixels)
: INHERITED(info)
- , fOwnPixels(ownsPixels)
+ , fReleaseProc(ownsPixels ? sk_free_releaseproc : NULL)
+ , fReleaseProcContext(NULL) {
+ // This constructor is now DEPRICATED.
+ SkASSERT(is_valid(info, ctable));
+ SkASSERT(rowBytes >= info.minRowBytes());
+
+ if (kIndex_8_SkColorType != info.fColorType) {
+ ctable = NULL;
+ }
+
+ fStorage = storage;
+ fCTable = ctable;
+ fRB = rowBytes;
+ SkSafeRef(ctable);
+
+ this->setPreLocked(fStorage, rowBytes, fCTable);
+}
+
+SkMallocPixelRef::SkMallocPixelRef(const SkImageInfo& info, void* storage,
+ size_t rowBytes, SkColorTable* ctable,
+ SkMallocPixelRef::ReleaseProc proc,
+ void* context)
+ : INHERITED(info)
+ , fReleaseProc(proc)
+ , fReleaseProcContext(context)
{
SkASSERT(is_valid(info, ctable));
SkASSERT(rowBytes >= info.minRowBytes());
@@ -98,20 +173,23 @@ SkMallocPixelRef::SkMallocPixelRef(const SkImageInfo& info, void* storage,
fCTable = ctable;
fRB = rowBytes;
SkSafeRef(ctable);
-
- this->setPreLocked(fStorage, fCTable);
+
+ this->setPreLocked(fStorage, rowBytes, fCTable);
}
+
SkMallocPixelRef::~SkMallocPixelRef() {
SkSafeUnref(fCTable);
- if (fOwnPixels) {
- sk_free(fStorage);
+ if (fReleaseProc != NULL) {
+ fReleaseProc(fStorage, fReleaseProcContext);
}
}
-void* SkMallocPixelRef::onLockPixels(SkColorTable** ctable) {
- *ctable = fCTable;
- return fStorage;
+bool SkMallocPixelRef::onNewLockPixels(LockRec* rec) {
+ rec->fPixels = fStorage;
+ rec->fRowBytes = fRB;
+ rec->fColorTable = fCTable;
+ return true;
}
void SkMallocPixelRef::onUnlockPixels() {
@@ -122,10 +200,10 @@ size_t SkMallocPixelRef::getAllocatedSizeInBytes() const {
return this->info().getSafeSize(fRB);
}
-void SkMallocPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkMallocPixelRef::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
- buffer.write32(fRB);
+ buffer.write32(SkToU32(fRB));
// TODO: replace this bulk write with a chunky one that can trim off any
// trailing bytes on each scanline (in case rowbytes > width*size)
@@ -137,19 +215,32 @@ void SkMallocPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
}
}
-SkMallocPixelRef::SkMallocPixelRef(SkFlattenableReadBuffer& buffer)
+SkMallocPixelRef::SkMallocPixelRef(SkReadBuffer& buffer)
: INHERITED(buffer, NULL)
- , fOwnPixels(true)
+ , fReleaseProc(sk_free_releaseproc)
+ , fReleaseProcContext(NULL)
{
fRB = buffer.read32();
size_t size = buffer.isValid() ? this->info().getSafeSize(fRB) : 0;
- fStorage = sk_malloc_throw(size);
- buffer.readByteArray(fStorage, size);
+ if (buffer.validateAvailable(size)) {
+ fStorage = sk_malloc_throw(size);
+ buffer.readByteArray(fStorage, size);
+ } else {
+ fStorage = NULL;
+ }
+
if (buffer.readBool()) {
fCTable = SkNEW_ARGS(SkColorTable, (buffer));
} else {
fCTable = NULL;
}
- this->setPreLocked(fStorage, fCTable);
+ this->setPreLocked(fStorage, fRB, fCTable);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+SkPixelRef* SkMallocPixelRef::PRFactory::create(const SkImageInfo& info,
+ SkColorTable* ctable) {
+ return SkMallocPixelRef::NewAllocate(info, info.minRowBytes(), ctable);
}
diff --git a/chromium/third_party/skia/src/core/SkMask.cpp b/chromium/third_party/skia/src/core/SkMask.cpp
index 09744194b9d..929835717ba 100644
--- a/chromium/third_party/skia/src/core/SkMask.cpp
+++ b/chromium/third_party/skia/src/core/SkMask.cpp
@@ -5,18 +5,15 @@
* found in the LICENSE file.
*/
-
-#include "Sk64.h"
#include "SkMask.h"
/** returns the product if it is positive and fits in 31 bits. Otherwise this
returns 0.
*/
static int32_t safeMul32(int32_t a, int32_t b) {
- Sk64 size;
- size.setMul(a, b);
- if (size.is32() && size.isPos()) {
- return size.get32();
+ int64_t size = sk_64_mul(a, b);
+ if (size > 0 && sk_64_isS32(size)) {
+ return sk_64_asS32(size);
}
return 0;
}
@@ -28,7 +25,7 @@ size_t SkMask::computeImageSize() const {
size_t SkMask::computeTotalImageSize() const {
size_t size = this->computeImageSize();
if (fFormat == SkMask::k3D_Format) {
- size = safeMul32(size, 3);
+ size = safeMul32(SkToS32(size), 3);
}
return size;
}
diff --git a/chromium/third_party/skia/src/core/SkMaskFilter.cpp b/chromium/third_party/skia/src/core/SkMaskFilter.cpp
index 1bc17bb47fa..2ab2843641a 100644
--- a/chromium/third_party/skia/src/core/SkMaskFilter.cpp
+++ b/chromium/third_party/skia/src/core/SkMaskFilter.cpp
@@ -9,7 +9,6 @@
#include "SkMaskFilter.h"
#include "SkBlitter.h"
-#include "SkBounder.h"
#include "SkDraw.h"
#include "SkRasterClip.h"
#include "SkRRect.h"
@@ -26,6 +25,10 @@ bool SkMaskFilter::filterMask(SkMask*, const SkMask&, const SkMatrix&,
return false;
}
+bool SkMaskFilter::asABlur(BlurRec*) const {
+ return false;
+}
+
static void extractMaskSubset(const SkMask& src, SkMask* dst) {
SkASSERT(src.fBounds.contains(dst->fBounds));
@@ -177,17 +180,15 @@ static void draw_nine_clipped(const SkMask& mask, const SkIRect& outerR,
}
}
-static void draw_nine(const SkMask& mask, const SkIRect& outerR,
- const SkIPoint& center, bool fillCenter,
- const SkRasterClip& clip, SkBounder* bounder,
- SkBlitter* blitter) {
+static void draw_nine(const SkMask& mask, const SkIRect& outerR, const SkIPoint& center,
+ bool fillCenter, const SkRasterClip& clip, SkBlitter* blitter) {
// if we get here, we need to (possibly) resolve the clip and blitter
SkAAClipBlitterWrapper wrapper(clip, blitter);
blitter = wrapper.getBlitter();
SkRegion::Cliperator clipper(wrapper.getRgn(), outerR);
- if (!clipper.done() && (!bounder || bounder->doIRect(outerR))) {
+ if (!clipper.done()) {
const SkIRect& cr = clipper.rect();
do {
draw_nine_clipped(mask, outerR, center, fillCenter, cr, blitter);
@@ -204,8 +205,8 @@ static int countNestedRects(const SkPath& path, SkRect rects[2]) {
}
bool SkMaskFilter::filterRRect(const SkRRect& devRRect, const SkMatrix& matrix,
- const SkRasterClip& clip, SkBounder* bounder,
- SkBlitter* blitter, SkPaint::Style style) const {
+ const SkRasterClip& clip, SkBlitter* blitter,
+ SkPaint::Style style) const {
// Attempt to speed up drawing by creating a nine patch. If a nine patch
// cannot be used, return false to allow our caller to recover and perform
// the drawing another way.
@@ -217,15 +218,14 @@ bool SkMaskFilter::filterRRect(const SkRRect& devRRect, const SkMatrix& matrix,
SkASSERT(NULL == patch.fMask.fImage);
return false;
}
- draw_nine(patch.fMask, patch.fOuterRect, patch.fCenter, true, clip,
- bounder, blitter);
+ draw_nine(patch.fMask, patch.fOuterRect, patch.fCenter, true, clip, blitter);
SkMask::FreeImage(patch.fMask.fImage);
return true;
}
bool SkMaskFilter::filterPath(const SkPath& devPath, const SkMatrix& matrix,
- const SkRasterClip& clip, SkBounder* bounder,
- SkBlitter* blitter, SkPaint::Style style) const {
+ const SkRasterClip& clip, SkBlitter* blitter,
+ SkPaint::Style style) const {
SkRect rects[2];
int rectCount = 0;
if (SkPaint::kFill_Style == style) {
@@ -242,8 +242,8 @@ bool SkMaskFilter::filterPath(const SkPath& devPath, const SkMatrix& matrix,
return false;
case kTrue_FilterReturn:
- draw_nine(patch.fMask, patch.fOuterRect, patch.fCenter,
- 1 == rectCount, clip, bounder, blitter);
+ draw_nine(patch.fMask, patch.fOuterRect, patch.fCenter, 1 == rectCount, clip,
+ blitter);
SkMask::FreeImage(patch.fMask.fImage);
return true;
@@ -274,7 +274,7 @@ bool SkMaskFilter::filterPath(const SkPath& devPath, const SkMatrix& matrix,
SkRegion::Cliperator clipper(wrapper.getRgn(), dstM.fBounds);
- if (!clipper.done() && (bounder == NULL || bounder->doIRect(dstM.fBounds))) {
+ if (!clipper.done()) {
const SkIRect& cr = clipper.rect();
do {
blitter->blitMask(dstM, cr);
@@ -298,7 +298,7 @@ SkMaskFilter::filterRectsToNine(const SkRect[], int count, const SkMatrix&,
}
#if SK_SUPPORT_GPU
-bool SkMaskFilter::asNewEffect(GrEffectRef** effect, GrTexture*) const {
+bool SkMaskFilter::asNewEffect(GrEffectRef** effect, GrTexture*, const SkMatrix&) const {
return false;
}
@@ -309,58 +309,23 @@ bool SkMaskFilter::canFilterMaskGPU(const SkRect& devBounds,
return false;
}
-bool SkMaskFilter::filterMaskGPU(GrContext* context,
- const SkBitmap& srcBM,
- const SkRect& maskRect,
- SkBitmap* resultBM) const {
- SkAutoTUnref<GrTexture> src;
- bool canOverwriteSrc = false;
- if (NULL == srcBM.getTexture()) {
- GrTextureDesc desc;
- // Needs to be a render target to be overwritten in filterMaskGPU
- desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
- desc.fConfig = SkBitmapConfig2GrPixelConfig(srcBM.config());
- desc.fWidth = srcBM.width();
- desc.fHeight = srcBM.height();
-
- // TODO: right now this is exact to guard against out of bounds reads
- // by the filter code. More thought needs to be devoted to the
- // "filterMaskGPU" contract and then enforced (i.e., clamp the code
- // in "filterMaskGPU" so it never samples beyond maskRect)
- GrAutoScratchTexture ast(context, desc, GrContext::kExact_ScratchTexMatch);
- if (NULL == ast.texture()) {
- return false;
- }
-
- SkAutoLockPixels alp(srcBM);
- ast.texture()->writePixels(0, 0, srcBM.width(), srcBM.height(),
- desc.fConfig,
- srcBM.getPixels(), srcBM.rowBytes());
-
- src.reset(ast.detach());
- canOverwriteSrc = true;
- } else {
- src.reset((GrTexture*) srcBM.getTexture());
- src.get()->ref();
- }
- GrTexture* dst;
+ bool SkMaskFilter::directFilterMaskGPU(GrContext* context,
+ GrPaint* grp,
+ const SkStrokeRec& strokeRec,
+ const SkPath& path) const {
+ return false;
+}
- bool result = this->filterMaskGPU(src, maskRect, &dst, canOverwriteSrc);
- if (!result) {
- return false;
- }
- SkAutoUnref aur(dst);
- SkImageInfo info;
- resultBM->setConfig(srcBM.config(), dst->width(), dst->height());
- if (!resultBM->asImageInfo(&info)) {
- return false;
- }
- resultBM->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, dst)))->unref();
- return true;
+bool SkMaskFilter::directFilterRRectMaskGPU(GrContext* context,
+ GrPaint* grp,
+ const SkStrokeRec& strokeRec,
+ const SkRRect& rrect) const {
+ return false;
}
bool SkMaskFilter::filterMaskGPU(GrTexture* src,
+ const SkMatrix& ctm,
const SkRect& maskRect,
GrTexture** result,
bool canOverwriteSrc) const {
diff --git a/chromium/third_party/skia/src/core/SkMaskGamma.h b/chromium/third_party/skia/src/core/SkMaskGamma.h
index 1f2b73caacd..08ed97f913f 100644
--- a/chromium/third_party/skia/src/core/SkMaskGamma.h
+++ b/chromium/third_party/skia/src/core/SkMaskGamma.h
@@ -136,6 +136,22 @@ public:
*/
PreBlend preBlend(SkColor color) const;
+ /**
+ * Get dimensions for the full table set, so it can be allocated as a block.
+ */
+ void getGammaTableDimensions(int* tableWidth, int* numTables) const {
+ *tableWidth = 256;
+ *numTables = (1 << MAX_LUM_BITS);
+ }
+
+ /**
+ * Provides direct access to the full table set, so it can be uploaded
+ * into a texture.
+ */
+ const uint8_t* getGammaTables() const {
+ return (const uint8_t*) fGammaTables;
+ }
+
private:
static const int MAX_LUM_BITS =
B_LUM_BITS > (R_LUM_BITS > G_LUM_BITS ? R_LUM_BITS : G_LUM_BITS)
diff --git a/chromium/third_party/skia/src/core/SkMath.cpp b/chromium/third_party/skia/src/core/SkMath.cpp
index 2693e5c13c1..aeacebecd45 100644
--- a/chromium/third_party/skia/src/core/SkMath.cpp
+++ b/chromium/third_party/skia/src/core/SkMath.cpp
@@ -6,17 +6,13 @@
*/
#include "SkMathPriv.h"
-#include "SkCordic.h"
#include "SkFloatBits.h"
#include "SkFloatingPoint.h"
-#include "Sk64.h"
#include "SkScalar.h"
-#ifdef SK_SCALAR_IS_FLOAT
- const uint32_t gIEEENotANumber = 0x7FFFFFFF;
- const uint32_t gIEEEInfinity = 0x7F800000;
- const uint32_t gIEEENegativeInfinity = 0xFF800000;
-#endif
+const uint32_t gIEEENotANumber = 0x7FFFFFFF;
+const uint32_t gIEEEInfinity = 0x7F800000;
+const uint32_t gIEEENegativeInfinity = 0xFF800000;
#define sub_shift(zeros, x, n) \
zeros -= n; \
@@ -47,73 +43,9 @@ int SkCLZ_portable(uint32_t x) {
return zeros;
}
-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
- // we want (hi << (32 - shift)) | (lo >> shift) but rounded
- int roundBit = (lo >> (shift - 1)) & 1;
- return ((hi << (32 - shift)) | (lo >> shift)) + roundBit;
- }
-}
-
SkFixed SkFixedMul_portable(SkFixed a, SkFixed b) {
-#if 0
- Sk64 tmp;
-
- tmp.setMul(a, b);
- tmp.shiftRight(16);
- return tmp.fLo;
-#elif defined(SkLONGLONG)
- return static_cast<SkFixed>((SkLONGLONG)a * b >> 16);
+#if defined(SkLONGLONG)
+ return static_cast<SkFixed>((int64_t)a * b >> 16);
#else
int sa = SkExtractSign(a);
int sb = SkExtractSign(b);
@@ -132,103 +64,6 @@ SkFixed SkFixedMul_portable(SkFixed a, SkFixed b) {
#endif
}
-SkFract SkFractMul_portable(SkFract a, SkFract b) {
-#if 0
- Sk64 tmp;
- tmp.setMul(a, b);
- return tmp.getFract();
-#elif defined(SkLONGLONG)
- return static_cast<SkFract>((SkLONGLONG)a * b >> 30);
-#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
-}
-
-int SkFixedMulCommon(SkFixed a, int b, int bias) {
- // this function only works if b is 16bits
- SkASSERT(b == (int16_t)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);
-}
-
-#ifdef SK_DEBUGx
- #define TEST_FASTINVERT
-#endif
-
-SkFixed SkFixedFastInvert(SkFixed x) {
-/* Adapted (stolen) from gglRecip()
-*/
-
- if (x == SK_Fixed1) {
- return SK_Fixed1;
- }
-
- int sign = SkExtractSign(x);
- uint32_t a = SkApplySign(x, sign);
-
- if (a <= 2) {
- return SkApplySign(SK_MaxS32, sign);
- }
-
-#ifdef TEST_FASTINVERT
- SkFixed orig = a;
- uint32_t slow = SkFixedDiv(SK_Fixed1, a);
-#endif
-
- // normalize a
- int lz = SkCLZ(a);
- a = a << lz >> 16;
-
- // compute 1/a approximation (0.5 <= a < 1.0)
- uint32_t r = 0x17400 - a; // (2.90625 (~2.914) - 2*a) >> 1
-
- // Newton-Raphson iteration:
- // x = r*(2 - a*r) = ((r/2)*(1 - a*r/2))*4
- r = ( (0x10000 - ((a*r)>>16)) * r ) >> 15;
- r = ( (0x10000 - ((a*r)>>16)) * r ) >> (30 - lz);
-
-#ifdef TEST_FASTINVERT
- SkDebugf("SkFixedFastInvert(%x %g) = %x %g Slow[%x %g]\n",
- orig, orig/65536.,
- r, r/65536.,
- slow, slow/65536.);
-#endif
-
- return SkApplySign(r, sign);
-}
-
///////////////////////////////////////////////////////////////////////////////
#define DIVBITS_ITER(n) \
@@ -297,26 +132,6 @@ int32_t SkDivBits(int32_t numer, int32_t denom, int shift_bias) {
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) {
@@ -342,41 +157,8 @@ int32_t SkSqrtBits(int32_t x, int count) {
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);
@@ -392,7 +174,6 @@ float SkScalarSinCos(float radians, float* cosValue) {
}
return sinValue;
}
-#endif
#define INTERP_SINTABLE
#define BUILD_TABLE_AT_RUNTIMEx
@@ -506,12 +287,3 @@ SkFixed SkFixedSinCos(SkFixed radians, SkFixed* cosValuePtr) {
}
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); }
diff --git a/chromium/third_party/skia/src/core/SkMathPriv.h b/chromium/third_party/skia/src/core/SkMathPriv.h
index 4eaad8b9b16..f93ab610787 100644
--- a/chromium/third_party/skia/src/core/SkMathPriv.h
+++ b/chromium/third_party/skia/src/core/SkMathPriv.h
@@ -39,16 +39,6 @@ static inline unsigned SkClampUMax(unsigned value, unsigned max) {
return value;
}
-/** Computes the 64bit product of a * b, and then shifts the answer down by
- shift bits, returning the low 32bits. shift must be [0..63]
- e.g. to perform a fixedmul, call SkMulShift(a, b, 16)
- */
-int32_t SkMulShift(int32_t a, int32_t b, unsigned shift);
-
-/** Return the integer cube root of value, with a bias of bitBias
- */
-int32_t SkCubeRootBits(int32_t value, int bitBias);
-
///////////////////////////////////////////////////////////////////////////////
/** Return a*b/255, truncating away any fractional bits. Only valid if both
diff --git a/chromium/third_party/skia/src/core/SkMatrix.cpp b/chromium/third_party/skia/src/core/SkMatrix.cpp
index d9c2677a577..95662fc4cd4 100644
--- a/chromium/third_party/skia/src/core/SkMatrix.cpp
+++ b/chromium/third_party/skia/src/core/SkMatrix.cpp
@@ -6,20 +6,29 @@
*/
#include "SkMatrix.h"
-#include "Sk64.h"
#include "SkFloatBits.h"
-#include "SkOnce.h"
#include "SkString.h"
-#ifdef SK_SCALAR_IS_FLOAT
- #define kMatrix22Elem SK_Scalar1
+#include <stddef.h>
- static inline float SkDoubleToFloat(double x) {
- return static_cast<float>(x);
- }
-#else
- #define kMatrix22Elem SK_Fract1
-#endif
+// In a few places, we performed the following
+// a * b + c * d + e
+// as
+// a * b + (c * d + e)
+//
+// sdot and scross are indended to capture these compound operations into a
+// function, with an eye toward considering upscaling the intermediates to
+// doubles for more precision (as we do in concat and invert).
+//
+// However, these few lines that performed the last add before the "dot", cause
+// tiny image differences, so we guard that change until we see the impact on
+// chrome's layouttests.
+//
+#define SK_LEGACY_MATRIX_MATH_ORDER
+
+static inline float SkDoubleToFloat(double x) {
+ return static_cast<float>(x);
+}
/* [scale-x skew-x trans-x] [X] [X']
[skew-y scale-y trans-y] * [Y] = [Y']
@@ -27,11 +36,10 @@
*/
void SkMatrix::reset() {
- fMat[kMScaleX] = fMat[kMScaleY] = SK_Scalar1;
+ fMat[kMScaleX] = fMat[kMScaleY] = fMat[kMPersp2] = 1;
fMat[kMSkewX] = fMat[kMSkewY] =
fMat[kMTransX] = fMat[kMTransY] =
fMat[kMPersp0] = fMat[kMPersp1] = 0;
- fMat[kMPersp2] = kMatrix22Elem;
this->setTypeMask(kIdentity_Mask | kRectStaysRect_Mask);
}
@@ -45,38 +53,19 @@ enum {
kRectStaysRect_Shift
};
-#ifdef SK_SCALAR_IS_FLOAT
- static const int32_t kScalar1Int = 0x3f800000;
-#else
- #define scalarAsInt(x) (x)
- static const int32_t kScalar1Int = (1 << 16);
- static const int32_t kPersp1Int = (1 << 30);
-#endif
-
-#ifdef SK_SCALAR_SLOW_COMPARES
- static const int32_t kPersp1Int = 0x3f800000;
-#endif
+static const int32_t kScalar1Int = 0x3f800000;
uint8_t SkMatrix::computePerspectiveTypeMask() const {
-#ifdef SK_SCALAR_SLOW_COMPARES
- if (SkScalarAs2sCompliment(fMat[kMPersp0]) |
- SkScalarAs2sCompliment(fMat[kMPersp1]) |
- (SkScalarAs2sCompliment(fMat[kMPersp2]) - kPersp1Int)) {
- return SkToU8(kORableMasks);
- }
-#else
// Benchmarking suggests that replacing this set of SkScalarAs2sCompliment
// is a win, but replacing those below is not. We don't yet understand
// that result.
- if (fMat[kMPersp0] != 0 || fMat[kMPersp1] != 0 ||
- fMat[kMPersp2] != kMatrix22Elem) {
+ if (fMat[kMPersp0] != 0 || fMat[kMPersp1] != 0 || fMat[kMPersp2] != 1) {
// If this is a perspective transform, we return true for all other
// transform flags - this does not disable any optimizations, respects
// the rule that the type mask must be conservative, and speeds up
// type mask computation.
return SkToU8(kORableMasks);
}
-#endif
return SkToU8(kOnlyPerspectiveValid_Mask | kUnknown_Mask);
}
@@ -84,20 +73,7 @@ uint8_t SkMatrix::computePerspectiveTypeMask() const {
uint8_t SkMatrix::computeTypeMask() const {
unsigned mask = 0;
-#ifdef SK_SCALAR_SLOW_COMPARES
- if (SkScalarAs2sCompliment(fMat[kMPersp0]) |
- SkScalarAs2sCompliment(fMat[kMPersp1]) |
- (SkScalarAs2sCompliment(fMat[kMPersp2]) - kPersp1Int)) {
- return SkToU8(kORableMasks);
- }
-
- if (SkScalarAs2sCompliment(fMat[kMTransX]) |
- SkScalarAs2sCompliment(fMat[kMTransY])) {
- mask |= kTranslate_Mask;
- }
-#else
- if (fMat[kMPersp0] != 0 || fMat[kMPersp1] != 0 ||
- fMat[kMPersp2] != kMatrix22Elem) {
+ if (fMat[kMPersp0] != 0 || fMat[kMPersp1] != 0 || fMat[kMPersp2] != 1) {
// Once it is determined that that this is a perspective transform,
// all other flags are moot as far as optimizations are concerned.
return SkToU8(kORableMasks);
@@ -106,7 +82,6 @@ uint8_t SkMatrix::computeTypeMask() const {
if (fMat[kMTransX] != 0 || fMat[kMTransY] != 0) {
mask |= kTranslate_Mask;
}
-#endif
int m00 = SkScalarAs2sCompliment(fMat[SkMatrix::kMScaleX]);
int m01 = SkScalarAs2sCompliment(fMat[SkMatrix::kMSkewX]);
@@ -158,8 +133,6 @@ uint8_t SkMatrix::computeTypeMask() const {
///////////////////////////////////////////////////////////////////////////////
-#ifdef SK_SCALAR_IS_FLOAT
-
bool operator==(const SkMatrix& a, const SkMatrix& b) {
const SkScalar* SK_RESTRICT ma = a.fMat;
const SkScalar* SK_RESTRICT mb = b.fMat;
@@ -169,8 +142,6 @@ bool operator==(const SkMatrix& a, const SkMatrix& b) {
ma[6] == mb[6] && ma[7] == mb[7] && ma[8] == mb[8];
}
-#endif
-
///////////////////////////////////////////////////////////////////////////////
// helper function to determine if upper-left 2x2 of matrix is degenerate
@@ -249,15 +220,27 @@ bool SkMatrix::preservesRightAngles(SkScalar tol) const {
///////////////////////////////////////////////////////////////////////////////
+static inline SkScalar sdot(SkScalar a, SkScalar b, SkScalar c, SkScalar d) {
+ return a * b + c * d;
+}
+
+static inline SkScalar sdot(SkScalar a, SkScalar b, SkScalar c, SkScalar d,
+ SkScalar e, SkScalar f) {
+ return a * b + c * d + e * f;
+}
+
+static inline SkScalar scross(SkScalar a, SkScalar b, SkScalar c, SkScalar d) {
+ return a * b - c * d;
+}
+
void SkMatrix::setTranslate(SkScalar dx, SkScalar dy) {
if (dx || dy) {
fMat[kMTransX] = dx;
fMat[kMTransY] = dy;
- fMat[kMScaleX] = fMat[kMScaleY] = SK_Scalar1;
+ fMat[kMScaleX] = fMat[kMScaleY] = fMat[kMPersp2] = 1;
fMat[kMSkewX] = fMat[kMSkewY] =
fMat[kMPersp0] = fMat[kMPersp1] = 0;
- fMat[kMPersp2] = kMatrix22Elem;
this->setTypeMask(kTranslate_Mask | kRectStaysRect_Mask);
} else {
@@ -265,50 +248,49 @@ void SkMatrix::setTranslate(SkScalar dx, SkScalar dy) {
}
}
-bool SkMatrix::preTranslate(SkScalar dx, SkScalar dy) {
+void SkMatrix::preTranslate(SkScalar dx, SkScalar dy) {
+ if (!dx && !dy) {
+ return;
+ }
+
if (this->hasPerspective()) {
SkMatrix m;
m.setTranslate(dx, dy);
- return this->preConcat(m);
- }
-
- if (dx || dy) {
- fMat[kMTransX] += SkScalarMul(fMat[kMScaleX], dx) +
- SkScalarMul(fMat[kMSkewX], dy);
- fMat[kMTransY] += SkScalarMul(fMat[kMSkewY], dx) +
- SkScalarMul(fMat[kMScaleY], dy);
-
+ this->preConcat(m);
+ } else {
+ fMat[kMTransX] += sdot(fMat[kMScaleX], dx, fMat[kMSkewX], dy);
+ fMat[kMTransY] += sdot(fMat[kMSkewY], dx, fMat[kMScaleY], dy);
this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
- return true;
}
-bool SkMatrix::postTranslate(SkScalar dx, SkScalar dy) {
+void SkMatrix::postTranslate(SkScalar dx, SkScalar dy) {
+ if (!dx && !dy) {
+ return;
+ }
+
if (this->hasPerspective()) {
SkMatrix m;
m.setTranslate(dx, dy);
- return this->postConcat(m);
- }
-
- if (dx || dy) {
+ this->postConcat(m);
+ } else {
fMat[kMTransX] += dx;
fMat[kMTransY] += dy;
this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
- return true;
}
///////////////////////////////////////////////////////////////////////////////
void SkMatrix::setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
- if (SK_Scalar1 == sx && SK_Scalar1 == sy) {
+ if (1 == sx && 1 == sy) {
this->reset();
} else {
fMat[kMScaleX] = sx;
fMat[kMScaleY] = sy;
- fMat[kMTransX] = px - SkScalarMul(sx, px);
- fMat[kMTransY] = py - SkScalarMul(sy, py);
- fMat[kMPersp2] = kMatrix22Elem;
+ fMat[kMTransX] = px - sx * px;
+ fMat[kMTransY] = py - sy * py;
+ fMat[kMPersp2] = 1;
fMat[kMSkewX] = fMat[kMSkewY] =
fMat[kMPersp0] = fMat[kMPersp1] = 0;
@@ -318,12 +300,12 @@ void SkMatrix::setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
}
void SkMatrix::setScale(SkScalar sx, SkScalar sy) {
- if (SK_Scalar1 == sx && SK_Scalar1 == sy) {
+ if (1 == sx && 1 == sy) {
this->reset();
} else {
fMat[kMScaleX] = sx;
fMat[kMScaleY] = sy;
- fMat[kMPersp2] = kMatrix22Elem;
+ fMat[kMPersp2] = 1;
fMat[kMTransX] = fMat[kMTransY] =
fMat[kMSkewX] = fMat[kMSkewY] =
@@ -337,75 +319,59 @@ bool SkMatrix::setIDiv(int divx, int divy) {
if (!divx || !divy) {
return false;
}
- this->setScale(SK_Scalar1 / divx, SK_Scalar1 / divy);
+ this->setScale(SkScalarInvert(divx), SkScalarInvert(divy));
return true;
}
-bool SkMatrix::preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
+void SkMatrix::preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
+ if (1 == sx && 1 == sy) {
+ return;
+ }
+
SkMatrix m;
m.setScale(sx, sy, px, py);
- return this->preConcat(m);
+ this->preConcat(m);
}
-bool SkMatrix::preScale(SkScalar sx, SkScalar sy) {
- if (SK_Scalar1 == sx && SK_Scalar1 == sy) {
- return true;
+void SkMatrix::preScale(SkScalar sx, SkScalar sy) {
+ if (1 == sx && 1 == sy) {
+ return;
}
-#ifdef SK_SCALAR_IS_FIXED
- SkMatrix m;
- m.setScale(sx, sy);
- return this->preConcat(m);
-#else
// the assumption is that these multiplies are very cheap, and that
// a full concat and/or just computing the matrix type is more expensive.
// Also, the fixed-point case checks for overflow, but the float doesn't,
// so we can get away with these blind multiplies.
- fMat[kMScaleX] = SkScalarMul(fMat[kMScaleX], sx);
- fMat[kMSkewY] = SkScalarMul(fMat[kMSkewY], sx);
- fMat[kMPersp0] = SkScalarMul(fMat[kMPersp0], sx);
+ fMat[kMScaleX] *= sx;
+ fMat[kMSkewY] *= sx;
+ fMat[kMPersp0] *= sx;
- fMat[kMSkewX] = SkScalarMul(fMat[kMSkewX], sy);
- fMat[kMScaleY] = SkScalarMul(fMat[kMScaleY], sy);
- fMat[kMPersp1] = SkScalarMul(fMat[kMPersp1], sy);
+ fMat[kMSkewX] *= sy;
+ fMat[kMScaleY] *= sy;
+ fMat[kMPersp1] *= sy;
this->orTypeMask(kScale_Mask);
- return true;
-#endif
}
-bool SkMatrix::postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
- if (SK_Scalar1 == sx && SK_Scalar1 == sy) {
- return true;
+void SkMatrix::postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
+ if (1 == sx && 1 == sy) {
+ return;
}
SkMatrix m;
m.setScale(sx, sy, px, py);
- return this->postConcat(m);
+ this->postConcat(m);
}
-bool SkMatrix::postScale(SkScalar sx, SkScalar sy) {
- if (SK_Scalar1 == sx && SK_Scalar1 == sy) {
- return true;
+void SkMatrix::postScale(SkScalar sx, SkScalar sy) {
+ if (1 == sx && 1 == sy) {
+ return;
}
SkMatrix m;
m.setScale(sx, sy);
- return this->postConcat(m);
+ this->postConcat(m);
}
-#ifdef SK_SCALAR_IS_FIXED
- static inline SkFixed roundidiv(SkFixed numer, int denom) {
- int ns = numer >> 31;
- int ds = denom >> 31;
- numer = (numer ^ ns) - ns;
- denom = (denom ^ ds) - ds;
-
- SkFixed answer = (numer + (denom >> 1)) / denom;
- int as = ns ^ ds;
- return (answer ^ as) - as;
- }
-#endif
-
// this guy perhaps can go away, if we have a fract/high-precision way to
// scale matrices
bool SkMatrix::postIDiv(int divx, int divy) {
@@ -413,15 +379,6 @@ bool SkMatrix::postIDiv(int divx, int divy) {
return false;
}
-#ifdef SK_SCALAR_IS_FIXED
- fMat[kMScaleX] = roundidiv(fMat[kMScaleX], divx);
- fMat[kMSkewX] = roundidiv(fMat[kMSkewX], divx);
- fMat[kMTransX] = roundidiv(fMat[kMTransX], divx);
-
- fMat[kMScaleY] = roundidiv(fMat[kMScaleY], divy);
- fMat[kMSkewY] = roundidiv(fMat[kMSkewY], divy);
- fMat[kMTransY] = roundidiv(fMat[kMTransY], divy);
-#else
const float invX = 1.f / divx;
const float invY = 1.f / divy;
@@ -432,7 +389,6 @@ bool SkMatrix::postIDiv(int divx, int divy) {
fMat[kMScaleY] *= invY;
fMat[kMSkewY] *= invY;
fMat[kMTransY] *= invY;
-#endif
this->setTypeMask(kUnknown_Mask);
return true;
@@ -442,18 +398,18 @@ bool SkMatrix::postIDiv(int divx, int divy) {
void SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV,
SkScalar px, SkScalar py) {
- const SkScalar oneMinusCosV = SK_Scalar1 - cosV;
+ const SkScalar oneMinusCosV = 1 - cosV;
fMat[kMScaleX] = cosV;
fMat[kMSkewX] = -sinV;
- fMat[kMTransX] = SkScalarMul(sinV, py) + SkScalarMul(oneMinusCosV, px);
+ fMat[kMTransX] = sdot(sinV, py, oneMinusCosV, px);
fMat[kMSkewY] = sinV;
fMat[kMScaleY] = cosV;
- fMat[kMTransY] = SkScalarMul(-sinV, px) + SkScalarMul(oneMinusCosV, py);
+ fMat[kMTransY] = sdot(-sinV, px, oneMinusCosV, py);
fMat[kMPersp0] = fMat[kMPersp1] = 0;
- fMat[kMPersp2] = kMatrix22Elem;
+ fMat[kMPersp2] = 1;
this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
@@ -468,7 +424,7 @@ void SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV) {
fMat[kMTransY] = 0;
fMat[kMPersp0] = fMat[kMPersp1] = 0;
- fMat[kMPersp2] = kMatrix22Elem;
+ fMat[kMPersp2] = 1;
this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
@@ -485,84 +441,84 @@ void SkMatrix::setRotate(SkScalar degrees) {
this->setSinCos(sinV, cosV);
}
-bool SkMatrix::preRotate(SkScalar degrees, SkScalar px, SkScalar py) {
+void SkMatrix::preRotate(SkScalar degrees, SkScalar px, SkScalar py) {
SkMatrix m;
m.setRotate(degrees, px, py);
- return this->preConcat(m);
+ this->preConcat(m);
}
-bool SkMatrix::preRotate(SkScalar degrees) {
+void SkMatrix::preRotate(SkScalar degrees) {
SkMatrix m;
m.setRotate(degrees);
- return this->preConcat(m);
+ this->preConcat(m);
}
-bool SkMatrix::postRotate(SkScalar degrees, SkScalar px, SkScalar py) {
+void SkMatrix::postRotate(SkScalar degrees, SkScalar px, SkScalar py) {
SkMatrix m;
m.setRotate(degrees, px, py);
- return this->postConcat(m);
+ this->postConcat(m);
}
-bool SkMatrix::postRotate(SkScalar degrees) {
+void SkMatrix::postRotate(SkScalar degrees) {
SkMatrix m;
m.setRotate(degrees);
- return this->postConcat(m);
+ this->postConcat(m);
}
////////////////////////////////////////////////////////////////////////////////////
void SkMatrix::setSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
- fMat[kMScaleX] = SK_Scalar1;
+ fMat[kMScaleX] = 1;
fMat[kMSkewX] = sx;
- fMat[kMTransX] = SkScalarMul(-sx, py);
+ fMat[kMTransX] = -sx * py;
fMat[kMSkewY] = sy;
- fMat[kMScaleY] = SK_Scalar1;
- fMat[kMTransY] = SkScalarMul(-sy, px);
+ fMat[kMScaleY] = 1;
+ fMat[kMTransY] = -sy * px;
fMat[kMPersp0] = fMat[kMPersp1] = 0;
- fMat[kMPersp2] = kMatrix22Elem;
+ fMat[kMPersp2] = 1;
this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
void SkMatrix::setSkew(SkScalar sx, SkScalar sy) {
- fMat[kMScaleX] = SK_Scalar1;
+ fMat[kMScaleX] = 1;
fMat[kMSkewX] = sx;
fMat[kMTransX] = 0;
fMat[kMSkewY] = sy;
- fMat[kMScaleY] = SK_Scalar1;
+ fMat[kMScaleY] = 1;
fMat[kMTransY] = 0;
fMat[kMPersp0] = fMat[kMPersp1] = 0;
- fMat[kMPersp2] = kMatrix22Elem;
+ fMat[kMPersp2] = 1;
this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
-bool SkMatrix::preSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
+void SkMatrix::preSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
SkMatrix m;
m.setSkew(sx, sy, px, py);
- return this->preConcat(m);
+ this->preConcat(m);
}
-bool SkMatrix::preSkew(SkScalar sx, SkScalar sy) {
+void SkMatrix::preSkew(SkScalar sx, SkScalar sy) {
SkMatrix m;
m.setSkew(sx, sy);
- return this->preConcat(m);
+ this->preConcat(m);
}
-bool SkMatrix::postSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
+void SkMatrix::postSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
SkMatrix m;
m.setSkew(sx, sy, px, py);
- return this->postConcat(m);
+ this->postConcat(m);
}
-bool SkMatrix::postSkew(SkScalar sx, SkScalar sy) {
+void SkMatrix::postSkew(SkScalar sx, SkScalar sy) {
SkMatrix m;
m.setSkew(sx, sy);
- return this->postConcat(m);
+ this->postConcat(m);
}
///////////////////////////////////////////////////////////////////////////////
@@ -579,8 +535,8 @@ bool SkMatrix::setRectToRect(const SkRect& src, const SkRect& dst,
sk_bzero(fMat, 8 * sizeof(SkScalar));
this->setTypeMask(kScale_Mask | kRectStaysRect_Mask);
} else {
- SkScalar tx, sx = SkScalarDiv(dst.width(), src.width());
- SkScalar ty, sy = SkScalarDiv(dst.height(), src.height());
+ SkScalar tx, sx = dst.width() / src.width();
+ SkScalar ty, sy = dst.height() / src.height();
bool xLarger = false;
if (align != kFill_ScaleToFit) {
@@ -592,15 +548,15 @@ bool SkMatrix::setRectToRect(const SkRect& src, const SkRect& dst,
}
}
- tx = dst.fLeft - SkScalarMul(src.fLeft, sx);
- ty = dst.fTop - SkScalarMul(src.fTop, sy);
+ tx = dst.fLeft - src.fLeft * sx;
+ ty = dst.fTop - src.fTop * sy;
if (align == kCenter_ScaleToFit || align == kEnd_ScaleToFit) {
SkScalar diff;
if (xLarger) {
- diff = dst.width() - SkScalarMul(src.width(), sy);
+ diff = dst.width() - src.width() * sy;
} else {
- diff = dst.height() - SkScalarMul(src.height(), sy);
+ diff = dst.height() - src.height() * sy;
}
if (align == kCenter_ScaleToFit) {
@@ -622,7 +578,7 @@ bool SkMatrix::setRectToRect(const SkRect& src, const SkRect& dst,
fMat[kMPersp0] = fMat[kMPersp1] = 0;
unsigned mask = kRectStaysRect_Mask;
- if (sx != SK_Scalar1 || sy != SK_Scalar1) {
+ if (sx != 1 || sy != 1) {
mask |= kScale_Mask;
}
if (tx || ty) {
@@ -631,86 +587,28 @@ bool SkMatrix::setRectToRect(const SkRect& src, const SkRect& dst,
this->setTypeMask(mask);
}
// shared cleanup
- fMat[kMPersp2] = kMatrix22Elem;
+ fMat[kMPersp2] = 1;
return true;
}
///////////////////////////////////////////////////////////////////////////////
-#ifdef SK_SCALAR_IS_FLOAT
- static inline int fixmuladdmul(float a, float b, float c, float d,
- float* result) {
- *result = SkDoubleToFloat((double)a * b + (double)c * d);
- return true;
- }
-
- static inline bool rowcol3(const float row[], const float col[],
- float* result) {
- *result = row[0] * col[0] + row[1] * col[3] + row[2] * col[6];
- return true;
- }
-
- 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 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 bool rowcol3(const SkFixed row[], const SkFixed col[],
- SkFixed* result) {
- 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);
-
- if (tmp1.isFixed()) {
- *result = tmp1.getFixed();
- return true;
- }
- return false;
- }
+static inline float muladdmul(float a, float b, float c, float d) {
+ return SkDoubleToFloat((double)a * b + (double)c * d);
+}
- static inline int negifaddoverflows(SkFixed& result, SkFixed a, SkFixed b) {
- SkFixed c = a + b;
- result = c;
- return (c ^ a) & (c ^ b);
- }
-#endif
+static inline float rowcol3(const float row[], const float col[]) {
+ return row[0] * col[0] + row[1] * col[3] + row[2] * col[6];
+}
static void normalize_perspective(SkScalar mat[9]) {
- if (SkScalarAbs(mat[SkMatrix::kMPersp2]) > kMatrix22Elem) {
+ if (SkScalarAbs(mat[SkMatrix::kMPersp2]) > 1) {
for (int i = 0; i < 9; i++)
mat[i] = SkScalarHalf(mat[i]);
}
}
-bool SkMatrix::setConcat(const SkMatrix& a, const SkMatrix& b) {
+void SkMatrix::setConcat(const SkMatrix& a, const SkMatrix& b) {
TypeMask aType = a.getPerspectiveTypeMaskOnly();
TypeMask bType = b.getPerspectiveTypeMaskOnly();
@@ -722,94 +620,76 @@ bool SkMatrix::setConcat(const SkMatrix& a, const SkMatrix& b) {
SkMatrix tmp;
if ((aType | bType) & kPerspective_Mask) {
- if (!rowcol3(&a.fMat[0], &b.fMat[0], &tmp.fMat[kMScaleX])) {
- return false;
- }
- if (!rowcol3(&a.fMat[0], &b.fMat[1], &tmp.fMat[kMSkewX])) {
- return false;
- }
- if (!rowcol3(&a.fMat[0], &b.fMat[2], &tmp.fMat[kMTransX])) {
- return false;
- }
-
- if (!rowcol3(&a.fMat[3], &b.fMat[0], &tmp.fMat[kMSkewY])) {
- return false;
- }
- if (!rowcol3(&a.fMat[3], &b.fMat[1], &tmp.fMat[kMScaleY])) {
- return false;
- }
- if (!rowcol3(&a.fMat[3], &b.fMat[2], &tmp.fMat[kMTransY])) {
- return false;
- }
-
- if (!rowcol3(&a.fMat[6], &b.fMat[0], &tmp.fMat[kMPersp0])) {
- return false;
- }
- if (!rowcol3(&a.fMat[6], &b.fMat[1], &tmp.fMat[kMPersp1])) {
- return false;
- }
- if (!rowcol3(&a.fMat[6], &b.fMat[2], &tmp.fMat[kMPersp2])) {
- return false;
- }
+ tmp.fMat[kMScaleX] = rowcol3(&a.fMat[0], &b.fMat[0]);
+ tmp.fMat[kMSkewX] = rowcol3(&a.fMat[0], &b.fMat[1]);
+ tmp.fMat[kMTransX] = rowcol3(&a.fMat[0], &b.fMat[2]);
+ tmp.fMat[kMSkewY] = rowcol3(&a.fMat[3], &b.fMat[0]);
+ tmp.fMat[kMScaleY] = rowcol3(&a.fMat[3], &b.fMat[1]);
+ tmp.fMat[kMTransY] = rowcol3(&a.fMat[3], &b.fMat[2]);
+ tmp.fMat[kMPersp0] = rowcol3(&a.fMat[6], &b.fMat[0]);
+ tmp.fMat[kMPersp1] = rowcol3(&a.fMat[6], &b.fMat[1]);
+ tmp.fMat[kMPersp2] = rowcol3(&a.fMat[6], &b.fMat[2]);
normalize_perspective(tmp.fMat);
tmp.setTypeMask(kUnknown_Mask);
} else { // not perspective
- if (!fixmuladdmul(a.fMat[kMScaleX], b.fMat[kMScaleX],
- a.fMat[kMSkewX], b.fMat[kMSkewY], &tmp.fMat[kMScaleX])) {
- return false;
- }
- if (!fixmuladdmul(a.fMat[kMScaleX], b.fMat[kMSkewX],
- a.fMat[kMSkewX], b.fMat[kMScaleY], &tmp.fMat[kMSkewX])) {
- return false;
- }
- if (!fixmuladdmul(a.fMat[kMScaleX], b.fMat[kMTransX],
- a.fMat[kMSkewX], b.fMat[kMTransY], &tmp.fMat[kMTransX])) {
- return false;
- }
- if (negifaddoverflows(tmp.fMat[kMTransX], tmp.fMat[kMTransX],
- a.fMat[kMTransX]) < 0) {
- return false;
- }
-
- if (!fixmuladdmul(a.fMat[kMSkewY], b.fMat[kMScaleX],
- a.fMat[kMScaleY], b.fMat[kMSkewY], &tmp.fMat[kMSkewY])) {
- return false;
- }
- if (!fixmuladdmul(a.fMat[kMSkewY], b.fMat[kMSkewX],
- a.fMat[kMScaleY], b.fMat[kMScaleY], &tmp.fMat[kMScaleY])) {
- return false;
- }
- if (!fixmuladdmul(a.fMat[kMSkewY], b.fMat[kMTransX],
- a.fMat[kMScaleY], b.fMat[kMTransY], &tmp.fMat[kMTransY])) {
- return false;
- }
- if (negifaddoverflows(tmp.fMat[kMTransY], tmp.fMat[kMTransY],
- a.fMat[kMTransY]) < 0) {
- return false;
- }
-
+ tmp.fMat[kMScaleX] = muladdmul(a.fMat[kMScaleX],
+ b.fMat[kMScaleX],
+ a.fMat[kMSkewX],
+ b.fMat[kMSkewY]);
+
+ tmp.fMat[kMSkewX] = muladdmul(a.fMat[kMScaleX],
+ b.fMat[kMSkewX],
+ a.fMat[kMSkewX],
+ b.fMat[kMScaleY]);
+
+ tmp.fMat[kMTransX] = muladdmul(a.fMat[kMScaleX],
+ b.fMat[kMTransX],
+ a.fMat[kMSkewX],
+ b.fMat[kMTransY]);
+
+ tmp.fMat[kMTransX] += a.fMat[kMTransX];
+
+ tmp.fMat[kMSkewY] = muladdmul(a.fMat[kMSkewY],
+ b.fMat[kMScaleX],
+ a.fMat[kMScaleY],
+ b.fMat[kMSkewY]);
+
+ tmp.fMat[kMScaleY] = muladdmul(a.fMat[kMSkewY],
+ b.fMat[kMSkewX],
+ a.fMat[kMScaleY],
+ b.fMat[kMScaleY]);
+
+ tmp.fMat[kMTransY] = muladdmul(a.fMat[kMSkewY],
+ b.fMat[kMTransX],
+ a.fMat[kMScaleY],
+ b.fMat[kMTransY]);
+
+ tmp.fMat[kMTransY] += a.fMat[kMTransY];
tmp.fMat[kMPersp0] = tmp.fMat[kMPersp1] = 0;
- tmp.fMat[kMPersp2] = kMatrix22Elem;
+ tmp.fMat[kMPersp2] = 1;
//SkDebugf("Concat mat non-persp type: %d\n", tmp.getType());
//SkASSERT(!(tmp.getType() & kPerspective_Mask));
tmp.setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
*this = tmp;
}
- return true;
}
-bool SkMatrix::preConcat(const SkMatrix& mat) {
+void SkMatrix::preConcat(const SkMatrix& mat) {
// check for identity first, so we don't do a needless copy of ourselves
// to ourselves inside setConcat()
- return mat.isIdentity() || this->setConcat(*this, mat);
+ if(!mat.isIdentity()) {
+ this->setConcat(*this, mat);
+ }
}
-bool SkMatrix::postConcat(const SkMatrix& mat) {
+void SkMatrix::postConcat(const SkMatrix& mat) {
// check for identity first, so we don't do a needless copy of ourselves
// to ourselves inside setConcat()
- return mat.isIdentity() || this->setConcat(mat, *this);
+ if (!mat.isIdentity()) {
+ this->setConcat(mat, *this);
+ }
}
///////////////////////////////////////////////////////////////////////////////
@@ -818,94 +698,56 @@ bool SkMatrix::postConcat(const SkMatrix& mat) {
precision may be most important (here and matrix concat). Hence to avoid
bitmap blitting artifacts when walking the inverse, we use doubles for
the intermediate math, even though we know that is more expensive.
- The fixed counter part is us using Sk64 for temp calculations.
*/
-#ifdef SK_SCALAR_IS_FLOAT
- typedef double SkDetScalar;
- #define SkPerspMul(a, b) SkScalarMul(a, b)
- #define SkScalarMulShift(a, b, s) SkDoubleToFloat((a) * (b))
- static double sk_inv_determinant(const float mat[9], int isPerspective,
- int* /* (only used in Fixed case) */) {
- double det;
-
- if (isPerspective) {
- det = mat[SkMatrix::kMScaleX] * ((double)mat[SkMatrix::kMScaleY] * mat[SkMatrix::kMPersp2] - (double)mat[SkMatrix::kMTransY] * mat[SkMatrix::kMPersp1]) +
- mat[SkMatrix::kMSkewX] * ((double)mat[SkMatrix::kMTransY] * mat[SkMatrix::kMPersp0] - (double)mat[SkMatrix::kMSkewY] * mat[SkMatrix::kMPersp2]) +
- mat[SkMatrix::kMTransX] * ((double)mat[SkMatrix::kMSkewY] * mat[SkMatrix::kMPersp1] - (double)mat[SkMatrix::kMScaleY] * mat[SkMatrix::kMPersp0]);
- } else {
- det = (double)mat[SkMatrix::kMScaleX] * mat[SkMatrix::kMScaleY] - (double)mat[SkMatrix::kMSkewX] * mat[SkMatrix::kMSkewY];
- }
+static inline SkScalar scross_dscale(SkScalar a, SkScalar b,
+ SkScalar c, SkScalar d, double scale) {
+ return SkDoubleToScalar(scross(a, b, c, d) * scale);
+}
- // Since the determinant is on the order of the cube of the matrix members,
- // compare to the cube of the default nearly-zero constant (although an
- // estimate of the condition number would be better if it wasn't so expensive).
- if (SkScalarNearlyZero((float)det, SK_ScalarNearlyZero * SK_ScalarNearlyZero * SK_ScalarNearlyZero)) {
- return 0;
- }
- return 1.0 / det;
- }
- // we declar a,b,c,d to all be doubles, because we want to perform
- // double-precision muls and subtract, even though the original values are
- // from the matrix, which are floats.
- static float inline mul_diff_scale(double a, double b, double c, double d,
- double scale) {
- return SkDoubleToFloat((a * b - c * d) * scale);
- }
-#else
- typedef SkFixed SkDetScalar;
- #define SkPerspMul(a, b) SkFractMul(a, b)
- #define SkScalarMulShift(a, b, s) SkMulShift(a, b, s)
- static void set_muladdmul(Sk64* dst, int32_t a, int32_t b, int32_t c,
- int32_t 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[SkMatrix::kMScaleX], fracmuladdmul(mat[SkMatrix::kMScaleY], mat[SkMatrix::kMPersp2], -mat[SkMatrix::kMTransY], mat[SkMatrix::kMPersp1]));
- tmp2.setMul(mat[SkMatrix::kMSkewX], fracmuladdmul(mat[SkMatrix::kMTransY], mat[SkMatrix::kMPersp0], -mat[SkMatrix::kMSkewY], mat[SkMatrix::kMPersp2]));
- tmp1.add(tmp2);
- tmp2.setMul(mat[SkMatrix::kMTransX], fracmuladdmul(mat[SkMatrix::kMSkewY], mat[SkMatrix::kMPersp1], -mat[SkMatrix::kMScaleY], mat[SkMatrix::kMPersp0]));
- tmp1.add(tmp2);
- } else {
- tmp1.setMul(mat[SkMatrix::kMScaleX], mat[SkMatrix::kMScaleY]);
- tmp2.setMul(mat[SkMatrix::kMSkewX], mat[SkMatrix::kMSkewY]);
- tmp1.sub(tmp2);
- }
+static inline double dcross(double a, double b, double c, double d) {
+ return a * b - c * d;
+}
- int s = tmp1.getClzAbs();
- *shift = s;
+static inline SkScalar dcross_dscale(double a, double b,
+ double c, double d, double scale) {
+ return SkDoubleToScalar(dcross(a, b, c, d) * scale);
+}
- SkFixed denom;
- if (s <= 32) {
- denom = tmp1.getShiftRight(33 - s);
- } else {
- denom = (int32_t)tmp1.fLo << (s - 33);
- }
+static double sk_inv_determinant(const float mat[9], int isPerspective) {
+ double det;
- 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);
+ if (isPerspective) {
+ det = mat[SkMatrix::kMScaleX] *
+ dcross(mat[SkMatrix::kMScaleY], mat[SkMatrix::kMPersp2],
+ mat[SkMatrix::kMTransY], mat[SkMatrix::kMPersp1])
+ +
+ mat[SkMatrix::kMSkewX] *
+ dcross(mat[SkMatrix::kMTransY], mat[SkMatrix::kMPersp0],
+ mat[SkMatrix::kMSkewY], mat[SkMatrix::kMPersp2])
+ +
+ mat[SkMatrix::kMTransX] *
+ dcross(mat[SkMatrix::kMSkewY], mat[SkMatrix::kMPersp1],
+ mat[SkMatrix::kMScaleY], mat[SkMatrix::kMPersp0]);
+ } else {
+ det = dcross(mat[SkMatrix::kMScaleX], mat[SkMatrix::kMScaleY],
+ mat[SkMatrix::kMSkewX], mat[SkMatrix::kMSkewY]);
}
-#endif
+
+ // Since the determinant is on the order of the cube of the matrix members,
+ // compare to the cube of the default nearly-zero constant (although an
+ // estimate of the condition number would be better if it wasn't so expensive).
+ if (SkScalarNearlyZero((float)det, SK_ScalarNearlyZero * SK_ScalarNearlyZero * SK_ScalarNearlyZero)) {
+ return 0;
+ }
+ return 1.0 / det;
+}
void SkMatrix::SetAffineIdentity(SkScalar affine[6]) {
- affine[kAScaleX] = SK_Scalar1;
+ affine[kAScaleX] = 1;
affine[kASkewY] = 0;
affine[kASkewX] = 0;
- affine[kAScaleY] = SK_Scalar1;
+ affine[kAScaleY] = 1;
affine[kATransX] = 0;
affine[kATransY] = 0;
}
@@ -950,9 +792,9 @@ bool SkMatrix::invertNonIdentity(SkMatrix* inv) const {
inv->fMat[kMScaleX] = invX;
inv->fMat[kMScaleY] = invY;
- inv->fMat[kMPersp2] = kMatrix22Elem;
- inv->fMat[kMTransX] = -SkScalarMul(fMat[kMTransX], invX);
- inv->fMat[kMTransY] = -SkScalarMul(fMat[kMTransY], invY);
+ inv->fMat[kMPersp2] = 1;
+ inv->fMat[kMTransX] = -fMat[kMTransX] * invX;
+ inv->fMat[kMTransY] = -fMat[kMTransY] * invY;
inv->setTypeMask(mask | kRectStaysRect_Mask);
} else {
@@ -967,9 +809,8 @@ bool SkMatrix::invertNonIdentity(SkMatrix* inv) const {
return invertible;
}
- int isPersp = mask & kPerspective_Mask;
- int shift;
- SkDetScalar scale = sk_inv_determinant(fMat, isPersp, &shift);
+ int isPersp = mask & kPerspective_Mask;
+ double scale = sk_inv_determinant(fMat, isPersp);
if (scale == 0) { // underflow
return false;
@@ -982,83 +823,29 @@ bool SkMatrix::invertNonIdentity(SkMatrix* inv) const {
}
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
- {
- int32_t 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
- }
+ inv->fMat[kMScaleX] = scross_dscale(fMat[kMScaleY], fMat[kMPersp2], fMat[kMTransY], fMat[kMPersp1], scale);
+ inv->fMat[kMSkewX] = scross_dscale(fMat[kMTransX], fMat[kMPersp1], fMat[kMSkewX], fMat[kMPersp2], scale);
+ inv->fMat[kMTransX] = scross_dscale(fMat[kMSkewX], fMat[kMTransY], fMat[kMTransX], fMat[kMScaleY], scale);
- 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
- }
+ inv->fMat[kMSkewY] = scross_dscale(fMat[kMTransY], fMat[kMPersp0], fMat[kMSkewY], fMat[kMPersp2], scale);
+ inv->fMat[kMScaleY] = scross_dscale(fMat[kMScaleX], fMat[kMPersp2], fMat[kMTransX], fMat[kMPersp0], scale);
+ inv->fMat[kMTransY] = scross_dscale(fMat[kMTransX], fMat[kMSkewY], fMat[kMScaleX], fMat[kMTransY], scale);
- int fixedShift = 61 - shift;
- int sk64shift = 44 - shift + clzNumer;
+ inv->fMat[kMPersp0] = scross_dscale(fMat[kMSkewY], fMat[kMPersp1], fMat[kMScaleY], fMat[kMPersp0], scale);
+ inv->fMat[kMPersp1] = scross_dscale(fMat[kMSkewX], fMat[kMPersp0], fMat[kMScaleX], fMat[kMPersp1], scale);
+ inv->fMat[kMPersp2] = scross_dscale(fMat[kMScaleX], fMat[kMScaleY], fMat[kMSkewX], fMat[kMSkewY], scale);
+ } else { // not perspective
+ inv->fMat[kMScaleX] = SkDoubleToScalar(fMat[kMScaleY] * scale);
+ inv->fMat[kMSkewX] = SkDoubleToScalar(-fMat[kMSkewX] * scale);
+ inv->fMat[kMTransX] = dcross_dscale(fMat[kMSkewX], fMat[kMTransY], fMat[kMScaleY], fMat[kMTransX], scale);
- 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] = SkDoubleToScalar(-fMat[kMSkewY] * scale);
+ inv->fMat[kMScaleY] = SkDoubleToScalar(fMat[kMScaleX] * scale);
+ inv->fMat[kMTransY] = dcross_dscale(fMat[kMSkewY], fMat[kMTransX], fMat[kMScaleX], fMat[kMTransY], scale);
- 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] = SkDoubleToFloat(fMat[kMScaleY] * scale);
- inv->fMat[kMSkewX] = SkDoubleToFloat(-fMat[kMSkewX] * scale);
- inv->fMat[kMTransX] = mul_diff_scale(fMat[kMSkewX], fMat[kMTransY],
- fMat[kMScaleY], fMat[kMTransX], scale);
-
- inv->fMat[kMSkewY] = SkDoubleToFloat(-fMat[kMSkewY] * scale);
- inv->fMat[kMScaleY] = SkDoubleToFloat(fMat[kMScaleX] * scale);
- inv->fMat[kMTransY] = mul_diff_scale(fMat[kMSkewY], fMat[kMTransX],
- fMat[kMScaleX], fMat[kMTransY], scale);
-#endif
inv->fMat[kMPersp0] = 0;
inv->fMat[kMPersp1] = 0;
- inv->fMat[kMPersp2] = kMatrix22Elem;
-
+ inv->fMat[kMPersp2] = 1;
}
inv->setTypeMask(fTypeMask);
@@ -1104,8 +891,8 @@ void SkMatrix::Scale_pts(const SkMatrix& m, SkPoint dst[],
SkScalar mx = m.fMat[kMScaleX];
SkScalar my = m.fMat[kMScaleY];
do {
- dst->fY = SkScalarMul(src->fY, my);
- dst->fX = SkScalarMul(src->fX, mx);
+ dst->fY = src->fY * my;
+ dst->fX = src->fX * mx;
src += 1;
dst += 1;
} while (--count);
@@ -1122,8 +909,8 @@ void SkMatrix::ScaleTrans_pts(const SkMatrix& m, SkPoint dst[],
SkScalar tx = m.fMat[kMTransX];
SkScalar ty = m.fMat[kMTransY];
do {
- dst->fY = SkScalarMulAdd(src->fY, my, ty);
- dst->fX = SkScalarMulAdd(src->fX, mx, tx);
+ dst->fY = src->fY * my + ty;
+ dst->fX = src->fX * mx + tx;
src += 1;
dst += 1;
} while (--count);
@@ -1143,8 +930,8 @@ void SkMatrix::Rot_pts(const SkMatrix& m, SkPoint dst[],
SkScalar sy = src->fY;
SkScalar sx = src->fX;
src += 1;
- dst->fY = SkScalarMul(sx, ky) + SkScalarMul(sy, my);
- dst->fX = SkScalarMul(sx, mx) + SkScalarMul(sy, kx);
+ dst->fY = sdot(sx, ky, sy, my);
+ dst->fX = sdot(sx, mx, sy, kx);
dst += 1;
} while (--count);
}
@@ -1165,8 +952,13 @@ void SkMatrix::RotTrans_pts(const SkMatrix& m, SkPoint dst[],
SkScalar sy = src->fY;
SkScalar sx = src->fX;
src += 1;
- dst->fY = SkScalarMul(sx, ky) + SkScalarMulAdd(sy, my, ty);
- dst->fX = SkScalarMul(sx, mx) + SkScalarMulAdd(sy, kx, tx);
+#ifdef SK_LEGACY_MATRIX_MATH_ORDER
+ dst->fY = sx * ky + (sy * my + ty);
+ dst->fX = sx * mx + (sy * kx + tx);
+#else
+ dst->fY = sdot(sx, ky, sy, my) + ty;
+ dst->fX = sdot(sx, mx, sy, kx) + tx;
+#endif
dst += 1;
} while (--count);
}
@@ -1176,33 +968,25 @@ void SkMatrix::Persp_pts(const SkMatrix& m, SkPoint dst[],
const SkPoint src[], int count) {
SkASSERT(m.hasPerspective());
-#ifdef SK_SCALAR_IS_FIXED
- SkFixed persp2 = SkFractToFixed(m.fMat[kMPersp2]);
-#endif
-
if (count > 0) {
do {
SkScalar sy = src->fY;
SkScalar sx = src->fX;
src += 1;
- 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]) + persp2;
+ SkScalar x = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) + m.fMat[kMTransX];
+ SkScalar y = sdot(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
+#ifdef SK_LEGACY_MATRIX_MATH_ORDER
+ SkScalar z = sx * m.fMat[kMPersp0] + (sy * m.fMat[kMPersp1] + m.fMat[kMPersp2]);
#else
- float z = SkScalarMul(sx, m.fMat[kMPersp0]) +
- SkScalarMulAdd(sy, m.fMat[kMPersp1], m.fMat[kMPersp2]);
+ SkScalar z = sdot(sx, m.fMat[kMPersp0], sy, m.fMat[kMPersp1]) + m.fMat[kMPersp2];
#endif
if (z) {
z = SkScalarFastInvert(z);
}
- dst->fY = SkScalarMul(y, z);
- dst->fX = SkScalarMul(x, z);
+ dst->fY = y * z;
+ dst->fX = x * z;
dst += 1;
} while (--count);
}
@@ -1246,15 +1030,9 @@ void SkMatrix::mapHomogeneousPoints(SkScalar dst[], const SkScalar src[], int co
SkScalar sw = src[2];
src += 3;
- SkScalar x = SkScalarMul(sx, fMat[kMScaleX]) +
- SkScalarMul(sy, fMat[kMSkewX]) +
- SkScalarMul(sw, fMat[kMTransX]);
- SkScalar y = SkScalarMul(sx, fMat[kMSkewY]) +
- SkScalarMul(sy, fMat[kMScaleY]) +
- SkScalarMul(sw, fMat[kMTransY]);
- SkScalar w = SkScalarMul(sx, fMat[kMPersp0]) +
- SkScalarMul(sy, fMat[kMPersp1]) +
- SkScalarMul(sw, fMat[kMPersp2]);
+ SkScalar x = sdot(sx, fMat[kMScaleX], sy, fMat[kMSkewX], sw, fMat[kMTransX]);
+ SkScalar y = sdot(sx, fMat[kMSkewY], sy, fMat[kMScaleY], sw, fMat[kMTransY]);
+ SkScalar w = sdot(sx, fMat[kMPersp0], sy, fMat[kMPersp1], sw, fMat[kMPersp2]);
dst[0] = x;
dst[1] = y;
@@ -1315,7 +1093,8 @@ SkScalar SkMatrix::mapRadius(SkScalar radius) const {
SkScalar d0 = vec[0].length();
SkScalar d1 = vec[1].length();
- return SkScalarMean(d0, d1);
+ // return geometric mean
+ return SkScalarSqrt(d0 * d1);
}
///////////////////////////////////////////////////////////////////////////////
@@ -1324,51 +1103,26 @@ void SkMatrix::Persp_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
SkPoint* pt) {
SkASSERT(m.hasPerspective());
- 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
+ SkScalar x = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) + m.fMat[kMTransX];
+ SkScalar y = sdot(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
+ SkScalar z = sdot(sx, m.fMat[kMPersp0], sy, m.fMat[kMPersp1]) + m.fMat[kMPersp2];
if (z) {
z = SkScalarFastInvert(z);
}
- pt->fX = SkScalarMul(x, z);
- pt->fY = SkScalarMul(y, z);
+ pt->fX = x * z;
+ pt->fY = 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::RotTrans_xy(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];
+#ifdef SK_LEGACY_MATRIX_MATH_ORDER
+ pt->fX = sx * m.fMat[kMScaleX] + (sy * m.fMat[kMSkewX] + m.fMat[kMTransX]);
+ pt->fY = sx * m.fMat[kMSkewY] + (sy * m.fMat[kMScaleY] + m.fMat[kMTransY]);
#else
- pt->fX = SkScalarMul(sx, m.fMat[kMScaleX]) +
- SkScalarMulAdd(sy, m.fMat[kMSkewX], m.fMat[kMTransX]);
- pt->fY = SkScalarMul(sx, m.fMat[kMSkewY]) +
- SkScalarMulAdd(sy, m.fMat[kMScaleY], m.fMat[kMTransY]);
+ pt->fX = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) + m.fMat[kMTransX];
+ pt->fY = sdot(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
#endif
}
@@ -1378,14 +1132,12 @@ void SkMatrix::Rot_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
SkASSERT(0 == m.fMat[kMTransX]);
SkASSERT(0 == m.fMat[kMTransY]);
-#ifdef SK_SCALAR_IS_FIXED
- pt->fX = fixmuladdmul(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]);
- pt->fY = fixmuladdmul(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]);
+#ifdef SK_LEGACY_MATRIX_MATH_ORDER
+ pt->fX = sx * m.fMat[kMScaleX] + (sy * m.fMat[kMSkewX] + m.fMat[kMTransX]);
+ pt->fY = sx * m.fMat[kMSkewY] + (sy * m.fMat[kMScaleY] + m.fMat[kMTransY]);
#else
- pt->fX = SkScalarMul(sx, m.fMat[kMScaleX]) +
- SkScalarMulAdd(sy, m.fMat[kMSkewX], m.fMat[kMTransX]);
- pt->fY = SkScalarMul(sx, m.fMat[kMSkewY]) +
- SkScalarMulAdd(sy, m.fMat[kMScaleY], m.fMat[kMTransY]);
+ pt->fX = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) + m.fMat[kMTransX];
+ pt->fY = sdot(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
#endif
}
@@ -1394,8 +1146,8 @@ void SkMatrix::ScaleTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
SkASSERT((m.getType() & (kScale_Mask | kAffine_Mask | kPerspective_Mask))
== kScale_Mask);
- pt->fX = SkScalarMulAdd(sx, m.fMat[kMScaleX], m.fMat[kMTransX]);
- pt->fY = SkScalarMulAdd(sy, m.fMat[kMScaleY], m.fMat[kMTransY]);
+ pt->fX = sx * m.fMat[kMScaleX] + m.fMat[kMTransX];
+ pt->fY = sy * m.fMat[kMScaleY] + m.fMat[kMTransY];
}
void SkMatrix::Scale_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
@@ -1405,8 +1157,8 @@ void SkMatrix::Scale_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
SkASSERT(0 == m.fMat[kMTransX]);
SkASSERT(0 == m.fMat[kMTransY]);
- pt->fX = SkScalarMul(sx, m.fMat[kMScaleX]);
- pt->fY = SkScalarMul(sy, m.fMat[kMScaleY]);
+ pt->fX = sx * m.fMat[kMScaleX];
+ pt->fY = sy * m.fMat[kMScaleY];
}
void SkMatrix::Trans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
@@ -1440,19 +1192,13 @@ const SkMatrix::MapXYProc SkMatrix::gMapXYProcs[] = {
///////////////////////////////////////////////////////////////////////////////
// if its nearly zero (just made up 26, 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
+#define PerspNearlyZero(x) SkScalarNearlyZero(x, (1.0f / (1 << 26)))
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)) {
+ PerspNearlyZero(fMat[kMPersp2] - 1)) {
if (stepX) {
*stepX = SkScalarToFixed(fMat[kMScaleX]);
}
@@ -1460,17 +1206,12 @@ bool SkMatrix::fixedStepInX(SkScalar y, SkFixed* stepX, SkFixed* stepY) const {
*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
+ SkScalar z = y * fMat[kMPersp1] + fMat[kMPersp2];
if (stepX) {
- *stepX = SkScalarToFixed(SkScalarDiv(fMat[kMScaleX], z));
+ *stepX = SkScalarToFixed(fMat[kMScaleX] / z);
}
if (stepY) {
- *stepY = SkScalarToFixed(SkScalarDiv(fMat[kMSkewY], z));
+ *stepY = SkScalarToFixed(fMat[kMSkewY] / z);
}
}
}
@@ -1532,143 +1273,6 @@ int SkPerspIter::next() {
///////////////////////////////////////////////////////////////////////////////
-#ifdef SK_SCALAR_IS_FIXED
-
-static inline bool 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);
- if (y == 0) {
- return false;
- }
- 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);
- if (!w1.is32()) {
- return false;
- }
- x = w1.get32();
- break;
- }
- }
- pt->set(x, y);
- return true;
-}
-
-bool SkMatrix::Poly2Proc(const SkPoint srcPt[], SkMatrix* dst,
- const SkPoint& scalePt) {
- // need to check if SkFixedDiv overflows...
-
- const SkFixed scale = scalePt.fY;
- 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;
- dst->setTypeMask(kUnknown_Mask);
- return true;
-}
-
-bool SkMatrix::Poly3Proc(const SkPoint srcPt[], SkMatrix* dst,
- const SkPoint& scale) {
- // really, need to check if SkFixedDiv overflow'd
-
- dst->fMat[kMScaleX] = SkFixedDiv(srcPt[2].fX - srcPt[0].fX, scale.fX);
- dst->fMat[kMSkewY] = SkFixedDiv(srcPt[2].fY - srcPt[0].fY, scale.fX);
- dst->fMat[kMPersp0] = 0;
- dst->fMat[kMSkewX] = SkFixedDiv(srcPt[1].fX - srcPt[0].fX, scale.fY);
- dst->fMat[kMScaleY] = SkFixedDiv(srcPt[1].fY - srcPt[0].fY, scale.fY);
- dst->fMat[kMPersp1] = 0;
- dst->fMat[kMTransX] = srcPt[0].fX;
- dst->fMat[kMTransY] = srcPt[0].fY;
- dst->fMat[kMPersp2] = SK_Fract1;
- dst->setTypeMask(kUnknown_Mask);
- return true;
-}
-
-bool SkMatrix::Poly4Proc(const SkPoint srcPt[], SkMatrix* dst,
- const SkPoint& scale) {
- 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) {
- SkFixed denom = SkMulDiv(x1, y2, x2) - y1;
- if (0 == denom) {
- return false;
- }
- a1 = SkFractDiv(SkMulDiv(x0 - x1, y2, x2) - y0 + y1, denom);
- } else {
- SkFixed denom = x1 - SkMulDiv(y1, x2, y2);
- if (0 == denom) {
- return false;
- }
- a1 = SkFractDiv(x0 - x1 - SkMulDiv(y0 - y1, x2, y2), denom);
- }
-
- /* check if abs(x1) > abs(y1) */
- if ( x1 > 0 ? y1 > 0 ? x1 > y1 : x1 > -y1 : y1 > 0 ? -x1 > y1 : x1 < y1) {
- SkFixed denom = y2 - SkMulDiv(x2, y1, x1);
- if (0 == denom) {
- return false;
- }
- a2 = SkFractDiv(y0 - y2 - SkMulDiv(x0 - x2, y1, x1), denom);
- } else {
- SkFixed denom = SkMulDiv(y2, x1, y1) - x2;
- if (0 == denom) {
- return false;
- }
- a2 = SkFractDiv(SkMulDiv(y0 - y2, x1, y1) - x0 + x2, denom);
- }
-
- // need to check if SkFixedDiv overflows...
- dst->fMat[kMScaleX] = SkFixedDiv(SkFractMul(a2, srcPt[3].fX) +
- srcPt[3].fX - srcPt[0].fX, scale.fX);
- dst->fMat[kMSkewY] = SkFixedDiv(SkFractMul(a2, srcPt[3].fY) +
- srcPt[3].fY - srcPt[0].fY, scale.fX);
- dst->fMat[kMPersp0] = SkFixedDiv(a2, scale.fX);
- dst->fMat[kMSkewX] = SkFixedDiv(SkFractMul(a1, srcPt[1].fX) +
- srcPt[1].fX - srcPt[0].fX, scale.fY);
- dst->fMat[kMScaleY] = SkFixedDiv(SkFractMul(a1, srcPt[1].fY) +
- srcPt[1].fY - srcPt[0].fY, scale.fY);
- dst->fMat[kMPersp1] = SkFixedDiv(a1, scale.fY);
- dst->fMat[kMTransX] = srcPt[0].fX;
- dst->fMat[kMTransY] = srcPt[0].fY;
- dst->fMat[kMPersp2] = SK_Fract1;
- dst->setTypeMask(kUnknown_Mask);
- return true;
-}
-
-#else /* Scalar is float */
-
static inline bool checkForZero(float x) {
return x*x == 0;
}
@@ -1695,8 +1299,7 @@ static inline bool poly_to_point(SkPoint* pt, const SkPoint poly[], int count) {
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);
+ x = sdot(pt1.fX, pt2.fX, pt1.fY, pt2.fY) / y;
break;
}
}
@@ -1758,13 +1361,13 @@ bool SkMatrix::Poly4Proc(const SkPoint srcPt[], SkMatrix* dst,
if (checkForZero(denom)) {
return false;
}
- a1 = SkScalarDiv(SkScalarMulDiv(x0 - x1, y2, x2) - y0 + y1, denom);
+ a1 = (SkScalarMulDiv(x0 - x1, y2, x2) - y0 + y1) / denom;
} else {
float denom = x1 - SkScalarMulDiv(y1, x2, y2);
if (checkForZero(denom)) {
return false;
}
- a1 = SkScalarDiv(x0 - x1 - SkScalarMulDiv(y0 - y1, x2, y2), denom);
+ a1 = (x0 - x1 - SkScalarMulDiv(y0 - y1, x2, y2)) / denom;
}
/* check if abs(x1) > abs(y1) */
@@ -1773,27 +1376,25 @@ bool SkMatrix::Poly4Proc(const SkPoint srcPt[], SkMatrix* dst,
if (checkForZero(denom)) {
return false;
}
- a2 = SkScalarDiv(y0 - y2 - SkScalarMulDiv(x0 - x2, y1, x1), denom);
+ a2 = (y0 - y2 - SkScalarMulDiv(x0 - x2, y1, x1)) / denom;
} else {
float denom = SkScalarMulDiv(y2, x1, y1) - x2;
if (checkForZero(denom)) {
return false;
}
- a2 = SkScalarDiv(SkScalarMulDiv(y0 - y2, x1, y1) - x0 + x2, denom);
+ a2 = (SkScalarMulDiv(y0 - y2, x1, y1) - x0 + x2) / denom;
}
- float invScale = 1 / scale.fX;
- dst->fMat[kMScaleX] = SkScalarMul(SkScalarMul(a2, srcPt[3].fX) +
- srcPt[3].fX - srcPt[0].fX, invScale);
- dst->fMat[kMSkewY] = SkScalarMul(SkScalarMul(a2, srcPt[3].fY) +
- srcPt[3].fY - srcPt[0].fY, invScale);
- dst->fMat[kMPersp0] = SkScalarMul(a2, invScale);
- invScale = 1 / scale.fY;
- dst->fMat[kMSkewX] = SkScalarMul(SkScalarMul(a1, srcPt[1].fX) +
- srcPt[1].fX - srcPt[0].fX, invScale);
- dst->fMat[kMScaleY] = SkScalarMul(SkScalarMul(a1, srcPt[1].fY) +
- srcPt[1].fY - srcPt[0].fY, invScale);
- dst->fMat[kMPersp1] = SkScalarMul(a1, invScale);
+ float invScale = SkScalarInvert(scale.fX);
+ dst->fMat[kMScaleX] = (a2 * srcPt[3].fX + srcPt[3].fX - srcPt[0].fX) * invScale;
+ dst->fMat[kMSkewY] = (a2 * srcPt[3].fY + srcPt[3].fY - srcPt[0].fY) * invScale;
+ dst->fMat[kMPersp0] = a2 * invScale;
+
+ invScale = SkScalarInvert(scale.fY);
+ dst->fMat[kMSkewX] = (a1 * srcPt[1].fX + srcPt[1].fX - srcPt[0].fX) * invScale;
+ dst->fMat[kMScaleY] = (a1 * srcPt[1].fY + srcPt[1].fY - srcPt[0].fY) * invScale;
+ dst->fMat[kMPersp1] = a1 * invScale;
+
dst->fMat[kMTransX] = srcPt[0].fX;
dst->fMat[kMTransY] = srcPt[0].fY;
dst->fMat[kMPersp2] = 1;
@@ -1801,8 +1402,6 @@ bool SkMatrix::Poly4Proc(const SkPoint srcPt[], SkMatrix* dst,
return true;
}
-#endif
-
typedef bool (*PolyMapProc)(const SkPoint[], SkMatrix*, const SkPoint&);
/* Taken from Rob Johnson's original sample code in QuickDraw GX
@@ -1847,105 +1446,153 @@ bool SkMatrix::setPolyToPoly(const SkPoint src[], const SkPoint dst[],
if (!proc(dst, &tempMap, scale)) {
return false;
}
- if (!result.setConcat(tempMap, result)) {
- return false;
- }
- *this = result;
+ this->setConcat(tempMap, result);
return true;
}
///////////////////////////////////////////////////////////////////////////////
-enum MinOrMax {
- kMin_MinOrMax,
- kMax_MinOrMax
+enum MinMaxOrBoth {
+ kMin_MinMaxOrBoth,
+ kMax_MinMaxOrBoth,
+ kBoth_MinMaxOrBoth
};
-template <MinOrMax MIN_OR_MAX> SkScalar get_stretch_factor(SkMatrix::TypeMask typeMask,
- const SkScalar m[9]) {
+template <MinMaxOrBoth MIN_MAX_OR_BOTH> bool get_scale_factor(SkMatrix::TypeMask typeMask,
+ const SkScalar m[9],
+ SkScalar results[/*1 or 2*/]) {
if (typeMask & SkMatrix::kPerspective_Mask) {
- return -SK_Scalar1;
+ return false;
}
if (SkMatrix::kIdentity_Mask == typeMask) {
- return SK_Scalar1;
+ results[0] = SK_Scalar1;
+ if (kBoth_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
+ results[1] = SK_Scalar1;
+ }
+ return true;
}
if (!(typeMask & SkMatrix::kAffine_Mask)) {
- if (kMin_MinOrMax == MIN_OR_MAX) {
- return SkMinScalar(SkScalarAbs(m[SkMatrix::kMScaleX]),
- SkScalarAbs(m[SkMatrix::kMScaleY]));
+ if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
+ results[0] = SkMinScalar(SkScalarAbs(m[SkMatrix::kMScaleX]),
+ SkScalarAbs(m[SkMatrix::kMScaleY]));
+ } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
+ results[0] = SkMaxScalar(SkScalarAbs(m[SkMatrix::kMScaleX]),
+ SkScalarAbs(m[SkMatrix::kMScaleY]));
} else {
- return SkMaxScalar(SkScalarAbs(m[SkMatrix::kMScaleX]),
- SkScalarAbs(m[SkMatrix::kMScaleY]));
+ results[0] = SkScalarAbs(m[SkMatrix::kMScaleX]);
+ results[1] = SkScalarAbs(m[SkMatrix::kMScaleY]);
+ if (results[0] > results[1]) {
+ SkTSwap(results[0], results[1]);
+ }
}
+ return true;
}
// ignore the translation part of the matrix, just look at 2x2 portion.
// compute singular values, take largest or smallest abs value.
// [a b; b c] = A^T*A
- SkScalar a = SkScalarMul(m[SkMatrix::kMScaleX], m[SkMatrix::kMScaleX]) +
- SkScalarMul(m[SkMatrix::kMSkewY], m[SkMatrix::kMSkewY]);
- SkScalar b = SkScalarMul(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewX]) +
- SkScalarMul(m[SkMatrix::kMScaleY], m[SkMatrix::kMSkewY]);
- SkScalar c = SkScalarMul(m[SkMatrix::kMSkewX], m[SkMatrix::kMSkewX]) +
- SkScalarMul(m[SkMatrix::kMScaleY], m[SkMatrix::kMScaleY]);
+ SkScalar a = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMScaleX],
+ m[SkMatrix::kMSkewY], m[SkMatrix::kMSkewY]);
+ SkScalar b = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewX],
+ m[SkMatrix::kMScaleY], m[SkMatrix::kMSkewY]);
+ SkScalar c = sdot(m[SkMatrix::kMSkewX], m[SkMatrix::kMSkewX],
+ m[SkMatrix::kMScaleY], m[SkMatrix::kMScaleY]);
// eigenvalues of A^T*A are the squared singular values of A.
// characteristic equation is det((A^T*A) - l*I) = 0
// l^2 - (a + c)l + (ac-b^2)
// solve using quadratic equation (divisor is non-zero since l^2 has 1 coeff
// and roots are guaranteed to be pos and real).
- SkScalar chosenRoot;
- SkScalar bSqd = SkScalarMul(b,b);
+ SkScalar bSqd = b * b;
// if upper left 2x2 is orthogonal save some math
if (bSqd <= SK_ScalarNearlyZero*SK_ScalarNearlyZero) {
- if (kMin_MinOrMax == MIN_OR_MAX) {
- chosenRoot = SkMinScalar(a, c);
+ if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
+ results[0] = SkMinScalar(a, c);
+ } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
+ results[0] = SkMaxScalar(a, c);
} else {
- chosenRoot = SkMaxScalar(a, c);
+ results[0] = a;
+ results[1] = c;
+ if (results[0] > results[1]) {
+ SkTSwap(results[0], results[1]);
+ }
}
} else {
SkScalar aminusc = a - c;
SkScalar apluscdiv2 = SkScalarHalf(a + c);
- SkScalar x = SkScalarHalf(SkScalarSqrt(SkScalarMul(aminusc, aminusc) + 4 * bSqd));
- if (kMin_MinOrMax == MIN_OR_MAX) {
- chosenRoot = apluscdiv2 - x;
+ SkScalar x = SkScalarHalf(SkScalarSqrt(aminusc * aminusc + 4 * bSqd));
+ if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
+ results[0] = apluscdiv2 - x;
+ } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
+ results[0] = apluscdiv2 + x;
} else {
- chosenRoot = apluscdiv2 + x;
+ results[0] = apluscdiv2 - x;
+ results[1] = apluscdiv2 + x;
}
}
- SkASSERT(chosenRoot >= 0);
- return SkScalarSqrt(chosenRoot);
+ SkASSERT(results[0] >= 0);
+ results[0] = SkScalarSqrt(results[0]);
+ if (kBoth_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
+ SkASSERT(results[1] >= 0);
+ results[1] = SkScalarSqrt(results[1]);
+ }
+ return true;
}
-SkScalar SkMatrix::getMinStretch() const {
- return get_stretch_factor<kMin_MinOrMax>(this->getType(), fMat);
+SkScalar SkMatrix::getMinScale() const {
+ SkScalar factor;
+ if (get_scale_factor<kMin_MinMaxOrBoth>(this->getType(), fMat, &factor)) {
+ return factor;
+ } else {
+ return -1;
+ }
}
-SkScalar SkMatrix::getMaxStretch() const {
- return get_stretch_factor<kMax_MinOrMax>(this->getType(), fMat);
+SkScalar SkMatrix::getMaxScale() const {
+ SkScalar factor;
+ if (get_scale_factor<kMax_MinMaxOrBoth>(this->getType(), fMat, &factor)) {
+ return factor;
+ } else {
+ return -1;
+ }
}
-static void reset_identity_matrix(SkMatrix* identity) {
- identity->reset();
+bool SkMatrix::getMinMaxScales(SkScalar scaleFactors[2]) const {
+ return get_scale_factor<kBoth_MinMaxOrBoth>(this->getType(), fMat, scaleFactors);
}
+namespace {
+
+struct PODMatrix {
+ SkScalar matrix[9];
+ uint32_t typemask;
+
+ const SkMatrix& asSkMatrix() const { return *reinterpret_cast<const SkMatrix*>(this); }
+};
+SK_COMPILE_ASSERT(sizeof(PODMatrix) == sizeof(SkMatrix), PODMatrixSizeMismatch);
+
+} // namespace
+
const SkMatrix& SkMatrix::I() {
- // If you can use C++11 now, you might consider replacing this with a constexpr constructor.
- static SkMatrix gIdentity;
- SK_DECLARE_STATIC_ONCE(once);
- SkOnce(&once, reset_identity_matrix, &gIdentity);
- return gIdentity;
+ SK_COMPILE_ASSERT(offsetof(SkMatrix, fMat) == offsetof(PODMatrix, matrix), BadfMat);
+ SK_COMPILE_ASSERT(offsetof(SkMatrix, fTypeMask) == offsetof(PODMatrix, typemask), BadfTypeMask);
+
+ static const PODMatrix identity = { {SK_Scalar1, 0, 0,
+ 0, SK_Scalar1, 0,
+ 0, 0, SK_Scalar1 },
+ kIdentity_Mask | kRectStaysRect_Mask};
+ SkASSERT(identity.asSkMatrix().isIdentity());
+ return identity.asSkMatrix();
}
const SkMatrix& SkMatrix::InvalidMatrix() {
- static SkMatrix gInvalid;
- static bool gOnce;
- if (!gOnce) {
- gInvalid.setAll(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax,
- SK_ScalarMax, SK_ScalarMax, SK_ScalarMax,
- SK_ScalarMax, SK_ScalarMax, SK_ScalarMax);
- gInvalid.getType(); // force the type to be computed
- gOnce = true;
- }
- return gInvalid;
+ SK_COMPILE_ASSERT(offsetof(SkMatrix, fMat) == offsetof(PODMatrix, matrix), BadfMat);
+ SK_COMPILE_ASSERT(offsetof(SkMatrix, fTypeMask) == offsetof(PODMatrix, typemask), BadfTypeMask);
+
+ static const PODMatrix invalid =
+ { {SK_ScalarMax, SK_ScalarMax, SK_ScalarMax,
+ SK_ScalarMax, SK_ScalarMax, SK_ScalarMax,
+ SK_ScalarMax, SK_ScalarMax, SK_ScalarMax },
+ kTranslate_Mask | kScale_Mask | kAffine_Mask | kPerspective_Mask };
+ return invalid.asSkMatrix();
}
///////////////////////////////////////////////////////////////////////////////
@@ -1977,17 +1624,13 @@ void SkMatrix::dump() const {
this->toString(&str);
SkDebugf("%s\n", str.c_str());
}
+#endif
+#ifndef SK_IGNORE_TO_STRING
void SkMatrix::toString(SkString* str) const {
str->appendf("[%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f]",
-#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
}
#endif
@@ -2073,7 +1716,7 @@ bool SkDecomposeUpper2x2(const SkMatrix& matrix,
double Sa, Sb, Sd;
// if M is already symmetric (i.e., M = I*S)
if (SkScalarNearlyEqual(B, C)) {
- cosQ = SK_Scalar1;
+ cosQ = 1;
sinQ = 0;
Sa = A;
@@ -2082,7 +1725,7 @@ bool SkDecomposeUpper2x2(const SkMatrix& matrix,
} else {
cosQ = A + D;
sinQ = C - B;
- SkScalar reciplen = SK_Scalar1/SkScalarSqrt(cosQ*cosQ + sinQ*sinQ);
+ SkScalar reciplen = SkScalarInvert(SkScalarSqrt(cosQ*cosQ + sinQ*sinQ));
cosQ *= reciplen;
sinQ *= reciplen;
@@ -2098,7 +1741,7 @@ bool SkDecomposeUpper2x2(const SkMatrix& matrix,
// From this, should be able to reconstruct S as U*W*U^T
if (SkScalarNearlyZero(SkDoubleToScalar(Sb))) {
// already diagonalized
- cos1 = SK_Scalar1;
+ cos1 = 1;
sin1 = 0;
w1 = Sa;
w2 = Sd;
@@ -2117,7 +1760,7 @@ bool SkDecomposeUpper2x2(const SkMatrix& matrix,
}
cos1 = SkDoubleToScalar(Sb); sin1 = SkDoubleToScalar(w1 - Sa);
- SkScalar reciplen = SK_Scalar1/SkScalarSqrt(cos1*cos1 + sin1*sin1);
+ SkScalar reciplen = SkScalarInvert(SkScalarSqrt(cos1*cos1 + sin1*sin1));
cos1 *= reciplen;
sin1 *= reciplen;
diff --git a/chromium/third_party/skia/src/core/SkMatrixClipStateMgr.cpp b/chromium/third_party/skia/src/core/SkMatrixClipStateMgr.cpp
new file mode 100644
index 00000000000..1fc7fe83213
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkMatrixClipStateMgr.cpp
@@ -0,0 +1,419 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkMatrixClipStateMgr.h"
+#include "SkPictureRecord.h"
+
+bool SkMatrixClipStateMgr::MatrixClipState::ClipInfo::clipPath(SkPictureRecord* picRecord,
+ const SkPath& path,
+ SkRegion::Op op,
+ bool doAA,
+ int matrixID) {
+ int pathID = picRecord->addPathToHeap(path);
+
+ ClipOp* newClip = fClips.append();
+ newClip->fClipType = kPath_ClipType;
+ newClip->fGeom.fPathID = pathID;
+ newClip->fOp = op;
+ newClip->fDoAA = doAA;
+ newClip->fMatrixID = matrixID;
+ return false;
+}
+
+bool SkMatrixClipStateMgr::MatrixClipState::ClipInfo::clipRegion(SkPictureRecord* picRecord,
+ int regionID,
+ SkRegion::Op op,
+ int matrixID) {
+ ClipOp* newClip = fClips.append();
+ newClip->fClipType = kRegion_ClipType;
+ newClip->fGeom.fRegionID = regionID;
+ newClip->fOp = op;
+ newClip->fDoAA = true; // not necessary but sanity preserving
+ newClip->fMatrixID = matrixID;
+ return false;
+}
+
+void SkMatrixClipStateMgr::writeDeltaMat(int currentMatID, int desiredMatID) {
+ const SkMatrix& current = this->lookupMat(currentMatID);
+ const SkMatrix& desired = this->lookupMat(desiredMatID);
+
+ SkMatrix delta;
+ bool result = current.invert(&delta);
+ if (result) {
+ delta.preConcat(desired);
+ }
+ fPicRecord->recordConcat(delta);
+}
+
+// Note: this only writes out the clips for the current save state. To get the
+// entire clip stack requires iterating of the entire matrix/clip stack.
+void SkMatrixClipStateMgr::MatrixClipState::ClipInfo::writeClip(int* curMatID,
+ SkMatrixClipStateMgr* mgr) {
+ for (int i = 0; i < fClips.count(); ++i) {
+ ClipOp& curClip = fClips[i];
+
+ // TODO: use the matrix ID to skip writing the identity matrix
+ // over and over, i.e.:
+ // if (*curMatID != curClip.fMatrixID) {
+ // mgr->writeDeltaMat...
+ // *curMatID...
+ // }
+ // Right now this optimization would throw off the testing harness.
+ // TODO: right now we're writing out the delta matrix from the prior
+ // matrix state. This is a side-effect of writing out the entire
+ // clip stack and should be resolved when that is fixed.
+ mgr->writeDeltaMat(*curMatID, curClip.fMatrixID);
+ *curMatID = curClip.fMatrixID;
+
+ size_t offset = 0;
+
+ switch (curClip.fClipType) {
+ case kRect_ClipType:
+ offset = mgr->getPicRecord()->recordClipRect(curClip.fGeom.fRRect.rect(),
+ curClip.fOp, curClip.fDoAA);
+ break;
+ case kRRect_ClipType:
+ offset = mgr->getPicRecord()->recordClipRRect(curClip.fGeom.fRRect, curClip.fOp,
+ curClip.fDoAA);
+ break;
+ case kPath_ClipType:
+ offset = mgr->getPicRecord()->recordClipPath(curClip.fGeom.fPathID, curClip.fOp,
+ curClip.fDoAA);
+ break;
+ case kRegion_ClipType: {
+ const SkRegion* region = mgr->lookupRegion(curClip.fGeom.fRegionID);
+ offset = mgr->getPicRecord()->recordClipRegion(*region, curClip.fOp);
+ break;
+ }
+ default:
+ SkASSERT(0);
+ }
+
+ mgr->addClipOffset(offset);
+ }
+}
+
+SkMatrixClipStateMgr::SkMatrixClipStateMgr()
+ : fPicRecord(NULL)
+ , fMatrixClipStack(sizeof(MatrixClipState),
+ fMatrixClipStackStorage,
+ sizeof(fMatrixClipStackStorage))
+ , fCurOpenStateID(kIdentityWideOpenStateID) {
+
+ fSkipOffsets = SkNEW(SkTDArray<int>);
+
+ // The first slot in the matrix dictionary is reserved for the identity matrix
+ fMatrixDict.append()->reset();
+
+ fCurMCState = (MatrixClipState*)fMatrixClipStack.push_back();
+ new (fCurMCState) MatrixClipState(NULL, 0); // balanced in restore()
+
+#ifdef SK_DEBUG
+ fActualDepth = 0;
+#endif
+}
+
+SkMatrixClipStateMgr::~SkMatrixClipStateMgr() {
+ for (int i = 0; i < fRegionDict.count(); ++i) {
+ SkDELETE(fRegionDict[i]);
+ }
+
+ SkDELETE(fSkipOffsets);
+}
+
+
+int SkMatrixClipStateMgr::MCStackPush(SkCanvas::SaveFlags flags) {
+ MatrixClipState* newTop = (MatrixClipState*)fMatrixClipStack.push_back();
+ new (newTop) MatrixClipState(fCurMCState, flags); // balanced in restore()
+ fCurMCState = newTop;
+
+ SkDEBUGCODE(this->validate();)
+
+ return fMatrixClipStack.count();
+}
+
+int SkMatrixClipStateMgr::save(SkCanvas::SaveFlags flags) {
+ SkDEBUGCODE(this->validate();)
+
+ return this->MCStackPush(flags);
+}
+
+int SkMatrixClipStateMgr::saveLayer(const SkRect* bounds, const SkPaint* paint,
+ SkCanvas::SaveFlags flags) {
+#ifdef SK_DEBUG
+ if (fCurMCState->fIsSaveLayer) {
+ SkASSERT(0 == fSkipOffsets->count());
+ }
+#endif
+
+ // Since the saveLayer call draws something we need to potentially dump
+ // out the MC state
+ SkDEBUGCODE(bool saved =) this->call(kOther_CallType);
+
+ int result = this->MCStackPush(flags);
+ ++fCurMCState->fLayerID;
+ fCurMCState->fIsSaveLayer = true;
+
+#ifdef SK_DEBUG
+ if (saved) {
+ fCurMCState->fExpectedDepth++; // 1 for nesting save
+ }
+ fCurMCState->fExpectedDepth++; // 1 for saveLayer
+#endif
+
+ *fStateIDStack.append() = fCurOpenStateID;
+ fCurMCState->fSavedSkipOffsets = fSkipOffsets;
+
+ // TODO: recycle these rather then new & deleting them on every saveLayer/
+ // restore
+ fSkipOffsets = SkNEW(SkTDArray<int>);
+
+ fPicRecord->recordSaveLayer(bounds, paint, flags | SkCanvas::kMatrixClip_SaveFlag);
+#ifdef SK_DEBUG
+ fActualDepth++;
+#endif
+ return result;
+}
+
+void SkMatrixClipStateMgr::restore() {
+ SkDEBUGCODE(this->validate();)
+
+ if (fCurMCState->fIsSaveLayer) {
+ if (fCurMCState->fHasOpen) {
+ fCurMCState->fHasOpen = false;
+ fPicRecord->recordRestore(); // Close the open block inside the saveLayer
+#ifdef SK_DEBUG
+ SkASSERT(fActualDepth > 0);
+ fActualDepth--;
+#endif
+ } else {
+ SkASSERT(0 == fSkipOffsets->count());
+ }
+
+ // The saveLayer's don't carry any matrix or clip state in the
+ // new scheme so make sure the saveLayer's recordRestore doesn't
+ // try to finalize them (i.e., fill in their skip offsets).
+ fPicRecord->recordRestore(false); // close of saveLayer
+#ifdef SK_DEBUG
+ SkASSERT(fActualDepth > 0);
+ fActualDepth--;
+#endif
+
+ SkASSERT(fStateIDStack.count() >= 1);
+ fCurOpenStateID = fStateIDStack[fStateIDStack.count()-1];
+ fStateIDStack.pop();
+
+ SkASSERT(0 == fSkipOffsets->count());
+ SkASSERT(NULL != fCurMCState->fSavedSkipOffsets);
+
+ SkDELETE(fSkipOffsets);
+ fSkipOffsets = fCurMCState->fSavedSkipOffsets;
+ }
+
+ bool prevHadOpen = fCurMCState->fHasOpen;
+ bool prevWasSaveLayer = fCurMCState->fIsSaveLayer;
+
+ fCurMCState->~MatrixClipState(); // balanced in save()
+ fMatrixClipStack.pop_back();
+ fCurMCState = (MatrixClipState*)fMatrixClipStack.back();
+
+ if (!prevWasSaveLayer) {
+ fCurMCState->fHasOpen = prevHadOpen;
+ }
+
+ if (fCurMCState->fIsSaveLayer) {
+ if (0 != fSkipOffsets->count()) {
+ SkASSERT(fCurMCState->fHasOpen);
+ }
+ }
+
+ SkDEBUGCODE(this->validate();)
+}
+
+// kIdentityWideOpenStateID (0) is reserved for the identity/wide-open clip state
+int32_t SkMatrixClipStateMgr::NewMCStateID() {
+ // TODO: guard against wrap around
+ // TODO: make uint32_t
+ static int32_t gMCStateID = kIdentityWideOpenStateID;
+ ++gMCStateID;
+ return gMCStateID;
+}
+
+bool SkMatrixClipStateMgr::isNestingMCState(int stateID) {
+ return fStateIDStack.count() > 0 && fStateIDStack[fStateIDStack.count()-1] == fCurOpenStateID;
+}
+
+bool SkMatrixClipStateMgr::call(CallType callType) {
+ SkDEBUGCODE(this->validate();)
+
+ if (kMatrix_CallType == callType || kClip_CallType == callType) {
+ fCurMCState->fMCStateID = NewMCStateID();
+ SkDEBUGCODE(this->validate();)
+ return false;
+ }
+
+ SkASSERT(kOther_CallType == callType);
+
+ if (fCurMCState->fMCStateID == fCurOpenStateID) {
+ // Required MC state is already active one - nothing to do
+ SkDEBUGCODE(this->validate();)
+ return false;
+ }
+
+ if (kIdentityWideOpenStateID != fCurOpenStateID &&
+ !this->isNestingMCState(fCurOpenStateID)) {
+ // Don't write a restore if the open state is one in which a saveLayer
+ // is nested. The save after the saveLayer's restore will close it.
+ fPicRecord->recordRestore(); // Close the open block
+ fCurMCState->fHasOpen = false;
+#ifdef SK_DEBUG
+ SkASSERT(fActualDepth > 0);
+ fActualDepth--;
+#endif
+ }
+
+ // Install the required MC state as the active one
+ fCurOpenStateID = fCurMCState->fMCStateID;
+
+ if (kIdentityWideOpenStateID == fCurOpenStateID) {
+ SkASSERT(0 == fActualDepth);
+ SkASSERT(!fCurMCState->fHasOpen);
+ SkASSERT(0 == fSkipOffsets->count());
+ return false;
+ }
+
+ SkASSERT(!fCurMCState->fHasOpen);
+ SkASSERT(0 == fSkipOffsets->count());
+ fCurMCState->fHasOpen = true;
+ fPicRecord->recordSave(SkCanvas::kMatrixClip_SaveFlag);
+#ifdef SK_DEBUG
+ fActualDepth++;
+ SkASSERT(fActualDepth == fCurMCState->fExpectedDepth);
+#endif
+
+ // write out clips
+ SkDeque::Iter iter(fMatrixClipStack, SkDeque::Iter::kBack_IterStart);
+ const MatrixClipState* state;
+ // Loop back across the MC states until the last saveLayer. The MC
+ // state in front of the saveLayer has already been written out.
+ for (state = (const MatrixClipState*) iter.prev();
+ state != NULL;
+ state = (const MatrixClipState*) iter.prev()) {
+ if (state->fIsSaveLayer) {
+ break;
+ }
+ }
+
+ int curMatID;
+
+ if (NULL == state) {
+ // There was no saveLayer in the MC stack so we need to output them all
+ iter.reset(fMatrixClipStack, SkDeque::Iter::kFront_IterStart);
+ state = (const MatrixClipState*) iter.next();
+ curMatID = kIdentityMatID;
+ } else {
+ // SkDeque's iterators actually return the previous location so we
+ // need to reverse and go forward one to get back on track.
+ iter.next();
+ SkDEBUGCODE(const MatrixClipState* test = (const MatrixClipState*)) iter.next();
+ SkASSERT(test == state);
+
+ curMatID = state->fMatrixInfo->getID(this);
+
+ // TODO: this assumes that, in the case of Save|SaveLayer when the SaveLayer
+ // doesn't save the clip, that the SaveLayer doesn't add any additional clip state.
+ // This assumption will be removed when we explicitly store the clip state in
+ // self-contained objects. It is valid for the small set of skps.
+ if (NULL != state->fPrev && state->fClipInfo == state->fPrev->fClipInfo) {
+ // By the above assumption the SaveLayer's MC state has already been
+ // written out by the prior Save so don't output it again.
+ state = (const MatrixClipState*) iter.next();
+ }
+ }
+
+ for ( ; state != NULL; state = (const MatrixClipState*) iter.next()) {
+ state->fClipInfo->writeClip(&curMatID, this);
+ }
+
+ // write out matrix
+ // TODO: this test isn't quite right. It should be:
+ // if (curMatID != fCurMCState->fMatrixInfo->getID(this)) {
+ // but right now the testing harness always expects a matrix if
+ // the matrices are non-I
+ if (kIdentityMatID != fCurMCState->fMatrixInfo->getID(this)) {
+ // TODO: writing out the delta matrix here is an artifact of the writing
+ // out of the entire clip stack (with its matrices). Ultimately we will
+ // write out the CTM here when the clip state is collapsed to a single path.
+ this->writeDeltaMat(curMatID, fCurMCState->fMatrixInfo->getID(this));
+ }
+
+ SkDEBUGCODE(this->validate();)
+ return true;
+}
+
+// Fill in the skip offsets for all the clips written in the current block
+void SkMatrixClipStateMgr::fillInSkips(SkWriter32* writer, int32_t restoreOffset) {
+ for (int i = 0; i < fSkipOffsets->count(); ++i) {
+ SkDEBUGCODE(int32_t peek = writer->readTAt<int32_t>((*fSkipOffsets)[i]);)
+ SkASSERT(-1 == peek);
+ writer->overwriteTAt<int32_t>((*fSkipOffsets)[i], restoreOffset);
+ }
+
+ fSkipOffsets->rewind();
+ SkASSERT(0 == fSkipOffsets->count());
+}
+
+void SkMatrixClipStateMgr::finish() {
+ if (kIdentityWideOpenStateID != fCurOpenStateID) {
+ fPicRecord->recordRestore(); // Close the open block
+ fCurMCState->fHasOpen = false;
+#ifdef SK_DEBUG
+ SkASSERT(fActualDepth > 0);
+ fActualDepth--;
+#endif
+ fCurOpenStateID = kIdentityWideOpenStateID;
+ SkASSERT(!fCurMCState->fHasOpen);
+ }
+}
+
+#ifdef SK_DEBUG
+void SkMatrixClipStateMgr::validate() {
+ if (fCurOpenStateID == fCurMCState->fMCStateID && !this->isNestingMCState(fCurOpenStateID)) {
+ // The current state is the active one so it should have a skip
+ // offset for each clip
+ SkDeque::Iter iter(fMatrixClipStack, SkDeque::Iter::kBack_IterStart);
+ int clipCount = 0;
+ for (const MatrixClipState* state = (const MatrixClipState*) iter.prev();
+ state != NULL;
+ state = (const MatrixClipState*) iter.prev()) {
+ if (NULL == state->fPrev || state->fPrev->fClipInfo != state->fClipInfo) {
+ clipCount += state->fClipInfo->numClips();
+ }
+ if (state->fIsSaveLayer) {
+ break;
+ }
+ }
+
+ SkASSERT(fSkipOffsets->count() == clipCount);
+ }
+}
+#endif
+
+int SkMatrixClipStateMgr::addRegionToDict(const SkRegion& region) {
+ int index = fRegionDict.count();
+ *fRegionDict.append() = SkNEW(SkRegion(region));
+ return index;
+}
+
+int SkMatrixClipStateMgr::addMatToDict(const SkMatrix& mat) {
+ if (mat.isIdentity()) {
+ return kIdentityMatID;
+ }
+
+ *fMatrixDict.append() = mat;
+ return fMatrixDict.count()-1;
+}
diff --git a/chromium/third_party/skia/src/core/SkMatrixClipStateMgr.h b/chromium/third_party/skia/src/core/SkMatrixClipStateMgr.h
new file mode 100644
index 00000000000..016baa008a6
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkMatrixClipStateMgr.h
@@ -0,0 +1,414 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkMatrixClipStateMgr_DEFINED
+#define SkMatrixClipStateMgr_DEFINED
+
+#include "SkCanvas.h"
+#include "SkMatrix.h"
+#include "SkRegion.h"
+#include "SkRRect.h"
+#include "SkTypes.h"
+#include "SkTDArray.h"
+
+class SkPictureRecord;
+class SkWriter32;
+
+// The SkMatrixClipStateMgr collapses the matrix/clip state of an SkPicture into
+// a series of save/restore blocks of consistent matrix clip state, e.g.:
+//
+// save
+// clip(s)
+// concat
+// ... draw ops ...
+// restore
+//
+// SaveLayers simply add another level, e.g.:
+//
+// save
+// clip(s)
+// concat
+// ... draw ops ...
+// saveLayer
+// save
+// clip(s)
+// concat
+// ... draw ops ...
+// restore
+// restore
+// restore
+//
+// As a side effect of this process all saves and saveLayers will become
+// kMatrixClip_SaveFlag style saves/saveLayers.
+
+// The SkMatrixClipStateMgr works by intercepting all the save*, restore, clip*,
+// and matrix calls sent to SkCanvas in order to track the current matrix/clip
+// state. All the other canvas calls get funnelled into a generic "call" entry
+// point that signals that a state block is required.
+class SkMatrixClipStateMgr {
+public:
+ static const int32_t kIdentityWideOpenStateID = 0;
+ static const int kIdentityMatID = 0;
+
+ class MatrixClipState : SkNoncopyable {
+ public:
+ class MatrixInfo {
+ public:
+ void reset() {
+ fMatrixID = kIdentityMatID;
+ fMatrix.reset();
+ }
+
+ void preTranslate(SkScalar dx, SkScalar dy) {
+ fMatrixID = -1;
+ fMatrix.preTranslate(dx, dy);
+ }
+
+ void preScale(SkScalar sx, SkScalar sy) {
+ fMatrixID = -1;
+ fMatrix.preScale(sx, sy);
+ }
+
+ void preRotate(SkScalar degrees) {
+ fMatrixID = -1;
+ fMatrix.preRotate(degrees);
+ }
+
+ void preSkew(SkScalar sx, SkScalar sy) {
+ fMatrixID = -1;
+ fMatrix.preSkew(sx, sy);
+ }
+
+ void preConcat(const SkMatrix& matrix) {
+ fMatrixID = -1;
+ fMatrix.preConcat(matrix);
+ }
+
+ void setMatrix(const SkMatrix& matrix) {
+ fMatrixID = -1;
+ fMatrix = matrix;
+ }
+
+ int getID(SkMatrixClipStateMgr* mgr) {
+ if (fMatrixID >= 0) {
+ return fMatrixID;
+ }
+
+ fMatrixID = mgr->addMatToDict(fMatrix);
+ return fMatrixID;
+ }
+
+ private:
+ SkMatrix fMatrix;
+ int fMatrixID;
+
+ typedef SkNoncopyable INHERITED;
+ };
+
+ class ClipInfo : SkNoncopyable {
+ public:
+ ClipInfo() {}
+
+ bool clipRect(const SkRect& rect,
+ SkRegion::Op op,
+ bool doAA,
+ int matrixID) {
+ ClipOp* newClip = fClips.append();
+ newClip->fClipType = kRect_ClipType;
+ newClip->fGeom.fRRect.setRect(rect); // storing the clipRect in the RRect
+ newClip->fOp = op;
+ newClip->fDoAA = doAA;
+ newClip->fMatrixID = matrixID;
+ return false;
+ }
+
+ bool clipRRect(const SkRRect& rrect,
+ SkRegion::Op op,
+ bool doAA,
+ int matrixID) {
+ ClipOp* newClip = fClips.append();
+ newClip->fClipType = kRRect_ClipType;
+ newClip->fGeom.fRRect = rrect;
+ newClip->fOp = op;
+ newClip->fDoAA = doAA;
+ newClip->fMatrixID = matrixID;
+ return false;
+ }
+
+ bool clipPath(SkPictureRecord* picRecord,
+ const SkPath& path,
+ SkRegion::Op op,
+ bool doAA,
+ int matrixID);
+ bool clipRegion(SkPictureRecord* picRecord,
+ int regionID,
+ SkRegion::Op op,
+ int matrixID);
+ void writeClip(int* curMatID, SkMatrixClipStateMgr* mgr);
+
+ SkDEBUGCODE(int numClips() const { return fClips.count(); })
+
+ private:
+ enum ClipType {
+ kRect_ClipType,
+ kRRect_ClipType,
+ kPath_ClipType,
+ kRegion_ClipType
+ };
+
+ class ClipOp {
+ public:
+ ClipType fClipType;
+
+ union {
+ SkRRect fRRect; // also stores clip rect
+ int fPathID;
+ int fRegionID;
+ } fGeom;
+
+ bool fDoAA;
+ SkRegion::Op fOp;
+
+ // The CTM in effect when this clip call was issued
+ int fMatrixID;
+ };
+
+ SkTDArray<ClipOp> fClips;
+
+ typedef SkNoncopyable INHERITED;
+ };
+
+ MatrixClipState(MatrixClipState* prev, int flags)
+ : fPrev(prev)
+ {
+ fHasOpen = false;
+
+ if (NULL == prev) {
+ fLayerID = 0;
+
+ fMatrixInfoStorage.reset();
+ fMatrixInfo = &fMatrixInfoStorage;
+ fClipInfo = &fClipInfoStorage; // ctor handles init of fClipInfoStorage
+
+ // The identity/wide-open-clip state is current by default
+ fMCStateID = kIdentityWideOpenStateID;
+#ifdef SK_DEBUG
+ fExpectedDepth = 1;
+#endif
+ }
+ else {
+ fLayerID = prev->fLayerID;
+
+ if (flags & SkCanvas::kMatrix_SaveFlag) {
+ fMatrixInfoStorage = *prev->fMatrixInfo;
+ fMatrixInfo = &fMatrixInfoStorage;
+ } else {
+ fMatrixInfo = prev->fMatrixInfo;
+ }
+
+ if (flags & SkCanvas::kClip_SaveFlag) {
+ // We don't copy the ClipOps of the previous clip states
+ fClipInfo = &fClipInfoStorage;
+ } else {
+ fClipInfo = prev->fClipInfo;
+ }
+
+ // Initially a new save/saveLayer represents the same MC state
+ // as its predecessor.
+ fMCStateID = prev->fMCStateID;
+#ifdef SK_DEBUG
+ fExpectedDepth = prev->fExpectedDepth;
+#endif
+ }
+
+ fIsSaveLayer = false;
+ }
+
+ MatrixInfo* fMatrixInfo;
+ MatrixInfo fMatrixInfoStorage;
+
+ ClipInfo* fClipInfo;
+ ClipInfo fClipInfoStorage;
+
+ // Tracks the current depth of saveLayers to support the isDrawingToLayer call
+ int fLayerID;
+ // Does this MC state represent a saveLayer call?
+ bool fIsSaveLayer;
+
+ // The next field is only valid when fIsSaveLayer is set.
+ SkTDArray<int>* fSavedSkipOffsets;
+
+ // Does the MC state have an open block in the skp?
+ bool fHasOpen;
+
+ MatrixClipState* fPrev;
+
+#ifdef SK_DEBUG
+ int fExpectedDepth; // debugging aid
+#endif
+
+ int32_t fMCStateID;
+ };
+
+ enum CallType {
+ kMatrix_CallType,
+ kClip_CallType,
+ kOther_CallType
+ };
+
+ SkMatrixClipStateMgr();
+ ~SkMatrixClipStateMgr();
+
+ void init(SkPictureRecord* picRecord) {
+ // Note: we're not taking a ref here. It is expected that the SkMatrixClipStateMgr
+ // is owned by the SkPictureRecord object
+ fPicRecord = picRecord;
+ }
+
+ SkPictureRecord* getPicRecord() { return fPicRecord; }
+
+ // TODO: need to override canvas' getSaveCount. Right now we pass the
+ // save* and restore calls on to the base SkCanvas in SkPictureRecord but
+ // this duplicates effort.
+ int getSaveCount() const { return fMatrixClipStack.count(); }
+
+ int save(SkCanvas::SaveFlags flags);
+
+ int saveLayer(const SkRect* bounds, const SkPaint* paint, SkCanvas::SaveFlags flags);
+
+ bool isDrawingToLayer() const {
+ return fCurMCState->fLayerID > 0;
+ }
+
+ void restore();
+
+ void translate(SkScalar dx, SkScalar dy) {
+ this->call(kMatrix_CallType);
+ fCurMCState->fMatrixInfo->preTranslate(dx, dy);
+ }
+
+ void scale(SkScalar sx, SkScalar sy) {
+ this->call(kMatrix_CallType);
+ fCurMCState->fMatrixInfo->preScale(sx, sy);
+ }
+
+ void rotate(SkScalar degrees) {
+ this->call(kMatrix_CallType);
+ fCurMCState->fMatrixInfo->preRotate(degrees);
+ }
+
+ void skew(SkScalar sx, SkScalar sy) {
+ this->call(kMatrix_CallType);
+ fCurMCState->fMatrixInfo->preSkew(sx, sy);
+ }
+
+ void concat(const SkMatrix& matrix) {
+ this->call(kMatrix_CallType);
+ fCurMCState->fMatrixInfo->preConcat(matrix);
+ }
+
+ void setMatrix(const SkMatrix& matrix) {
+ this->call(kMatrix_CallType);
+ fCurMCState->fMatrixInfo->setMatrix(matrix);
+ }
+
+ bool clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
+ this->call(SkMatrixClipStateMgr::kClip_CallType);
+ return fCurMCState->fClipInfo->clipRect(rect, op, doAA,
+ fCurMCState->fMatrixInfo->getID(this));
+ }
+
+ bool clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
+ this->call(SkMatrixClipStateMgr::kClip_CallType);
+ return fCurMCState->fClipInfo->clipRRect(rrect, op, doAA,
+ fCurMCState->fMatrixInfo->getID(this));
+ }
+
+ bool clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
+ this->call(SkMatrixClipStateMgr::kClip_CallType);
+ return fCurMCState->fClipInfo->clipPath(fPicRecord, path, op, doAA,
+ fCurMCState->fMatrixInfo->getID(this));
+ }
+
+ bool clipRegion(const SkRegion& region, SkRegion::Op op) {
+ this->call(SkMatrixClipStateMgr::kClip_CallType);
+ int regionID = this->addRegionToDict(region);
+ return fCurMCState->fClipInfo->clipRegion(fPicRecord, regionID, op,
+ fCurMCState->fMatrixInfo->getID(this));
+ }
+
+ bool call(CallType callType);
+
+ void fillInSkips(SkWriter32* writer, int32_t restoreOffset);
+
+ void finish();
+
+protected:
+ SkPictureRecord* fPicRecord;
+
+ uint32_t fMatrixClipStackStorage[43]; // sized to fit 2 clip states
+ SkDeque fMatrixClipStack;
+ MatrixClipState* fCurMCState;
+
+ // This dictionary doesn't actually de-duplicate the matrices (except for the
+ // identity matrix). It merely stores the matrices and allows them to be looked
+ // up by ID later. The de-duplication mainly falls upon the matrix/clip stack
+ // which stores the ID so a revisited clip/matrix (via popping the stack) will
+ // use the same ID.
+ SkTDArray<SkMatrix> fMatrixDict;
+
+ SkTDArray<SkRegion*> fRegionDict;
+
+ // The MCStateID of the state currently in effect in the byte stream. 0 if none.
+ int32_t fCurOpenStateID;
+ // The skip offsets for the current open state. These are the locations in the
+ // skp that must be filled in when the current open state is closed. These are
+ // here rather then distributed across the MatrixClipState's because saveLayers
+ // can cause MC states to be nested.
+ SkTDArray<int32_t> *fSkipOffsets; // TODO: should we store u32 or size_t instead?
+
+ SkDEBUGCODE(void validate();)
+
+ int MCStackPush(SkCanvas::SaveFlags flags);
+
+ void addClipOffset(size_t offset) {
+ SkASSERT(NULL != fSkipOffsets);
+ SkASSERT(kIdentityWideOpenStateID != fCurOpenStateID);
+ SkASSERT(fCurMCState->fHasOpen);
+ SkASSERT(!fCurMCState->fIsSaveLayer);
+
+ *fSkipOffsets->append() = SkToS32(offset);
+ }
+
+ void writeDeltaMat(int currentMatID, int desiredMatID);
+ static int32_t NewMCStateID();
+
+ int addRegionToDict(const SkRegion& region);
+ const SkRegion* lookupRegion(int index) {
+ SkASSERT(index >= 0 && index < fRegionDict.count());
+ return fRegionDict[index];
+ }
+
+ // TODO: add stats to check if the dictionary really does
+ // reduce the size of the SkPicture.
+ int addMatToDict(const SkMatrix& mat);
+ const SkMatrix& lookupMat(int index) {
+ SkASSERT(index >= 0 && index < fMatrixDict.count());
+ return fMatrixDict[index];
+ }
+
+ bool isNestingMCState(int stateID);
+
+#ifdef SK_DEBUG
+ int fActualDepth;
+#endif
+
+ // save layers are nested within a specific MC state. This stack tracks
+ // the nesting MC state's ID as save layers are pushed and popped.
+ SkTDArray<int> fStateIDStack;
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/core/SkMessageBus.h b/chromium/third_party/skia/src/core/SkMessageBus.h
index 0a408319c15..f36c42b4c7b 100644
--- a/chromium/third_party/skia/src/core/SkMessageBus.h
+++ b/chromium/third_party/skia/src/core/SkMessageBus.h
@@ -8,7 +8,7 @@
#ifndef SkMessageBus_DEFINED
#define SkMessageBus_DEFINED
-#include "SkOnce.h"
+#include "SkLazyPtr.h"
#include "SkTDArray.h"
#include "SkThread.h"
#include "SkTypes.h"
@@ -38,12 +38,21 @@ public:
private:
SkMessageBus();
static SkMessageBus* Get();
- static void New(SkMessageBus**);
+ static SkMessageBus* New();
SkTDArray<Inbox*> fInboxes;
SkMutex fInboxesMutex;
};
+// This must go in a single .cpp file, not some .h, or we risk creating more than one global
+// SkMessageBus per type when using shared libraries.
+#define DECLARE_SKMESSAGEBUS_MESSAGE(Message) \
+ template <> \
+ SkMessageBus<Message>* SkMessageBus<Message>::Get() { \
+ SK_DECLARE_STATIC_LAZY_PTR(SkMessageBus<Message>, bus, New); \
+ return bus.get(); \
+ }
+
// ----------------------- Implementation of SkMessageBus::Inbox -----------------------
template<typename Message>
@@ -88,19 +97,8 @@ template <typename Message>
SkMessageBus<Message>::SkMessageBus() {}
template <typename Message>
-/*static*/ void SkMessageBus<Message>::New(SkMessageBus<Message>** bus) {
- *bus = new SkMessageBus<Message>();
-}
-
-template <typename Message>
-/*static*/ SkMessageBus<Message>* SkMessageBus<Message>::Get() {
- // The first time this method is called, create the singleton bus for this message type.
- static SkMessageBus<Message>* bus = NULL;
- SK_DECLARE_STATIC_ONCE(once);
- SkOnce(&once, &New, &bus);
-
- SkASSERT(bus != NULL);
- return bus;
+/*static*/ SkMessageBus<Message>* SkMessageBus<Message>::New() {
+ return SkNEW(SkMessageBus<Message>);
}
template <typename Message>
diff --git a/chromium/third_party/skia/src/core/SkMetaData.cpp b/chromium/third_party/skia/src/core/SkMetaData.cpp
index 5a494b3511f..dfc2a949018 100644
--- a/chromium/third_party/skia/src/core/SkMetaData.cpp
+++ b/chromium/third_party/skia/src/core/SkMetaData.cpp
@@ -91,7 +91,7 @@ SkScalar* SkMetaData::setScalars(const char name[], int count, const SkScalar va
void SkMetaData::setString(const char name[], const char value[])
{
- (void)this->set(name, value, sizeof(char), kString_Type, strlen(value) + 1);
+ (void)this->set(name, value, sizeof(char), kString_Type, SkToInt(strlen(value) + 1));
}
void SkMetaData::setPtr(const char name[], void* ptr, PtrProc proc) {
@@ -105,7 +105,7 @@ void SkMetaData::setBool(const char name[], bool value)
}
void SkMetaData::setData(const char name[], const void* data, size_t byteCount) {
- (void)this->set(name, data, sizeof(char), kData_Type, byteCount);
+ (void)this->set(name, data, sizeof(char), kData_Type, SkToInt(byteCount));
}
void* SkMetaData::set(const char name[], const void* data, size_t dataSize, Type type, int count)
diff --git a/chromium/third_party/skia/src/core/SkMipMap.cpp b/chromium/third_party/skia/src/core/SkMipMap.cpp
index 4888b574e4a..cb88eb4596b 100644
--- a/chromium/third_party/skia/src/core/SkMipMap.cpp
+++ b/chromium/third_party/skia/src/core/SkMipMap.cpp
@@ -109,41 +109,35 @@ static void downsampleby2_proc4444(SkBitmap* dst, int x, int y,
*dst->getAddr16(x >> 1, y >> 1) = (uint16_t)collaps4444(c >> 2);
}
-static bool isPos32Bits(const Sk64& value) {
- return !value.isNeg() && value.is32();
-}
-
SkMipMap::Level* SkMipMap::AllocLevels(int levelCount, size_t pixelSize) {
if (levelCount < 0) {
return NULL;
}
- Sk64 size;
- size.setMul(levelCount + 1, sizeof(Level));
- size.add(SkToS32(pixelSize));
- if (!isPos32Bits(size)) {
+ int64_t size = sk_64_mul(levelCount + 1, sizeof(Level)) + pixelSize;
+ if (!sk_64_isS32(size)) {
return NULL;
}
- return (Level*)sk_malloc_throw(size.get32());
+ return (Level*)sk_malloc_throw(sk_64_asS32(size));
}
SkMipMap* SkMipMap::Build(const SkBitmap& src) {
void (*proc)(SkBitmap* dst, int x, int y, const SkBitmap& src);
- const SkBitmap::Config config = src.config();
- switch (config) {
- case SkBitmap::kARGB_8888_Config:
+ const SkColorType ct = src.colorType();
+ const SkAlphaType at = src.alphaType();
+ switch (ct) {
+ case kRGBA_8888_SkColorType:
+ case kBGRA_8888_SkColorType:
proc = downsampleby2_proc32;
break;
- case SkBitmap::kRGB_565_Config:
+ case kRGB_565_SkColorType:
proc = downsampleby2_proc16;
break;
- case SkBitmap::kARGB_4444_Config:
+ case kARGB_4444_SkColorType:
proc = downsampleby2_proc4444;
break;
- case SkBitmap::kIndex8_Config:
- case SkBitmap::kA8_Config:
default:
- return NULL; // don't build mipmaps for these configs
+ return NULL; // don't build mipmaps for any other colortypes (yet)
}
SkAutoLockPixels alp(src);
@@ -163,7 +157,7 @@ SkMipMap* SkMipMap::Build(const SkBitmap& src) {
if (0 == width || 0 == height) {
break;
}
- size += SkBitmap::ComputeRowBytes(config, width) * height;
+ size += SkColorTypeMinRowBytes(ct, width) * height;
countLevels += 1;
}
}
@@ -186,7 +180,7 @@ SkMipMap* SkMipMap::Build(const SkBitmap& src) {
for (int i = 0; i < countLevels; ++i) {
width >>= 1;
height >>= 1;
- rowBytes = SkToU32(SkBitmap::ComputeRowBytes(config, width));
+ rowBytes = SkToU32(SkColorTypeMinRowBytes(ct, width));
levels[i].fPixels = addr;
levels[i].fWidth = width;
@@ -195,8 +189,7 @@ SkMipMap* SkMipMap::Build(const SkBitmap& src) {
levels[i].fScale = (float)width / src.width();
SkBitmap dstBM;
- dstBM.setConfig(config, width, height, rowBytes);
- dstBM.setPixels(addr);
+ dstBM.installPixels(SkImageInfo::Make(width, height, ct, at), addr, rowBytes);
srcBM.lockPixels();
for (int y = 0; y < height; y++) {
diff --git a/chromium/third_party/skia/src/core/SkOnce.h b/chromium/third_party/skia/src/core/SkOnce.h
deleted file mode 100644
index 89de1124421..00000000000
--- a/chromium/third_party/skia/src/core/SkOnce.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright 2013 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkOnce_DEFINED
-#define SkOnce_DEFINED
-
-// SkOnce.h defines SK_DECLARE_STATIC_ONCE and SkOnce(), which you can use
-// together to create a threadsafe way to call a function just once. This
-// is particularly useful for lazy singleton initialization. E.g.
-//
-// static void set_up_my_singleton(Singleton** singleton) {
-// *singleton = new Singleton(...);
-// }
-// ...
-// const Singleton& GetSingleton() {
-// static Singleton* singleton = NULL;
-// SK_DECLARE_STATIC_ONCE(once);
-// SkOnce(&once, set_up_my_singleton, &singleton);
-// SkASSERT(NULL != singleton);
-// return *singleton;
-// }
-//
-// OnceTest.cpp also should serve as a few other simple examples.
-
-#include "SkThread.h"
-#include "SkTypes.h"
-
-#ifdef SK_USE_POSIX_THREADS
-# define SK_ONCE_INIT { false, { PTHREAD_MUTEX_INITIALIZER } }
-#else
-# define SK_ONCE_INIT { false, SkBaseMutex() }
-#endif
-
-#define SK_DECLARE_STATIC_ONCE(name) static SkOnceFlag name = SK_ONCE_INIT
-
-struct SkOnceFlag; // If manually created, initialize with SkOnceFlag once = SK_ONCE_INIT
-
-template <typename Func, typename Arg>
-inline void SkOnce(SkOnceFlag* once, Func f, Arg arg);
-
-// ---------------------- Implementation details below here. -----------------------------
-
-struct SkOnceFlag {
- bool done;
- SkBaseMutex mutex;
-};
-
-// TODO(bungeman, mtklein): move all these *barrier* functions to SkThread when refactoring lands.
-
-#ifdef SK_BUILD_FOR_WIN
-#include <intrin.h>
-inline static void compiler_barrier() {
- _ReadWriteBarrier();
-}
-#else
-inline static void compiler_barrier() {
- asm volatile("" : : : "memory");
-}
-#endif
-
-inline static void full_barrier_on_arm() {
-#ifdef SK_CPU_ARM
-#if SK_ARM_ARCH >= 7
- asm volatile("dmb" : : : "memory");
-#else
- asm volatile("mcr p15, 0, %0, c7, c10, 5" : : "r" (0) : "memory");
-#endif
-#endif
-}
-
-// On every platform, we issue a compiler barrier to prevent it from reordering
-// code. That's enough for platforms like x86 where release and acquire
-// barriers are no-ops. On other platforms we may need to be more careful;
-// ARM, in particular, needs real code for both acquire and release. We use a
-// full barrier, which acts as both, because that the finest precision ARM
-// provides.
-
-inline static void release_barrier() {
- compiler_barrier();
- full_barrier_on_arm();
-}
-
-inline static void acquire_barrier() {
- compiler_barrier();
- full_barrier_on_arm();
-}
-
-// We've pulled a pretty standard double-checked locking implementation apart
-// into its main fast path and a slow path that's called when we suspect the
-// one-time code hasn't run yet.
-
-// This is the guts of the code, called when we suspect the one-time code hasn't been run yet.
-// This should be rarely called, so we separate it from SkOnce and don't mark it as inline.
-// (We don't mind if this is an actual function call, but odds are it'll be inlined anyway.)
-template <typename Func, typename Arg>
-static void sk_once_slow(SkOnceFlag* once, Func f, Arg arg) {
- const SkAutoMutexAcquire lock(once->mutex);
- if (!once->done) {
- f(arg);
- // Also known as a store-store/load-store barrier, this makes sure that the writes
- // done before here---in particular, those done by calling f(arg)---are observable
- // before the writes after the line, *done = true.
- //
- // In version control terms this is like saying, "check in the work up
- // to and including f(arg), then check in *done=true as a subsequent change".
- //
- // We'll use this in the fast path to make sure f(arg)'s effects are
- // observable whenever we observe *done == true.
- release_barrier();
- once->done = true;
- }
-}
-
-// We nabbed this code from the dynamic_annotations library, and in their honor
-// we check the same define. If you find yourself wanting more than just
-// ANNOTATE_BENIGN_RACE, it might make sense to pull that in as a dependency
-// rather than continue to reproduce it here.
-
-#if DYNAMIC_ANNOTATIONS_ENABLED
-// TSAN provides this hook to supress a known-safe apparent race.
-extern "C" {
-void AnnotateBenignRace(const char* file, int line, const volatile void* mem, const char* desc);
-}
-#define ANNOTATE_BENIGN_RACE(mem, desc) AnnotateBenignRace(__FILE__, __LINE__, mem, desc)
-#else
-#define ANNOTATE_BENIGN_RACE(mem, desc)
-#endif
-
-// This is our fast path, called all the time. We do really want it to be inlined.
-template <typename Func, typename Arg>
-inline void SkOnce(SkOnceFlag* once, Func f, Arg arg) {
- ANNOTATE_BENIGN_RACE(&(once->done), "Don't worry TSAN, we're sure this is safe.");
- if (!once->done) {
- sk_once_slow(once, f, arg);
- }
- // Also known as a load-load/load-store barrier, this acquire barrier makes
- // sure that anything we read from memory---in particular, memory written by
- // calling f(arg)---is at least as current as the value we read from once->done.
- //
- // In version control terms, this is a lot like saying "sync up to the
- // commit where we wrote once->done = true".
- //
- // The release barrier in sk_once_slow guaranteed that once->done = true
- // happens after f(arg), so by syncing to once->done = true here we're
- // forcing ourselves to also wait until the effects of f(arg) are readble.
- acquire_barrier();
-}
-
-#undef ANNOTATE_BENIGN_RACE
-
-#endif // SkOnce_DEFINED
diff --git a/chromium/third_party/skia/src/core/SkOrderedReadBuffer.h b/chromium/third_party/skia/src/core/SkOrderedReadBuffer.h
index 2c4f480e739..3286f6b9df1 100644
--- a/chromium/third_party/skia/src/core/SkOrderedReadBuffer.h
+++ b/chromium/third_party/skia/src/core/SkOrderedReadBuffer.h
@@ -1,140 +1,9 @@
-
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
+// Temporary shim to keep a couple dependencies working in Chromium.
#ifndef SkOrderedReadBuffer_DEFINED
#define SkOrderedReadBuffer_DEFINED
-#include "SkRefCnt.h"
-#include "SkBitmapHeap.h"
-#include "SkFlattenableBuffers.h"
-#include "SkPath.h"
-#include "SkPicture.h"
-#include "SkReader32.h"
-
-class SkBitmap;
-
-#if defined(SK_DEBUG) && defined(SK_BUILD_FOR_MAC)
- #define DEBUG_NON_DETERMINISTIC_ASSERT
-#endif
-
-class SkOrderedReadBuffer : public SkFlattenableReadBuffer {
-public:
- SkOrderedReadBuffer();
- SkOrderedReadBuffer(const void* data, size_t size);
- SkOrderedReadBuffer(SkStream* stream);
- virtual ~SkOrderedReadBuffer();
-
- virtual SkOrderedReadBuffer* getOrderedBinaryBuffer() SK_OVERRIDE { return this; }
-
- SkReader32* getReader32() { return &fReader; }
-
- uint32_t size() { return fReader.size(); }
- uint32_t offset() { return fReader.offset(); }
- bool eof() { return fReader.eof(); }
- const void* skip(size_t size) { return fReader.skip(size); }
-
- // primitives
- virtual bool readBool() SK_OVERRIDE;
- virtual SkColor readColor() SK_OVERRIDE;
- virtual SkFixed readFixed() SK_OVERRIDE;
- virtual int32_t readInt() SK_OVERRIDE;
- virtual SkScalar readScalar() SK_OVERRIDE;
- virtual uint32_t readUInt() SK_OVERRIDE;
- virtual int32_t read32() SK_OVERRIDE;
-
- // strings -- the caller is responsible for freeing the string contents
- virtual void readString(SkString* string) SK_OVERRIDE;
- virtual void* readEncodedString(size_t* length, SkPaint::TextEncoding encoding) SK_OVERRIDE;
-
- // common data structures
- virtual SkFlattenable* readFlattenable(SkFlattenable::Type) SK_OVERRIDE;
- virtual void readPoint(SkPoint* point) SK_OVERRIDE;
- virtual void readMatrix(SkMatrix* matrix) SK_OVERRIDE;
- virtual void readIRect(SkIRect* rect) SK_OVERRIDE;
- virtual void readRect(SkRect* rect) SK_OVERRIDE;
- virtual void readRegion(SkRegion* region) SK_OVERRIDE;
- virtual void readPath(SkPath* path) SK_OVERRIDE;
-
- // binary data and arrays
- virtual bool readByteArray(void* value, size_t size) SK_OVERRIDE;
- virtual bool readColorArray(SkColor* colors, size_t size) SK_OVERRIDE;
- virtual bool readIntArray(int32_t* values, size_t size) SK_OVERRIDE;
- virtual bool readPointArray(SkPoint* points, size_t size) SK_OVERRIDE;
- virtual bool readScalarArray(SkScalar* values, size_t size) SK_OVERRIDE;
-
- // helpers to get info about arrays and binary data
- virtual uint32_t getArrayCount() SK_OVERRIDE;
-
- virtual void readBitmap(SkBitmap* bitmap) SK_OVERRIDE;
- virtual SkTypeface* readTypeface() SK_OVERRIDE;
-
- void setBitmapStorage(SkBitmapHeapReader* bitmapStorage) {
- SkRefCnt_SafeAssign(fBitmapStorage, bitmapStorage);
- }
-
- void setTypefaceArray(SkTypeface* array[], int count) {
- fTFArray = array;
- fTFCount = count;
- }
-
- /**
- * Call this with a pre-loaded array of Factories, in the same order as
- * were created/written by the writer. SkPicture uses this.
- */
- void setFactoryPlayback(SkFlattenable::Factory array[], int count) {
- fFactoryTDArray = NULL;
- fFactoryArray = array;
- fFactoryCount = count;
- }
-
- /**
- * Call this with an initially empty array, so the reader can cache each
- * factory it sees by name. Used by the pipe code in conjunction with
- * SkOrderedWriteBuffer::setNamedFactoryRecorder.
- */
- void setFactoryArray(SkTDArray<SkFlattenable::Factory>* array) {
- fFactoryTDArray = array;
- fFactoryArray = NULL;
- fFactoryCount = 0;
- }
-
- /**
- * Provide a function to decode an SkBitmap from encoded data. Only used if the writer
- * encoded the SkBitmap. If the proper decoder cannot be used, a red bitmap with the
- * appropriate size will be used.
- */
- void setBitmapDecoder(SkPicture::InstallPixelRefProc bitmapDecoder) {
- fBitmapDecoder = bitmapDecoder;
- }
-
-private:
- bool readArray(void* value, size_t size, size_t elementSize);
-
- SkReader32 fReader;
- void* fMemoryPtr;
-
- SkBitmapHeapReader* fBitmapStorage;
- SkTypeface** fTFArray;
- int fTFCount;
-
- SkTDArray<SkFlattenable::Factory>* fFactoryTDArray;
- SkFlattenable::Factory* fFactoryArray;
- int fFactoryCount;
-
- SkPicture::InstallPixelRefProc fBitmapDecoder;
-
-#ifdef DEBUG_NON_DETERMINISTIC_ASSERT
- // Debugging counter to keep track of how many bitmaps we
- // have decoded.
- int fDecodedBitmapIndex;
-#endif // DEBUG_NON_DETERMINISTIC_ASSERT
+#include "SkReadBuffer.h"
- typedef SkFlattenableReadBuffer INHERITED;
-};
+typedef SkReadBuffer SkOrderedReadBuffer;
-#endif // SkOrderedReadBuffer_DEFINED
+#endif//SkOrderedReadBuffer_DEFINED
diff --git a/chromium/third_party/skia/src/core/SkOrderedWriteBuffer.h b/chromium/third_party/skia/src/core/SkOrderedWriteBuffer.h
deleted file mode 100644
index f3b414e104a..00000000000
--- a/chromium/third_party/skia/src/core/SkOrderedWriteBuffer.h
+++ /dev/null
@@ -1,117 +0,0 @@
-
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkOrderedWriteBuffer_DEFINED
-#define SkOrderedWriteBuffer_DEFINED
-
-#include "SkFlattenableBuffers.h"
-
-#include "SkRefCnt.h"
-#include "SkBitmapHeap.h"
-#include "SkPath.h"
-#include "SkPicture.h"
-#include "SkWriter32.h"
-
-class SkBitmap;
-class SkFlattenable;
-class SkFactorySet;
-class SkNamedFactorySet;
-class SkRefCntSet;
-
-class SkOrderedWriteBuffer : public SkFlattenableWriteBuffer {
-public:
- SkOrderedWriteBuffer(size_t minSize);
- SkOrderedWriteBuffer(size_t minSize, void* initialStorage, size_t storageSize);
- virtual ~SkOrderedWriteBuffer();
-
- virtual bool isOrderedBinaryBuffer() SK_OVERRIDE { return true; }
- virtual SkOrderedWriteBuffer* getOrderedBinaryBuffer() SK_OVERRIDE { return this; }
-
- SkWriter32* getWriter32() { return &fWriter; }
- void reset(void* storage, size_t storageSize) { fWriter.reset(storage, storageSize); }
-
- // Returns true if we've written only into the storage passed into constructor or reset.
- // (You may be able to use this to avoid a call to writeToMemory.)
- bool wroteOnlyToStorage() const { return fWriter.wroteOnlyToStorage(); }
-
- void writeToMemory(void* dst) { fWriter.flatten(dst); }
- uint32_t* reserve(size_t size) { return fWriter.reserve(size); }
-
- size_t bytesWritten() const { return fWriter.bytesWritten(); }
- // Deprecated. Please call bytesWritten instead. TODO(mtklein): clean up
- size_t size() const { return this->bytesWritten(); }
-
- virtual void writeByteArray(const void* data, size_t size) SK_OVERRIDE;
- virtual void writeBool(bool value) SK_OVERRIDE;
- virtual void writeFixed(SkFixed value) SK_OVERRIDE;
- virtual void writeScalar(SkScalar value) SK_OVERRIDE;
- virtual void writeScalarArray(const SkScalar* value, uint32_t count) SK_OVERRIDE;
- virtual void writeInt(int32_t value) SK_OVERRIDE;
- virtual void writeIntArray(const int32_t* value, uint32_t count) SK_OVERRIDE;
- virtual void writeUInt(uint32_t value) SK_OVERRIDE;
- virtual void write32(int32_t value) SK_OVERRIDE;
- virtual void writeString(const char* value) SK_OVERRIDE;
- virtual void writeEncodedString(const void* value, size_t byteLength,
- SkPaint::TextEncoding encoding) SK_OVERRIDE;
-
- virtual void writeFlattenable(const SkFlattenable* flattenable) SK_OVERRIDE;
- virtual void writeColor(const SkColor& color) SK_OVERRIDE;
- virtual void writeColorArray(const SkColor* color, uint32_t count) SK_OVERRIDE;
- virtual void writePoint(const SkPoint& point) SK_OVERRIDE;
- virtual void writePointArray(const SkPoint* point, uint32_t count) SK_OVERRIDE;
- virtual void writeMatrix(const SkMatrix& matrix) SK_OVERRIDE;
- virtual void writeIRect(const SkIRect& rect)SK_OVERRIDE;
- virtual void writeRect(const SkRect& rect) SK_OVERRIDE;
- virtual void writeRegion(const SkRegion& region) SK_OVERRIDE;
- virtual void writePath(const SkPath& path) SK_OVERRIDE;
- virtual size_t writeStream(SkStream* stream, size_t length) SK_OVERRIDE;
-
- virtual void writeBitmap(const SkBitmap& bitmap) SK_OVERRIDE;
- virtual void writeTypeface(SkTypeface* typeface) SK_OVERRIDE;
-
- virtual bool writeToStream(SkWStream*) SK_OVERRIDE;
-
- SkFactorySet* setFactoryRecorder(SkFactorySet*);
- SkNamedFactorySet* setNamedFactoryRecorder(SkNamedFactorySet*);
-
- SkRefCntSet* getTypefaceRecorder() const { return fTFSet; }
- SkRefCntSet* setTypefaceRecorder(SkRefCntSet*);
-
- /**
- * Set an SkBitmapHeap to store bitmaps rather than flattening.
- *
- * Incompatible with an EncodeBitmap function. If an EncodeBitmap function is set, setting an
- * SkBitmapHeap will set the function to NULL in release mode and crash in debug.
- */
- void setBitmapHeap(SkBitmapHeap*);
-
- /**
- * Provide a function to encode an SkBitmap to an SkData. writeBitmap will attempt to use
- * bitmapEncoder to store the SkBitmap. If the reader does not provide a function to decode, it
- * will not be able to restore SkBitmaps, but will still be able to read the rest of the stream.
- * bitmapEncoder will never be called with a NULL pixelRefOffset.
- *
- * Incompatible with the SkBitmapHeap. If an encoder is set fBitmapHeap will be set to NULL in
- * release and crash in debug.
- */
- void setBitmapEncoder(SkPicture::EncodeBitmap bitmapEncoder);
-
-private:
- SkFactorySet* fFactorySet;
- SkNamedFactorySet* fNamedFactorySet;
- SkWriter32 fWriter;
-
- SkBitmapHeap* fBitmapHeap;
- SkRefCntSet* fTFSet;
-
- SkPicture::EncodeBitmap fBitmapEncoder;
-
- typedef SkFlattenableWriteBuffer INHERITED;
-};
-
-#endif // SkOrderedWriteBuffer_DEFINED
diff --git a/chromium/third_party/skia/src/core/SkPackBits.cpp b/chromium/third_party/skia/src/core/SkPackBits.cpp
index 7a1444b14c0..3c6197b6f27 100644
--- a/chromium/third_party/skia/src/core/SkPackBits.cpp
+++ b/chromium/third_party/skia/src/core/SkPackBits.cpp
@@ -10,7 +10,7 @@
#define GATHER_STATSx
static inline void small_memcpy(void* SK_RESTRICT dst,
- const void* SK_RESTRICT src, int n) {
+ const void* SK_RESTRICT src, size_t n) {
SkASSERT(n > 0 && n <= 15);
uint8_t* d = (uint8_t*)dst;
const uint8_t* s = (const uint8_t*)src;
@@ -34,7 +34,7 @@ static inline void small_memcpy(void* SK_RESTRICT dst,
}
}
-static inline void small_memset(void* dst, uint8_t value, int n) {
+static inline void small_memset(void* dst, uint8_t value, size_t n) {
SkASSERT(n > 0 && n <= 15);
uint8_t* d = (uint8_t*)dst;
switch (n) {
@@ -196,7 +196,7 @@ size_t SkPackBits::Pack16(const uint16_t* SK_RESTRICT src, int count,
const uint16_t* stop = src + count;
for (;;) {
- count = stop - src;
+ count = SkToInt(stop - src);
SkASSERT(count >= 0);
if (count == 0) {
return dst - origDst;
@@ -218,7 +218,7 @@ size_t SkPackBits::Pack16(const uint16_t* SK_RESTRICT src, int count,
break;
}
} while (*s == value);
- dst = flush_same16(dst, value, s - src);
+ dst = flush_same16(dst, value, SkToInt(s - src));
} else { // accumulate diff values...
do {
if (++s == stop) {
@@ -227,7 +227,7 @@ size_t SkPackBits::Pack16(const uint16_t* SK_RESTRICT src, int count,
} while (*s != s[-1]);
s -= 1; // back up so we don't grab one of the "same" values that follow
FLUSH_DIFF:
- dst = flush_diff16(dst, src, s - src);
+ dst = flush_diff16(dst, src, SkToInt(s - src));
}
src = s;
}
@@ -239,7 +239,7 @@ size_t SkPackBits::Pack8(const uint8_t* SK_RESTRICT src, int count,
const uint8_t* stop = src + count;
for (;;) {
- count = stop - src;
+ count = SkToInt(stop - src);
SkASSERT(count >= 0);
if (count == 0) {
return dst - origDst;
@@ -260,7 +260,7 @@ size_t SkPackBits::Pack8(const uint8_t* SK_RESTRICT src, int count,
break;
}
} while (*s == value);
- dst = flush_same8(dst, value, s - src);
+ dst = flush_same8(dst, value, SkToInt(s - src));
} else { // accumulate diff values...
do {
if (++s == stop) {
@@ -271,7 +271,7 @@ size_t SkPackBits::Pack8(const uint8_t* SK_RESTRICT src, int count,
} while (*s != s[-1] || s[-1] != s[-2]);
s -= 2; // back up so we don't grab the "same" values that follow
FLUSH_DIFF:
- dst = flush_diff8(dst, src, s - src);
+ dst = flush_diff8(dst, src, SkToInt(s - src));
}
src = s;
}
@@ -298,7 +298,7 @@ int SkPackBits::Unpack16(const uint8_t* SK_RESTRICT src, size_t srcSize,
dst += n;
}
SkASSERT(src == stop);
- return dst - origDst;
+ return SkToInt(dst - origDst);
}
int SkPackBits::Unpack8(const uint8_t* SK_RESTRICT src, size_t srcSize,
@@ -319,7 +319,7 @@ int SkPackBits::Unpack8(const uint8_t* SK_RESTRICT src, size_t srcSize,
dst += n;
}
SkASSERT(src == stop);
- return dst - origDst;
+ return SkToInt(dst - origDst);
}
enum UnpackState {
@@ -339,7 +339,7 @@ void SkPackBits::Unpack8(uint8_t* SK_RESTRICT dst, size_t dstSkip,
// state 1: do the skip-loop
while (dstSkip > 0) {
- unsigned n = *src++;
+ size_t n = *src++;
if (n <= 127) { // repeat count (n + 1)
n += 1;
if (n > dstSkip) {
@@ -387,7 +387,7 @@ void SkPackBits::Unpack8(uint8_t* SK_RESTRICT dst, size_t dstSkip,
// copy at most dstWrite bytes into dst[]
while (dstWrite > 0) {
- unsigned n = *src++;
+ size_t n = *src++;
if (n <= 127) { // repeat count (n + 1)
n += 1;
if (n > dstWrite) {
diff --git a/chromium/third_party/skia/src/core/SkPaint.cpp b/chromium/third_party/skia/src/core/SkPaint.cpp
index 91a76e151fb..16d8bb2e4ed 100644
--- a/chromium/third_party/skia/src/core/SkPaint.cpp
+++ b/chromium/third_party/skia/src/core/SkPaint.cpp
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -18,8 +17,8 @@
#include "SkImageFilter.h"
#include "SkMaskFilter.h"
#include "SkMaskGamma.h"
-#include "SkOrderedReadBuffer.h"
-#include "SkOrderedWriteBuffer.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkPaintDefaults.h"
#include "SkPaintOptionsAndroid.h"
#include "SkPathEffect.h"
@@ -35,6 +34,28 @@
#include "SkTypeface.h"
#include "SkXfermode.h"
+enum {
+ kColor_DirtyBit = 1 << 0,
+ kTextSize_DirtyBit = 1 << 1,
+ kTextScaleX_DirtyBit = 1 << 2,
+ kTextSkewX_DirtyBit = 1 << 3,
+ kStrokeWidth_DirtyBit = 1 << 4,
+ kStrokeMiter_DirtyBit = 1 << 5,
+
+ kPOD_DirtyBitMask = 63,
+
+ kPathEffect_DirtyBit = 1 << 6,
+ kShader_DirtyBit = 1 << 7,
+ kXfermode_DirtyBit = 1 << 8,
+ kMaskFilter_DirtyBit = 1 << 9,
+ kColorFilter_DirtyBit = 1 << 10,
+ kRasterizer_DirtyBit = 1 << 11,
+ kLooper_DirtyBit = 1 << 12,
+ kImageFilter_DirtyBit = 1 << 13,
+ kTypeface_DirtyBit = 1 << 14,
+ kAnnotation_DirtyBit = 1 << 15,
+ kPaintOptionsAndroid_DirtyBit = 1 << 16,
+};
// define this to get a printf for out-of-range parameter in setters
// e.g. setTextSize(-1)
@@ -49,14 +70,7 @@
#endif
SkPaint::SkPaint() {
- // since we may have padding, we zero everything so that our memcmp() call
- // in operator== will work correctly.
- // with this, we can skip 0 and null individual initializations
- sk_bzero(this, sizeof(*this));
-
-#if 0 // not needed with the bzero call above
- fTypeface = NULL;
- fTextSkewX = 0;
+ fTypeface = NULL;
fPathEffect = NULL;
fShader = NULL;
fXfermode = NULL;
@@ -66,20 +80,25 @@ SkPaint::SkPaint() {
fLooper = NULL;
fImageFilter = NULL;
fAnnotation = NULL;
- fWidth = 0;
-#endif
- fTextSize = SkPaintDefaults_TextSize;
- fTextScaleX = SK_Scalar1;
- fColor = SK_ColorBLACK;
- fMiterLimit = SkPaintDefaults_MiterLimit;
- fFlags = SkPaintDefaults_Flags;
- fCapType = kDefault_Cap;
- fJoinType = kDefault_Join;
- fTextAlign = kLeft_Align;
- fStyle = kFill_Style;
+ fTextSize = SkPaintDefaults_TextSize;
+ fTextScaleX = SK_Scalar1;
+ fTextSkewX = 0;
+ fColor = SK_ColorBLACK;
+ fWidth = 0;
+ fMiterLimit = SkPaintDefaults_MiterLimit;
+
+ // Zero all bitfields, then set some non-zero defaults.
+ fBitfields = 0;
+ fFlags = SkPaintDefaults_Flags;
+ fCapType = kDefault_Cap;
+ fJoinType = kDefault_Join;
+ fTextAlign = kLeft_Align;
+ fStyle = kFill_Style;
fTextEncoding = kUTF8_TextEncoding;
- fHinting = SkPaintDefaults_Hinting;
+ fHinting = SkPaintDefaults_Hinting;
+
+ fDirtyBits = 0;
#ifdef SK_BUILD_FOR_ANDROID
new (&fPaintOptionsAndroid) SkPaintOptionsAndroid;
fGenerationID = 0;
@@ -87,22 +106,36 @@ SkPaint::SkPaint() {
}
SkPaint::SkPaint(const SkPaint& src) {
- memcpy(this, &src, sizeof(src));
-
- SkSafeRef(fTypeface);
- SkSafeRef(fPathEffect);
- SkSafeRef(fShader);
- SkSafeRef(fXfermode);
- SkSafeRef(fMaskFilter);
- SkSafeRef(fColorFilter);
- SkSafeRef(fRasterizer);
- SkSafeRef(fLooper);
- SkSafeRef(fImageFilter);
- SkSafeRef(fAnnotation);
+#define COPY(field) field = src.field
+#define REF_COPY(field) field = SkSafeRef(src.field)
+
+ REF_COPY(fTypeface);
+ REF_COPY(fPathEffect);
+ REF_COPY(fShader);
+ REF_COPY(fXfermode);
+ REF_COPY(fMaskFilter);
+ REF_COPY(fColorFilter);
+ REF_COPY(fRasterizer);
+ REF_COPY(fLooper);
+ REF_COPY(fImageFilter);
+ REF_COPY(fAnnotation);
+
+ COPY(fTextSize);
+ COPY(fTextScaleX);
+ COPY(fTextSkewX);
+ COPY(fColor);
+ COPY(fWidth);
+ COPY(fMiterLimit);
+ COPY(fBitfields);
+ COPY(fDirtyBits);
#ifdef SK_BUILD_FOR_ANDROID
new (&fPaintOptionsAndroid) SkPaintOptionsAndroid(src.fPaintOptionsAndroid);
+ COPY(fGenerationID);
#endif
+
+#undef COPY
+#undef REF_COPY
}
SkPaint::~SkPaint() {
@@ -119,52 +152,72 @@ SkPaint::~SkPaint() {
}
SkPaint& SkPaint::operator=(const SkPaint& src) {
- SkASSERT(&src);
+ if (this == &src) {
+ return *this;
+ }
- SkSafeRef(src.fTypeface);
- SkSafeRef(src.fPathEffect);
- SkSafeRef(src.fShader);
- SkSafeRef(src.fXfermode);
- SkSafeRef(src.fMaskFilter);
- SkSafeRef(src.fColorFilter);
- SkSafeRef(src.fRasterizer);
- SkSafeRef(src.fLooper);
- SkSafeRef(src.fImageFilter);
- SkSafeRef(src.fAnnotation);
+#define COPY(field) field = src.field
+#define REF_COPY(field) SkSafeUnref(field); field = SkSafeRef(src.field)
- SkSafeUnref(fTypeface);
- SkSafeUnref(fPathEffect);
- SkSafeUnref(fShader);
- SkSafeUnref(fXfermode);
- SkSafeUnref(fMaskFilter);
- SkSafeUnref(fColorFilter);
- SkSafeUnref(fRasterizer);
- SkSafeUnref(fLooper);
- SkSafeUnref(fImageFilter);
- SkSafeUnref(fAnnotation);
+ SkASSERT(&src);
-#ifdef SK_BUILD_FOR_ANDROID
- fPaintOptionsAndroid.~SkPaintOptionsAndroid();
+ REF_COPY(fTypeface);
+ REF_COPY(fPathEffect);
+ REF_COPY(fShader);
+ REF_COPY(fXfermode);
+ REF_COPY(fMaskFilter);
+ REF_COPY(fColorFilter);
+ REF_COPY(fRasterizer);
+ REF_COPY(fLooper);
+ REF_COPY(fImageFilter);
+ REF_COPY(fAnnotation);
+
+ COPY(fTextSize);
+ COPY(fTextScaleX);
+ COPY(fTextSkewX);
+ COPY(fColor);
+ COPY(fWidth);
+ COPY(fMiterLimit);
+ COPY(fBitfields);
+ COPY(fDirtyBits);
- uint32_t oldGenerationID = fGenerationID;
-#endif
- memcpy(this, &src, sizeof(src));
#ifdef SK_BUILD_FOR_ANDROID
- fGenerationID = oldGenerationID + 1;
-
+ fPaintOptionsAndroid.~SkPaintOptionsAndroid();
new (&fPaintOptionsAndroid) SkPaintOptionsAndroid(src.fPaintOptionsAndroid);
+ ++fGenerationID;
#endif
return *this;
+
+#undef COPY
+#undef REF_COPY
}
bool operator==(const SkPaint& a, const SkPaint& b) {
+#define EQUAL(field) (a.field == b.field)
+ // Don't check fGenerationID or fDirtyBits, which can be different for logically equal paints.
+ return EQUAL(fTypeface)
+ && EQUAL(fPathEffect)
+ && EQUAL(fShader)
+ && EQUAL(fXfermode)
+ && EQUAL(fMaskFilter)
+ && EQUAL(fColorFilter)
+ && EQUAL(fRasterizer)
+ && EQUAL(fLooper)
+ && EQUAL(fImageFilter)
+ && EQUAL(fAnnotation)
+ && EQUAL(fTextSize)
+ && EQUAL(fTextScaleX)
+ && EQUAL(fTextSkewX)
+ && EQUAL(fColor)
+ && EQUAL(fWidth)
+ && EQUAL(fMiterLimit)
+ && EQUAL(fBitfields)
#ifdef SK_BUILD_FOR_ANDROID
- //assumes that fGenerationID is the last field in the struct
- return !memcmp(&a, &b, SK_OFFSETOF(SkPaint, fGenerationID));
-#else
- return !memcmp(&a, &b, sizeof(a));
+ && EQUAL(fPaintOptionsAndroid)
#endif
+ ;
+#undef EQUAL
}
void SkPaint::reset() {
@@ -198,31 +251,14 @@ void SkPaint::setPaintOptionsAndroid(const SkPaintOptionsAndroid& options) {
if (options != fPaintOptionsAndroid) {
fPaintOptionsAndroid = options;
GEN_ID_INC;
+ fDirtyBits |= kPaintOptionsAndroid_DirtyBit;
}
}
#endif
-SkPaint::FilterLevel SkPaint::getFilterLevel() const {
- int level = 0;
- if (fFlags & kFilterBitmap_Flag) {
- level |= 1;
- }
- if (fFlags & kHighQualityFilterBitmap_Flag) {
- level |= 2;
- }
- return (FilterLevel)level;
-}
-
void SkPaint::setFilterLevel(FilterLevel level) {
- unsigned mask = kFilterBitmap_Flag | kHighQualityFilterBitmap_Flag;
- unsigned flags = 0;
- if (level & 1) {
- flags |= kFilterBitmap_Flag;
- }
- if (level & 2) {
- flags |= kHighQualityFilterBitmap_Flag;
- }
- this->setFlags((fFlags & ~mask) | flags);
+ GEN_ID_INC_EVAL((unsigned) level != fFilterLevel);
+ fFilterLevel = level;
}
void SkPaint::setHinting(Hinting hintingLevel) {
@@ -283,6 +319,10 @@ void SkPaint::setDevKernText(bool doDevKern) {
this->setFlags(SkSetClearMask(fFlags, doDevKern, kDevKernText_Flag));
}
+void SkPaint::setDistanceFieldTextTEMP(bool doDistanceFieldText) {
+ this->setFlags(SkSetClearMask(fFlags, doDistanceFieldText, kDistanceFieldTextTEMP_Flag));
+}
+
void SkPaint::setStyle(Style style) {
if ((unsigned)style < kStyleCount) {
GEN_ID_INC_EVAL((unsigned)style != fStyle);
@@ -297,6 +337,7 @@ void SkPaint::setStyle(Style style) {
void SkPaint::setColor(SkColor color) {
GEN_ID_INC_EVAL(color != fColor);
fColor = color;
+ fDirtyBits |= kColor_DirtyBit;
}
void SkPaint::setAlpha(U8CPU a) {
@@ -312,6 +353,7 @@ void SkPaint::setStrokeWidth(SkScalar width) {
if (width >= 0) {
GEN_ID_INC_EVAL(width != fWidth);
fWidth = width;
+ fDirtyBits |= kStrokeWidth_DirtyBit;
} else {
#ifdef SK_REPORT_API_RANGE_CHECK
SkDebugf("SkPaint::setStrokeWidth() called with negative value\n");
@@ -323,6 +365,7 @@ void SkPaint::setStrokeMiter(SkScalar limit) {
if (limit >= 0) {
GEN_ID_INC_EVAL(limit != fMiterLimit);
fMiterLimit = limit;
+ fDirtyBits |= kStrokeMiter_DirtyBit;
} else {
#ifdef SK_REPORT_API_RANGE_CHECK
SkDebugf("SkPaint::setStrokeMiter() called with negative value\n");
@@ -369,6 +412,7 @@ void SkPaint::setTextSize(SkScalar ts) {
if (ts >= 0) {
GEN_ID_INC_EVAL(ts != fTextSize);
fTextSize = ts;
+ fDirtyBits |= kTextSize_DirtyBit;
} else {
#ifdef SK_REPORT_API_RANGE_CHECK
SkDebugf("SkPaint::setTextSize() called with negative value\n");
@@ -379,11 +423,13 @@ void SkPaint::setTextSize(SkScalar ts) {
void SkPaint::setTextScaleX(SkScalar scaleX) {
GEN_ID_INC_EVAL(scaleX != fTextScaleX);
fTextScaleX = scaleX;
+ fDirtyBits |= kTextScaleX_DirtyBit;
}
void SkPaint::setTextSkewX(SkScalar skewX) {
GEN_ID_INC_EVAL(skewX != fTextSkewX);
fTextSkewX = skewX;
+ fDirtyBits |= kTextSkewX_DirtyBit;
}
void SkPaint::setTextEncoding(TextEncoding encoding) {
@@ -399,33 +445,43 @@ void SkPaint::setTextEncoding(TextEncoding encoding) {
///////////////////////////////////////////////////////////////////////////////
+// Returns dst with the given bitmask enabled or disabled, depending on value.
+inline static uint32_t set_mask(uint32_t dst, uint32_t bitmask, bool value) {
+ return value ? (dst | bitmask) : (dst & ~bitmask);
+}
+
SkTypeface* SkPaint::setTypeface(SkTypeface* font) {
SkRefCnt_SafeAssign(fTypeface, font);
GEN_ID_INC;
+ fDirtyBits = set_mask(fDirtyBits, kTypeface_DirtyBit, font != NULL);
return font;
}
SkRasterizer* SkPaint::setRasterizer(SkRasterizer* r) {
SkRefCnt_SafeAssign(fRasterizer, r);
GEN_ID_INC;
+ fDirtyBits = set_mask(fDirtyBits, kRasterizer_DirtyBit, r != NULL);
return r;
}
SkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper) {
SkRefCnt_SafeAssign(fLooper, looper);
GEN_ID_INC;
+ fDirtyBits = set_mask(fDirtyBits, kLooper_DirtyBit, looper != NULL);
return looper;
}
SkImageFilter* SkPaint::setImageFilter(SkImageFilter* imageFilter) {
SkRefCnt_SafeAssign(fImageFilter, imageFilter);
GEN_ID_INC;
+ fDirtyBits = set_mask(fDirtyBits, kImageFilter_DirtyBit, imageFilter != NULL);
return imageFilter;
}
SkAnnotation* SkPaint::setAnnotation(SkAnnotation* annotation) {
SkRefCnt_SafeAssign(fAnnotation, annotation);
GEN_ID_INC;
+ fDirtyBits = set_mask(fDirtyBits, kAnnotation_DirtyBit, annotation != NULL);
return annotation;
}
@@ -470,42 +526,6 @@ static void DetachDescProc(SkTypeface* typeface, const SkDescriptor* desc,
*((SkGlyphCache**)context) = SkGlyphCache::DetachCache(typeface, desc);
}
-#ifdef SK_BUILD_FOR_ANDROID
-const SkGlyph& SkPaint::getUnicharMetrics(SkUnichar text,
- const SkMatrix* deviceMatrix) {
- SkGlyphCache* cache;
- descriptorProc(NULL, deviceMatrix, DetachDescProc, &cache, true);
-
- const SkGlyph& glyph = cache->getUnicharMetrics(text);
-
- SkGlyphCache::AttachCache(cache);
- return glyph;
-}
-
-const SkGlyph& SkPaint::getGlyphMetrics(uint16_t glyphId,
- const SkMatrix* deviceMatrix) {
- SkGlyphCache* cache;
- descriptorProc(NULL, deviceMatrix, DetachDescProc, &cache, true);
-
- const SkGlyph& glyph = cache->getGlyphIDMetrics(glyphId);
-
- SkGlyphCache::AttachCache(cache);
- return glyph;
-}
-
-const void* SkPaint::findImage(const SkGlyph& glyph,
- const SkMatrix* deviceMatrix) {
- // See ::detachCache()
- SkGlyphCache* cache;
- descriptorProc(NULL, deviceMatrix, DetachDescProc, &cache, true);
-
- const void* image = cache->findImage(glyph);
-
- SkGlyphCache::AttachCache(cache);
- return image;
-}
-#endif
-
int SkPaint::textToGlyphs(const void* textData, size_t byteLength,
uint16_t glyphs[]) const {
if (byteLength == 0) {
@@ -519,12 +539,11 @@ int SkPaint::textToGlyphs(const void* textData, size_t byteLength,
case kUTF8_TextEncoding:
return SkUTF8_CountUnichars((const char*)textData, byteLength);
case kUTF16_TextEncoding:
- return SkUTF16_CountUnichars((const uint16_t*)textData,
- byteLength >> 1);
+ return SkUTF16_CountUnichars((const uint16_t*)textData, SkToInt(byteLength >> 1));
case kUTF32_TextEncoding:
- return byteLength >> 2;
+ return SkToInt(byteLength >> 2);
case kGlyphID_TextEncoding:
- return byteLength >> 1;
+ return SkToInt(byteLength >> 1);
default:
SkDEBUGFAIL("unknown text encoding");
}
@@ -537,7 +556,7 @@ int SkPaint::textToGlyphs(const void* textData, size_t byteLength,
if (this->getTextEncoding() == kGlyphID_TextEncoding) {
// we want to ignore the low bit of byteLength
memcpy(glyphs, textData, byteLength >> 1 << 1);
- return byteLength >> 1;
+ return SkToInt(byteLength >> 1);
}
SkAutoGlyphCache autoCache(*this, NULL, NULL);
@@ -572,7 +591,7 @@ int SkPaint::textToGlyphs(const void* textData, size_t byteLength,
default:
SkDEBUGFAIL("unknown text encoding");
}
- return gptr - glyphs;
+ return SkToInt(gptr - glyphs);
}
bool SkPaint::containsText(const void* textData, size_t byteLength) const {
@@ -899,7 +918,7 @@ static const SkGlyph& sk_getMetrics_utf32_xy(SkGlyphCache* cache,
SkASSERT(text != NULL);
const int32_t* ptr = *(const int32_t**)text;
- SkUnichar uni = *--ptr;
+ SkUnichar uni = *ptr++;
*text = (const char*)ptr;
return cache->getUnicharMetrics(uni, x, y);
}
@@ -1010,16 +1029,9 @@ static void set_bounds(const SkGlyph& g, SkRect* bounds) {
// we don't overflow along the way
typedef int64_t Sk48Dot16;
-#ifdef SK_SCALAR_IS_FLOAT
- static inline float Sk48Dot16ToScalar(Sk48Dot16 x) {
- return (float) (x * 1.5258789e-5); // x * (1 / 65536.0f)
- }
-#else
- static inline SkFixed Sk48Dot16ToScalar(Sk48Dot16 x) {
- // just return the low 32bits
- return static_cast<SkFixed>(x);
- }
-#endif
+static inline float Sk48Dot16ToScalar(Sk48Dot16 x) {
+ return (float) (x * 1.5258789e-5); // x * (1 / 65536.0f)
+}
static void join_bounds_x(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dx) {
SkScalar sx = Sk48Dot16ToScalar(dx);
@@ -1303,6 +1315,8 @@ SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const {
metrics->fXMin = SkScalarMul(metrics->fXMin, scale);
metrics->fXMax = SkScalarMul(metrics->fXMax, scale);
metrics->fXHeight = SkScalarMul(metrics->fXHeight, scale);
+ metrics->fUnderlineThickness = SkScalarMul(metrics->fUnderlineThickness, scale);
+ metrics->fUnderlinePosition = SkScalarMul(metrics->fUnderlinePosition, scale);
}
return metrics->fDescent - metrics->fAscent + metrics->fLeading;
}
@@ -1481,8 +1495,8 @@ void SkPaint::getPosTextPath(const void* textData, size_t length,
}
static void add_flattenable(SkDescriptor* desc, uint32_t tag,
- SkOrderedWriteBuffer* buffer) {
- buffer->writeToMemory(desc->addEntry(tag, buffer->size(), NULL));
+ SkWriteBuffer* buffer) {
+ buffer->writeToMemory(desc->addEntry(tag, buffer->bytesWritten(), NULL));
}
// SkFontHost can override this choice in FilterRec()
@@ -1544,10 +1558,10 @@ static SkColor computeLuminanceColor(const SkPaint& paint) {
#endif
static bool tooBigForLCD(const SkScalerContext::Rec& rec) {
- SkScalar area = SkScalarMul(rec.fPost2x2[0][0], rec.fPost2x2[1][1]) -
- SkScalarMul(rec.fPost2x2[1][0], rec.fPost2x2[0][1]);
- SkScalar size = SkScalarMul(area, rec.fTextSize);
- return SkScalarAbs(size) > SkIntToScalar(SK_MAX_SIZE_FOR_LCDTEXT);
+ SkScalar area = rec.fPost2x2[0][0] * rec.fPost2x2[1][1] -
+ rec.fPost2x2[1][0] * rec.fPost2x2[0][1];
+ SkScalar size = SkScalarSqrt(SkScalarAbs(area)) * rec.fTextSize;
+ return size > SkIntToScalar(SK_MAX_SIZE_FOR_LCDTEXT);
}
/*
@@ -1556,13 +1570,8 @@ static bool tooBigForLCD(const SkScalerContext::Rec& rec) {
* typically returns the same looking resuts for tiny changes in the matrix.
*/
static SkScalar sk_relax(SkScalar x) {
-#ifdef SK_SCALAR_IS_FLOAT
int n = sk_float_round2int(x * 1024);
return n / 1024.0f;
-#else
- // round to the nearest 10 fractional bits
- return (x + (1 << 5)) & ~(1024 - 1);
-#endif
}
void SkScalerContext::MakeRec(const SkPaint& paint,
@@ -1659,7 +1668,7 @@ void SkScalerContext::MakeRec(const SkPaint& paint,
flags |= SkScalerContext::kSubpixelPositioning_Flag;
}
if (paint.isAutohinted()) {
- flags |= SkScalerContext::kAutohinting_Flag;
+ flags |= SkScalerContext::kForceAutohinting_Flag;
}
if (paint.isVerticalText()) {
flags |= SkScalerContext::kVertical_Flag;
@@ -1728,6 +1737,7 @@ static SkScalar gDeviceGamma = SK_ScalarMin;
* the returned SkMaskGamma pointer is refed or forgotten.
*/
static const SkMaskGamma& cachedMaskGamma(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma) {
+ gMaskGammaCacheMutex.assertHeld();
if (0 == contrast && SK_Scalar1 == paintGamma && SK_Scalar1 == deviceGamma) {
if (NULL == gLinearMaskGamma) {
gLinearMaskGamma = SkNEW(SkMaskGamma);
@@ -1805,10 +1815,8 @@ void SkScalerContext::PostMakeRec(const SkPaint&, SkScalerContext::Rec* rec) {
/*
* ignoreGamma tells us that the caller just wants metrics that are unaffected
- * by gamma correction, so we jam the luminance field to 0 (most common value
- * for black text) in hopes that we get a cache hit easier. A better solution
- * would be for the fontcache lookup to know to ignore the luminance field
- * entirely, but not sure how to do that and keep it fast.
+ * by gamma correction, so we set the rec to ignore preblend: i.e. gamma = 1,
+ * contrast = 0, luminanceColor = transparent black.
*/
void SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties,
const SkMatrix* deviceMatrix,
@@ -1818,7 +1826,7 @@ void SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties,
SkScalerContext::MakeRec(*this, deviceProperties, deviceMatrix, &rec);
if (ignoreGamma) {
- rec.setLuminanceColor(0);
+ rec.ignorePreBlend();
}
size_t descSize = sizeof(rec);
@@ -1827,20 +1835,18 @@ void SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties,
SkMaskFilter* mf = this->getMaskFilter();
SkRasterizer* ra = this->getRasterizer();
- SkOrderedWriteBuffer peBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
- SkOrderedWriteBuffer mfBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
- SkOrderedWriteBuffer raBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
+ SkWriteBuffer peBuffer, mfBuffer, raBuffer;
if (pe) {
peBuffer.writeFlattenable(pe);
- descSize += peBuffer.size();
+ descSize += peBuffer.bytesWritten();
entryCount += 1;
rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion
// seems like we could support kLCD as well at this point...
}
if (mf) {
mfBuffer.writeFlattenable(mf);
- descSize += mfBuffer.size();
+ descSize += mfBuffer.bytesWritten();
entryCount += 1;
rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing with maskfilters
/* Pre-blend is not currently applied to filtered text.
@@ -1851,15 +1857,15 @@ void SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties,
}
if (ra) {
raBuffer.writeFlattenable(ra);
- descSize += raBuffer.size();
+ descSize += raBuffer.bytesWritten();
entryCount += 1;
rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion
}
#ifdef SK_BUILD_FOR_ANDROID
- SkOrderedWriteBuffer androidBuffer(128);
+ SkWriteBuffer androidBuffer;
fPaintOptionsAndroid.flatten(androidBuffer);
- descSize += androidBuffer.size();
+ descSize += androidBuffer.bytesWritten();
entryCount += 1;
#endif
@@ -1944,9 +1950,10 @@ void SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties,
}
SkGlyphCache* SkPaint::detachCache(const SkDeviceProperties* deviceProperties,
- const SkMatrix* deviceMatrix) const {
+ const SkMatrix* deviceMatrix,
+ bool ignoreGamma) const {
SkGlyphCache* cache;
- this->descriptorProc(deviceProperties, deviceMatrix, DetachDescProc, &cache, false);
+ this->descriptorProc(deviceProperties, deviceMatrix, DetachDescProc, &cache, ignoreGamma);
return cache;
}
@@ -1962,6 +1969,33 @@ SkMaskGamma::PreBlend SkScalerContext::GetMaskPreBlend(const SkScalerContext::Re
return maskGamma.preBlend(rec.getLuminanceColor());
}
+size_t SkScalerContext::GetGammaLUTSize(SkScalar contrast, SkScalar paintGamma,
+ SkScalar deviceGamma, int* width, int* height) {
+ SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
+ const SkMaskGamma& maskGamma = cachedMaskGamma(contrast,
+ paintGamma,
+ deviceGamma);
+
+ maskGamma.getGammaTableDimensions(width, height);
+ size_t size = (*width)*(*height)*sizeof(uint8_t);
+
+ return size;
+}
+
+void SkScalerContext::GetGammaLUTData(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma,
+ void* data) {
+ SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
+ const SkMaskGamma& maskGamma = cachedMaskGamma(contrast,
+ paintGamma,
+ deviceGamma);
+ int width, height;
+ maskGamma.getGammaTableDimensions(&width, &height);
+ size_t size = width*height*sizeof(uint8_t);
+ const uint8_t* gammaTables = maskGamma.getGammaTables();
+ memcpy(data, gammaTables, size);
+}
+
+
///////////////////////////////////////////////////////////////////////////////
#include "SkStream.h"
@@ -1998,12 +2032,89 @@ static uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) {
return (a << 24) | (b << 16) | (c << 8) | d;
}
+#ifdef SK_DEBUG
+ static void ASSERT_FITS_IN(uint32_t value, int bitCount) {
+ SkASSERT(bitCount > 0 && bitCount <= 32);
+ uint32_t mask = ~0U;
+ mask >>= (32 - bitCount);
+ SkASSERT(0 == (value & ~mask));
+ }
+#else
+ #define ASSERT_FITS_IN(value, bitcount)
+#endif
+
enum FlatFlags {
kHasTypeface_FlatFlag = 0x01,
kHasEffects_FlatFlag = 0x02,
kHasNonDefaultPaintOptionsAndroid_FlatFlag = 0x04,
+
+ kFlatFlagMask = 0x7,
+};
+
+enum BitsPerField {
+ kFlags_BPF = 16,
+ kHint_BPF = 2,
+ kAlign_BPF = 2,
+ kFilter_BPF = 2,
+ kFlatFlags_BPF = 3,
};
+static inline int BPF_Mask(int bits) {
+ return (1 << bits) - 1;
+}
+
+static uint32_t pack_paint_flags(unsigned flags, unsigned hint, unsigned align,
+ unsigned filter, unsigned flatFlags) {
+ ASSERT_FITS_IN(flags, kFlags_BPF);
+ ASSERT_FITS_IN(hint, kHint_BPF);
+ ASSERT_FITS_IN(align, kAlign_BPF);
+ ASSERT_FITS_IN(filter, kFilter_BPF);
+ ASSERT_FITS_IN(flatFlags, kFlatFlags_BPF);
+
+ // left-align the fields of "known" size, and right-align the last (flatFlags) so it can easly
+ // add more bits in the future.
+ return (flags << 16) | (hint << 14) | (align << 12) | (filter << 10) | flatFlags;
+}
+
+static FlatFlags unpack_paint_flags(SkPaint* paint, uint32_t packed) {
+ paint->setFlags(packed >> 16);
+ paint->setHinting((SkPaint::Hinting)((packed >> 14) & BPF_Mask(kHint_BPF)));
+ paint->setTextAlign((SkPaint::Align)((packed >> 12) & BPF_Mask(kAlign_BPF)));
+ paint->setFilterLevel((SkPaint::FilterLevel)((packed >> 10) & BPF_Mask(kFilter_BPF)));
+ return (FlatFlags)(packed & kFlatFlagMask);
+}
+
+// V22_COMPATIBILITY_CODE
+static FlatFlags unpack_paint_flags_v22(SkPaint* paint, uint32_t packed) {
+ enum {
+ kFilterBitmap_Flag = 0x02,
+ kHighQualityFilterBitmap_Flag = 0x4000,
+
+ kAll_Flags = kFilterBitmap_Flag | kHighQualityFilterBitmap_Flag
+ };
+
+ // previously flags:16, textAlign:8, flatFlags:8
+ // now flags:16, hinting:4, textAlign:4, flatFlags:8
+ unsigned flags = packed >> 16;
+ int filter = 0;
+ if (flags & kFilterBitmap_Flag) {
+ filter |= 1;
+ }
+ if (flags & kHighQualityFilterBitmap_Flag) {
+ filter |= 2;
+ }
+ paint->setFilterLevel((SkPaint::FilterLevel)filter);
+ flags &= ~kAll_Flags; // remove these (now dead) bit flags
+
+ paint->setFlags(flags);
+
+ // hinting added later. 0 in this nibble means use the default.
+ uint32_t hinting = (packed >> 12) & 0xF;
+ paint->setHinting(0 == hinting ? SkPaint::kNormal_Hinting : static_cast<SkPaint::Hinting>(hinting-1));
+ paint->setTextAlign(static_cast<SkPaint::Align>((packed >> 8) & 0xF));
+ return (FlatFlags)(packed & kFlatFlagMask);
+}
+
// The size of a flat paint's POD fields
static const uint32_t kPODPaintSize = 5 * sizeof(SkScalar) +
1 * sizeof(SkColor) +
@@ -2013,7 +2124,7 @@ static const uint32_t kPODPaintSize = 5 * sizeof(SkScalar) +
/* To save space/time, we analyze the paint, and write a truncated version of
it if there are not tricky elements like shaders, etc.
*/
-void SkPaint::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkPaint::flatten(SkWriteBuffer& buffer) const {
uint8_t flatFlags = 0;
if (this->getTypeface()) {
flatFlags |= kHasTypeface_FlatFlag;
@@ -2035,42 +2146,20 @@ void SkPaint::flatten(SkFlattenableWriteBuffer& buffer) const {
}
#endif
- if (buffer.isOrderedBinaryBuffer()) {
- SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
- uint32_t* ptr = buffer.getOrderedBinaryBuffer()->reserve(kPODPaintSize);
-
- ptr = write_scalar(ptr, this->getTextSize());
- ptr = write_scalar(ptr, this->getTextScaleX());
- ptr = write_scalar(ptr, this->getTextSkewX());
- ptr = write_scalar(ptr, this->getStrokeWidth());
- ptr = write_scalar(ptr, this->getStrokeMiter());
- *ptr++ = this->getColor();
- // previously flags:16, textAlign:8, flatFlags:8
- // now flags:16, hinting:4, textAlign:4, flatFlags:8
- *ptr++ = (this->getFlags() << 16) |
- // hinting added later. 0 in this nibble means use the default.
- ((this->getHinting()+1) << 12) |
- (this->getTextAlign() << 8) |
- flatFlags;
- *ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(),
- this->getStyle(), this->getTextEncoding());
- } else {
- buffer.writeScalar(fTextSize);
- buffer.writeScalar(fTextScaleX);
- buffer.writeScalar(fTextSkewX);
- buffer.writeScalar(fWidth);
- buffer.writeScalar(fMiterLimit);
- buffer.writeColor(fColor);
- buffer.writeUInt(fFlags);
- buffer.writeUInt(fHinting);
- buffer.writeUInt(fTextAlign);
- buffer.writeUInt(flatFlags);
-
- buffer.writeUInt(fCapType);
- buffer.writeUInt(fJoinType);
- buffer.writeUInt(fStyle);
- buffer.writeUInt(fTextEncoding);
- }
+ SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
+ uint32_t* ptr = buffer.reserve(kPODPaintSize);
+
+ ptr = write_scalar(ptr, this->getTextSize());
+ ptr = write_scalar(ptr, this->getTextScaleX());
+ ptr = write_scalar(ptr, this->getTextSkewX());
+ ptr = write_scalar(ptr, this->getStrokeWidth());
+ ptr = write_scalar(ptr, this->getStrokeMiter());
+ *ptr++ = this->getColor();
+
+ *ptr++ = pack_paint_flags(this->getFlags(), this->getHinting(), this->getTextAlign(),
+ this->getFilterLevel(), flatFlags);
+ *ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(),
+ this->getStyle(), this->getTextEncoding());
// now we're done with ptr and the (pre)reserved space. If we need to write
// additional fields, use the buffer directly
@@ -2101,59 +2190,32 @@ void SkPaint::flatten(SkFlattenableWriteBuffer& buffer) const {
#endif
}
-void SkPaint::unflatten(SkFlattenableReadBuffer& buffer) {
- uint8_t flatFlags = 0;
- if (buffer.isOrderedBinaryBuffer()) {
- SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
- const void* podData = buffer.getOrderedBinaryBuffer()->skip(kPODPaintSize);
- const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData);
-
- // the order we read must match the order we wrote in flatten()
- this->setTextSize(read_scalar(pod));
- this->setTextScaleX(read_scalar(pod));
- this->setTextSkewX(read_scalar(pod));
- this->setStrokeWidth(read_scalar(pod));
- this->setStrokeMiter(read_scalar(pod));
- this->setColor(*pod++);
-
- // previously flags:16, textAlign:8, flatFlags:8
- // now flags:16, hinting:4, textAlign:4, flatFlags:8
- uint32_t tmp = *pod++;
- this->setFlags(tmp >> 16);
-
- // hinting added later. 0 in this nibble means use the default.
- uint32_t hinting = (tmp >> 12) & 0xF;
- this->setHinting(0 == hinting ? kNormal_Hinting : static_cast<Hinting>(hinting-1));
-
- this->setTextAlign(static_cast<Align>((tmp >> 8) & 0xF));
-
- flatFlags = tmp & 0xFF;
-
- tmp = *pod++;
- this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF));
- this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF));
- this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF));
- this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF));
+void SkPaint::unflatten(SkReadBuffer& buffer) {
+ SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
+ const void* podData = buffer.skip(kPODPaintSize);
+ const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData);
+
+ // the order we read must match the order we wrote in flatten()
+ this->setTextSize(read_scalar(pod));
+ this->setTextScaleX(read_scalar(pod));
+ this->setTextSkewX(read_scalar(pod));
+ this->setStrokeWidth(read_scalar(pod));
+ this->setStrokeMiter(read_scalar(pod));
+ this->setColor(*pod++);
+
+ unsigned flatFlags = 0;
+ if (buffer.isVersionLT(SkReadBuffer::kFilterLevelIsEnum_Version)) {
+ flatFlags = unpack_paint_flags_v22(this, *pod++);
} else {
- this->setTextSize(buffer.readScalar());
- this->setTextScaleX(buffer.readScalar());
- this->setTextSkewX(buffer.readScalar());
- // Skip the hinting scalar factor, which is not supported.
- buffer.readScalar();
- this->setStrokeWidth(buffer.readScalar());
- this->setStrokeMiter(buffer.readScalar());
- this->setColor(buffer.readColor());
- this->setFlags(buffer.readUInt());
- this->setHinting(static_cast<SkPaint::Hinting>(buffer.readUInt()));
- this->setTextAlign(static_cast<SkPaint::Align>(buffer.readUInt()));
- flatFlags = buffer.readUInt();
-
- this->setStrokeCap(static_cast<SkPaint::Cap>(buffer.readUInt()));
- this->setStrokeJoin(static_cast<SkPaint::Join>(buffer.readUInt()));
- this->setStyle(static_cast<SkPaint::Style>(buffer.readUInt()));
- this->setTextEncoding(static_cast<SkPaint::TextEncoding>(buffer.readUInt()));
+ flatFlags = unpack_paint_flags(this, *pod++);
}
+ uint32_t tmp = *pod++;
+ this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF));
+ this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF));
+ this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF));
+ this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF));
+
if (flatFlags & kHasTypeface_FlatFlag) {
this->setTypeface(buffer.readTypeface());
} else {
@@ -2171,7 +2233,7 @@ void SkPaint::unflatten(SkFlattenableReadBuffer& buffer) {
SkSafeUnref(this->setImageFilter(buffer.readImageFilter()));
if (buffer.readBool()) {
- this->setAnnotation(SkNEW_ARGS(SkAnnotation, (buffer)))->unref();
+ this->setAnnotation(SkAnnotation::Create(buffer))->unref();
}
} else {
this->setPathEffect(NULL);
@@ -2201,18 +2263,21 @@ void SkPaint::unflatten(SkFlattenableReadBuffer& buffer) {
SkShader* SkPaint::setShader(SkShader* shader) {
GEN_ID_INC_EVAL(shader != fShader);
SkRefCnt_SafeAssign(fShader, shader);
+ fDirtyBits = set_mask(fDirtyBits, kShader_DirtyBit, shader != NULL);
return shader;
}
SkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter) {
GEN_ID_INC_EVAL(filter != fColorFilter);
SkRefCnt_SafeAssign(fColorFilter, filter);
+ fDirtyBits = set_mask(fDirtyBits, kColorFilter_DirtyBit, filter != NULL);
return filter;
}
SkXfermode* SkPaint::setXfermode(SkXfermode* mode) {
GEN_ID_INC_EVAL(mode != fXfermode);
SkRefCnt_SafeAssign(fXfermode, mode);
+ fDirtyBits = set_mask(fDirtyBits, kXfermode_DirtyBit, mode != NULL);
return mode;
}
@@ -2220,18 +2285,21 @@ SkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) {
SkSafeUnref(fXfermode);
fXfermode = SkXfermode::Create(mode);
GEN_ID_INC;
+ fDirtyBits = set_mask(fDirtyBits, kXfermode_DirtyBit, fXfermode != NULL);
return fXfermode;
}
SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect) {
GEN_ID_INC_EVAL(effect != fPathEffect);
SkRefCnt_SafeAssign(fPathEffect, effect);
+ fDirtyBits = set_mask(fDirtyBits, kPathEffect_DirtyBit, effect != NULL);
return effect;
}
SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) {
GEN_ID_INC_EVAL(filter != fMaskFilter);
SkRefCnt_SafeAssign(fMaskFilter, filter);
+ fDirtyBits = set_mask(fDirtyBits, kMaskFilter_DirtyBit, filter != NULL);
return filter;
}
@@ -2302,10 +2370,14 @@ const SkRect& SkPaint::doComputeFastBounds(const SkRect& origSrc,
this->getMaskFilter()->computeFastBounds(*storage, storage);
}
+ if (this->getImageFilter()) {
+ this->getImageFilter()->computeFastBounds(*storage, storage);
+ }
+
return *storage;
}
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkPaint::toString(SkString* str) const {
str->append("<dl><dt>SkPaint:</dt><dd><dl>");
@@ -2475,7 +2547,6 @@ void SkPaint::toString(SkString* str) const {
}
#endif
-
///////////////////////////////////////////////////////////////////////////////
static bool has_thick_frame(const SkPaint& paint) {
@@ -2513,7 +2584,7 @@ SkTextToPathIter::SkTextToPathIter( const char text[], size_t length,
fPaint.setPathEffect(NULL);
}
- fCache = fPaint.detachCache(NULL, NULL);
+ fCache = fPaint.detachCache(NULL, NULL, false);
SkPaint::Style style = SkPaint::kFill_Style;
SkPathEffect* pe = NULL;
@@ -2598,3 +2669,97 @@ bool SkPaint::nothingToDraw() const {
}
return false;
}
+
+void SkPaint::setBitfields(uint32_t bitfields) {
+ fBitfields = bitfields;
+}
+
+inline static unsigned popcount(uint8_t x) {
+ // As in Hacker's delight, adapted for just 8 bits.
+ x = (x & 0x55) + ((x >> 1) & 0x55); // a b c d w x y z -> a+b c+d w+x y+z
+ x = (x & 0x33) + ((x >> 2) & 0x33); // a+b c+d w+x y+z -> a+b+c+d w+x+y+z
+ x = (x & 0x0F) + ((x >> 4) & 0x0F); // a+b+c+d w+x+y+z -> a+b+c+d+w+x+y+z
+ return x;
+}
+
+void SkPaint::FlatteningTraits::Flatten(SkWriteBuffer& buffer, const SkPaint& paint) {
+ const uint32_t dirty = paint.fDirtyBits;
+
+ // Each of the low 7 dirty bits corresponds to a 4-byte flat value,
+ // plus one for the dirty bits and one for the bitfields
+ const size_t flatBytes = 4 * (popcount(dirty & kPOD_DirtyBitMask) + 2);
+ SkASSERT(flatBytes <= 32);
+ uint32_t* u32 = buffer.reserve(flatBytes);
+ *u32++ = dirty;
+ *u32++ = paint.getBitfields();
+ if (0 == dirty) {
+ return;
+ }
+
+#define F(dst, field) if (dirty & k##field##_DirtyBit) *dst++ = paint.get##field()
+ F(u32, Color);
+ SkScalar* f32 = reinterpret_cast<SkScalar*>(u32);
+ F(f32, TextSize);
+ F(f32, TextScaleX);
+ F(f32, TextSkewX);
+ F(f32, StrokeWidth);
+ F(f32, StrokeMiter);
+#undef F
+#define F(field) if (dirty & k##field##_DirtyBit) buffer.writeFlattenable(paint.get##field())
+ F(PathEffect);
+ F(Shader);
+ F(Xfermode);
+ F(MaskFilter);
+ F(ColorFilter);
+ F(Rasterizer);
+ F(Looper);
+ F(ImageFilter);
+#undef F
+ if (dirty & kTypeface_DirtyBit) buffer.writeTypeface(paint.getTypeface());
+ if (dirty & kAnnotation_DirtyBit) paint.getAnnotation()->writeToBuffer(buffer);
+#ifdef SK_BUILD_FOR_ANDROID
+ if (dirty & kPaintOptionsAndroid_DirtyBit) paint.getPaintOptionsAndroid().flatten(buffer);
+#endif
+}
+
+void SkPaint::FlatteningTraits::Unflatten(SkReadBuffer& buffer, SkPaint* paint) {
+ const uint32_t dirty = buffer.readUInt();
+ paint->setBitfields(buffer.readUInt());
+ if (dirty == 0) {
+ return;
+ }
+#define F(field, reader) if (dirty & k##field##_DirtyBit) paint->set##field(buffer.reader())
+// Same function, except it unrefs the object newly set on the paint:
+#define F_UNREF(field, reader) \
+ if (dirty & k##field##_DirtyBit) \
+ paint->set##field(buffer.reader())->unref()
+
+ F(Color, readUInt);
+ F(TextSize, readScalar);
+ F(TextScaleX, readScalar);
+ F(TextSkewX, readScalar);
+ F(StrokeWidth, readScalar);
+ F(StrokeMiter, readScalar);
+ F_UNREF(PathEffect, readPathEffect);
+ F_UNREF(Shader, readShader);
+ F_UNREF(Xfermode, readXfermode);
+ F_UNREF(MaskFilter, readMaskFilter);
+ F_UNREF(ColorFilter, readColorFilter);
+ F_UNREF(Rasterizer, readRasterizer);
+ F_UNREF(Looper, readDrawLooper);
+ F_UNREF(ImageFilter, readImageFilter);
+ F(Typeface, readTypeface);
+#undef F
+#undef F_UNREF
+ if (dirty & kAnnotation_DirtyBit) {
+ paint->setAnnotation(SkAnnotation::Create(buffer))->unref();
+ }
+#ifdef SK_BUILD_FOR_ANDROID
+ if (dirty & kPaintOptionsAndroid_DirtyBit) {
+ SkPaintOptionsAndroid options;
+ options.unflatten(buffer);
+ paint->setPaintOptionsAndroid(options);
+ }
+#endif
+ SkASSERT(dirty == paint->fDirtyBits);
+}
diff --git a/chromium/third_party/skia/src/core/SkPaintOptionsAndroid.cpp b/chromium/third_party/skia/src/core/SkPaintOptionsAndroid.cpp
index f8a65e9d90f..56f1bd1654e 100644
--- a/chromium/third_party/skia/src/core/SkPaintOptionsAndroid.cpp
+++ b/chromium/third_party/skia/src/core/SkPaintOptionsAndroid.cpp
@@ -7,7 +7,8 @@
*/
#include "SkPaintOptionsAndroid.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkTDict.h"
#include "SkThread.h"
#include <cstring>
@@ -25,13 +26,13 @@ SkLanguage SkLanguage::getParent() const {
return SkLanguage(tag, parentTagLen);
}
-void SkPaintOptionsAndroid::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkPaintOptionsAndroid::flatten(SkWriteBuffer& buffer) const {
buffer.writeUInt(fFontVariant);
buffer.writeString(fLanguage.getTag().c_str());
buffer.writeBool(fUseFontFallbacks);
}
-void SkPaintOptionsAndroid::unflatten(SkFlattenableReadBuffer& buffer) {
+void SkPaintOptionsAndroid::unflatten(SkReadBuffer& buffer) {
fFontVariant = (FontVariant)buffer.readUInt();
SkString tag;
buffer.readString(&tag);
diff --git a/chromium/third_party/skia/src/core/SkPaintPriv.cpp b/chromium/third_party/skia/src/core/SkPaintPriv.cpp
index ce053890192..a8b52e998c7 100644
--- a/chromium/third_party/skia/src/core/SkPaintPriv.cpp
+++ b/chromium/third_party/skia/src/core/SkPaintPriv.cpp
@@ -76,3 +76,22 @@ bool isPaintOpaque(const SkPaint* paint,
}
return false;
}
+
+bool NeedsDeepCopy(const SkPaint& paint) {
+ /*
+ * The types below are not yet immutable/reentrant-safe, and so we return
+ * true if instances of them are present in the paint.
+ *
+ * Eventually we hope this list will be empty, and we can always return
+ * false.
+ */
+ return false
+#ifdef SK_SUPPORT_LEGACY_SHADER_LOCALMATRIX
+ || paint.getShader()
+#endif
+#ifdef SK_SUPPORT_LEGACY_LAYERRASTERIZER_API
+ || paint.getRasterizer()
+#endif
+ || paint.getImageFilter()
+ ;
+}
diff --git a/chromium/third_party/skia/src/core/SkPaintPriv.h b/chromium/third_party/skia/src/core/SkPaintPriv.h
index 38c9063e566..9668fef1275 100644
--- a/chromium/third_party/skia/src/core/SkPaintPriv.h
+++ b/chromium/third_party/skia/src/core/SkPaintPriv.h
@@ -22,4 +22,11 @@ class SkPaint;
*/
bool isPaintOpaque(const SkPaint* paint,
const SkBitmap* bmpReplacesShader = NULL);
+
+/** Returns true if the provided paint has fields which are not
+ immutable (and will thus require deep copying).
+ @param paint the paint to be analyzed
+ @return true if the paint requires a deep copy
+*/
+bool NeedsDeepCopy(const SkPaint& paint);
#endif
diff --git a/chromium/third_party/skia/src/core/SkPath.cpp b/chromium/third_party/skia/src/core/SkPath.cpp
index af8b1aa56e2..075cfdb4215 100644
--- a/chromium/third_party/skia/src/core/SkPath.cpp
+++ b/chromium/third_party/skia/src/core/SkPath.cpp
@@ -359,10 +359,13 @@ The test fails if:
There's more than four changes of direction.
There's a discontinuity on the line (e.g., a move in the middle)
The line reverses direction.
- The rectangle doesn't complete a cycle.
The path contains a quadratic or cubic.
The path contains fewer than four points.
- The final point isn't equal to the first point.
+ *The rectangle doesn't complete a cycle.
+ *The final point isn't equal to the first point.
+
+ *These last two conditions we relax if we have a 3-edge path that would
+ form a rectangle if it were closed (as we do when we fill a path)
It's OK if the path has:
Several colinear line segments composing a rectangle side.
@@ -374,7 +377,18 @@ must travel in opposite directions.
FIXME: Allow colinear quads and cubics to be treated like lines.
FIXME: If the API passes fill-only, return true if the filled stroke
is a rectangle, though the caller failed to close the path.
+
+ first,last,next direction state-machine:
+ 0x1 is set if the segment is horizontal
+ 0x2 is set if the segment is moving to the right or down
+ thus:
+ two directions are opposites iff (dirA ^ dirB) == 0x2
+ two directions are perpendicular iff (dirA ^ dirB) == 0x1
+
*/
+static int rect_make_dir(SkScalar dx, SkScalar dy) {
+ return ((0 != dx) << 0) | ((dx > 0 || dy > 0) << 1);
+}
bool SkPath::isRectContour(bool allowPartial, int* currVerb, const SkPoint** ptsPtr,
bool* isClosed, Direction* direction) const {
int corners = 0;
@@ -407,8 +421,7 @@ bool SkPath::isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts
if (left == right && top == bottom) {
break; // single point on side OK
}
- nextDirection = (left != right) << 0 |
- (left < right || top < bottom) << 1;
+ nextDirection = rect_make_dir(right - left, bottom - top);
if (0 == corners) {
firstDirection = nextDirection;
first = last;
@@ -460,6 +473,25 @@ bool SkPath::isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts
}
// Success if 4 corners and first point equals last
bool result = 4 == corners && (first == last || autoClose);
+ if (!result) {
+ // check if we are just an incomplete rectangle, in which case we can
+ // return true, but not claim to be closed.
+ // e.g.
+ // 3 sided rectangle
+ // 4 sided but the last edge is not long enough to reach the start
+ //
+ SkScalar closeX = first.x() - last.x();
+ SkScalar closeY = first.y() - last.y();
+ if (closeX && closeY) {
+ return false; // we're diagonal, abort (can we ever reach this?)
+ }
+ int closeDirection = rect_make_dir(closeX, closeY);
+ // make sure the close-segment doesn't double-back on itself
+ if (3 == corners || (4 == corners && closeDirection == lastDirection)) {
+ result = true;
+ autoClose = false; // we are not closed
+ }
+ }
if (savePts) {
*ptsPtr = savePts;
}
@@ -472,6 +504,14 @@ bool SkPath::isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts
return result;
}
+SkPath::PathAsRect SkPath::asRect(Direction* direction) const {
+ SK_COMPILE_ASSERT(0 == kNone_PathAsRect, path_as_rect_mismatch);
+ SK_COMPILE_ASSERT(1 == kFill_PathAsRect, path_as_rect_mismatch);
+ SK_COMPILE_ASSERT(2 == kStroke_PathAsRect, path_as_rect_mismatch);
+ bool isClosed = false;
+ return (PathAsRect) (isRect(&isClosed, direction) + isClosed);
+}
+
bool SkPath::isRect(SkRect* rect) const {
SkDEBUGCODE(this->validate();)
int currVerb = 0;
@@ -1403,14 +1443,14 @@ void SkPath::arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
///////////////////////////////////////////////////////////////////////////////
-void SkPath::addPath(const SkPath& path, SkScalar dx, SkScalar dy) {
+void SkPath::addPath(const SkPath& path, SkScalar dx, SkScalar dy, AddPathMode mode) {
SkMatrix matrix;
matrix.setTranslate(dx, dy);
- this->addPath(path, matrix);
+ this->addPath(path, matrix, mode);
}
-void SkPath::addPath(const SkPath& path, const SkMatrix& matrix) {
+void SkPath::addPath(const SkPath& path, const SkMatrix& matrix, AddPathMode mode) {
SkPathRef::Editor(&fPathRef, path.countVerbs(), path.countPoints());
RawIter iter(path);
@@ -1418,12 +1458,17 @@ void SkPath::addPath(const SkPath& path, const SkMatrix& matrix) {
Verb verb;
SkMatrix::MapPtsProc proc = matrix.getMapPtsProc();
-
+ bool firstVerb = true;
while ((verb = iter.next(pts)) != kDone_Verb) {
switch (verb) {
case kMove_Verb:
proc(matrix, &pts[0], &pts[0], 1);
- this->moveTo(pts[0]);
+ if (firstVerb && mode == kExtend_AddPathMode && !isEmpty()) {
+ injectMoveToIfNeeded(); // In case last contour is closed
+ this->lineTo(pts[0]);
+ } else {
+ this->moveTo(pts[0]);
+ }
break;
case kLine_Verb:
proc(matrix, &pts[1], &pts[1], 1);
@@ -1447,6 +1492,7 @@ void SkPath::addPath(const SkPath& path, const SkMatrix& matrix) {
default:
SkDEBUGFAIL("unknown verb");
}
+ firstVerb = false;
}
}
@@ -2026,11 +2072,7 @@ size_t SkPath::writeToMemory(void* storage) const {
int32_t packed = (fConvexity << kConvexity_SerializationShift) |
(fFillType << kFillType_SerializationShift) |
- (fDirection << kDirection_SerializationShift)
-#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
- | (0x1 << kNewFormat_SerializationShift)
-#endif
- ;
+ (fDirection << kDirection_SerializationShift);
buffer.write32(packed);
@@ -2051,15 +2093,7 @@ size_t SkPath::readFromMemory(const void* storage, size_t length) {
fConvexity = (packed >> kConvexity_SerializationShift) & 0xFF;
fFillType = (packed >> kFillType_SerializationShift) & 0xFF;
fDirection = (packed >> kDirection_SerializationShift) & 0x3;
-#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
- bool newFormat = (packed >> kNewFormat_SerializationShift) & 1;
-#endif
-
- SkPathRef* pathRef = SkPathRef::CreateFromBuffer(&buffer
-#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
- , newFormat, packed
-#endif
- );
+ SkPathRef* pathRef = SkPathRef::CreateFromBuffer(&buffer);
size_t sizeRead = 0;
if (buffer.isValid()) {
@@ -2136,7 +2170,7 @@ void SkPath::dump(bool forceClose, const char title[]) const {
append_params(&builder, "path.cubicTo", &pts[1], 3);
break;
case kClose_Verb:
- builder.append("path.close();\n");
+ builder.append("path.close();");
break;
default:
SkDebugf(" path: UNKNOWN VERB %d, aborting dump...\n", verb);
@@ -2189,7 +2223,7 @@ void SkPath::validate() const {
static int sign(SkScalar x) { return x < 0; }
#define kValueNeverReturnedBySign 2
-static bool AlmostEqual(SkScalar compA, SkScalar compB) {
+static bool almost_equal(SkScalar compA, SkScalar compB) {
// The error epsilon was empirically derived; worse case round rects
// with a mid point outset by 2x float epsilon in tests had an error
// of 12.
@@ -2213,8 +2247,7 @@ struct Convexicator {
// warnings
fLastPt.set(0, 0);
fCurrPt.set(0, 0);
- fVec0.set(0, 0);
- fVec1.set(0, 0);
+ fLastVec.set(0, 0);
fFirstVec.set(0, 0);
fDx = fDy = 0;
@@ -2240,7 +2273,7 @@ struct Convexicator {
fLastPt = fCurrPt;
fCurrPt = pt;
if (++fPtCount == 2) {
- fFirstVec = fVec1 = vec;
+ fFirstVec = fLastVec = vec;
} else {
SkASSERT(fPtCount > 2);
this->addVec(vec);
@@ -2269,31 +2302,28 @@ struct Convexicator {
private:
void addVec(const SkVector& vec) {
SkASSERT(vec.fX || vec.fY);
- fVec0 = fVec1;
- fVec1 = vec;
- SkScalar cross = SkPoint::CrossProduct(fVec0, fVec1);
+ SkScalar cross = SkPoint::CrossProduct(fLastVec, vec);
SkScalar smallest = SkTMin(fCurrPt.fX, SkTMin(fCurrPt.fY, SkTMin(fLastPt.fX, fLastPt.fY)));
SkScalar largest = SkTMax(fCurrPt.fX, SkTMax(fCurrPt.fY, SkTMax(fLastPt.fX, fLastPt.fY)));
largest = SkTMax(largest, -smallest);
- int sign = AlmostEqual(largest, largest + cross) ? 0 : SkScalarSignAsInt(cross);
- if (0 == fSign) {
- fSign = sign;
- if (1 == sign) {
- fDirection = SkPath::kCW_Direction;
- } else if (-1 == sign) {
- fDirection = SkPath::kCCW_Direction;
- }
- } else if (sign) {
- if (fSign != sign) {
+ if (!almost_equal(largest, largest + cross)) {
+ int sign = SkScalarSignAsInt(cross);
+ if (0 == fSign) {
+ fSign = sign;
+ fDirection = (1 == sign) ? SkPath::kCW_Direction : SkPath::kCCW_Direction;
+ } else if (sign && fSign != sign) {
fConvexity = SkPath::kConcave_Convexity;
fDirection = SkPath::kUnknown_Direction;
}
+ fLastVec = vec;
}
}
SkPoint fLastPt;
SkPoint fCurrPt;
- SkVector fVec0, fVec1, fFirstVec;
+ // fLastVec does not necessarily start at fLastPt. We only advance it when the cross product
+ // value with the current vec is deemed to be of a significant value.
+ SkVector fLastVec, fFirstVec;
int fPtCount; // non-degenerate points
int fSign;
SkPath::Convexity fConvexity;
diff --git a/chromium/third_party/skia/src/core/SkPathEffect.cpp b/chromium/third_party/skia/src/core/SkPathEffect.cpp
index 59ba3ec31fb..01d5d6f9619 100644
--- a/chromium/third_party/skia/src/core/SkPathEffect.cpp
+++ b/chromium/third_party/skia/src/core/SkPathEffect.cpp
@@ -8,7 +8,8 @@
#include "SkPathEffect.h"
#include "SkPath.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
///////////////////////////////////////////////////////////////////////////////
@@ -21,6 +22,10 @@ bool SkPathEffect::asPoints(PointData* results, const SkPath& src,
return false;
}
+SkPathEffect::DashType SkPathEffect::asADash(DashInfo* info) const {
+ return kNone_DashType;
+}
+
///////////////////////////////////////////////////////////////////////////////
SkPairPathEffect::SkPairPathEffect(SkPathEffect* pe0, SkPathEffect* pe1)
@@ -39,13 +44,13 @@ SkPairPathEffect::~SkPairPathEffect() {
/*
Format: [oe0-factory][pe1-factory][pe0-size][pe0-data][pe1-data]
*/
-void SkPairPathEffect::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkPairPathEffect::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeFlattenable(fPE0);
buffer.writeFlattenable(fPE1);
}
-SkPairPathEffect::SkPairPathEffect(SkFlattenableReadBuffer& buffer) {
+SkPairPathEffect::SkPairPathEffect(SkReadBuffer& buffer) {
fPE0 = buffer.readPathEffect();
fPE1 = buffer.readPathEffect();
// either of these may fail, so we have to check for nulls later on
diff --git a/chromium/third_party/skia/src/core/SkPathHeap.cpp b/chromium/third_party/skia/src/core/SkPathHeap.cpp
index c6e2129e9ed..84ffb04b80e 100644
--- a/chromium/third_party/skia/src/core/SkPathHeap.cpp
+++ b/chromium/third_party/skia/src/core/SkPathHeap.cpp
@@ -8,7 +8,9 @@
#include "SkPathHeap.h"
#include "SkPath.h"
#include "SkStream.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkTSearch.h"
+#include "SkWriteBuffer.h"
#include <new>
#define kPathCount 64
@@ -16,7 +18,7 @@
SkPathHeap::SkPathHeap() : fHeap(kPathCount * sizeof(SkPath)) {
}
-SkPathHeap::SkPathHeap(SkFlattenableReadBuffer& buffer)
+SkPathHeap::SkPathHeap(SkReadBuffer& buffer)
: fHeap(kPathCount * sizeof(SkPath)) {
const int count = buffer.readInt();
@@ -48,7 +50,39 @@ int SkPathHeap::append(const SkPath& path) {
return fPaths.count();
}
-void SkPathHeap::flatten(SkFlattenableWriteBuffer& buffer) const {
+SkPathHeap::LookupEntry::LookupEntry(const SkPath& path)
+ : fGenerationID(path.getGenerationID()), fStorageSlot(0) {
+}
+
+SkPathHeap::LookupEntry* SkPathHeap::addIfNotPresent(const SkPath& path) {
+ LookupEntry searchKey(path);
+ int index = SkTSearch<const LookupEntry, LookupEntry::Less>(
+ fLookupTable.begin(),
+ fLookupTable.count(),
+ searchKey,
+ sizeof(LookupEntry));
+ if (index < 0) {
+ index = ~index;
+ *fLookupTable.insert(index) = LookupEntry(path);
+ }
+
+ return &fLookupTable[index];;
+}
+
+int SkPathHeap::insert(const SkPath& path) {
+ SkPathHeap::LookupEntry* entry = this->addIfNotPresent(path);
+
+ if (entry->storageSlot() > 0) {
+ return entry->storageSlot();
+ }
+
+ int newSlot = this->append(path);
+ SkASSERT(newSlot > 0);
+ entry->setStorageSlot(newSlot);
+ return newSlot;
+}
+
+void SkPathHeap::flatten(SkWriteBuffer& buffer) const {
int count = fPaths.count();
buffer.writeInt(count);
diff --git a/chromium/third_party/skia/src/core/SkPathHeap.h b/chromium/third_party/skia/src/core/SkPathHeap.h
index 095e84a2028..377d8d968ba 100644
--- a/chromium/third_party/skia/src/core/SkPathHeap.h
+++ b/chromium/third_party/skia/src/core/SkPathHeap.h
@@ -13,15 +13,15 @@
#include "SkTDArray.h"
class SkPath;
-class SkFlattenableReadBuffer;
-class SkFlattenableWriteBuffer;
+class SkReadBuffer;
+class SkWriteBuffer;
class SkPathHeap : public SkRefCnt {
public:
SK_DECLARE_INST_COUNT(SkPathHeap)
SkPathHeap();
- SkPathHeap(SkFlattenableReadBuffer&);
+ SkPathHeap(SkReadBuffer&);
virtual ~SkPathHeap();
/** Copy the path into the heap, and return the new total number of paths.
@@ -30,13 +30,18 @@ public:
*/
int append(const SkPath&);
+ /** Add the specified path to the heap using its gen ID to de-duplicate.
+ Returns the path's index in the heap + 1.
+ */
+ int insert(const SkPath&);
+
// called during picture-playback
int count() const { return fPaths.count(); }
const SkPath& operator[](int index) const {
return *fPaths[index];
}
- void flatten(SkFlattenableWriteBuffer&) const;
+ void flatten(SkWriteBuffer&) const;
private:
// we store the paths in the heap (placement new)
@@ -44,6 +49,27 @@ private:
// we just store ptrs into fHeap here
SkTDArray<SkPath*> fPaths;
+ class LookupEntry {
+ public:
+ LookupEntry(const SkPath& path);
+
+ int storageSlot() const { return fStorageSlot; }
+ void setStorageSlot(int storageSlot) { fStorageSlot = storageSlot; }
+
+ static bool Less(const LookupEntry& a, const LookupEntry& b) {
+ return a.fGenerationID < b.fGenerationID;
+ }
+
+ private:
+ uint32_t fGenerationID; // the SkPath's generation ID
+ // the path's index in the heap + 1. It is 0 if the path is not yet in the heap.
+ int fStorageSlot;
+ };
+
+ SkTDArray<LookupEntry> fLookupTable;
+
+ SkPathHeap::LookupEntry* addIfNotPresent(const SkPath& path);
+
typedef SkRefCnt INHERITED;
};
diff --git a/chromium/third_party/skia/src/core/SkPathMeasure.cpp b/chromium/third_party/skia/src/core/SkPathMeasure.cpp
index c519f93dcea..48f7571c074 100644
--- a/chromium/third_party/skia/src/core/SkPathMeasure.cpp
+++ b/chromium/third_party/skia/src/core/SkPathMeasure.cpp
@@ -23,12 +23,7 @@ enum {
static inline SkScalar tValue2Scalar(int t) {
SkASSERT((unsigned)t <= kMaxTValue);
-
-#ifdef SK_SCALAR_IS_FLOAT
return t * 3.05185e-5f; // t / 32767
-#else
- return (t + (t >> 14)) << 1;
-#endif
}
SkScalar SkPathMeasure::Segment::getScalarT() const {
diff --git a/chromium/third_party/skia/src/core/SkPathRef.cpp b/chromium/third_party/skia/src/core/SkPathRef.cpp
index 0711e3f0699..de7a8f56ae0 100644
--- a/chromium/third_party/skia/src/core/SkPathRef.cpp
+++ b/chromium/third_party/skia/src/core/SkPathRef.cpp
@@ -6,7 +6,7 @@
*/
#include "SkBuffer.h"
-#include "SkOnce.h"
+#include "SkLazyPtr.h"
#include "SkPath.h"
#include "SkPathRef.h"
@@ -28,16 +28,16 @@ SkPathRef::Editor::Editor(SkAutoTUnref<SkPathRef>* pathRef,
}
//////////////////////////////////////////////////////////////////////////////
-void SkPathRef::CreateEmptyImpl(SkPathRef** empty) {
- *empty = SkNEW(SkPathRef);
- (*empty)->computeBounds(); // Preemptively avoid a race to clear fBoundsIsDirty.
+
+SkPathRef* SkPathRef::CreateEmptyImpl() {
+ SkPathRef* p = SkNEW(SkPathRef);
+ p->computeBounds(); // Preemptively avoid a race to clear fBoundsIsDirty.
+ return p;
}
SkPathRef* SkPathRef::CreateEmpty() {
- static SkPathRef* gEmptyPathRef;
- SK_DECLARE_STATIC_ONCE(once);
- SkOnce(&once, SkPathRef::CreateEmptyImpl, &gEmptyPathRef);
- return SkRef(gEmptyPathRef);
+ SK_DECLARE_STATIC_LAZY_PTR(SkPathRef, empty, CreateEmptyImpl);
+ return SkRef(empty.get());
}
void SkPathRef::CreateTransformedCopy(SkAutoTUnref<SkPathRef>* dst,
@@ -105,11 +105,7 @@ void SkPathRef::CreateTransformedCopy(SkAutoTUnref<SkPathRef>* dst,
SkDEBUGCODE((*dst)->validate();)
}
-SkPathRef* SkPathRef::CreateFromBuffer(SkRBuffer* buffer
-#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
- , bool newFormat, int32_t oldPacked
-#endif
- ) {
+SkPathRef* SkPathRef::CreateFromBuffer(SkRBuffer* buffer) {
SkPathRef* ref = SkNEW(SkPathRef);
bool isOval;
uint8_t segmentMask;
@@ -121,18 +117,8 @@ SkPathRef* SkPathRef::CreateFromBuffer(SkRBuffer* buffer
}
ref->fIsFinite = (packed >> kIsFinite_SerializationShift) & 1;
-
-#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
- if (newFormat) {
-#endif
- segmentMask = (packed >> kSegmentMask_SerializationShift) & 0xF;
- isOval = (packed >> kIsOval_SerializationShift) & 1;
-#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
- } else {
- segmentMask = (oldPacked >> SkPath::kOldSegmentMask_SerializationShift) & 0xF;
- isOval = (oldPacked >> SkPath::kOldIsOval_SerializationShift) & 1;
- }
-#endif
+ segmentMask = (packed >> kSegmentMask_SerializationShift) & 0xF;
+ isOval = (packed >> kIsOval_SerializationShift) & 1;
int32_t verbCount, pointCount, conicCount;
if (!buffer->readU32(&(ref->fGenerationID)) ||
@@ -288,8 +274,8 @@ void SkPathRef::copy(const SkPathRef& ref,
SkDEBUGCODE(this->validate();)
}
-SkPoint* SkPathRef::growForRepeatedVerb(int /*SkPath::Verb*/ verb,
- int numVbs,
+SkPoint* SkPathRef::growForRepeatedVerb(int /*SkPath::Verb*/ verb,
+ int numVbs,
SkScalar** weights) {
// This value is just made-up for now. When count is 4, calling memset was much
// slower than just writing the loop. This seems odd, and hopefully in the
diff --git a/chromium/third_party/skia/src/core/SkPicture.cpp b/chromium/third_party/skia/src/core/SkPicture.cpp
index 2b9b9e934c0..76c2b9def9c 100644
--- a/chromium/third_party/skia/src/core/SkPicture.cpp
+++ b/chromium/third_party/skia/src/core/SkPicture.cpp
@@ -11,9 +11,11 @@
#include "SkPicturePlayback.h"
#include "SkPictureRecord.h"
+#include "SkBBHFactory.h"
#include "SkBitmapDevice.h"
#include "SkCanvas.h"
#include "SkChunkAlloc.h"
+#include "SkPaintPriv.h"
#include "SkPicture.h"
#include "SkRegion.h"
#include "SkStream.h"
@@ -26,6 +28,14 @@
#include "SkRTree.h"
#include "SkBBoxHierarchyRecord.h"
+#if SK_SUPPORT_GPU
+#include "GrContext.h"
+#endif
+
+template <typename T> int SafeCount(const T* obj) {
+ return obj ? obj->count() : 0;
+}
+
#define DUMP_BUFFER_SIZE 65536
//#define ENABLE_TIME_DRAW // dumps milliseconds for each draw
@@ -113,46 +123,57 @@ static void validateMatrix(const SkMatrix* matrix) {
///////////////////////////////////////////////////////////////////////////////
-SkPicture::SkPicture() {
- fRecord = NULL;
+SkPicture::SkPicture()
+ : fAccelData(NULL) {
+ this->needsNewGenID();
fPlayback = NULL;
fWidth = fHeight = 0;
}
-SkPicture::SkPicture(const SkPicture& src) : INHERITED() {
+SkPicture::SkPicture(int width, int height,
+ const SkPictureRecord& record,
+ bool deepCopyOps)
+ : fWidth(width)
+ , fHeight(height)
+ , fAccelData(NULL) {
+ this->needsNewGenID();
+
+ SkPictInfo info;
+ this->createHeader(&info);
+ fPlayback = SkNEW_ARGS(SkPicturePlayback, (record, info, deepCopyOps));
+}
+
+SkPicture::SkPicture(const SkPicture& src)
+ : INHERITED()
+ , fAccelData(NULL) {
+ this->needsNewGenID();
fWidth = src.fWidth;
fHeight = src.fHeight;
- fRecord = NULL;
- /* We want to copy the src's playback. However, if that hasn't been built
- yet, we need to fake a call to endRecording() without actually calling
- it (since it is destructive, and we don't want to change src).
- */
if (src.fPlayback) {
fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fPlayback));
- } else if (src.fRecord) {
- // here we do a fake src.endRecording()
- fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fRecord));
+ fUniqueID = src.uniqueID(); // need to call method to ensure != 0
} else {
fPlayback = NULL;
}
}
SkPicture::~SkPicture() {
- SkSafeUnref(fRecord);
SkDELETE(fPlayback);
+ SkSafeUnref(fAccelData);
}
void SkPicture::swap(SkPicture& other) {
- SkTSwap(fRecord, other.fRecord);
+ SkTSwap(fUniqueID, other.fUniqueID);
SkTSwap(fPlayback, other.fPlayback);
+ SkTSwap(fAccelData, other.fAccelData);
SkTSwap(fWidth, other.fWidth);
SkTSwap(fHeight, other.fHeight);
}
SkPicture* SkPicture::clone() const {
SkPicture* clonedPicture = SkNEW(SkPicture);
- clone(clonedPicture, 1);
+ this->clone(clonedPicture, 1);
return clonedPicture;
}
@@ -162,14 +183,9 @@ void SkPicture::clone(SkPicture* pictures, int count) const {
for (int i = 0; i < count; i++) {
SkPicture* clone = &pictures[i];
+ clone->needsNewGenID();
clone->fWidth = fWidth;
clone->fHeight = fHeight;
- clone->fRecord = NULL;
-
- if (NULL != clone->fRecord) {
- clone->fRecord->unref();
- clone->fRecord = NULL;
- }
SkDELETE(clone->fPlayback);
/* We want to copy the src's playback. However, if that hasn't been built
@@ -177,85 +193,92 @@ void SkPicture::clone(SkPicture* pictures, int count) const {
it (since it is destructive, and we don't want to change src).
*/
if (fPlayback) {
+ if (!copyInfo.initialized) {
+ int paintCount = SafeCount(fPlayback->fPaints);
+
+ /* The alternative to doing this is to have a clone method on the paint and have it
+ * make the deep copy of its internal structures as needed. The holdup to doing
+ * that is at this point we would need to pass the SkBitmapHeap so that we don't
+ * unnecessarily flatten the pixels in a bitmap shader.
+ */
+ copyInfo.paintData.setCount(paintCount);
+
+ /* Use an SkBitmapHeap to avoid flattening bitmaps in shaders. If there already is
+ * one, use it. If this SkPicturePlayback was created from a stream, fBitmapHeap
+ * will be NULL, so create a new one.
+ */
+ if (fPlayback->fBitmapHeap.get() == NULL) {
+ // FIXME: Put this on the stack inside SkPicture::clone.
+ SkBitmapHeap* heap = SkNEW(SkBitmapHeap);
+ copyInfo.controller.setBitmapStorage(heap);
+ heap->unref();
+ } else {
+ copyInfo.controller.setBitmapStorage(fPlayback->fBitmapHeap);
+ }
+
+ SkDEBUGCODE(int heapSize = SafeCount(fPlayback->fBitmapHeap.get());)
+ for (int i = 0; i < paintCount; i++) {
+ if (NeedsDeepCopy(fPlayback->fPaints->at(i))) {
+ copyInfo.paintData[i] =
+ SkFlatData::Create<SkPaint::FlatteningTraits>(&copyInfo.controller,
+ fPlayback->fPaints->at(i), 0);
+
+ } else {
+ // this is our sentinel, which we use in the unflatten loop
+ copyInfo.paintData[i] = NULL;
+ }
+ }
+ SkASSERT(SafeCount(fPlayback->fBitmapHeap.get()) == heapSize);
+
+ // needed to create typeface playback
+ copyInfo.controller.setupPlaybacks();
+ copyInfo.initialized = true;
+ }
+
clone->fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fPlayback, &copyInfo));
- } else if (fRecord) {
- // here we do a fake src.endRecording()
- clone->fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fRecord, true));
+ clone->fUniqueID = this->uniqueID(); // need to call method to ensure != 0
} else {
clone->fPlayback = NULL;
}
}
}
-///////////////////////////////////////////////////////////////////////////////
-
-SkCanvas* SkPicture::beginRecording(int width, int height,
- uint32_t recordingFlags) {
- if (fPlayback) {
- SkDELETE(fPlayback);
- fPlayback = NULL;
- }
-
- if (NULL != fRecord) {
- fRecord->unref();
- fRecord = NULL;
- }
+SkPicture::AccelData::Domain SkPicture::AccelData::GenerateDomain() {
+ static int32_t gNextID = 0;
- SkBitmap bm;
- bm.setConfig(SkBitmap::kNo_Config, width, height);
- SkAutoTUnref<SkBaseDevice> dev(SkNEW_ARGS(SkBitmapDevice, (bm)));
-
- // Must be set before calling createBBoxHierarchy
- fWidth = width;
- fHeight = height;
-
- if (recordingFlags & kOptimizeForClippedPlayback_RecordingFlag) {
- SkBBoxHierarchy* tree = this->createBBoxHierarchy();
- SkASSERT(NULL != tree);
- fRecord = SkNEW_ARGS(SkBBoxHierarchyRecord, (recordingFlags, tree, dev));
- tree->unref();
- } else {
- fRecord = SkNEW_ARGS(SkPictureRecord, (recordingFlags, dev));
+ int32_t id = sk_atomic_inc(&gNextID);
+ if (id >= 1 << (8 * sizeof(Domain))) {
+ SK_CRASH();
}
- fRecord->beginRecording();
- return fRecord;
+ return static_cast<Domain>(id);
}
-SkBBoxHierarchy* SkPicture::createBBoxHierarchy() const {
- // These values were empirically determined to produce reasonable
- // performance in most cases.
- static const int kRTreeMinChildren = 6;
- static const int kRTreeMaxChildren = 11;
-
- SkScalar aspectRatio = SkScalarDiv(SkIntToScalar(fWidth),
- SkIntToScalar(fHeight));
- bool sortDraws = false; // Do not sort draw calls when bulk loading.
+///////////////////////////////////////////////////////////////////////////////
- return SkRTree::Create(kRTreeMinChildren, kRTreeMaxChildren,
- aspectRatio, sortDraws);
+const SkPicture::OperationList& SkPicture::OperationList::InvalidList() {
+ static OperationList gInvalid;
+ return gInvalid;
}
-SkCanvas* SkPicture::getRecordingCanvas() const {
- // will be null if we are not recording
- return fRecord;
+const SkPicture::OperationList& SkPicture::EXPERIMENTAL_getActiveOps(const SkIRect& queryRect) const {
+ SkASSERT(NULL != fPlayback);
+ if (NULL != fPlayback) {
+ return fPlayback->getActiveOps(queryRect);
+ }
+ return OperationList::InvalidList();
}
-void SkPicture::endRecording() {
- if (NULL == fPlayback) {
- if (NULL != fRecord) {
- fRecord->endRecording();
- fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fRecord));
- fRecord->unref();
- fRecord = NULL;
- }
+size_t SkPicture::EXPERIMENTAL_curOpID() const {
+ if (NULL != fPlayback) {
+ return fPlayback->curOpID();
}
- SkASSERT(NULL == fRecord);
+ return 0;
}
-void SkPicture::draw(SkCanvas* surface, SkDrawPictureCallback* callback) {
- this->endRecording();
- if (fPlayback) {
+void SkPicture::draw(SkCanvas* surface, SkDrawPictureCallback* callback) const {
+ SkASSERT(NULL != fPlayback);
+ if (NULL != fPlayback) {
fPlayback->draw(*surface, callback);
}
}
@@ -266,29 +289,42 @@ void SkPicture::draw(SkCanvas* surface, SkDrawPictureCallback* callback) {
static const char kMagic[] = { 's', 'k', 'i', 'a', 'p', 'i', 'c', 't' };
-bool SkPicture::StreamIsSKP(SkStream* stream, SkPictInfo* pInfo) {
- if (NULL == stream) {
+bool SkPicture::IsValidPictInfo(const SkPictInfo& info) {
+ if (0 != memcmp(info.fMagic, kMagic, sizeof(kMagic))) {
return false;
}
- // Check magic bytes.
- char magic[sizeof(kMagic)];
- stream->read(magic, sizeof(kMagic));
- if (0 != memcmp(magic, kMagic, sizeof(kMagic))) {
+ if (info.fVersion < MIN_PICTURE_VERSION ||
+ info.fVersion > CURRENT_PICTURE_VERSION) {
return false;
}
+ return true;
+}
+
+bool SkPicture::InternalOnly_StreamIsSKP(SkStream* stream, SkPictInfo* pInfo) {
+ if (NULL == stream) {
+ return false;
+ }
+
+ // Check magic bytes.
SkPictInfo info;
- if (!stream->read(&info, sizeof(SkPictInfo))) {
+ SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
+ if (!stream->read(&info, sizeof(info)) || !IsValidPictInfo(info)) {
return false;
}
- if (PICTURE_VERSION != info.fVersion
-#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
- // V16 is backwards compatible with V15
- && PRIOR_PICTURE_VERSION != info.fVersion // TODO: remove when .skps regenerated
-#endif
- ) {
+ if (pInfo != NULL) {
+ *pInfo = info;
+ }
+ return true;
+}
+
+bool SkPicture::InternalOnly_BufferIsSKP(SkReadBuffer& buffer, SkPictInfo* pInfo) {
+ // Check magic bytes.
+ SkPictInfo info;
+ SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
+ if (!buffer.readByteArray(&info, sizeof(info)) || !IsValidPictInfo(info)) {
return false;
}
@@ -300,55 +336,76 @@ bool SkPicture::StreamIsSKP(SkStream* stream, SkPictInfo* pInfo) {
SkPicture::SkPicture(SkPicturePlayback* playback, int width, int height)
: fPlayback(playback)
- , fRecord(NULL)
, fWidth(width)
- , fHeight(height) {}
+ , fHeight(height)
+ , fAccelData(NULL) {
+ this->needsNewGenID();
+}
SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc proc) {
SkPictInfo info;
- if (!StreamIsSKP(stream, &info)) {
+ if (!InternalOnly_StreamIsSKP(stream, &info)) {
return NULL;
}
- SkPicturePlayback* playback;
// Check to see if there is a playback to recreate.
if (stream->readBool()) {
- playback = SkPicturePlayback::CreateFromStream(stream, info, proc);
+ SkPicturePlayback* playback = SkPicturePlayback::CreateFromStream(stream, info, proc);
if (NULL == playback) {
return NULL;
}
- } else {
- playback = NULL;
+
+ return SkNEW_ARGS(SkPicture, (playback, info.fWidth, info.fHeight));
}
- return SkNEW_ARGS(SkPicture, (playback, info.fWidth, info.fHeight));
+ return NULL;
}
-void SkPicture::serialize(SkWStream* stream, EncodeBitmap encoder) const {
- SkPicturePlayback* playback = fPlayback;
+SkPicture* SkPicture::CreateFromBuffer(SkReadBuffer& buffer) {
+ SkPictInfo info;
- if (NULL == playback && fRecord) {
- playback = SkNEW_ARGS(SkPicturePlayback, (*fRecord));
+ if (!InternalOnly_BufferIsSKP(buffer, &info)) {
+ return NULL;
}
- SkPictInfo info;
+ // Check to see if there is a playback to recreate.
+ if (buffer.readBool()) {
+ SkPicturePlayback* playback = SkPicturePlayback::CreateFromBuffer(buffer, info);
+ if (NULL == playback) {
+ return NULL;
+ }
- info.fVersion = PICTURE_VERSION;
- info.fWidth = fWidth;
- info.fHeight = fHeight;
- info.fFlags = SkPictInfo::kCrossProcess_Flag;
-#ifdef SK_SCALAR_IS_FLOAT
- info.fFlags |= SkPictInfo::kScalarIsFloat_Flag;
-#endif
- if (8 == sizeof(void*)) {
- info.fFlags |= SkPictInfo::kPtrIs64Bit_Flag;
+ return SkNEW_ARGS(SkPicture, (playback, info.fWidth, info.fHeight));
}
- // Write 8 magic bytes to ID this file format.
+ return NULL;
+}
+
+void SkPicture::createHeader(SkPictInfo* info) const {
+ // Copy magic bytes at the beginning of the header
SkASSERT(sizeof(kMagic) == 8);
- stream->write(kMagic, sizeof(kMagic));
+ SkASSERT(sizeof(kMagic) == sizeof(info->fMagic));
+ memcpy(info->fMagic, kMagic, sizeof(kMagic));
+
+ // Set picture info after magic bytes in the header
+ info->fVersion = CURRENT_PICTURE_VERSION;
+ info->fWidth = fWidth;
+ info->fHeight = fHeight;
+ info->fFlags = SkPictInfo::kCrossProcess_Flag;
+ // TODO: remove this flag, since we're always float (now)
+ info->fFlags |= SkPictInfo::kScalarIsFloat_Flag;
+
+ if (8 == sizeof(void*)) {
+ info->fFlags |= SkPictInfo::kPtrIs64Bit_Flag;
+ }
+}
+void SkPicture::serialize(SkWStream* stream, EncodeBitmap encoder) const {
+ SkPicturePlayback* playback = fPlayback;
+
+ SkPictInfo info;
+ this->createHeader(&info);
stream->write(&info, sizeof(info));
if (playback) {
stream->writeBool(true);
@@ -362,8 +419,51 @@ void SkPicture::serialize(SkWStream* stream, EncodeBitmap encoder) const {
}
}
+void SkPicture::WriteTagSize(SkWriteBuffer& buffer, uint32_t tag, size_t size) {
+ buffer.writeUInt(tag);
+ buffer.writeUInt(SkToU32(size));
+}
+
+void SkPicture::WriteTagSize(SkWStream* stream, uint32_t tag, size_t size) {
+ stream->write32(tag);
+ stream->write32(SkToU32(size));
+}
+
+void SkPicture::flatten(SkWriteBuffer& buffer) const {
+ SkPicturePlayback* playback = fPlayback;
+
+ SkPictInfo info;
+ this->createHeader(&info);
+ buffer.writeByteArray(&info, sizeof(info));
+ if (playback) {
+ buffer.writeBool(true);
+ playback->flatten(buffer);
+ // delete playback if it is a local version (i.e. cons'd up just now)
+ if (playback != fPlayback) {
+ SkDELETE(playback);
+ }
+ } else {
+ buffer.writeBool(false);
+ }
+}
+
+#if SK_SUPPORT_GPU
+bool SkPicture::suitableForGpuRasterization(GrContext* context, const char **reason) const {
+ if (NULL == fPlayback) {
+ if (NULL != reason) {
+ *reason = "Missing playback object.";
+ }
+ return false;
+ }
+
+ return fPlayback->suitableForGpuRasterization(context, reason);
+}
+#endif
+
bool SkPicture::willPlayBackBitmaps() const {
- if (!fPlayback) return false;
+ if (!fPlayback) {
+ return false;
+ }
return fPlayback->containsBitmaps();
}
@@ -375,3 +475,21 @@ void SkPicture::abortPlayback() {
fPlayback->abort();
}
#endif
+
+static int32_t next_picture_generation_id() {
+ static int32_t gPictureGenerationID = 0;
+ // do a loop in case our global wraps around, as we never want to
+ // return a 0
+ int32_t genID;
+ do {
+ genID = sk_atomic_inc(&gPictureGenerationID) + 1;
+ } while (SK_InvalidGenID == genID);
+ return genID;
+}
+
+uint32_t SkPicture::uniqueID() const {
+ if (SK_InvalidGenID == fUniqueID) {
+ fUniqueID = next_picture_generation_id();
+ }
+ return fUniqueID;
+}
diff --git a/chromium/third_party/skia/src/core/SkPictureFlat.cpp b/chromium/third_party/skia/src/core/SkPictureFlat.cpp
index 149cf7cc02c..7b2e67f5efd 100644
--- a/chromium/third_party/skia/src/core/SkPictureFlat.cpp
+++ b/chromium/third_party/skia/src/core/SkPictureFlat.cpp
@@ -60,12 +60,12 @@ SkRefCnt* SkTypefacePlayback::set(int index, SkRefCnt* obj) {
///////////////////////////////////////////////////////////////////////////////
-SkFlatController::SkFlatController()
+SkFlatController::SkFlatController(uint32_t writeBufferFlags)
: fBitmapHeap(NULL)
, fTypefaceSet(NULL)
, fTypefacePlayback(NULL)
, fFactorySet(NULL)
-, fWriteBufferFlags(0) {}
+, fWriteBufferFlags(writeBufferFlags) {}
SkFlatController::~SkFlatController() {
SkSafeUnref(fBitmapHeap);
@@ -89,52 +89,3 @@ SkNamedFactorySet* SkFlatController::setNamedFactorySet(SkNamedFactorySet* set)
SkRefCnt_SafeAssign(fFactorySet, set);
return set;
}
-
-///////////////////////////////////////////////////////////////////////////////
-
-SkFlatData* SkFlatData::Create(SkFlatController* controller,
- const void* obj,
- int index,
- void (*flattenProc)(SkOrderedWriteBuffer&, const void*)) {
- // a buffer of 256 bytes should be sufficient for most paints, regions,
- // and matrices.
- intptr_t storage[256];
- SkOrderedWriteBuffer buffer(256, storage, sizeof(storage));
-
- buffer.setBitmapHeap(controller->getBitmapHeap());
- buffer.setTypefaceRecorder(controller->getTypefaceSet());
- buffer.setNamedFactoryRecorder(controller->getNamedFactorySet());
- buffer.setFlags(controller->getWriteBufferFlags());
-
- flattenProc(buffer, obj);
- uint32_t size = buffer.size();
- SkASSERT(SkIsAlign4(size));
-
- // Allocate enough memory to hold SkFlatData struct and the flat data itself.
- size_t allocSize = sizeof(SkFlatData) + size;
- SkFlatData* result = (SkFlatData*) controller->allocThrow(allocSize);
-
- // Put the serialized contents into the data section of the new allocation.
- buffer.writeToMemory(result->data());
- // Stamp the index, size and checksum in the header.
- result->stampHeader(index, size);
- return result;
-}
-
-void SkFlatData::unflatten(void* result,
- void (*unflattenProc)(SkOrderedReadBuffer&, void*),
- SkBitmapHeap* bitmapHeap,
- SkTypefacePlayback* facePlayback) const {
-
- SkOrderedReadBuffer buffer(this->data(), fFlatSize);
-
- if (bitmapHeap) {
- buffer.setBitmapStorage(bitmapHeap);
- }
- if (facePlayback) {
- facePlayback->setupBuffer(buffer);
- }
-
- unflattenProc(buffer, result);
- SkASSERT(fFlatSize == (int32_t)buffer.offset());
-}
diff --git a/chromium/third_party/skia/src/core/SkPictureFlat.h b/chromium/third_party/skia/src/core/SkPictureFlat.h
index ac8e304c0f2..5d1a6b52d6e 100644
--- a/chromium/third_party/skia/src/core/SkPictureFlat.h
+++ b/chromium/third_party/skia/src/core/SkPictureFlat.h
@@ -10,21 +10,16 @@
//#define SK_DEBUG_SIZE
-#include "SkBitmap.h"
#include "SkBitmapHeap.h"
#include "SkChecksum.h"
#include "SkChunkAlloc.h"
-#include "SkMatrix.h"
-#include "SkOrderedReadBuffer.h"
-#include "SkOrderedWriteBuffer.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkPaint.h"
-#include "SkPath.h"
#include "SkPicture.h"
#include "SkPtrRecorder.h"
-#include "SkRegion.h"
#include "SkTDynamicHash.h"
#include "SkTRefArray.h"
-#include "SkTSearch.h"
enum DrawType {
UNUSED,
@@ -68,7 +63,12 @@ enum DrawType {
COMMENT,
END_COMMENT_GROUP,
- LAST_DRAWTYPE_ENUM = END_COMMENT_GROUP
+ // new ops -- feel free to re-alphabetize on next version bump
+ DRAW_DRRECT,
+ PUSH_CULL,
+ POP_CULL,
+
+ LAST_DRAWTYPE_ENUM = POP_CULL
};
// In the 'match' method, this constant will match any flavor of DRAW_BITMAP*
@@ -77,7 +77,8 @@ static const int kDRAW_BITMAP_FLAVOR = LAST_DRAWTYPE_ENUM+1;
enum DrawVertexFlags {
DRAW_VERTICES_HAS_TEXS = 0x01,
DRAW_VERTICES_HAS_COLORS = 0x02,
- DRAW_VERTICES_HAS_INDICES = 0x04
+ DRAW_VERTICES_HAS_INDICES = 0x04,
+ DRAW_VERTICES_HAS_XFER = 0x08,
};
///////////////////////////////////////////////////////////////////////////////
@@ -111,7 +112,7 @@ public:
void setCount(int count);
SkRefCnt* set(int index, SkRefCnt*);
- void setupBuffer(SkOrderedReadBuffer& buffer) const {
+ void setupBuffer(SkReadBuffer& buffer) const {
buffer.setTypefaceArray((SkTypeface**)fArray, fCount);
}
@@ -132,7 +133,7 @@ public:
SkFlattenable::Factory* base() const { return fArray; }
- void setupBuffer(SkOrderedReadBuffer& buffer) const {
+ void setupBuffer(SkReadBuffer& buffer) const {
buffer.setFactoryPlayback(fArray, fCount);
}
@@ -151,19 +152,17 @@ private:
// SkFlatData: is a simple indexable container for the flattened data
// which is agnostic to the type of data is is indexing. It is
// also responsible for flattening/unflattening objects but
-// details of that operation are hidden in the provided procs
+// details of that operation are hidden in the provided traits
// SkFlatDictionary: is an abstract templated dictionary that maintains a
// searchable set of SkFlatData objects of type T.
// SkFlatController: is an interface provided to SkFlatDictionary which handles
// allocation (and unallocation in some cases). It also holds
// ref count recorders and the like.
//
-// NOTE: any class that wishes to be used in conjunction with SkFlatDictionary
-// must subclass the dictionary and provide the necessary flattening procs.
-// The end of this header contains dictionary subclasses for some common classes
-// like SkBitmap, SkMatrix, SkPaint, and SkRegion. SkFlatController must also
-// be implemented, or SkChunkFlatController can be used to use an
-// SkChunkAllocator and never do replacements.
+// NOTE: any class that wishes to be used in conjunction with SkFlatDictionary must subclass the
+// dictionary and provide the necessary flattening traits. SkFlatController must also be
+// implemented, or SkChunkFlatController can be used to use an SkChunkAllocator and never do
+// replacements.
//
//
///////////////////////////////////////////////////////////////////////////////
@@ -174,7 +173,7 @@ class SkFlatController : public SkRefCnt {
public:
SK_DECLARE_INST_COUNT(SkFlatController)
- SkFlatController();
+ SkFlatController(uint32_t writeBufferFlags = 0);
virtual ~SkFlatController();
/**
* Return a new block of memory for the SkFlatDictionary to use.
@@ -248,17 +247,12 @@ protected:
*/
SkNamedFactorySet* setNamedFactorySet(SkNamedFactorySet*);
- /**
- * Set the flags to be used during flattening.
- */
- void setWriteBufferFlags(uint32_t flags) { fWriteBufferFlags = flags; }
-
private:
SkBitmapHeap* fBitmapHeap;
SkRefCntSet* fTypefaceSet;
SkTypefacePlayback* fTypefacePlayback;
SkNamedFactorySet* fFactorySet;
- uint32_t fWriteBufferFlags;
+ const uint32_t fWriteBufferFlags;
typedef SkRefCnt INHERITED;
};
@@ -266,16 +260,48 @@ private:
class SkFlatData {
public:
// Flatten obj into an SkFlatData with this index. controller owns the SkFlatData*.
- static SkFlatData* Create(SkFlatController* controller,
- const void* obj,
- int index,
- void (*flattenProc)(SkOrderedWriteBuffer&, const void*));
-
- // Unflatten this into result, using bitmapHeap and facePlayback for bitmaps and fonts if given.
- void unflatten(void* result,
- void (*unflattenProc)(SkOrderedReadBuffer&, void*),
+ template <typename Traits, typename T>
+ static SkFlatData* Create(SkFlatController* controller, const T& obj, int index) {
+ // A buffer of 256 bytes should fit most paints, regions, and matrices.
+ uint32_t storage[64];
+ SkWriteBuffer buffer(storage, sizeof(storage), controller->getWriteBufferFlags());
+
+ buffer.setBitmapHeap(controller->getBitmapHeap());
+ buffer.setTypefaceRecorder(controller->getTypefaceSet());
+ buffer.setNamedFactoryRecorder(controller->getNamedFactorySet());
+
+ Traits::Flatten(buffer, obj);
+ size_t size = buffer.bytesWritten();
+ SkASSERT(SkIsAlign4(size));
+
+ // Allocate enough memory to hold SkFlatData struct and the flat data itself.
+ size_t allocSize = sizeof(SkFlatData) + size;
+ SkFlatData* result = (SkFlatData*) controller->allocThrow(allocSize);
+
+ // Put the serialized contents into the data section of the new allocation.
+ buffer.writeToMemory(result->data());
+ // Stamp the index, size and checksum in the header.
+ result->stampHeader(index, SkToS32(size));
+ return result;
+ }
+
+ // Unflatten this into result, using bitmapHeap and facePlayback for bitmaps and fonts if given
+ template <typename Traits, typename T>
+ void unflatten(T* result,
SkBitmapHeap* bitmapHeap = NULL,
- SkTypefacePlayback* facePlayback = NULL) const;
+ SkTypefacePlayback* facePlayback = NULL) const {
+ SkReadBuffer buffer(this->data(), fFlatSize);
+
+ if (bitmapHeap) {
+ buffer.setBitmapStorage(bitmapHeap);
+ }
+ if (facePlayback) {
+ facePlayback->setupBuffer(buffer);
+ }
+
+ Traits::Unflatten(buffer, result);
+ SkASSERT(fFlatSize == (int32_t)buffer.offset());
+ }
// Do these contain the same data? Ignores index() and topBot().
bool operator==(const SkFlatData& that) const {
@@ -309,10 +335,10 @@ public:
}
private:
- // For SkTDynamicHash.
- static const SkFlatData& Identity(const SkFlatData& flat) { return flat; }
- static uint32_t Hash(const SkFlatData& flat) { return flat.checksum(); }
- static bool Equal(const SkFlatData& a, const SkFlatData& b) { return a == b; }
+ struct HashTraits {
+ static const SkFlatData& GetKey(const SkFlatData& flat) { return flat; }
+ static uint32_t Hash(const SkFlatData& flat) { return flat.checksum(); }
+ };
void setIndex(int index) { fIndex = index; }
uint8_t* data() { return (uint8_t*)this + sizeof(*this); }
@@ -332,22 +358,16 @@ private:
mutable SkScalar fTopBot[2]; // Cache of FontMetrics fTop, fBottom. Starts as [NaN,?].
// uint32_t flattenedData[] implicitly hangs off the end.
- template <class T> friend class SkFlatDictionary;
+ template <typename T, typename Traits> friend class SkFlatDictionary;
};
-template <class T>
+template <typename T, typename Traits>
class SkFlatDictionary {
- static const size_t kWriteBufferGrowthBytes = 1024;
-
public:
- SkFlatDictionary(SkFlatController* controller, size_t scratchSizeGuess = 0)
- : fFlattenProc(NULL)
- , fUnflattenProc(NULL)
- , fController(SkRef(controller))
- , fScratchSize(scratchSizeGuess)
- , fScratch(AllocScratch(fScratchSize))
- , fWriteBuffer(kWriteBufferGrowthBytes)
- , fWriteBufferReady(false) {
+ explicit SkFlatDictionary(SkFlatController* controller)
+ : fController(SkRef(controller))
+ , fScratch(controller->getWriteBufferFlags())
+ , fReady(false) {
this->reset();
}
@@ -357,25 +377,16 @@ public:
*/
void reset() {
fIndexedData.rewind();
- // TODO(mtklein): There's no reason to have the index start from 1. Clean this up.
- // index 0 is always empty since it is used as a signal that find failed
- fIndexedData.push(NULL);
- fNextIndex = 1;
- }
-
- ~SkFlatDictionary() {
- sk_free(fScratch);
}
int count() const {
- SkASSERT(fIndexedData.count() == fNextIndex);
- SkASSERT(fHash.count() == fNextIndex - 1);
- return fNextIndex - 1;
+ SkASSERT(fHash.count() == fIndexedData.count());
+ return fHash.count();
}
// For testing only. Index is zero-based.
const SkFlatData* operator[](int index) {
- return fIndexedData[index+1];
+ return fIndexedData[index];
}
/**
@@ -418,11 +429,12 @@ public:
return flat;
}
- // findAndReturnMutableFlat gave us index (fNextIndex-1), but we'll use the old one.
- fIndexedData.remove(flat->index());
- fNextIndex--;
+ // findAndReturnMutableFlat put flat at the back. Swap it into found->index() instead.
+ // indices in SkFlatData are 1-based, while fIndexedData is 0-based. Watch out!
+ SkASSERT(flat->index() == this->count());
flat->setIndex(found->index());
- fIndexedData[flat->index()] = flat;
+ fIndexedData.removeShuffle(found->index()-1);
+ SkASSERT(flat == fIndexedData[found->index()-1]);
// findAndReturnMutableFlat already called fHash.add(), so we just clean up the old entry.
fHash.remove(*found);
@@ -444,7 +456,7 @@ public:
}
SkTRefArray<T>* array = SkTRefArray<T>::Create(count);
for (int i = 0; i < count; i++) {
- this->unflatten(&array->writableAt(i), fIndexedData[i+1]);
+ this->unflatten(&array->writableAt(i), fIndexedData[i]);
}
return array;
}
@@ -454,7 +466,8 @@ public:
* Caller takes ownership of the result.
*/
T* unflatten(int index) const {
- const SkFlatData* element = fIndexedData[index];
+ // index is 1-based, while fIndexedData is 0-based.
+ const SkFlatData* element = fIndexedData[index-1];
SkASSERT(index == element->index());
T* dst = new T;
@@ -470,78 +483,54 @@ public:
return this->findAndReturnMutableFlat(element);
}
-protected:
- void (*fFlattenProc)(SkOrderedWriteBuffer&, const void*);
- void (*fUnflattenProc)(SkOrderedReadBuffer&, void*);
-
private:
- // Layout: [ SkFlatData header, 20 bytes ] [ data ..., 4-byte aligned ]
- static size_t SizeWithPadding(size_t flatDataSize) {
- SkASSERT(SkIsAlign4(flatDataSize));
- return sizeof(SkFlatData) + flatDataSize;
- }
-
- // Allocate a new scratch SkFlatData. Must be sk_freed.
- static SkFlatData* AllocScratch(size_t scratchSize) {
- return (SkFlatData*) sk_malloc_throw(SizeWithPadding(scratchSize));
- }
-
- // We have to delay fWriteBuffer's initialization until its first use; fController might not
+ // We have to delay fScratch's initialization until its first use; fController might not
// be fully set up by the time we get it in the constructor.
- void lazyWriteBufferInit() {
- if (fWriteBufferReady) {
+ void lazyInit() {
+ if (fReady) {
return;
}
+
// Without a bitmap heap, we'll flatten bitmaps into paints. That's never what you want.
SkASSERT(fController->getBitmapHeap() != NULL);
- fWriteBuffer.setBitmapHeap(fController->getBitmapHeap());
- fWriteBuffer.setTypefaceRecorder(fController->getTypefaceSet());
- fWriteBuffer.setNamedFactoryRecorder(fController->getNamedFactorySet());
- fWriteBuffer.setFlags(fController->getWriteBufferFlags());
- fWriteBufferReady = true;
+ fScratch.setBitmapHeap(fController->getBitmapHeap());
+ fScratch.setTypefaceRecorder(fController->getTypefaceSet());
+ fScratch.setNamedFactoryRecorder(fController->getNamedFactorySet());
+ fReady = true;
}
// As findAndReturnFlat, but returns a mutable pointer for internal use.
SkFlatData* findAndReturnMutableFlat(const T& element) {
// Only valid until the next call to resetScratch().
- const SkFlatData& scratch = this->resetScratch(element, fNextIndex);
+ const SkFlatData& scratch = this->resetScratch(element, this->count()+1);
SkFlatData* candidate = fHash.find(scratch);
- if (candidate != NULL) return candidate;
+ if (candidate != NULL) {
+ return candidate;
+ }
SkFlatData* detached = this->detachScratch();
fHash.add(detached);
- *fIndexedData.insert(fNextIndex) = detached;
- fNextIndex++;
+ *fIndexedData.append() = detached;
+ SkASSERT(fIndexedData.top()->index() == this->count());
return detached;
}
// This reference is valid only until the next call to resetScratch() or detachScratch().
const SkFlatData& resetScratch(const T& element, int index) {
- this->lazyWriteBufferInit();
-
- // Flatten element into fWriteBuffer (using fScratch as storage).
- fWriteBuffer.reset(fScratch->data(), fScratchSize);
- fFlattenProc(fWriteBuffer, &element);
- const size_t bytesWritten = fWriteBuffer.bytesWritten();
-
- // If all the flattened bytes fit into fScratch, we can skip a call to writeToMemory.
- if (!fWriteBuffer.wroteOnlyToStorage()) {
- SkASSERT(bytesWritten > fScratchSize);
- // It didn't all fit. Copy into a larger replacement SkFlatData.
- // We can't just realloc because it might move the pointer and confuse writeToMemory.
- SkFlatData* larger = AllocScratch(bytesWritten);
- fWriteBuffer.writeToMemory(larger->data());
-
- // Carry on with this larger scratch to minimize the likelihood of future resizing.
- sk_free(fScratch);
- fScratchSize = bytesWritten;
- fScratch = larger;
- }
+ this->lazyInit();
- // The data is in fScratch now but we need to stamp its header.
- fScratch->stampHeader(index, bytesWritten);
- return *fScratch;
+ // Layout of fScratch: [ SkFlatData header, 20 bytes ] [ data ..., 4-byte aligned ]
+ fScratch.reset();
+ fScratch.reserve(sizeof(SkFlatData));
+ Traits::Flatten(fScratch, element);
+ const size_t dataSize = fScratch.bytesWritten() - sizeof(SkFlatData);
+
+ // Reinterpret data in fScratch as an SkFlatData.
+ SkFlatData* scratch = (SkFlatData*)fScratch.getWriter32()->contiguousArray();
+ SkASSERT(scratch != NULL);
+ scratch->stampHeader(index, SkToS32(dataSize));
+ return *scratch;
}
// This result is owned by fController and lives as long as it does (unless unalloc'd).
@@ -549,54 +538,36 @@ private:
// Allocate a new SkFlatData exactly big enough to hold our current scratch.
// We use the controller for this allocation to extend the allocation's lifetime and allow
// the controller to do whatever memory management it wants.
- const size_t paddedSize = SizeWithPadding(fScratch->flatSize());
- SkFlatData* detached = (SkFlatData*)fController->allocThrow(paddedSize);
+ SkFlatData* detached = (SkFlatData*)fController->allocThrow(fScratch.bytesWritten());
// Copy scratch into the new SkFlatData.
- memcpy(detached, fScratch, paddedSize);
+ SkFlatData* scratch = (SkFlatData*)fScratch.getWriter32()->contiguousArray();
+ SkASSERT(scratch != NULL);
+ memcpy(detached, scratch, fScratch.bytesWritten());
// We can now reuse fScratch, and detached will live until fController dies.
return detached;
}
void unflatten(T* dst, const SkFlatData* element) const {
- element->unflatten(dst,
- fUnflattenProc,
- fController->getBitmapHeap(),
- fController->getTypefacePlayback());
+ element->unflatten<Traits>(dst,
+ fController->getBitmapHeap(),
+ fController->getTypefacePlayback());
}
// All SkFlatData* stored in fIndexedData and fHash are owned by the controller.
SkAutoTUnref<SkFlatController> fController;
- size_t fScratchSize; // How many bytes fScratch has allocated for data itself.
- SkFlatData* fScratch; // Owned, must be freed with sk_free.
- SkOrderedWriteBuffer fWriteBuffer;
- bool fWriteBufferReady;
-
- // We map between SkFlatData and a 1-based integer index.
- int fNextIndex;
+ SkWriteBuffer fScratch;
+ bool fReady;
- // For index -> SkFlatData. fIndexedData[0] is always NULL.
+ // For index -> SkFlatData. 0-based, while all indices in the API are 1-based. Careful!
SkTDArray<const SkFlatData*> fIndexedData;
// For SkFlatData -> cached SkFlatData, which has index().
- SkTDynamicHash<SkFlatData, SkFlatData,
- SkFlatData::Identity, SkFlatData::Hash, SkFlatData::Equal> fHash;
+ SkTDynamicHash<SkFlatData, SkFlatData, SkFlatData::HashTraits> fHash;
};
-///////////////////////////////////////////////////////////////////////////////
-// Some common dictionaries are defined here for both reference and convenience
-///////////////////////////////////////////////////////////////////////////////
-
-template <class T>
-static void SkFlattenObjectProc(SkOrderedWriteBuffer& buffer, const void* obj) {
- ((T*)obj)->flatten(buffer);
-}
-
-template <class T>
-static void SkUnflattenObjectProc(SkOrderedReadBuffer& buffer, void* obj) {
- ((T*)obj)->unflatten(buffer);
-}
+typedef SkFlatDictionary<SkPaint, SkPaint::FlatteningTraits> SkPaintDictionary;
class SkChunkFlatController : public SkFlatController {
public:
@@ -634,49 +605,4 @@ private:
mutable SkTypefacePlayback fTypefacePlayback;
};
-class SkMatrixDictionary : public SkFlatDictionary<SkMatrix> {
- public:
- // All matrices fit in 36 bytes.
- SkMatrixDictionary(SkFlatController* controller)
- : SkFlatDictionary<SkMatrix>(controller, 36) {
- fFlattenProc = &flattenMatrix;
- fUnflattenProc = &unflattenMatrix;
- }
-
- static void flattenMatrix(SkOrderedWriteBuffer& buffer, const void* obj) {
- buffer.getWriter32()->writeMatrix(*(SkMatrix*)obj);
- }
-
- static void unflattenMatrix(SkOrderedReadBuffer& buffer, void* obj) {
- buffer.getReader32()->readMatrix((SkMatrix*)obj);
- }
-};
-
-class SkPaintDictionary : public SkFlatDictionary<SkPaint> {
- public:
- // The largest paint across ~60 .skps was 500 bytes.
- SkPaintDictionary(SkFlatController* controller)
- : SkFlatDictionary<SkPaint>(controller, 512) {
- fFlattenProc = &SkFlattenObjectProc<SkPaint>;
- fUnflattenProc = &SkUnflattenObjectProc<SkPaint>;
- }
-};
-
-class SkRegionDictionary : public SkFlatDictionary<SkRegion> {
- public:
- SkRegionDictionary(SkFlatController* controller)
- : SkFlatDictionary<SkRegion>(controller) {
- fFlattenProc = &flattenRegion;
- fUnflattenProc = &unflattenRegion;
- }
-
- static void flattenRegion(SkOrderedWriteBuffer& buffer, const void* obj) {
- buffer.getWriter32()->writeRegion(*(SkRegion*)obj);
- }
-
- static void unflattenRegion(SkOrderedReadBuffer& buffer, void* obj) {
- buffer.getReader32()->readRegion((SkRegion*)obj);
- }
-};
-
#endif
diff --git a/chromium/third_party/skia/src/core/SkPicturePlayback.cpp b/chromium/third_party/skia/src/core/SkPicturePlayback.cpp
index 82c7a03bcd2..16887107fb5 100644
--- a/chromium/third_party/skia/src/core/SkPicturePlayback.cpp
+++ b/chromium/third_party/skia/src/core/SkPicturePlayback.cpp
@@ -1,19 +1,22 @@
-
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
-#include "SkPicturePlayback.h"
-#include "SkPictureRecord.h"
-#include "SkTypeface.h"
-#include "SkOrderedReadBuffer.h"
-#include "SkOrderedWriteBuffer.h"
#include <new>
#include "SkBBoxHierarchy.h"
+#include "SkPicturePlayback.h"
+#include "SkPictureRecord.h"
#include "SkPictureStateTree.h"
+#include "SkReadBuffer.h"
+#include "SkTypeface.h"
#include "SkTSort.h"
+#include "SkWriteBuffer.h"
+
+#if SK_SUPPORT_GPU
+#include "GrContext.h"
+#endif
template <typename T> int SafeCount(const T* obj) {
return obj ? obj->count() : 0;
@@ -24,11 +27,51 @@ template <typename T> int SafeCount(const T* obj) {
*/
#define SPEW_CLIP_SKIPPINGx
-SkPicturePlayback::SkPicturePlayback() {
+SkPicturePlayback::PlaybackReplacements::ReplacementInfo*
+SkPicturePlayback::PlaybackReplacements::push() {
+ SkDEBUGCODE(this->validate());
+ return fReplacements.push();
+}
+
+void SkPicturePlayback::PlaybackReplacements::freeAll() {
+ for (int i = 0; i < fReplacements.count(); ++i) {
+ SkDELETE(fReplacements[i].fBM);
+ }
+ fReplacements.reset();
+}
+
+#ifdef SK_DEBUG
+void SkPicturePlayback::PlaybackReplacements::validate() const {
+ // Check that the ranges are monotonically increasing and non-overlapping
+ if (fReplacements.count() > 0) {
+ SkASSERT(fReplacements[0].fStart < fReplacements[0].fStop);
+
+ for (int i = 1; i < fReplacements.count(); ++i) {
+ SkASSERT(fReplacements[i].fStart < fReplacements[i].fStop);
+ SkASSERT(fReplacements[i-1].fStop < fReplacements[i].fStart);
+ }
+ }
+}
+#endif
+
+SkPicturePlayback::SkPicturePlayback(const SkPictInfo& info)
+ : fInfo(info) {
this->init();
}
-SkPicturePlayback::SkPicturePlayback(const SkPictureRecord& record, bool deepCopy) {
+void SkPicturePlayback::initForPlayback() const {
+ // ensure that the paths bounds are pre-computed
+ if (NULL != fPathHeap.get()) {
+ for (int i = 0; i < fPathHeap->count(); i++) {
+ (*fPathHeap.get())[i].updateBoundsCache();
+ }
+ }
+}
+
+SkPicturePlayback::SkPicturePlayback(const SkPictureRecord& record,
+ const SkPictInfo& info,
+ bool deepCopyOps)
+ : fInfo(info) {
#ifdef SK_DEBUG_SIZE
size_t overallBytes, bitmapBytes, matricesBytes,
paintBytes, pathBytes, pictureBytes, regionBytes;
@@ -66,61 +109,39 @@ SkPicturePlayback::SkPicturePlayback(const SkPictureRecord& record, bool deepCop
record.dumpPaints();
#endif
- record.validate(record.writeStream().bytesWritten(), 0);
- const SkWriter32& writer = record.writeStream();
- init();
- if (writer.bytesWritten() == 0) {
- fOpData = SkData::NewEmpty();
- return;
- }
+ this->init();
+
+ fOpData = record.opData(deepCopyOps);
fBoundingHierarchy = record.fBoundingHierarchy;
fStateTree = record.fStateTree;
SkSafeRef(fBoundingHierarchy);
SkSafeRef(fStateTree);
+ fContentInfo.set(record.fContentInfo);
if (NULL != fBoundingHierarchy) {
fBoundingHierarchy->flushDeferredInserts();
}
- {
- size_t size = writer.bytesWritten();
- void* buffer = sk_malloc_throw(size);
- writer.flatten(buffer);
- SkASSERT(!fOpData);
- fOpData = SkData::NewFromMalloc(buffer, size);
- }
-
// copy over the refcnt dictionary to our reader
record.fFlattenableHeap.setupPlaybacks();
fBitmaps = record.fBitmapHeap->extractBitmaps();
- fMatrices = record.fMatrices.unflattenToArray();
fPaints = record.fPaints.unflattenToArray();
- fRegions = record.fRegions.unflattenToArray();
fBitmapHeap.reset(SkSafeRef(record.fBitmapHeap));
- fPathHeap.reset(SkSafeRef(record.fPathHeap));
+ fPathHeap.reset(SkSafeRef(record.pathHeap()));
- // ensure that the paths bounds are pre-computed
- if (fPathHeap.get()) {
- for (int i = 0; i < fPathHeap->count(); i++) {
- (*fPathHeap)[i].updateBoundsCache();
- }
- }
+ this->initForPlayback();
- const SkTDArray<SkPicture* >& pictures = record.getPictureRefs();
+ const SkTDArray<const SkPicture* >& pictures = record.getPictureRefs();
fPictureCount = pictures.count();
if (fPictureCount > 0) {
- fPictureRefs = SkNEW_ARRAY(SkPicture*, fPictureCount);
+ fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount);
for (int i = 0; i < fPictureCount; i++) {
- if (deepCopy) {
- fPictureRefs[i] = pictures[i]->clone();
- } else {
- fPictureRefs[i] = pictures[i];
- fPictureRefs[i]->ref();
- }
+ fPictureRefs[i] = pictures[i];
+ fPictureRefs[i]->ref();
}
}
@@ -146,96 +167,39 @@ SkPicturePlayback::SkPicturePlayback(const SkPictureRecord& record, bool deepCop
#endif
}
-static bool needs_deep_copy(const SkPaint& paint) {
- /*
- * These fields are known to be immutable, and so can be shallow-copied
- *
- * getTypeface()
- * getAnnotation()
- * paint.getColorFilter()
- * getXfermode()
- */
-
- return paint.getPathEffect() ||
- paint.getShader() ||
- paint.getMaskFilter() ||
- paint.getRasterizer() ||
- paint.getLooper() ||
- paint.getImageFilter();
-}
-
-SkPicturePlayback::SkPicturePlayback(const SkPicturePlayback& src, SkPictCopyInfo* deepCopyInfo) {
+SkPicturePlayback::SkPicturePlayback(const SkPicturePlayback& src, SkPictCopyInfo* deepCopyInfo)
+ : fInfo(src.fInfo) {
this->init();
fBitmapHeap.reset(SkSafeRef(src.fBitmapHeap.get()));
fPathHeap.reset(SkSafeRef(src.fPathHeap.get()));
- fMatrices = SkSafeRef(src.fMatrices);
- fRegions = SkSafeRef(src.fRegions);
fOpData = SkSafeRef(src.fOpData);
fBoundingHierarchy = src.fBoundingHierarchy;
fStateTree = src.fStateTree;
+ fContentInfo.set(src.fContentInfo);
SkSafeRef(fBoundingHierarchy);
SkSafeRef(fStateTree);
if (deepCopyInfo) {
+ SkASSERT(deepCopyInfo->initialized);
+
int paintCount = SafeCount(src.fPaints);
if (src.fBitmaps) {
fBitmaps = SkTRefArray<SkBitmap>::Create(src.fBitmaps->begin(), src.fBitmaps->count());
}
- if (!deepCopyInfo->initialized) {
- /* The alternative to doing this is to have a clone method on the paint and have it make
- * the deep copy of its internal structures as needed. The holdup to doing that is at
- * this point we would need to pass the SkBitmapHeap so that we don't unnecessarily
- * flatten the pixels in a bitmap shader.
- */
- deepCopyInfo->paintData.setCount(paintCount);
-
- /* Use an SkBitmapHeap to avoid flattening bitmaps in shaders. If there already is one,
- * use it. If this SkPicturePlayback was created from a stream, fBitmapHeap will be
- * NULL, so create a new one.
- */
- if (fBitmapHeap.get() == NULL) {
- // FIXME: Put this on the stack inside SkPicture::clone. Further, is it possible to
- // do the rest of this initialization in SkPicture::clone as well?
- SkBitmapHeap* heap = SkNEW(SkBitmapHeap);
- deepCopyInfo->controller.setBitmapStorage(heap);
- heap->unref();
- } else {
- deepCopyInfo->controller.setBitmapStorage(fBitmapHeap);
- }
-
- SkDEBUGCODE(int heapSize = SafeCount(fBitmapHeap.get());)
- for (int i = 0; i < paintCount; i++) {
- if (needs_deep_copy(src.fPaints->at(i))) {
- deepCopyInfo->paintData[i] = SkFlatData::Create(&deepCopyInfo->controller,
- &src.fPaints->at(i), 0,
- &SkFlattenObjectProc<SkPaint>);
- } else {
- // this is our sentinel, which we use in the unflatten loop
- deepCopyInfo->paintData[i] = NULL;
- }
- }
- SkASSERT(SafeCount(fBitmapHeap.get()) == heapSize);
-
- // needed to create typeface playback
- deepCopyInfo->controller.setupPlaybacks();
- deepCopyInfo->initialized = true;
- }
-
fPaints = SkTRefArray<SkPaint>::Create(paintCount);
SkASSERT(deepCopyInfo->paintData.count() == paintCount);
SkBitmapHeap* bmHeap = deepCopyInfo->controller.getBitmapHeap();
SkTypefacePlayback* tfPlayback = deepCopyInfo->controller.getTypefacePlayback();
for (int i = 0; i < paintCount; i++) {
if (deepCopyInfo->paintData[i]) {
- deepCopyInfo->paintData[i]->unflatten(&fPaints->writableAt(i),
- &SkUnflattenObjectProc<SkPaint>,
- bmHeap, tfPlayback);
+ deepCopyInfo->paintData[i]->unflatten<SkPaint::FlatteningTraits>(
+ &fPaints->writableAt(i), bmHeap, tfPlayback);
} else {
// needs_deep_copy was false, so just need to assign
fPaints->writableAt(i) = src.fPaints->at(i);
@@ -248,7 +212,7 @@ SkPicturePlayback::SkPicturePlayback(const SkPicturePlayback& src, SkPictCopyInf
}
fPictureCount = src.fPictureCount;
- fPictureRefs = SkNEW_ARRAY(SkPicture*, fPictureCount);
+ fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount);
for (int i = 0; i < fPictureCount; i++) {
if (deepCopyInfo) {
fPictureRefs[i] = src.fPictureRefs[i]->clone();
@@ -261,27 +225,31 @@ SkPicturePlayback::SkPicturePlayback(const SkPicturePlayback& src, SkPictCopyInf
void SkPicturePlayback::init() {
fBitmaps = NULL;
- fMatrices = NULL;
fPaints = NULL;
fPictureRefs = NULL;
- fRegions = NULL;
fPictureCount = 0;
fOpData = NULL;
fFactoryPlayback = NULL;
fBoundingHierarchy = NULL;
fStateTree = NULL;
+ fCachedActiveOps = NULL;
+ fCurOffset = 0;
+ fUseBBH = true;
+ fStart = 0;
+ fStop = 0;
+ fReplacements = NULL;
}
SkPicturePlayback::~SkPicturePlayback() {
- fOpData->unref();
+ SkSafeUnref(fOpData);
SkSafeUnref(fBitmaps);
- SkSafeUnref(fMatrices);
SkSafeUnref(fPaints);
- SkSafeUnref(fRegions);
SkSafeUnref(fBoundingHierarchy);
SkSafeUnref(fStateTree);
+ SkDELETE(fCachedActiveOps);
+
for (int i = 0; i < fPictureCount; i++) {
fPictureRefs[i]->unref();
}
@@ -291,13 +259,12 @@ SkPicturePlayback::~SkPicturePlayback() {
}
void SkPicturePlayback::dumpSize() const {
- SkDebugf("--- picture size: ops=%d bitmaps=%d [%d] matrices=%d [%d] paints=%d [%d] paths=%d regions=%d\n",
+ SkDebugf("--- picture size: ops=%d bitmaps=%d [%d] paints=%d [%d]\n",
fOpData->size(),
SafeCount(fBitmaps), SafeCount(fBitmaps) * sizeof(SkBitmap),
- SafeCount(fMatrices), SafeCount(fMatrices) * sizeof(SkMatrix),
- SafeCount(fPaints), SafeCount(fPaints) * sizeof(SkPaint),
- SafeCount(fPathHeap.get()),
- SafeCount(fRegions));
+ SafeCount(fPaints), SafeCount(fPaints) * sizeof(SkPaint));
+ SkDebugf("--- picture size: paths=%d\n",
+ SafeCount(fPathHeap.get()));
}
bool SkPicturePlayback::containsBitmaps() const {
@@ -315,63 +282,58 @@ bool SkPicturePlayback::containsBitmaps() const {
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
-#define PICT_READER_TAG SkSetFourByteTag('r', 'e', 'a', 'd')
-#define PICT_FACTORY_TAG SkSetFourByteTag('f', 'a', 'c', 't')
-#define PICT_TYPEFACE_TAG SkSetFourByteTag('t', 'p', 'f', 'c')
-#define PICT_PICTURE_TAG SkSetFourByteTag('p', 'c', 't', 'r')
-
-// This tag specifies the size of the ReadBuffer, needed for the following tags
-#define PICT_BUFFER_SIZE_TAG SkSetFourByteTag('a', 'r', 'a', 'y')
-// these are all inside the ARRAYS tag
-#define PICT_BITMAP_BUFFER_TAG SkSetFourByteTag('b', 't', 'm', 'p')
-#define PICT_MATRIX_BUFFER_TAG SkSetFourByteTag('m', 't', 'r', 'x')
-#define PICT_PAINT_BUFFER_TAG SkSetFourByteTag('p', 'n', 't', ' ')
-#define PICT_PATH_BUFFER_TAG SkSetFourByteTag('p', 't', 'h', ' ')
-#define PICT_REGION_BUFFER_TAG SkSetFourByteTag('r', 'g', 'n', ' ')
-
-// Always write this guy last (with no length field afterwards)
-#define PICT_EOF_TAG SkSetFourByteTag('e', 'o', 'f', ' ')
-
#include "SkStream.h"
-static void writeTagSize(SkOrderedWriteBuffer& buffer, uint32_t tag,
- uint32_t size) {
- buffer.writeUInt(tag);
- buffer.writeUInt(size);
-}
+static size_t compute_chunk_size(SkFlattenable::Factory* array, int count) {
+ size_t size = 4; // for 'count'
+
+ for (int i = 0; i < count; i++) {
+ const char* name = SkFlattenable::FactoryToName(array[i]);
+ if (NULL == name || 0 == *name) {
+ size += SkWStream::SizeOfPackedUInt(0);
+ } else {
+ size_t len = strlen(name);
+ size += SkWStream::SizeOfPackedUInt(len);
+ size += len;
+ }
+ }
-static void writeTagSize(SkWStream* stream, uint32_t tag,
- uint32_t size) {
- stream->write32(tag);
- stream->write32(size);
+ return size;
}
-static void writeFactories(SkWStream* stream, const SkFactorySet& rec) {
+void SkPicturePlayback::WriteFactories(SkWStream* stream, const SkFactorySet& rec) {
int count = rec.count();
- writeTagSize(stream, PICT_FACTORY_TAG, count);
-
SkAutoSTMalloc<16, SkFlattenable::Factory> storage(count);
SkFlattenable::Factory* array = (SkFlattenable::Factory*)storage.get();
rec.copyToArray(array);
+ size_t size = compute_chunk_size(array, count);
+
+ // TODO: write_tag_size should really take a size_t
+ SkPicture::WriteTagSize(stream, SK_PICT_FACTORY_TAG, (uint32_t) size);
+ SkDEBUGCODE(size_t start = stream->bytesWritten());
+ stream->write32(count);
+
for (int i = 0; i < count; i++) {
const char* name = SkFlattenable::FactoryToName(array[i]);
// SkDebugf("---- write factories [%d] %p <%s>\n", i, array[i], name);
if (NULL == name || 0 == *name) {
stream->writePackedUInt(0);
} else {
- uint32_t len = strlen(name);
+ size_t len = strlen(name);
stream->writePackedUInt(len);
stream->write(name, len);
}
}
+
+ SkASSERT(size == (stream->bytesWritten() - start));
}
-static void writeTypefaces(SkWStream* stream, const SkRefCntSet& rec) {
+void SkPicturePlayback::WriteTypefaces(SkWStream* stream, const SkRefCntSet& rec) {
int count = rec.count();
- writeTagSize(stream, PICT_TYPEFACE_TAG, count);
+ SkPicture::WriteTagSize(stream, SK_PICT_TYPEFACE_TAG, count);
SkAutoSTMalloc<16, SkTypeface*> storage(count);
SkTypeface** array = (SkTypeface**)storage.get();
@@ -382,51 +344,36 @@ static void writeTypefaces(SkWStream* stream, const SkRefCntSet& rec) {
}
}
-void SkPicturePlayback::flattenToBuffer(SkOrderedWriteBuffer& buffer) const {
+void SkPicturePlayback::flattenToBuffer(SkWriteBuffer& buffer) const {
int i, n;
if ((n = SafeCount(fBitmaps)) > 0) {
- writeTagSize(buffer, PICT_BITMAP_BUFFER_TAG, n);
+ SkPicture::WriteTagSize(buffer, SK_PICT_BITMAP_BUFFER_TAG, n);
for (i = 0; i < n; i++) {
buffer.writeBitmap((*fBitmaps)[i]);
}
}
- if ((n = SafeCount(fMatrices)) > 0) {
- writeTagSize(buffer, PICT_MATRIX_BUFFER_TAG, n);
- for (i = 0; i < n; i++) {
- buffer.writeMatrix((*fMatrices)[i]);
- }
-
- }
-
if ((n = SafeCount(fPaints)) > 0) {
- writeTagSize(buffer, PICT_PAINT_BUFFER_TAG, n);
+ SkPicture::WriteTagSize(buffer, SK_PICT_PAINT_BUFFER_TAG, n);
for (i = 0; i < n; i++) {
buffer.writePaint((*fPaints)[i]);
}
}
if ((n = SafeCount(fPathHeap.get())) > 0) {
- writeTagSize(buffer, PICT_PATH_BUFFER_TAG, n);
+ SkPicture::WriteTagSize(buffer, SK_PICT_PATH_BUFFER_TAG, n);
fPathHeap->flatten(buffer);
}
-
- if ((n = SafeCount(fRegions)) > 0) {
- writeTagSize(buffer, PICT_REGION_BUFFER_TAG, n);
- for (i = 0; i < n; i++) {
- buffer.writeRegion((*fRegions)[i]);
- }
- }
}
void SkPicturePlayback::serialize(SkWStream* stream,
SkPicture::EncodeBitmap encoder) const {
- writeTagSize(stream, PICT_READER_TAG, fOpData->size());
+ SkPicture::WriteTagSize(stream, SK_PICT_READER_TAG, fOpData->size());
stream->write(fOpData->bytes(), fOpData->size());
if (fPictureCount > 0) {
- writeTagSize(stream, PICT_PICTURE_TAG, fPictureCount);
+ SkPicture::WriteTagSize(stream, SK_PICT_PICTURE_TAG, fPictureCount);
for (int i = 0; i < fPictureCount; i++) {
fPictureRefs[i]->serialize(stream, encoder);
}
@@ -438,32 +385,46 @@ void SkPicturePlayback::serialize(SkWStream* stream,
SkRefCntSet typefaceSet;
SkFactorySet factSet;
- SkOrderedWriteBuffer buffer(1024);
-
- buffer.setFlags(SkFlattenableWriteBuffer::kCrossProcess_Flag);
+ SkWriteBuffer buffer(SkWriteBuffer::kCrossProcess_Flag);
buffer.setTypefaceRecorder(&typefaceSet);
buffer.setFactoryRecorder(&factSet);
buffer.setBitmapEncoder(encoder);
this->flattenToBuffer(buffer);
- // We have to write these to sets into the stream *before* we write
+ // We have to write these two sets into the stream *before* we write
// the buffer, since parsing that buffer will require that we already
// have these sets available to use.
- writeFactories(stream, factSet);
- writeTypefaces(stream, typefaceSet);
+ WriteFactories(stream, factSet);
+ WriteTypefaces(stream, typefaceSet);
- writeTagSize(stream, PICT_BUFFER_SIZE_TAG, buffer.size());
+ SkPicture::WriteTagSize(stream, SK_PICT_BUFFER_SIZE_TAG, buffer.bytesWritten());
buffer.writeToStream(stream);
}
- stream->write32(PICT_EOF_TAG);
+ stream->write32(SK_PICT_EOF_TAG);
+}
+
+void SkPicturePlayback::flatten(SkWriteBuffer& buffer) const {
+ SkPicture::WriteTagSize(buffer, SK_PICT_READER_TAG, fOpData->size());
+ buffer.writeByteArray(fOpData->bytes(), fOpData->size());
+
+ if (fPictureCount > 0) {
+ SkPicture::WriteTagSize(buffer, SK_PICT_PICTURE_TAG, fPictureCount);
+ for (int i = 0; i < fPictureCount; i++) {
+ fPictureRefs[i]->flatten(buffer);
+ }
+ }
+
+ // Write this picture playback's data into a writebuffer
+ this->flattenToBuffer(buffer);
+ buffer.write32(SK_PICT_EOF_TAG);
}
///////////////////////////////////////////////////////////////////////////////
/**
- * Return the corresponding SkFlattenableReadBuffer flags, given a set of
+ * Return the corresponding SkReadBuffer flags, given a set of
* SkPictInfo flags.
*/
static uint32_t pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags) {
@@ -471,9 +432,9 @@ static uint32_t pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags) {
uint32_t fSrc;
uint32_t fDst;
} gSD[] = {
- { SkPictInfo::kCrossProcess_Flag, SkFlattenableReadBuffer::kCrossProcess_Flag },
- { SkPictInfo::kScalarIsFloat_Flag, SkFlattenableReadBuffer::kScalarIsFloat_Flag },
- { SkPictInfo::kPtrIs64Bit_Flag, SkFlattenableReadBuffer::kPtrIs64Bit_Flag },
+ { SkPictInfo::kCrossProcess_Flag, SkReadBuffer::kCrossProcess_Flag },
+ { SkPictInfo::kScalarIsFloat_Flag, SkReadBuffer::kScalarIsFloat_Flag },
+ { SkPictInfo::kPtrIs64Bit_Flag, SkReadBuffer::kPtrIs64Bit_Flag },
};
uint32_t rbMask = 0;
@@ -485,8 +446,10 @@ static uint32_t pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags) {
return rbMask;
}
-bool SkPicturePlayback::parseStreamTag(SkStream* stream, const SkPictInfo& info, uint32_t tag,
- size_t size, SkPicture::InstallPixelRefProc proc) {
+bool SkPicturePlayback::parseStreamTag(SkStream* stream,
+ uint32_t tag,
+ uint32_t size,
+ SkPicture::InstallPixelRefProc proc) {
/*
* By the time we encounter BUFFER_SIZE_TAG, we need to have already seen
* its dependents: FACTORY_TAG and TYPEFACE_TAG. These two are not required
@@ -499,7 +462,7 @@ bool SkPicturePlayback::parseStreamTag(SkStream* stream, const SkPictInfo& info,
SkDEBUGCODE(bool haveBuffer = false;)
switch (tag) {
- case PICT_READER_TAG: {
+ case SK_PICT_READER_TAG: {
SkAutoMalloc storage(size);
if (stream->read(storage.get(), size) != size) {
return false;
@@ -507,8 +470,19 @@ bool SkPicturePlayback::parseStreamTag(SkStream* stream, const SkPictInfo& info,
SkASSERT(NULL == fOpData);
fOpData = SkData::NewFromMalloc(storage.detach(), size);
} break;
- case PICT_FACTORY_TAG: {
+ case SK_PICT_FACTORY_TAG: {
SkASSERT(!haveBuffer);
+ // Remove this code when v21 and below are no longer supported. At the
+ // same time add a new 'count' variable and use it rather then reusing 'size'.
+#ifndef DISABLE_V21_COMPATIBILITY_CODE
+ if (fInfo.fVersion >= 22) {
+ // in v22 this tag's size represents the size of the chunk in bytes
+ // and the number of factory strings is written out separately
+#endif
+ size = stream->readU32();
+#ifndef DISABLE_V21_COMPATIBILITY_CODE
+ }
+#endif
fFactoryPlayback = SkNEW_ARGS(SkFactoryPlayback, (size));
for (size_t i = 0; i < size; i++) {
SkString str;
@@ -520,10 +494,11 @@ bool SkPicturePlayback::parseStreamTag(SkStream* stream, const SkPictInfo& info,
fFactoryPlayback->base()[i] = SkFlattenable::NameToFactory(str.c_str());
}
} break;
- case PICT_TYPEFACE_TAG: {
+ case SK_PICT_TYPEFACE_TAG: {
SkASSERT(!haveBuffer);
- fTFPlayback.setCount(size);
- for (size_t i = 0; i < size; i++) {
+ const int count = SkToInt(size);
+ fTFPlayback.setCount(count);
+ for (int i = 0; i < count; i++) {
SkAutoTUnref<SkTypeface> tf(SkTypeface::Deserialize(stream));
if (!tf.get()) { // failed to deserialize
// fTFPlayback asserts it never has a null, so we plop in
@@ -533,9 +508,9 @@ bool SkPicturePlayback::parseStreamTag(SkStream* stream, const SkPictInfo& info,
fTFPlayback.set(i, tf);
}
} break;
- case PICT_PICTURE_TAG: {
+ case SK_PICT_PICTURE_TAG: {
fPictureCount = size;
- fPictureRefs = SkNEW_ARRAY(SkPicture*, fPictureCount);
+ fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount);
bool success = true;
int i = 0;
for ( ; i < fPictureCount; i++) {
@@ -556,14 +531,15 @@ bool SkPicturePlayback::parseStreamTag(SkStream* stream, const SkPictInfo& info,
return false;
}
} break;
- case PICT_BUFFER_SIZE_TAG: {
+ case SK_PICT_BUFFER_SIZE_TAG: {
SkAutoMalloc storage(size);
if (stream->read(storage.get(), size) != size) {
return false;
}
- SkOrderedReadBuffer buffer(storage.get(), size);
- buffer.setFlags(pictInfoFlagsToReadBufferFlags(info.fFlags));
+ SkReadBuffer buffer(storage.get(), size);
+ buffer.setFlags(pictInfoFlagsToReadBufferFlags(fInfo.fFlags));
+ buffer.setVersion(fInfo.fVersion);
fFactoryPlayback->setupBuffer(buffer);
fTFPlayback.setupBuffer(buffer);
@@ -582,38 +558,63 @@ bool SkPicturePlayback::parseStreamTag(SkStream* stream, const SkPictInfo& info,
return true; // success
}
-bool SkPicturePlayback::parseBufferTag(SkOrderedReadBuffer& buffer,
- uint32_t tag, size_t size) {
+bool SkPicturePlayback::parseBufferTag(SkReadBuffer& buffer,
+ uint32_t tag, uint32_t size) {
switch (tag) {
- case PICT_BITMAP_BUFFER_TAG: {
+ case SK_PICT_BITMAP_BUFFER_TAG: {
+ const int count = SkToInt(size);
fBitmaps = SkTRefArray<SkBitmap>::Create(size);
- for (size_t i = 0; i < size; ++i) {
+ for (int i = 0; i < count; ++i) {
SkBitmap* bm = &fBitmaps->writableAt(i);
buffer.readBitmap(bm);
bm->setImmutable();
}
} break;
- case PICT_MATRIX_BUFFER_TAG:
- fMatrices = SkTRefArray<SkMatrix>::Create(size);
- for (size_t i = 0; i < size; ++i) {
- buffer.readMatrix(&fMatrices->writableAt(i));
- }
- break;
- case PICT_PAINT_BUFFER_TAG: {
+ case SK_PICT_PAINT_BUFFER_TAG: {
+ const int count = SkToInt(size);
fPaints = SkTRefArray<SkPaint>::Create(size);
- for (size_t i = 0; i < size; ++i) {
+ for (int i = 0; i < count; ++i) {
buffer.readPaint(&fPaints->writableAt(i));
}
} break;
- case PICT_PATH_BUFFER_TAG:
+ case SK_PICT_PATH_BUFFER_TAG:
if (size > 0) {
fPathHeap.reset(SkNEW_ARGS(SkPathHeap, (buffer)));
}
break;
- case PICT_REGION_BUFFER_TAG: {
- fRegions = SkTRefArray<SkRegion>::Create(size);
- for (size_t i = 0; i < size; ++i) {
- buffer.readRegion(&fRegions->writableAt(i));
+ case SK_PICT_READER_TAG: {
+ SkAutoMalloc storage(size);
+ if (!buffer.readByteArray(storage.get(), size) ||
+ !buffer.validate(NULL == fOpData)) {
+ return false;
+ }
+ SkASSERT(NULL == fOpData);
+ fOpData = SkData::NewFromMalloc(storage.detach(), size);
+ } break;
+ case SK_PICT_PICTURE_TAG: {
+ if (!buffer.validate((0 == fPictureCount) && (NULL == fPictureRefs))) {
+ return false;
+ }
+ fPictureCount = size;
+ fPictureRefs = SkNEW_ARRAY(const SkPicture*, fPictureCount);
+ bool success = true;
+ int i = 0;
+ for ( ; i < fPictureCount; i++) {
+ fPictureRefs[i] = SkPicture::CreateFromBuffer(buffer);
+ if (NULL == fPictureRefs[i]) {
+ success = false;
+ break;
+ }
+ }
+ if (!success) {
+ // Delete all of the pictures that were already created (up to but excluding i):
+ for (int j = 0; j < i; j++) {
+ fPictureRefs[j]->unref();
+ }
+ // Delete the array
+ SkDELETE_ARRAY(fPictureRefs);
+ fPictureCount = 0;
+ return false;
}
} break;
default:
@@ -626,24 +627,50 @@ bool SkPicturePlayback::parseBufferTag(SkOrderedReadBuffer& buffer,
SkPicturePlayback* SkPicturePlayback::CreateFromStream(SkStream* stream,
const SkPictInfo& info,
SkPicture::InstallPixelRefProc proc) {
- SkAutoTDelete<SkPicturePlayback> playback(SkNEW(SkPicturePlayback));
+ SkAutoTDelete<SkPicturePlayback> playback(SkNEW_ARGS(SkPicturePlayback, (info)));
- if (!playback->parseStream(stream, info, proc)) {
+ if (!playback->parseStream(stream, proc)) {
return NULL;
}
return playback.detach();
}
-bool SkPicturePlayback::parseStream(SkStream* stream, const SkPictInfo& info,
+SkPicturePlayback* SkPicturePlayback::CreateFromBuffer(SkReadBuffer& buffer,
+ const SkPictInfo& info) {
+ SkAutoTDelete<SkPicturePlayback> playback(SkNEW_ARGS(SkPicturePlayback, (info)));
+ buffer.setVersion(info.fVersion);
+
+ if (!playback->parseBuffer(buffer)) {
+ return NULL;
+ }
+ return playback.detach();
+}
+
+bool SkPicturePlayback::parseStream(SkStream* stream,
SkPicture::InstallPixelRefProc proc) {
for (;;) {
uint32_t tag = stream->readU32();
- if (PICT_EOF_TAG == tag) {
+ if (SK_PICT_EOF_TAG == tag) {
break;
}
uint32_t size = stream->readU32();
- if (!this->parseStreamTag(stream, info, tag, size, proc)) {
+ if (!this->parseStreamTag(stream, tag, size, proc)) {
+ return false; // we're invalid
+ }
+ }
+ return true;
+}
+
+bool SkPicturePlayback::parseBuffer(SkReadBuffer& buffer) {
+ for (;;) {
+ uint32_t tag = buffer.readUInt();
+ if (SK_PICT_EOF_TAG == tag) {
+ break;
+ }
+
+ uint32_t size = buffer.readUInt();
+ if (!this->parseBufferTag(buffer, tag, size)) {
return false; // we're invalid
}
}
@@ -702,13 +729,81 @@ static DrawType read_op_and_size(SkReader32* reader, uint32_t* size) {
return (DrawType) op;
}
+uint32_t SkPicturePlayback::CachedOperationList::offset(int index) const {
+ SkASSERT(index < fOps.count());
+ return ((SkPictureStateTree::Draw*)fOps[index])->fOffset;
+}
+
+const SkMatrix& SkPicturePlayback::CachedOperationList::matrix(int index) const {
+ SkASSERT(index < fOps.count());
+ return *((SkPictureStateTree::Draw*)fOps[index])->fMatrix;
+}
+
+const SkPicture::OperationList& SkPicturePlayback::getActiveOps(const SkIRect& query) {
+ if (NULL == fStateTree || NULL == fBoundingHierarchy) {
+ return SkPicture::OperationList::InvalidList();
+ }
+
+ if (NULL == fCachedActiveOps) {
+ fCachedActiveOps = SkNEW(CachedOperationList);
+ }
+
+ if (query == fCachedActiveOps->fCacheQueryRect) {
+ return *fCachedActiveOps;
+ }
+
+ fCachedActiveOps->fOps.rewind();
+
+ fBoundingHierarchy->search(query, &(fCachedActiveOps->fOps));
+ if (0 != fCachedActiveOps->fOps.count()) {
+ SkTQSort<SkPictureStateTree::Draw>(
+ reinterpret_cast<SkPictureStateTree::Draw**>(fCachedActiveOps->fOps.begin()),
+ reinterpret_cast<SkPictureStateTree::Draw**>(fCachedActiveOps->fOps.end()-1));
+ }
+
+ fCachedActiveOps->fCacheQueryRect = query;
+ return *fCachedActiveOps;
+}
+
+class SkAutoResetOpID {
+public:
+ SkAutoResetOpID(SkPicturePlayback* playback) : fPlayback(playback) { }
+ ~SkAutoResetOpID() {
+ if (NULL != fPlayback) {
+ fPlayback->resetOpID();
+ }
+ }
+
+private:
+ SkPicturePlayback* fPlayback;
+};
+
+// TODO: Replace with hash or pass in "lastLookedUp" hint
+SkPicturePlayback::PlaybackReplacements::ReplacementInfo*
+SkPicturePlayback::PlaybackReplacements::lookupByStart(size_t start) {
+ SkDEBUGCODE(this->validate());
+ for (int i = 0; i < fReplacements.count(); ++i) {
+ if (start == fReplacements[i].fStart) {
+ return &fReplacements[i];
+ } else if (start < fReplacements[i].fStart) {
+ return NULL; // the ranges are monotonically increasing and non-overlapping
+ }
+ }
+
+ return NULL;
+}
+
void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback) {
+ SkAutoResetOpID aroi(this);
+ SkASSERT(0 == fCurOffset);
+
#ifdef ENABLE_TIME_DRAW
SkAutoTime at("SkPicture::draw", 50);
#endif
#ifdef SPEW_CLIP_SKIPPING
- SkipClipRec skipRect, skipRRect, skipRegion, skipPath;
+ SkipClipRec skipRect, skipRRect, skipRegion, skipPath, skipCull;
+ int opCount = 0;
#endif
#ifdef SK_BUILD_FOR_ANDROID
@@ -721,29 +816,44 @@ void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback)
SkReader32 reader(fOpData->bytes(), fOpData->size());
TextContainer text;
- SkTDArray<void*> results;
-
- if (NULL != fStateTree && NULL != fBoundingHierarchy) {
- SkRect clipBounds;
- if (canvas.getClipBounds(&clipBounds)) {
- SkIRect query;
- clipBounds.roundOut(&query);
- fBoundingHierarchy->search(query, &results);
- if (results.count() == 0) {
- return;
+ const SkTDArray<void*>* activeOps = NULL;
+
+ // When draw limits are enabled (i.e., 0 != fStart || 0 != fStop) the state
+ // tree isn't used to pick and choose the draw operations
+ if (0 == fStart && 0 == fStop) {
+ if (fUseBBH && NULL != fStateTree && NULL != fBoundingHierarchy) {
+ SkRect clipBounds;
+ if (canvas.getClipBounds(&clipBounds)) {
+ SkIRect query;
+ clipBounds.roundOut(&query);
+
+ const SkPicture::OperationList& activeOpsList = this->getActiveOps(query);
+ if (activeOpsList.valid()) {
+ if (0 == activeOpsList.numOps()) {
+ return; // nothing to draw
+ }
+
+ // Since the opList is valid we know it is our derived class
+ activeOps = &((const CachedOperationList&)activeOpsList).fOps;
+ }
}
- SkTQSort<SkPictureStateTree::Draw>(
- reinterpret_cast<SkPictureStateTree::Draw**>(results.begin()),
- reinterpret_cast<SkPictureStateTree::Draw**>(results.end()-1));
}
}
- SkPictureStateTree::Iterator it = (NULL == fStateTree) ?
+ SkPictureStateTree::Iterator it = (NULL == activeOps) ?
SkPictureStateTree::Iterator() :
- fStateTree->getIterator(results, &canvas);
+ fStateTree->getIterator(*activeOps, &canvas);
+
+ if (0 != fStart || 0 != fStop) {
+ reader.setOffset(fStart);
+ uint32_t size;
+ SkDEBUGCODE(DrawType op =) read_op_and_size(&reader, &size);
+ SkASSERT(SAVE_LAYER == op);
+ reader.setOffset(fStart+size);
+ }
if (it.isValid()) {
- uint32_t skipTo = it.draw();
+ uint32_t skipTo = it.nextDraw();
if (kDrawComplete == skipTo) {
return;
}
@@ -752,7 +862,8 @@ void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback)
// Record this, so we can concat w/ it if we encounter a setMatrix()
SkMatrix initialMatrix = canvas.getTotalMatrix();
- int originalSaveCount = canvas.getSaveCount();
+
+ SkAutoCanvasRestore acr(&canvas, false);
#ifdef SK_BUILD_FOR_ANDROID
fAbortCurrentPlayback = false;
@@ -764,7 +875,6 @@ void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback)
while (!reader.eof()) {
if (callback && callback->abortDrawing()) {
- canvas.restoreToCount(originalSaveCount);
return;
}
#ifdef SK_BUILD_FOR_ANDROID
@@ -772,19 +882,92 @@ void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback)
return;
}
#endif
+ if (0 != fStart || 0 != fStop) {
+ size_t offset = reader.offset() ;
+ if (offset >= fStop) {
+ uint32_t size;
+ SkDEBUGCODE(DrawType op =) read_op_and_size(&reader, &size);
+ SkASSERT(RESTORE == op);
+ return;
+ }
+ }
- size_t curOffset = reader.offset();
+ if (NULL != fReplacements) {
+ // Potentially replace a block of operations with a single drawBitmap call
+ SkPicturePlayback::PlaybackReplacements::ReplacementInfo* temp =
+ fReplacements->lookupByStart(reader.offset());
+ if (NULL != temp) {
+ SkASSERT(NULL != temp->fBM);
+ SkASSERT(NULL != temp->fPaint);
+ canvas.save();
+ canvas.setMatrix(initialMatrix);
+ canvas.drawBitmap(*temp->fBM, temp->fPos.fX, temp->fPos.fY, temp->fPaint);
+ canvas.restore();
+
+ if (it.isValid()) {
+ // This save is needed since the BBH will automatically issue
+ // a restore to balanced the saveLayer we're skipping
+ canvas.save();
+
+ // At this point we know that the PictureStateTree was aiming
+ // for some draw op within temp's saveLayer (although potentially
+ // in a separate saveLayer nested inside it).
+ // We need to skip all the operations inside temp's range
+ // along with all the associated state changes but update
+ // the state tree to the first operation outside temp's range.
+
+ uint32_t skipTo;
+ do {
+ skipTo = it.nextDraw();
+ if (kDrawComplete == skipTo) {
+ break;
+ }
+
+ if (skipTo <= temp->fStop) {
+ reader.setOffset(skipTo);
+ uint32_t size;
+ DrawType op = read_op_and_size(&reader, &size);
+ // Since we are relying on the normal SkPictureStateTree
+ // playback we need to convert any nested saveLayer calls
+ // it may issue into saves (so that all its internal
+ // restores will be balanced).
+ if (SAVE_LAYER == op) {
+ canvas.save();
+ }
+ }
+ } while (skipTo <= temp->fStop);
+
+ if (kDrawComplete == skipTo) {
+ break;
+ }
+
+ reader.setOffset(skipTo);
+ } else {
+ reader.setOffset(temp->fStop);
+ uint32_t size;
+ SkDEBUGCODE(DrawType op =) read_op_and_size(&reader, &size);
+ SkASSERT(RESTORE == op);
+ }
+ continue;
+ }
+ }
+
+#ifdef SPEW_CLIP_SKIPPING
+ opCount++;
+#endif
+
+ fCurOffset = reader.offset();
uint32_t size;
DrawType op = read_op_and_size(&reader, &size);
size_t skipTo = 0;
if (NOOP == op) {
// NOOPs are to be ignored - do not propagate them any further
- skipTo = curOffset + size;
+ skipTo = fCurOffset + size;
#ifdef SK_DEVELOPER
} else {
opIndex++;
if (this->preDraw(opIndex, op)) {
- skipTo = curOffset + size;
+ skipTo = fCurOffset + size;
}
#endif
}
@@ -795,7 +978,7 @@ void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback)
// iterator until at or after skipTo
uint32_t adjustedSkipTo;
do {
- adjustedSkipTo = it.draw();
+ adjustedSkipTo = it.nextDraw();
} while (adjustedSkipTo < skipTo);
skipTo = adjustedSkipTo;
}
@@ -815,7 +998,8 @@ void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback)
size_t offsetToRestore = reader.readInt();
SkASSERT(!offsetToRestore || \
offsetToRestore >= reader.offset());
- if (!canvas.clipPath(path, regionOp, doAA) && offsetToRestore) {
+ canvas.clipPath(path, regionOp, doAA);
+ if (canvas.isClipEmpty() && offsetToRestore) {
#ifdef SPEW_CLIP_SKIPPING
skipPath.recordSkip(offsetToRestore - reader.offset());
#endif
@@ -823,13 +1007,15 @@ void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback)
}
} break;
case CLIP_REGION: {
- const SkRegion& region = getRegion(reader);
+ SkRegion region;
+ this->getRegion(reader, &region);
uint32_t packed = reader.readInt();
SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
size_t offsetToRestore = reader.readInt();
SkASSERT(!offsetToRestore || \
offsetToRestore >= reader.offset());
- if (!canvas.clipRegion(region, regionOp) && offsetToRestore) {
+ canvas.clipRegion(region, regionOp);
+ if (canvas.isClipEmpty() && offsetToRestore) {
#ifdef SPEW_CLIP_SKIPPING
skipRegion.recordSkip(offsetToRestore - reader.offset());
#endif
@@ -844,7 +1030,8 @@ void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback)
size_t offsetToRestore = reader.readInt();
SkASSERT(!offsetToRestore || \
offsetToRestore >= reader.offset());
- if (!canvas.clipRect(rect, regionOp, doAA) && offsetToRestore) {
+ canvas.clipRect(rect, regionOp, doAA);
+ if (canvas.isClipEmpty() && offsetToRestore) {
#ifdef SPEW_CLIP_SKIPPING
skipRect.recordSkip(offsetToRestore - reader.offset());
#endif
@@ -858,27 +1045,45 @@ void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback)
SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
bool doAA = ClipParams_unpackDoAA(packed);
size_t offsetToRestore = reader.readInt();
- SkASSERT(!offsetToRestore || \
- offsetToRestore >= reader.offset());
- if (!canvas.clipRRect(rrect, regionOp, doAA) && offsetToRestore) {
+ SkASSERT(!offsetToRestore || offsetToRestore >= reader.offset());
+ canvas.clipRRect(rrect, regionOp, doAA);
+ if (canvas.isClipEmpty() && offsetToRestore) {
#ifdef SPEW_CLIP_SKIPPING
skipRRect.recordSkip(offsetToRestore - reader.offset());
#endif
reader.setOffset(offsetToRestore);
}
} break;
- case CONCAT:
- canvas.concat(*getMatrix(reader));
+ case PUSH_CULL: {
+ const SkRect& cullRect = reader.skipT<SkRect>();
+ size_t offsetToRestore = reader.readInt();
+ if (offsetToRestore && canvas.quickReject(cullRect)) {
+#ifdef SPEW_CLIP_SKIPPING
+ skipCull.recordSkip(offsetToRestore - reader.offset());
+#endif
+ reader.setOffset(offsetToRestore);
+ } else {
+ canvas.pushCull(cullRect);
+ }
+ } break;
+ case POP_CULL:
+ canvas.popCull();
+ break;
+ case CONCAT: {
+ SkMatrix matrix;
+ this->getMatrix(reader, &matrix);
+ canvas.concat(matrix);
break;
+ }
case DRAW_BITMAP: {
- const SkPaint* paint = getPaint(reader);
- const SkBitmap& bitmap = getBitmap(reader);
+ const SkPaint* paint = this->getPaint(reader);
+ const SkBitmap& bitmap = this->getBitmap(reader);
const SkPoint& loc = reader.skipT<SkPoint>();
canvas.drawBitmap(bitmap, loc.fX, loc.fY, paint);
} break;
case DRAW_BITMAP_RECT_TO_RECT: {
- const SkPaint* paint = getPaint(reader);
- const SkBitmap& bitmap = getBitmap(reader);
+ const SkPaint* paint = this->getPaint(reader);
+ const SkBitmap& bitmap = this->getBitmap(reader);
const SkRect* src = this->getRectPtr(reader); // may be null
const SkRect& dst = reader.skipT<SkRect>(); // required
SkCanvas::DrawBitmapRectFlags flags;
@@ -886,14 +1091,15 @@ void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback)
canvas.drawBitmapRectToRect(bitmap, src, dst, paint, flags);
} break;
case DRAW_BITMAP_MATRIX: {
- const SkPaint* paint = getPaint(reader);
- const SkBitmap& bitmap = getBitmap(reader);
- const SkMatrix* matrix = getMatrix(reader);
- canvas.drawBitmapMatrix(bitmap, *matrix, paint);
+ const SkPaint* paint = this->getPaint(reader);
+ const SkBitmap& bitmap = this->getBitmap(reader);
+ SkMatrix matrix;
+ this->getMatrix(reader, &matrix);
+ canvas.drawBitmapMatrix(bitmap, matrix, paint);
} break;
case DRAW_BITMAP_NINE: {
- const SkPaint* paint = getPaint(reader);
- const SkBitmap& bitmap = getBitmap(reader);
+ const SkPaint* paint = this->getPaint(reader);
+ const SkBitmap& bitmap = this->getBitmap(reader);
const SkIRect& src = reader.skipT<SkIRect>();
const SkRect& dst = reader.skipT<SkRect>();
canvas.drawBitmapNine(bitmap, src, dst, paint);
@@ -906,6 +1112,13 @@ void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback)
canvas.drawData(reader.skip(length), length);
// skip handles padding the read out to a multiple of 4
} break;
+ case DRAW_DRRECT: {
+ const SkPaint& paint = *this->getPaint(reader);
+ SkRRect outer, inner;
+ reader.readRRect(&outer);
+ reader.readRRect(&inner);
+ canvas.drawDRRect(outer, inner, paint);
+ } break;
case BEGIN_COMMENT_GROUP: {
const char* desc = reader.readString();
canvas.beginCommentGroup(desc);
@@ -919,35 +1132,35 @@ void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback)
canvas.endCommentGroup();
} break;
case DRAW_OVAL: {
- const SkPaint& paint = *getPaint(reader);
+ const SkPaint& paint = *this->getPaint(reader);
canvas.drawOval(reader.skipT<SkRect>(), paint);
} break;
case DRAW_PAINT:
- canvas.drawPaint(*getPaint(reader));
+ canvas.drawPaint(*this->getPaint(reader));
break;
case DRAW_PATH: {
- const SkPaint& paint = *getPaint(reader);
+ const SkPaint& paint = *this->getPaint(reader);
canvas.drawPath(getPath(reader), paint);
} break;
case DRAW_PICTURE:
- canvas.drawPicture(getPicture(reader));
+ canvas.drawPicture(this->getPicture(reader));
break;
case DRAW_POINTS: {
- const SkPaint& paint = *getPaint(reader);
+ const SkPaint& paint = *this->getPaint(reader);
SkCanvas::PointMode mode = (SkCanvas::PointMode)reader.readInt();
size_t count = reader.readInt();
const SkPoint* pts = (const SkPoint*)reader.skip(sizeof(SkPoint) * count);
canvas.drawPoints(mode, count, pts, paint);
} break;
case DRAW_POS_TEXT: {
- const SkPaint& paint = *getPaint(reader);
+ const SkPaint& paint = *this->getPaint(reader);
getText(reader, &text);
size_t points = reader.readInt();
const SkPoint* pos = (const SkPoint*)reader.skip(points * sizeof(SkPoint));
canvas.drawPosText(text.text(), text.length(), pos, paint);
} break;
case DRAW_POS_TEXT_TOP_BOTTOM: {
- const SkPaint& paint = *getPaint(reader);
+ const SkPaint& paint = *this->getPaint(reader);
getText(reader, &text);
size_t points = reader.readInt();
const SkPoint* pos = (const SkPoint*)reader.skip(points * sizeof(SkPoint));
@@ -958,7 +1171,7 @@ void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback)
}
} break;
case DRAW_POS_TEXT_H: {
- const SkPaint& paint = *getPaint(reader);
+ const SkPaint& paint = *this->getPaint(reader);
getText(reader, &text);
size_t xCount = reader.readInt();
const SkScalar constY = reader.readScalar();
@@ -967,7 +1180,7 @@ void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback)
paint);
} break;
case DRAW_POS_TEXT_H_TOP_BOTTOM: {
- const SkPaint& paint = *getPaint(reader);
+ const SkPaint& paint = *this->getPaint(reader);
getText(reader, &text);
size_t xCount = reader.readInt();
const SkScalar* xpos = (const SkScalar*)reader.skip((3 + xCount) * sizeof(SkScalar));
@@ -980,32 +1193,32 @@ void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback)
}
} break;
case DRAW_RECT: {
- const SkPaint& paint = *getPaint(reader);
+ const SkPaint& paint = *this->getPaint(reader);
canvas.drawRect(reader.skipT<SkRect>(), paint);
} break;
case DRAW_RRECT: {
- const SkPaint& paint = *getPaint(reader);
+ const SkPaint& paint = *this->getPaint(reader);
SkRRect rrect;
reader.readRRect(&rrect);
canvas.drawRRect(rrect, paint);
} break;
case DRAW_SPRITE: {
- const SkPaint* paint = getPaint(reader);
- const SkBitmap& bitmap = getBitmap(reader);
+ const SkPaint* paint = this->getPaint(reader);
+ const SkBitmap& bitmap = this->getBitmap(reader);
int left = reader.readInt();
int top = reader.readInt();
canvas.drawSprite(bitmap, left, top, paint);
} break;
case DRAW_TEXT: {
- const SkPaint& paint = *getPaint(reader);
- getText(reader, &text);
+ const SkPaint& paint = *this->getPaint(reader);
+ this->getText(reader, &text);
SkScalar x = reader.readScalar();
SkScalar y = reader.readScalar();
canvas.drawText(text.text(), text.length(), x, y, paint);
} break;
case DRAW_TEXT_TOP_BOTTOM: {
- const SkPaint& paint = *getPaint(reader);
- getText(reader, &text);
+ const SkPaint& paint = *this->getPaint(reader);
+ this->getText(reader, &text);
const SkScalar* ptr = (const SkScalar*)reader.skip(4 * sizeof(SkScalar));
// ptr[0] == x
// ptr[1] == y
@@ -1017,15 +1230,16 @@ void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback)
}
} break;
case DRAW_TEXT_ON_PATH: {
- const SkPaint& paint = *getPaint(reader);
+ const SkPaint& paint = *this->getPaint(reader);
getText(reader, &text);
- const SkPath& path = getPath(reader);
- const SkMatrix* matrix = getMatrix(reader);
- canvas.drawTextOnPath(text.text(), text.length(), path,
- matrix, paint);
+ const SkPath& path = this->getPath(reader);
+ SkMatrix matrix;
+ this->getMatrix(reader, &matrix);
+ canvas.drawTextOnPath(text.text(), text.length(), path, &matrix, paint);
} break;
case DRAW_VERTICES: {
- const SkPaint& paint = *getPaint(reader);
+ SkAutoTUnref<SkXfermode> xfer;
+ const SkPaint& paint = *this->getPaint(reader);
DrawVertexFlags flags = (DrawVertexFlags)reader.readInt();
SkCanvas::VertexMode vmode = (SkCanvas::VertexMode)reader.readInt();
int vCount = reader.readInt();
@@ -1048,7 +1262,14 @@ void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback)
indices = (const uint16_t*)reader.skip(
iCount * sizeof(uint16_t));
}
- canvas.drawVertices(vmode, vCount, verts, texs, colors, NULL,
+ if (flags & DRAW_VERTICES_HAS_XFER) {
+ int mode = reader.readInt();
+ if (mode < 0 || mode > SkXfermode::kLastMode) {
+ mode = SkXfermode::kModulate_Mode;
+ }
+ xfer.reset(SkXfermode::Create((SkXfermode::Mode)mode));
+ }
+ canvas.drawVertices(vmode, vCount, verts, texs, colors, xfer,
indices, iCount, paint);
} break;
case RESTORE:
@@ -1061,8 +1282,8 @@ void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback)
canvas.save((SkCanvas::SaveFlags) reader.readInt());
break;
case SAVE_LAYER: {
- const SkRect* boundsPtr = getRectPtr(reader);
- const SkPaint* paint = getPaint(reader);
+ const SkRect* boundsPtr = this->getRectPtr(reader);
+ const SkPaint* paint = this->getPaint(reader);
canvas.saveLayer(boundsPtr, paint, (SkCanvas::SaveFlags) reader.readInt());
} break;
case SCALE: {
@@ -1072,7 +1293,8 @@ void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback)
} break;
case SET_MATRIX: {
SkMatrix matrix;
- matrix.setConcat(initialMatrix, *getMatrix(reader));
+ this->getMatrix(reader, &matrix);
+ matrix.postConcat(initialMatrix);
canvas.setMatrix(matrix);
} break;
case SKEW: {
@@ -1094,7 +1316,7 @@ void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback)
#endif
if (it.isValid()) {
- uint32_t skipTo = it.draw();
+ uint32_t skipTo = it.nextDraw();
if (kDrawComplete == skipTo) {
break;
}
@@ -1104,15 +1326,65 @@ void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback)
#ifdef SPEW_CLIP_SKIPPING
{
- size_t size = skipRect.fSize + skipRRect.fSize + skipPath.fSize + skipRegion.fSize;
- SkDebugf("--- Clip skips %d%% rect:%d rrect:%d path:%d rgn:%d\n",
+ size_t size = skipRect.fSize + skipRRect.fSize + skipPath.fSize + skipRegion.fSize +
+ skipCull.fSize;
+ SkDebugf("--- Clip skips %d%% rect:%d rrect:%d path:%d rgn:%d cull:%d\n",
size * 100 / reader.offset(), skipRect.fCount, skipRRect.fCount,
- skipPath.fCount, skipRegion.fCount);
+ skipPath.fCount, skipRegion.fCount, skipCull.fCount);
+ SkDebugf("--- Total ops: %d\n", opCount);
}
#endif
// this->dumpSize();
}
+
+#if SK_SUPPORT_GPU
+bool SkPicturePlayback::suitableForGpuRasterization(GrContext* context, const char **reason,
+ int sampleCount) const {
+ // TODO: the heuristic used here needs to be refined
+ static const int kNumPaintWithPathEffectUsesTol = 1;
+ static const int kNumAAConcavePaths = 5;
+
+ SkASSERT(fContentInfo.numAAHairlineConcavePaths() <= fContentInfo.numAAConcavePaths());
+
+ int numNonDashedPathEffects = fContentInfo.numPaintWithPathEffectUses() -
+ fContentInfo.numFastPathDashEffects();
+
+ bool suitableForDash = (0 == fContentInfo.numPaintWithPathEffectUses()) ||
+ (numNonDashedPathEffects < kNumPaintWithPathEffectUsesTol
+ && 0 == sampleCount);
+
+ bool ret = suitableForDash &&
+ (fContentInfo.numAAConcavePaths() - fContentInfo.numAAHairlineConcavePaths())
+ < kNumAAConcavePaths;
+ if (!ret && NULL != reason) {
+ if (!suitableForDash) {
+ if (0 != sampleCount) {
+ *reason = "Can't use multisample on dash effect.";
+ } else {
+ *reason = "Too many non dashed path effects.";
+ }
+ } else if ((fContentInfo.numAAConcavePaths() - fContentInfo.numAAHairlineConcavePaths())
+ >= kNumAAConcavePaths)
+ *reason = "Too many anti-aliased concave paths.";
+ else
+ *reason = "Unknown reason for GPU unsuitability.";
+ }
+ return ret;
+}
+
+bool SkPicturePlayback::suitableForGpuRasterization(GrContext* context, const char **reason,
+ GrPixelConfig config, SkScalar dpi) const {
+
+ if (context != NULL) {
+ return this->suitableForGpuRasterization(context, reason,
+ context->getRecommendedSampleCount(config, dpi));
+ } else {
+ return this->suitableForGpuRasterization(NULL, reason);
+ }
+}
+
+#endif
///////////////////////////////////////////////////////////////////////////////
#ifdef SK_DEBUG_SIZE
@@ -1155,16 +1427,6 @@ int SkPicturePlayback::paths(size_t* size) {
*size = result;
return fPathCount;
}
-
-int SkPicturePlayback::regions(size_t* size) {
- size_t result = 0;
- for (int index = 0; index < fRegionCount; index++) {
- // const SkRegion& region = fRegions[index];
- result += sizeof(SkRegion); // region->size();
- }
- *size = result;
- return fRegionCount;
-}
#endif
#ifdef SK_DEBUG_DUMP
@@ -1217,11 +1479,11 @@ void dumpMatrix(const SkMatrix& matrix) const {
SkScalar perspX = matrix.getPerspX();
if (perspX != defaultMatrix.getPerspX())
bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "{kPerspX, %g}, ", SkFractToFloat(perspX));
+ "{kPerspX, %g}, ", perspX);
SkScalar perspY = matrix.getPerspY();
if (perspY != defaultMatrix.getPerspY())
bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "{kPerspY, %g}, ", SkFractToFloat(perspY));
+ "{kPerspY, %g}, ", perspY);
SkDebugf("%s{0}};\n", pBuffer);
}
@@ -1464,7 +1726,6 @@ void SkPicturePlayback::dumpStream() {
DUMP_INT(offsetToRestore);
} break;
case CLIP_REGION: {
- DUMP_PTR(SkRegion, &getRegion());
DUMP_INT(SkRegion::Op);
DUMP_INT(offsetToRestore);
} break;
@@ -1474,7 +1735,6 @@ void SkPicturePlayback::dumpStream() {
DUMP_INT(offsetToRestore);
} break;
case CONCAT:
- DUMP_PTR(SkMatrix, getMatrix());
break;
case DRAW_BITMAP: {
DUMP_PTR(SkPaint, getPaint());
@@ -1536,7 +1796,6 @@ void SkPicturePlayback::dumpStream() {
DUMP_PTR(SkPaint, getPaint());
DUMP_TEXT();
DUMP_PTR(SkPath, &getPath());
- DUMP_PTR(SkMatrix, getMatrix());
} break;
case RESTORE:
break;
@@ -1589,21 +1848,6 @@ void SkPicturePlayback::dump() const {
if (fBitmapCount > 0)
SkDebugf("%s0};\n", pBuffer);
- if (fMatrixCount > 0)
- SkDebugf("// matrices (%d)\n", fMatrixCount);
- for (index = 0; index < fMatrixCount; index++) {
- const SkMatrix& matrix = fMatrices[index];
- dumpMatrix(matrix);
- }
- bufferPtr = pBuffer;
- if (fMatrixCount > 0)
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "Matrices matrices = {");
- for (index = 0; index < fMatrixCount; index++)
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "matrix%p, ", &fMatrices[index]);
- if (fMatrixCount > 0)
- SkDebugf("%s0};\n", pBuffer);
if (fPaintCount > 0)
SkDebugf("// paints (%d)\n", fPaintCount);
@@ -1648,20 +1892,6 @@ void SkPicturePlayback::dump() const {
if (fPictureCount > 0)
SkDebugf("%s0};\n", pBuffer);
- for (index = 0; index < fRegionCount; index++) {
- const SkRegion& region = fRegions[index];
- dumpRegion(region);
- }
- bufferPtr = pBuffer;
- if (fRegionCount > 0)
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "Regions regions = {");
- for (index = 0; index < fRegionCount; index++)
- bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer),
- "region%p, ", &fRegions[index]);
- if (fRegionCount > 0)
- SkDebugf("%s0};\n", pBuffer);
-
const_cast<SkPicturePlayback*>(this)->dumpStream();
}
diff --git a/chromium/third_party/skia/src/core/SkPicturePlayback.h b/chromium/third_party/skia/src/core/SkPicturePlayback.h
index 6eb9ac34257..3cdd9af3f3f 100644
--- a/chromium/third_party/skia/src/core/SkPicturePlayback.h
+++ b/chromium/third_party/skia/src/core/SkPicturePlayback.h
@@ -5,32 +5,31 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
+
#ifndef SkPicturePlayback_DEFINED
#define SkPicturePlayback_DEFINED
-#include "SkPicture.h"
-#include "SkReader32.h"
-
#include "SkBitmap.h"
-#include "SkData.h"
-#include "SkMatrix.h"
-#include "SkOrderedReadBuffer.h"
-#include "SkPaint.h"
-#include "SkPath.h"
#include "SkPathHeap.h"
-#include "SkRegion.h"
-#include "SkRRect.h"
+#include "SkPicture.h"
#include "SkPictureFlat.h"
#ifdef SK_BUILD_FOR_ANDROID
#include "SkThread.h"
#endif
+class SkData;
class SkPictureRecord;
+class SkReader32;
class SkStream;
class SkWStream;
class SkBBoxHierarchy;
+class SkMatrix;
+class SkPaint;
+class SkPath;
class SkPictureStateTree;
+class SkReadBuffer;
+class SkRegion;
struct SkPictInfo {
enum Flags {
@@ -39,12 +38,87 @@ struct SkPictInfo {
kPtrIs64Bit_Flag = 1 << 2,
};
+ char fMagic[8];
uint32_t fVersion;
uint32_t fWidth;
uint32_t fHeight;
uint32_t fFlags;
};
+#define SK_PICT_READER_TAG SkSetFourByteTag('r', 'e', 'a', 'd')
+#define SK_PICT_FACTORY_TAG SkSetFourByteTag('f', 'a', 'c', 't')
+#define SK_PICT_TYPEFACE_TAG SkSetFourByteTag('t', 'p', 'f', 'c')
+#define SK_PICT_PICTURE_TAG SkSetFourByteTag('p', 'c', 't', 'r')
+
+// This tag specifies the size of the ReadBuffer, needed for the following tags
+#define SK_PICT_BUFFER_SIZE_TAG SkSetFourByteTag('a', 'r', 'a', 'y')
+// these are all inside the ARRAYS tag
+#define SK_PICT_BITMAP_BUFFER_TAG SkSetFourByteTag('b', 't', 'm', 'p')
+#define SK_PICT_PAINT_BUFFER_TAG SkSetFourByteTag('p', 'n', 't', ' ')
+#define SK_PICT_PATH_BUFFER_TAG SkSetFourByteTag('p', 't', 'h', ' ')
+
+// Always write this guy last (with no length field afterwards)
+#define SK_PICT_EOF_TAG SkSetFourByteTag('e', 'o', 'f', ' ')
+
+// SkPictureContentInfo is not serialized! It is intended solely for use
+// with suitableForGpuRasterization.
+class SkPictureContentInfo {
+public:
+ SkPictureContentInfo() { this->reset(); }
+
+ SkPictureContentInfo(const SkPictureContentInfo& src) { this->set(src); }
+
+ void set(const SkPictureContentInfo& src) {
+ fNumPaintWithPathEffectUses = src.fNumPaintWithPathEffectUses;
+ fNumFastPathDashEffects = src.fNumFastPathDashEffects;
+ fNumAAConcavePaths = src.fNumAAConcavePaths;
+ fNumAAHairlineConcavePaths = src.fNumAAHairlineConcavePaths;
+ }
+
+ void reset() {
+ fNumPaintWithPathEffectUses = 0;
+ fNumFastPathDashEffects = 0;
+ fNumAAConcavePaths = 0;
+ fNumAAHairlineConcavePaths = 0;
+ }
+
+ void swap(SkPictureContentInfo* other) {
+ SkTSwap(fNumPaintWithPathEffectUses, other->fNumPaintWithPathEffectUses);
+ SkTSwap(fNumFastPathDashEffects, other->fNumFastPathDashEffects);
+ SkTSwap(fNumAAConcavePaths, other->fNumAAConcavePaths);
+ SkTSwap(fNumAAHairlineConcavePaths, other->fNumAAHairlineConcavePaths);
+ }
+
+ void incPaintWithPathEffectUses() { ++fNumPaintWithPathEffectUses; }
+ int numPaintWithPathEffectUses() const { return fNumPaintWithPathEffectUses; }
+
+ void incFastPathDashEffects() { ++fNumFastPathDashEffects; }
+ int numFastPathDashEffects() const { return fNumFastPathDashEffects; }
+
+ void incAAConcavePaths() { ++fNumAAConcavePaths; }
+ int numAAConcavePaths() const { return fNumAAConcavePaths; }
+
+ void incAAHairlineConcavePaths() {
+ ++fNumAAHairlineConcavePaths;
+ SkASSERT(fNumAAHairlineConcavePaths <= fNumAAConcavePaths);
+ }
+ int numAAHairlineConcavePaths() const { return fNumAAHairlineConcavePaths; }
+
+private:
+ // This field is incremented every time a paint with a path effect is
+ // used (i.e., it is not a de-duplicated count)
+ int fNumPaintWithPathEffectUses;
+ // This field is incremented every time a paint with a path effect that is
+ // dashed, we are drawing a line, and we can use the gpu fast path
+ int fNumFastPathDashEffects;
+ // This field is incremented every time an anti-aliased drawPath call is
+ // issued with a concave path
+ int fNumAAConcavePaths;
+ // This field is incremented every time a drawPath call is
+ // issued for a hairline stroked concave path.
+ int fNumAAHairlineConcavePaths;
+};
+
/**
* Container for data that is needed to deep copy a SkPicture. The container
* enables the data to be generated once and reused for subsequent copies.
@@ -59,17 +133,25 @@ struct SkPictCopyInfo {
class SkPicturePlayback {
public:
- SkPicturePlayback();
- SkPicturePlayback(const SkPicturePlayback& src, SkPictCopyInfo* deepCopyInfo = NULL);
- explicit SkPicturePlayback(const SkPictureRecord& record, bool deepCopy = false);
- static SkPicturePlayback* CreateFromStream(SkStream*, const SkPictInfo&,
+ SkPicturePlayback(const SkPicturePlayback& src,
+ SkPictCopyInfo* deepCopyInfo = NULL);
+ SkPicturePlayback(const SkPictureRecord& record, const SkPictInfo&, bool deepCopyOps);
+ static SkPicturePlayback* CreateFromStream(SkStream*,
+ const SkPictInfo&,
SkPicture::InstallPixelRefProc);
+ static SkPicturePlayback* CreateFromBuffer(SkReadBuffer&,
+ const SkPictInfo&);
virtual ~SkPicturePlayback();
+ const SkPicture::OperationList& getActiveOps(const SkIRect& queryRect);
+
+ void setUseBBH(bool useBBH) { fUseBBH = useBBH; }
+
void draw(SkCanvas& canvas, SkDrawPictureCallback*);
void serialize(SkWStream*, SkPicture::EncodeBitmap) const;
+ void flatten(SkWriteBuffer&) const;
void dumpSize() const;
@@ -81,9 +163,14 @@ public:
void abort() { fAbortCurrentPlayback = true; }
#endif
+ size_t curOpID() const { return fCurOffset; }
+ void resetOpID() { fCurOffset = 0; }
+
protected:
- bool parseStream(SkStream*, const SkPictInfo&,
- SkPicture::InstallPixelRefProc);
+ explicit SkPicturePlayback(const SkPictInfo& info);
+
+ bool parseStream(SkStream*, SkPicture::InstallPixelRefProc);
+ bool parseBuffer(SkReadBuffer& buffer);
#ifdef SK_DEVELOPER
virtual bool preDraw(int opIndex, int type);
virtual void postDraw(int opIndex);
@@ -109,22 +196,19 @@ private:
return (*fBitmaps)[index];
}
- const SkMatrix* getMatrix(SkReader32& reader) {
- int index = reader.readInt();
- if (index == 0) {
- return NULL;
- }
- return &(*fMatrices)[index - 1];
+ void getMatrix(SkReader32& reader, SkMatrix* matrix) {
+ reader.readMatrix(matrix);
}
const SkPath& getPath(SkReader32& reader) {
- return (*fPathHeap)[reader.readInt() - 1];
+ int index = reader.readInt() - 1;
+ return (*fPathHeap.get())[index];
}
- SkPicture& getPicture(SkReader32& reader) {
+ const SkPicture* getPicture(SkReader32& reader) {
int index = reader.readInt();
SkASSERT(index > 0 && index <= fPictureCount);
- return *fPictureRefs[index - 1];
+ return fPictureRefs[index - 1];
}
const SkPaint* getPaint(SkReader32& reader) {
@@ -151,9 +235,8 @@ private:
}
}
- const SkRegion& getRegion(SkReader32& reader) {
- int index = reader.readInt();
- return (*fRegions)[index - 1];
+ void getRegion(SkReader32& reader, SkRegion* region) {
+ reader.readRegion(region);
}
void getText(SkReader32& reader, TextContainer* text) {
@@ -169,7 +252,6 @@ public:
int bitmaps(size_t* size);
int paints(size_t* size);
int paths(size_t* size);
- int regions(size_t* size);
#endif
#ifdef SK_DEBUG_DUMP
@@ -195,35 +277,149 @@ public:
void dump() const;
#endif
+#if SK_SUPPORT_GPU
+ /**
+ * sampleCount is the number of samples-per-pixel or zero if non-MSAA.
+ * It is defaulted to be zero.
+ */
+ bool suitableForGpuRasterization(GrContext* context, const char **reason,
+ int sampleCount = 0) const;
+
+ /**
+ * Calls getRecommendedSampleCount with GrPixelConfig and dpi to calculate sampleCount
+ * and then calls the above version of suitableForGpuRasterization
+ */
+ bool suitableForGpuRasterization(GrContext* context, const char **reason,
+ GrPixelConfig config, SkScalar dpi) const;
+#endif
+
private: // these help us with reading/writing
- bool parseStreamTag(SkStream*, const SkPictInfo&, uint32_t tag, size_t size,
- SkPicture::InstallPixelRefProc);
- bool parseBufferTag(SkOrderedReadBuffer&, uint32_t tag, size_t size);
- void flattenToBuffer(SkOrderedWriteBuffer&) const;
+ bool parseStreamTag(SkStream*, uint32_t tag, uint32_t size, SkPicture::InstallPixelRefProc);
+ bool parseBufferTag(SkReadBuffer&, uint32_t tag, uint32_t size);
+ void flattenToBuffer(SkWriteBuffer&) const;
private:
+ friend class SkPicture;
+ friend class SkGpuDevice; // for access to setDrawLimits & setReplacements
+
// Only used by getBitmap() if the passed in index is SkBitmapHeap::INVALID_SLOT. This empty
// bitmap allows playback to draw nothing and move on.
SkBitmap fBadBitmap;
SkAutoTUnref<SkBitmapHeap> fBitmapHeap;
- SkAutoTUnref<SkPathHeap> fPathHeap;
SkTRefArray<SkBitmap>* fBitmaps;
- SkTRefArray<SkMatrix>* fMatrices;
SkTRefArray<SkPaint>* fPaints;
- SkTRefArray<SkRegion>* fRegions;
SkData* fOpData; // opcodes and parameters
- SkPicture** fPictureRefs;
+ SkAutoTUnref<const SkPathHeap> fPathHeap; // reference counted
+
+ const SkPicture** fPictureRefs;
int fPictureCount;
SkBBoxHierarchy* fBoundingHierarchy;
SkPictureStateTree* fStateTree;
+ SkPictureContentInfo fContentInfo;
+
+ // Limit the opcode playback to be between the offsets 'start' and 'stop'.
+ // The opcode at 'start' should be a saveLayer while the opcode at
+ // 'stop' should be a restore. Neither of those commands will be issued.
+ // Set both start & stop to 0 to disable draw limiting
+ // Draw limiting cannot be enabled at the same time as draw replacing
+ void setDrawLimits(size_t start, size_t stop) {
+ SkASSERT(NULL == fReplacements);
+ fStart = start;
+ fStop = stop;
+ }
+
+ // PlaybackReplacements collects op ranges that can be replaced with
+ // a single drawBitmap call (using a precomputed bitmap).
+ class PlaybackReplacements {
+ public:
+ // All the operations between fStart and fStop (inclusive) will be replaced with
+ // a single drawBitmap call using fPos, fBM and fPaint.
+ // fPaint will be NULL if the picture's paint wasn't copyable
+ struct ReplacementInfo {
+ size_t fStart;
+ size_t fStop;
+ SkIPoint fPos;
+ SkBitmap* fBM;
+ const SkPaint* fPaint; // Note: this object doesn't own the paint
+ };
+
+ ~PlaybackReplacements() { this->freeAll(); }
+
+ // Add a new replacement range. The replacement ranges should be
+ // sorted in increasing order and non-overlapping (esp. no nested
+ // saveLayers).
+ ReplacementInfo* push();
+
+ private:
+ friend class SkPicturePlayback; // for access to lookupByStart
+
+ // look up a replacement range by its start offset
+ ReplacementInfo* lookupByStart(size_t start);
+
+ void freeAll();
+
+#ifdef SK_DEBUG
+ void validate() const;
+#endif
+
+ SkTDArray<ReplacementInfo> fReplacements;
+ };
+
+ // Replace all the draw ops in the replacement ranges in 'replacements' with
+ // the associated drawBitmap call
+ // Draw replacing cannot be enabled at the same time as draw limiting
+ void setReplacements(PlaybackReplacements* replacements) {
+ SkASSERT(fStart == 0 && fStop == 0);
+ fReplacements = replacements;
+ }
+
+ bool fUseBBH;
+ size_t fStart;
+ size_t fStop;
+ PlaybackReplacements* fReplacements;
+
+ class CachedOperationList : public SkPicture::OperationList {
+ public:
+ CachedOperationList() {
+ fCacheQueryRect.setEmpty();
+ }
+
+ virtual bool valid() const { return true; }
+ virtual int numOps() const SK_OVERRIDE { return fOps.count(); }
+ virtual uint32_t offset(int index) const SK_OVERRIDE;
+ virtual const SkMatrix& matrix(int index) const SK_OVERRIDE;
+
+ // The query rect for which the cached active ops are valid
+ SkIRect fCacheQueryRect;
+
+ // The operations which are active within 'fCachedQueryRect'
+ SkTDArray<void*> fOps;
+
+ private:
+ typedef SkPicture::OperationList INHERITED;
+ };
+
+ CachedOperationList* fCachedActiveOps;
+
SkTypefacePlayback fTFPlayback;
SkFactoryPlayback* fFactoryPlayback;
+
+ // The offset of the current operation when within the draw method
+ size_t fCurOffset;
+
+ const SkPictInfo fInfo;
+
+ static void WriteFactories(SkWStream* stream, const SkFactorySet& rec);
+ static void WriteTypefaces(SkWStream* stream, const SkRefCntSet& rec);
+
+ void initForPlayback() const;
+
#ifdef SK_BUILD_FOR_ANDROID
SkMutex fDrawMutex;
bool fAbortCurrentPlayback;
diff --git a/chromium/third_party/skia/src/core/SkPictureRecord.cpp b/chromium/third_party/skia/src/core/SkPictureRecord.cpp
index 6b49620d481..16856d639d7 100644
--- a/chromium/third_party/skia/src/core/SkPictureRecord.cpp
+++ b/chromium/third_party/skia/src/core/SkPictureRecord.cpp
@@ -1,10 +1,10 @@
-
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
+
#include "SkPictureRecord.h"
#include "SkTSearch.h"
#include "SkPixelRef.h"
@@ -13,9 +13,17 @@
#include "SkDevice.h"
#include "SkPictureStateTree.h"
-#define MIN_WRITER_SIZE 16384
#define HEAP_BLOCK_SIZE 4096
+// If SK_RECORD_LITERAL_PICTURES is defined, record our inputs as literally as possible.
+// Otherwise, we can be clever and record faster equivalents. kBeClever is normally true.
+static const bool kBeClever =
+#ifdef SK_RECORD_LITERAL_PICTURES
+ false;
+#else
+ true;
+#endif
+
enum {
// just need a value that save or getSaveCount would never return
kNoInitialSave = -1,
@@ -28,34 +36,35 @@ static const uint32_t kSaveSize = 2 * kUInt32Size;
static const uint32_t kSaveLayerNoBoundsSize = 4 * kUInt32Size;
static const uint32_t kSaveLayerWithBoundsSize = 4 * kUInt32Size + sizeof(SkRect);
-SkPictureRecord::SkPictureRecord(uint32_t flags, SkBaseDevice* device) :
- INHERITED(device),
- fBoundingHierarchy(NULL),
- fStateTree(NULL),
- fFlattenableHeap(HEAP_BLOCK_SIZE),
- fMatrices(&fFlattenableHeap),
- fPaints(&fFlattenableHeap),
- fRegions(&fFlattenableHeap),
- fWriter(MIN_WRITER_SIZE),
- fRecordFlags(flags) {
+SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags)
+ : INHERITED(dimensions.width(), dimensions.height())
+ , fBoundingHierarchy(NULL)
+ , fStateTree(NULL)
+ , fFlattenableHeap(HEAP_BLOCK_SIZE)
+ , fPaints(&fFlattenableHeap)
+ , fRecordFlags(flags)
+ , fOptsEnabled(kBeClever) {
#ifdef SK_DEBUG_SIZE
fPointBytes = fRectBytes = fTextBytes = 0;
fPointWrites = fRectWrites = fTextWrites = 0;
#endif
- fRestoreOffsetStack.setReserve(32);
-
fBitmapHeap = SkNEW(SkBitmapHeap);
fFlattenableHeap.setBitmapStorage(fBitmapHeap);
- fPathHeap = NULL; // lazy allocate
+
+#ifndef SK_COLLAPSE_MATRIX_CLIP_STATE
fFirstSavedLayerIndex = kNoSavedLayerIndex;
+#endif
fInitialSaveCount = kNoInitialSave;
+
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.init(this);
+#endif
}
SkPictureRecord::~SkPictureRecord() {
SkSafeUnref(fBitmapHeap);
- SkSafeUnref(fPathHeap);
SkSafeUnref(fBoundingHierarchy);
SkSafeUnref(fStateTree);
fFlattenableHeap.setBitmapStorage(NULL);
@@ -67,7 +76,7 @@ SkPictureRecord::~SkPictureRecord() {
// Return the offset of the paint inside a given op's byte stream. A zero
// return value means there is no paint (and you really shouldn't be calling
// this method)
-static inline uint32_t getPaintOffset(DrawType op, uint32_t opSize) {
+static inline size_t getPaintOffset(DrawType op, size_t opSize) {
// These offsets are where the paint would be if the op size doesn't overflow
static const uint8_t gPaintOffsets[LAST_DRAWTYPE_ENUM + 1] = {
0, // UNUSED - no paint
@@ -110,9 +119,13 @@ static inline uint32_t getPaintOffset(DrawType op, uint32_t opSize) {
0, // BEGIN_GROUP - no paint
0, // COMMENT - no paint
0, // END_GROUP - no paint
+ 1, // DRAWDRRECT - right after op code
+ 0, // PUSH_CULL - no paint
+ 0, // POP_CULL - no paint
};
- SkASSERT(sizeof(gPaintOffsets) == LAST_DRAWTYPE_ENUM + 1);
+ SK_COMPILE_ASSERT(sizeof(gPaintOffsets) == LAST_DRAWTYPE_ENUM + 1,
+ need_to_be_in_sync);
SkASSERT((unsigned)op <= (unsigned)LAST_DRAWTYPE_ENUM);
int overflow = 0;
@@ -138,33 +151,57 @@ static inline uint32_t getPaintOffset(DrawType op, uint32_t opSize) {
return gPaintOffsets[op] * sizeof(uint32_t) + overflow;
}
-SkBaseDevice* SkPictureRecord::setDevice(SkBaseDevice* device) {
- SkDEBUGFAIL("eeek, don't try to change the device on a recording canvas");
- return this->INHERITED::setDevice(device);
-}
+void SkPictureRecord::willSave(SaveFlags flags) {
-int SkPictureRecord::save(SaveFlags flags) {
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.save(flags);
+#else
// record the offset to us, making it non-positive to distinguish a save
// from a clip entry.
fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
+ this->recordSave(flags);
+#endif
+ this->INHERITED::willSave(flags);
+}
+
+void SkPictureRecord::recordSave(SaveFlags flags) {
// op + flags
- uint32_t size = kSaveSize;
+ size_t size = kSaveSize;
size_t initialOffset = this->addDraw(SAVE, &size);
- addInt(flags);
+ this->addInt(flags);
this->validate(initialOffset, size);
- return this->INHERITED::save(flags);
}
-int SkPictureRecord::saveLayer(const SkRect* bounds, const SkPaint* paint,
- SaveFlags flags) {
+SkCanvas::SaveLayerStrategy SkPictureRecord::willSaveLayer(const SkRect* bounds,
+ const SkPaint* paint, SaveFlags flags) {
+
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.saveLayer(bounds, paint, flags);
+#else
// record the offset to us, making it non-positive to distinguish a save
// from a clip entry.
fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
+ this->recordSaveLayer(bounds, paint, flags);
+ if (kNoSavedLayerIndex == fFirstSavedLayerIndex) {
+ fFirstSavedLayerIndex = fRestoreOffsetStack.count();
+ }
+#endif
+ this->INHERITED::willSaveLayer(bounds, paint, flags);
+ /* No need for a (potentially very big) layer which we don't actually need
+ at this time (and may not be able to afford since during record our
+ clip starts out the size of the picture, which is often much larger
+ than the size of the actual device we'll use during playback).
+ */
+ return kNoLayer_SaveLayerStrategy;
+}
+
+void SkPictureRecord::recordSaveLayer(const SkRect* bounds, const SkPaint* paint,
+ SaveFlags flags) {
// op + bool for 'bounds'
- uint32_t size = 2 * kUInt32Size;
+ size_t size = 2 * kUInt32Size;
if (NULL != bounds) {
size += sizeof(*bounds); // + rect
}
@@ -174,42 +211,42 @@ int SkPictureRecord::saveLayer(const SkRect* bounds, const SkPaint* paint,
SkASSERT(kSaveLayerNoBoundsSize == size || kSaveLayerWithBoundsSize == size);
size_t initialOffset = this->addDraw(SAVE_LAYER, &size);
- addRectPtr(bounds);
+ this->addRectPtr(bounds);
SkASSERT(initialOffset+getPaintOffset(SAVE_LAYER, size) == fWriter.bytesWritten());
- addPaintPtr(paint);
- addInt(flags);
-
- if (kNoSavedLayerIndex == fFirstSavedLayerIndex) {
- fFirstSavedLayerIndex = fRestoreOffsetStack.count();
- }
+ this->addPaintPtr(paint);
+ this->addInt(flags);
this->validate(initialOffset, size);
- /* Don't actually call saveLayer, because that will try to allocate an
- offscreen device (potentially very big) which we don't actually need
- at this time (and may not be able to afford since during record our
- clip starts out the size of the picture, which is often much larger
- than the size of the actual device we'll use during playback).
- */
- int count = this->INHERITED::save(flags);
- this->clipRectBounds(bounds, flags, NULL);
- return count;
}
bool SkPictureRecord::isDrawingToLayer() const {
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ return fMCMgr.isDrawingToLayer();
+#else
return fFirstSavedLayerIndex != kNoSavedLayerIndex;
+#endif
}
/*
+ * Read the op code from 'offset' in 'writer'.
+ */
+#ifdef SK_DEBUG
+static DrawType peek_op(SkWriter32* writer, size_t offset) {
+ return (DrawType)(writer->readTAt<uint32_t>(offset) >> 24);
+}
+#endif
+
+/*
* Read the op code from 'offset' in 'writer' and extract the size too.
*/
-static DrawType peek_op_and_size(SkWriter32* writer, int32_t offset, uint32_t* size) {
- uint32_t* peek = writer->peek32(offset);
+static DrawType peek_op_and_size(SkWriter32* writer, size_t offset, uint32_t* size) {
+ uint32_t peek = writer->readTAt<uint32_t>(offset);
uint32_t op;
- UNPACK_8_24(*peek, op, *size);
+ UNPACK_8_24(peek, op, *size);
if (MASK_24 == *size) {
// size required its own slot right after the op code
- *size = *writer->peek32(offset+kUInt32Size);
+ *size = writer->readTAt<uint32_t>(offset + kUInt32Size);
}
return (DrawType) op;
}
@@ -255,15 +292,14 @@ static bool match(SkWriter32* writer, uint32_t offset,
int numMatched;
for (numMatched = 0; numMatched < numCommands && curOffset < writer->bytesWritten(); ++numMatched) {
DrawType op = peek_op_and_size(writer, curOffset, &curSize);
- while (NOOP == op && curOffset < writer->bytesWritten()) {
+ while (NOOP == op) {
curOffset += curSize;
+ if (curOffset >= writer->bytesWritten()) {
+ return false;
+ }
op = peek_op_and_size(writer, curOffset, &curSize);
}
- if (curOffset >= writer->bytesWritten()) {
- return false; // ran out of byte stream
- }
-
if (kDRAW_BITMAP_FLAVOR == pattern[numMatched]) {
if (DRAW_BITMAP != op && DRAW_BITMAP_MATRIX != op &&
DRAW_BITMAP_NINE != op && DRAW_BITMAP_RECT_TO_RECT != op) {
@@ -312,7 +348,7 @@ static bool remove_save_layer1(SkWriter32* writer, int32_t offset,
// back up to the save block
// TODO: add a stack to track save*/restore offsets rather than searching backwards
while (offset > 0) {
- offset = *writer->peek32(offset);
+ offset = writer->readTAt<uint32_t>(offset);
}
int pattern[] = { SAVE_LAYER, kDRAW_BITMAP_FLAVOR, /* RESTORE */ };
@@ -327,7 +363,6 @@ static bool remove_save_layer1(SkWriter32* writer, int32_t offset,
return false;
}
-
return merge_savelayer_paint_into_drawbitmp(writer, paintDict,
result[0], result[1]);
}
@@ -337,8 +372,8 @@ static bool remove_save_layer1(SkWriter32* writer, int32_t offset,
* field alone so the NOOP can be skipped later.
*/
static void convert_command_to_noop(SkWriter32* writer, uint32_t offset) {
- uint32_t* ptr = writer->peek32(offset);
- *ptr = (*ptr & MASK_24) | (NOOP << 24);
+ uint32_t command = writer->readTAt<uint32_t>(offset);
+ writer->overwriteTAt(offset, (command & MASK_24) | (NOOP << 24));
}
/*
@@ -355,12 +390,12 @@ static bool merge_savelayer_paint_into_drawbitmp(SkWriter32* writer,
DRAW_BITMAP_NINE == dbmInfo.fActualOp ||
DRAW_BITMAP_RECT_TO_RECT == dbmInfo.fActualOp);
- uint32_t dbmPaintOffset = getPaintOffset(dbmInfo.fActualOp, dbmInfo.fSize);
- uint32_t slPaintOffset = getPaintOffset(SAVE_LAYER, saveLayerInfo.fSize);
+ size_t dbmPaintOffset = getPaintOffset(dbmInfo.fActualOp, dbmInfo.fSize);
+ size_t slPaintOffset = getPaintOffset(SAVE_LAYER, saveLayerInfo.fSize);
// we have a match, now we need to get the paints involved
- uint32_t dbmPaintId = *writer->peek32(dbmInfo.fOffset+dbmPaintOffset);
- uint32_t saveLayerPaintId = *writer->peek32(saveLayerInfo.fOffset+slPaintOffset);
+ uint32_t dbmPaintId = writer->readTAt<uint32_t>(dbmInfo.fOffset + dbmPaintOffset);
+ uint32_t saveLayerPaintId = writer->readTAt<uint32_t>(saveLayerInfo.fOffset + slPaintOffset);
if (0 == saveLayerPaintId) {
// In this case the saveLayer/restore isn't needed at all - just kill the saveLayer
@@ -373,9 +408,7 @@ static bool merge_savelayer_paint_into_drawbitmp(SkWriter32* writer,
// In this case just make the DBM* use the saveLayer's paint, kill the saveLayer
// and signal the caller (by returning true) to not add the RESTORE op
convert_command_to_noop(writer, saveLayerInfo.fOffset);
- uint32_t* ptr = writer->peek32(dbmInfo.fOffset+dbmPaintOffset);
- SkASSERT(0 == *ptr);
- *ptr = saveLayerPaintId;
+ writer->overwriteTAt(dbmInfo.fOffset + dbmPaintOffset, saveLayerPaintId);
return true;
}
@@ -393,7 +426,7 @@ static bool merge_savelayer_paint_into_drawbitmp(SkWriter32* writer,
SkColor layerColor = saveLayerPaint->getColor() | 0xFF000000; // force opaque
SkAutoTDelete<SkPaint> dbmPaint(paintDict->unflatten(dbmPaintId));
- if (NULL == dbmPaint.get() || dbmPaint->getColor() != layerColor) {
+ if (NULL == dbmPaint.get() || dbmPaint->getColor() != layerColor || !is_simple(*dbmPaint)) {
return false;
}
@@ -408,9 +441,7 @@ static bool merge_savelayer_paint_into_drawbitmp(SkWriter32* writer,
// kill the saveLayer and alter the DBMR2R's paint to be the modified one
convert_command_to_noop(writer, saveLayerInfo.fOffset);
- uint32_t* ptr = writer->peek32(dbmInfo.fOffset+dbmPaintOffset);
- SkASSERT(dbmPaintId == *ptr);
- *ptr = data->index();
+ writer->overwriteTAt(dbmInfo.fOffset + dbmPaintOffset, data->index());
return true;
}
@@ -431,7 +462,7 @@ static bool remove_save_layer2(SkWriter32* writer, int32_t offset,
// back up to the save block
// TODO: add a stack to track save*/restore offsets rather than searching backwards
while (offset > 0) {
- offset = *writer->peek32(offset);
+ offset = writer->readTAt<uint32_t>(offset);
}
int pattern[] = { SAVE_LAYER, SAVE, CLIP_RECT, kDRAW_BITMAP_FLAVOR, RESTORE, /* RESTORE */ };
@@ -450,6 +481,10 @@ static bool remove_save_layer2(SkWriter32* writer, int32_t offset,
result[0], result[3]);
}
+static bool is_drawing_op(DrawType op) {
+ return (op > CONCAT && op < ROTATE) || DRAW_DRRECT == op;
+}
+
/*
* Restore has just been called (but not recorded), so look back at the
* matching save(), and see if we can eliminate the pair of them, due to no
@@ -468,7 +503,7 @@ static bool collapse_save_clip_restore(SkWriter32* writer, int32_t offset,
// back up to the save block
while (offset > 0) {
- offset = *writer->peek32(offset);
+ offset = writer->readTAt<uint32_t>(offset);
}
// now offset points to a save
@@ -483,7 +518,7 @@ static bool collapse_save_clip_restore(SkWriter32* writer, int32_t offset,
SkASSERT(kSaveSize == opSize);
// get the save flag (last 4-bytes of the space allocated for the opSize)
- SkCanvas::SaveFlags saveFlags = (SkCanvas::SaveFlags) *writer->peek32(offset+4);
+ SkCanvas::SaveFlags saveFlags = (SkCanvas::SaveFlags) writer->readTAt<uint32_t>(offset + 4);
if (SkCanvas::kMatrixClip_SaveFlag != saveFlags) {
// This function's optimization is only correct for kMatrixClip style saves.
// TODO: set checkMatrix & checkClip booleans here and then check for the
@@ -498,7 +533,7 @@ static bool collapse_save_clip_restore(SkWriter32* writer, int32_t offset,
offset += opSize;
while (offset < restoreOffset) {
op = peek_op_and_size(writer, offset, &opSize);
- if ((op > CONCAT && op < ROTATE) || (SAVE_LAYER == op)) {
+ if (is_drawing_op(op) || (SAVE_LAYER == op)) {
// drawing verb, abort
return false;
}
@@ -572,7 +607,7 @@ static void apply_optimization_to_bbh(PictureRecordOptType opt, SkPictureStateTr
}
}
-void SkPictureRecord::restore() {
+void SkPictureRecord::willRestore() {
// FIXME: SkDeferredCanvas needs to be refactored to respect
// save/restore balancing so that the following test can be
// turned on permanently.
@@ -580,6 +615,13 @@ void SkPictureRecord::restore() {
SkASSERT(fRestoreOffsetStack.count() > 1);
#endif
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ if (fMCMgr.getSaveCount() == 1) {
+ return;
+ }
+
+ fMCMgr.restore();
+#else
// check for underflow
if (fRestoreOffsetStack.count() == 0) {
return;
@@ -589,9 +631,8 @@ void SkPictureRecord::restore() {
fFirstSavedLayerIndex = kNoSavedLayerIndex;
}
- uint32_t initialOffset, size;
size_t opt = 0;
- if (!(fRecordFlags & SkPicture::kDisableRecordOptimizations_RecordingFlag)) {
+ if (fOptsEnabled) {
for (opt = 0; opt < SK_ARRAY_COUNT(gPictureRecordOpts); ++opt) {
if (0 != (gPictureRecordOpts[opt].fFlags & kSkipIfBBoxHierarchy_Flag)
&& NULL != fBoundingHierarchy) {
@@ -599,8 +640,6 @@ void SkPictureRecord::restore() {
}
if ((*gPictureRecordOpts[opt].fProc)(&fWriter, fRestoreOffsetStack.top(), &fPaints)) {
// Some optimization fired so don't add the RESTORE
- size = 0;
- initialOffset = fWriter.bytesWritten();
apply_optimization_to_bbh(gPictureRecordOpts[opt].fType,
fStateTree, fBoundingHierarchy);
break;
@@ -608,77 +647,90 @@ void SkPictureRecord::restore() {
}
}
- if ((fRecordFlags & SkPicture::kDisableRecordOptimizations_RecordingFlag) ||
- SK_ARRAY_COUNT(gPictureRecordOpts) == opt) {
+ if (!fOptsEnabled || SK_ARRAY_COUNT(gPictureRecordOpts) == opt) {
// No optimization fired so add the RESTORE
- fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten());
- size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
- initialOffset = this->addDraw(RESTORE, &size);
+ this->recordRestore();
}
fRestoreOffsetStack.pop();
+#endif
+
+ this->INHERITED::willRestore();
+}
+void SkPictureRecord::recordRestore(bool fillInSkips) {
+ if (fillInSkips) {
+ this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten());
+ }
+ size_t size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
+ size_t initialOffset = this->addDraw(RESTORE, &size);
this->validate(initialOffset, size);
- return this->INHERITED::restore();
}
-bool SkPictureRecord::translate(SkScalar dx, SkScalar dy) {
+void SkPictureRecord::recordTranslate(const SkMatrix& m) {
+ SkASSERT(SkMatrix::kTranslate_Mask == m.getType());
+
// op + dx + dy
- uint32_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
+ size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
size_t initialOffset = this->addDraw(TRANSLATE, &size);
- addScalar(dx);
- addScalar(dy);
+ this->addScalar(m.getTranslateX());
+ this->addScalar(m.getTranslateY());
this->validate(initialOffset, size);
- return this->INHERITED::translate(dx, dy);
}
-bool SkPictureRecord::scale(SkScalar sx, SkScalar sy) {
+void SkPictureRecord::recordScale(const SkMatrix& m) {
+ SkASSERT(SkMatrix::kScale_Mask == m.getType());
+
// op + sx + sy
- uint32_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
+ size_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
size_t initialOffset = this->addDraw(SCALE, &size);
- addScalar(sx);
- addScalar(sy);
+ this->addScalar(m.getScaleX());
+ this->addScalar(m.getScaleY());
this->validate(initialOffset, size);
- return this->INHERITED::scale(sx, sy);
}
-bool SkPictureRecord::rotate(SkScalar degrees) {
- // op + degrees
- uint32_t size = 1 * kUInt32Size + sizeof(SkScalar);
- size_t initialOffset = this->addDraw(ROTATE, &size);
- addScalar(degrees);
- this->validate(initialOffset, size);
- return this->INHERITED::rotate(degrees);
-}
+void SkPictureRecord::didConcat(const SkMatrix& matrix) {
-bool SkPictureRecord::skew(SkScalar sx, SkScalar sy) {
- // op + sx + sy
- uint32_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
- size_t initialOffset = this->addDraw(SKEW, &size);
- addScalar(sx);
- addScalar(sy);
- this->validate(initialOffset, size);
- return this->INHERITED::skew(sx, sy);
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.concat(matrix);
+#else
+ switch (matrix.getType()) {
+ case SkMatrix::kTranslate_Mask:
+ this->recordTranslate(matrix);
+ break;
+ case SkMatrix::kScale_Mask:
+ this->recordScale(matrix);
+ break;
+ default:
+ this->recordConcat(matrix);
+ break;
+ }
+#endif
+ this->INHERITED::didConcat(matrix);
}
-bool SkPictureRecord::concat(const SkMatrix& matrix) {
+void SkPictureRecord::recordConcat(const SkMatrix& matrix) {
this->validate(fWriter.bytesWritten(), 0);
- // op + matrix index
- uint32_t size = 2 * kUInt32Size;
+ // op + matrix
+ size_t size = kUInt32Size + matrix.writeToMemory(NULL);
size_t initialOffset = this->addDraw(CONCAT, &size);
- addMatrix(matrix);
+ this->addMatrix(matrix);
this->validate(initialOffset, size);
- return this->INHERITED::concat(matrix);
}
-void SkPictureRecord::setMatrix(const SkMatrix& matrix) {
+void SkPictureRecord::didSetMatrix(const SkMatrix& matrix) {
+
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.setMatrix(matrix);
+#else
this->validate(fWriter.bytesWritten(), 0);
- // op + matrix index
- uint32_t size = 2 * kUInt32Size;
+ // op + matrix
+ size_t size = kUInt32Size + matrix.writeToMemory(NULL);
size_t initialOffset = this->addDraw(SET_MATRIX, &size);
- addMatrix(matrix);
+ this->addMatrix(matrix);
this->validate(initialOffset, size);
- this->INHERITED::setMatrix(matrix);
+#endif
+ this->INHERITED::didSetMatrix(matrix);
}
static bool regionOpExpands(SkRegion::Op op) {
@@ -697,12 +749,17 @@ static bool regionOpExpands(SkRegion::Op op) {
}
}
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
+ fMCMgr.fillInSkips(&fWriter, restoreOffset);
+}
+#else
void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
int32_t offset = fRestoreOffsetStack.top();
while (offset > 0) {
- uint32_t* peek = fWriter.peek32(offset);
- offset = *peek;
- *peek = restoreOffset;
+ uint32_t peek = fWriter.readTAt<uint32_t>(offset);
+ fWriter.overwriteTAt(offset, restoreOffset);
+ offset = peek;
}
#ifdef SK_DEBUG
@@ -712,22 +769,33 @@ void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t
SkASSERT(SAVE == drawOp || SAVE_LAYER == drawOp);
#endif
}
+#endif
void SkPictureRecord::beginRecording() {
// we have to call this *after* our constructor, to ensure that it gets
// recorded. This is balanced by restoreToCount() call from endRecording,
// which in-turn calls our overridden restore(), so those get recorded too.
- fInitialSaveCount = this->save(kMatrixClip_SaveFlag);
+ fInitialSaveCount = this->save();
}
void SkPictureRecord::endRecording() {
SkASSERT(kNoInitialSave != fInitialSaveCount);
this->restoreToCount(fInitialSaveCount);
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.finish();
+#endif
}
-void SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+int SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
+ size_t offset = fWriter.bytesWritten();
+ this->addInt(-1);
+ return offset;
+}
+#else
+size_t SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
if (fRestoreOffsetStack.isEmpty()) {
- return;
+ return -1;
}
// The RestoreOffset field is initially filled with a placeholder
@@ -742,7 +810,7 @@ void SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
// be 0, disabling their ability to trigger a jump-to-restore, otherwise
// they could hide this clips ability to expand the clip (i.e. go from
// empty to non-empty).
- fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
+ this->fillRestoreOffsetPlaceholdersForCurrentStackLevel(0);
// Reset the pointer back to the previous clip so that subsequent
// restores don't overwrite the offsets we just cleared.
@@ -750,244 +818,390 @@ void SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
}
size_t offset = fWriter.bytesWritten();
- addInt(prevOffset);
- fRestoreOffsetStack.top() = offset;
+ this->addInt(prevOffset);
+ fRestoreOffsetStack.top() = SkToU32(offset);
+ return offset;
}
+#endif
+
+void SkPictureRecord::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
-bool SkPictureRecord::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.clipRect(rect, op, doAA);
+#else
+ this->recordClipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
+#endif
+ this->INHERITED::onClipRect(rect, op, edgeStyle);
+}
+
+size_t SkPictureRecord::recordClipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
// id + rect + clip params
- uint32_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
+ size_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ size += kUInt32Size; // + restore offset
+#else
// recordRestoreOffsetPlaceholder doesn't always write an offset
if (!fRestoreOffsetStack.isEmpty()) {
// + restore offset
size += kUInt32Size;
}
+#endif
size_t initialOffset = this->addDraw(CLIP_RECT, &size);
- addRect(rect);
- addInt(ClipParams_pack(op, doAA));
- recordRestoreOffsetPlaceholder(op);
+ this->addRect(rect);
+ this->addInt(ClipParams_pack(op, doAA));
+ size_t offset = this->recordRestoreOffsetPlaceholder(op);
this->validate(initialOffset, size);
- return this->INHERITED::clipRect(rect, op, doAA);
+ return offset;
}
-bool SkPictureRecord::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
- if (rrect.isRect()) {
- return this->SkPictureRecord::clipRect(rrect.getBounds(), op, doAA);
- }
+void SkPictureRecord::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.clipRRect(rrect, op, doAA);
+#else
+ this->recordClipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
+#endif
+ this->updateClipConservativelyUsingBounds(rrect.getBounds(), op, false);
+}
+
+size_t SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
// op + rrect + clip params
- uint32_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
+ size_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ size += kUInt32Size; // + restore offset
+#else
// recordRestoreOffsetPlaceholder doesn't always write an offset
if (!fRestoreOffsetStack.isEmpty()) {
// + restore offset
size += kUInt32Size;
}
+#endif
size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
- addRRect(rrect);
- addInt(ClipParams_pack(op, doAA));
- recordRestoreOffsetPlaceholder(op);
-
+ this->addRRect(rrect);
+ this->addInt(ClipParams_pack(op, doAA));
+ size_t offset = recordRestoreOffsetPlaceholder(op);
this->validate(initialOffset, size);
-
- if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) {
- return this->updateClipConservativelyUsingBounds(rrect.getBounds(), op, false);
- } else {
- return this->INHERITED::clipRRect(rrect, op, doAA);
- }
+ return offset;
}
-bool SkPictureRecord::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
+void SkPictureRecord::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
- SkRect r;
- if (!path.isInverseFillType() && path.isRect(&r)) {
- return this->clipRect(r, op, doAA);
- }
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.clipPath(path, op, doAA);
+#else
+ int pathID = this->addPathToHeap(path);
+ this->recordClipPath(pathID, op, kSoft_ClipEdgeStyle == edgeStyle);
+#endif
+
+ this->updateClipConservativelyUsingBounds(path.getBounds(), op,
+ path.isInverseFillType());
+}
+size_t SkPictureRecord::recordClipPath(int pathID, SkRegion::Op op, bool doAA) {
// op + path index + clip params
- uint32_t size = 3 * kUInt32Size;
+ size_t size = 3 * kUInt32Size;
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ size += kUInt32Size; // + restore offset
+#else
// recordRestoreOffsetPlaceholder doesn't always write an offset
if (!fRestoreOffsetStack.isEmpty()) {
// + restore offset
size += kUInt32Size;
}
+#endif
size_t initialOffset = this->addDraw(CLIP_PATH, &size);
- addPath(path);
- addInt(ClipParams_pack(op, doAA));
- recordRestoreOffsetPlaceholder(op);
-
+ this->addInt(pathID);
+ this->addInt(ClipParams_pack(op, doAA));
+ size_t offset = recordRestoreOffsetPlaceholder(op);
this->validate(initialOffset, size);
+ return offset;
+}
- if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) {
- return this->updateClipConservativelyUsingBounds(path.getBounds(), op,
- path.isInverseFillType());
- } else {
- return this->INHERITED::clipPath(path, op, doAA);
- }
+void SkPictureRecord::onClipRegion(const SkRegion& region, SkRegion::Op op) {
+
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.clipRegion(region, op);
+#else
+ this->recordClipRegion(region, op);
+#endif
+ this->INHERITED::onClipRegion(region, op);
}
-bool SkPictureRecord::clipRegion(const SkRegion& region, SkRegion::Op op) {
- // op + region index + clip params
- uint32_t size = 3 * kUInt32Size;
+size_t SkPictureRecord::recordClipRegion(const SkRegion& region, SkRegion::Op op) {
+ // op + clip params + region
+ size_t size = 2 * kUInt32Size + region.writeToMemory(NULL);
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ size += kUInt32Size; // + restore offset
+#else
// recordRestoreOffsetPlaceholder doesn't always write an offset
if (!fRestoreOffsetStack.isEmpty()) {
// + restore offset
size += kUInt32Size;
}
+#endif
size_t initialOffset = this->addDraw(CLIP_REGION, &size);
- addRegion(region);
- addInt(ClipParams_pack(op, false));
- recordRestoreOffsetPlaceholder(op);
+ this->addRegion(region);
+ this->addInt(ClipParams_pack(op, false));
+ size_t offset = this->recordRestoreOffsetPlaceholder(op);
this->validate(initialOffset, size);
- return this->INHERITED::clipRegion(region, op);
+ return offset;
}
void SkPictureRecord::clear(SkColor color) {
+
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
+#endif
+
// op + color
- uint32_t size = 2 * kUInt32Size;
+ size_t size = 2 * kUInt32Size;
size_t initialOffset = this->addDraw(DRAW_CLEAR, &size);
- addInt(color);
+ this->addInt(color);
this->validate(initialOffset, size);
}
void SkPictureRecord::drawPaint(const SkPaint& paint) {
+
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
+#endif
+
// op + paint index
- uint32_t size = 2 * kUInt32Size;
+ size_t size = 2 * kUInt32Size;
size_t initialOffset = this->addDraw(DRAW_PAINT, &size);
SkASSERT(initialOffset+getPaintOffset(DRAW_PAINT, size) == fWriter.bytesWritten());
- addPaint(paint);
+ this->addPaint(paint);
this->validate(initialOffset, size);
}
void SkPictureRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
const SkPaint& paint) {
+
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
+#endif
+
// op + paint index + mode + count + point data
- uint32_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
+ size_t size = 4 * kUInt32Size + count * sizeof(SkPoint);
size_t initialOffset = this->addDraw(DRAW_POINTS, &size);
SkASSERT(initialOffset+getPaintOffset(DRAW_POINTS, size) == fWriter.bytesWritten());
- addPaint(paint);
- addInt(mode);
- addInt(count);
+ this->addPaint(paint);
+ if (paint.getPathEffect() != NULL) {
+ SkPathEffect::DashInfo info;
+ SkPathEffect::DashType dashType = paint.getPathEffect()->asADash(&info);
+ if (2 == count && SkPaint::kRound_Cap != paint.getStrokeCap() &&
+ SkPathEffect::kDash_DashType == dashType && 2 == info.fCount) {
+ fContentInfo.incFastPathDashEffects();
+ }
+ }
+ this->addInt(mode);
+ this->addInt(SkToInt(count));
fWriter.writeMul4(pts, count * sizeof(SkPoint));
this->validate(initialOffset, size);
}
void SkPictureRecord::drawOval(const SkRect& oval, const SkPaint& paint) {
+
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
+#endif
+
// op + paint index + rect
- uint32_t size = 2 * kUInt32Size + sizeof(oval);
+ size_t size = 2 * kUInt32Size + sizeof(oval);
size_t initialOffset = this->addDraw(DRAW_OVAL, &size);
SkASSERT(initialOffset+getPaintOffset(DRAW_OVAL, size) == fWriter.bytesWritten());
- addPaint(paint);
- addRect(oval);
+ this->addPaint(paint);
+ this->addRect(oval);
this->validate(initialOffset, size);
}
void SkPictureRecord::drawRect(const SkRect& rect, const SkPaint& paint) {
+
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
+#endif
+
// op + paint index + rect
- uint32_t size = 2 * kUInt32Size + sizeof(rect);
+ size_t size = 2 * kUInt32Size + sizeof(rect);
size_t initialOffset = this->addDraw(DRAW_RECT, &size);
SkASSERT(initialOffset+getPaintOffset(DRAW_RECT, size) == fWriter.bytesWritten());
- addPaint(paint);
- addRect(rect);
+ this->addPaint(paint);
+ this->addRect(rect);
this->validate(initialOffset, size);
}
void SkPictureRecord::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
- if (rrect.isRect()) {
+
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
+#endif
+
+ if (rrect.isRect() && kBeClever) {
this->SkPictureRecord::drawRect(rrect.getBounds(), paint);
- } else if (rrect.isOval()) {
+ } else if (rrect.isOval() && kBeClever) {
this->SkPictureRecord::drawOval(rrect.getBounds(), paint);
} else {
// op + paint index + rrect
- uint32_t initialOffset, size;
- size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
- initialOffset = this->addDraw(DRAW_RRECT, &size);
+ size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory;
+ size_t initialOffset = this->addDraw(DRAW_RRECT, &size);
SkASSERT(initialOffset+getPaintOffset(DRAW_RRECT, size) == fWriter.bytesWritten());
- addPaint(paint);
- addRRect(rrect);
+ this->addPaint(paint);
+ this->addRRect(rrect);
this->validate(initialOffset, size);
}
}
+void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
+ const SkPaint& paint) {
+
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
+#endif
+
+ // op + paint index + rrects
+ size_t size = 2 * kUInt32Size + SkRRect::kSizeInMemory * 2;
+ size_t initialOffset = this->addDraw(DRAW_DRRECT, &size);
+ SkASSERT(initialOffset+getPaintOffset(DRAW_DRRECT, size) == fWriter.bytesWritten());
+ this->addPaint(paint);
+ this->addRRect(outer);
+ this->addRRect(inner);
+ this->validate(initialOffset, size);
+}
+
void SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) {
+
+ if (paint.isAntiAlias() && !path.isConvex()) {
+ fContentInfo.incAAConcavePaths();
+
+ if (SkPaint::kStroke_Style == paint.getStyle() &&
+ 0 == paint.getStrokeWidth()) {
+ fContentInfo.incAAHairlineConcavePaths();
+ }
+ }
+
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
+#endif
+
// op + paint index + path index
- uint32_t size = 3 * kUInt32Size;
+ size_t size = 3 * kUInt32Size;
size_t initialOffset = this->addDraw(DRAW_PATH, &size);
SkASSERT(initialOffset+getPaintOffset(DRAW_PATH, size) == fWriter.bytesWritten());
- addPaint(paint);
- addPath(path);
+ this->addPaint(paint);
+ this->addPath(path);
this->validate(initialOffset, size);
}
void SkPictureRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
- const SkPaint* paint = NULL) {
+ const SkPaint* paint = NULL) {
+ if (bitmap.drawsNothing() && kBeClever) {
+ return;
+ }
+
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
+#endif
+
// op + paint index + bitmap index + left + top
- uint32_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
+ size_t size = 3 * kUInt32Size + 2 * sizeof(SkScalar);
size_t initialOffset = this->addDraw(DRAW_BITMAP, &size);
SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP, size) == fWriter.bytesWritten());
- addPaintPtr(paint);
- addBitmap(bitmap);
- addScalar(left);
- addScalar(top);
+ this->addPaintPtr(paint);
+ this->addBitmap(bitmap);
+ this->addScalar(left);
+ this->addScalar(top);
this->validate(initialOffset, size);
}
void SkPictureRecord::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
const SkRect& dst, const SkPaint* paint,
DrawBitmapRectFlags flags) {
+ if (bitmap.drawsNothing() && kBeClever) {
+ return;
+ }
+
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
+#endif
// id + paint index + bitmap index + bool for 'src' + flags
- uint32_t size = 5 * kUInt32Size;
+ size_t size = 5 * kUInt32Size;
if (NULL != src) {
size += sizeof(*src); // + rect
}
size += sizeof(dst); // + rect
size_t initialOffset = this->addDraw(DRAW_BITMAP_RECT_TO_RECT, &size);
- SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP_RECT_TO_RECT, size) == fWriter.bytesWritten());
- addPaintPtr(paint);
- addBitmap(bitmap);
- addRectPtr(src); // may be null
- addRect(dst);
- addInt(flags);
+ SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP_RECT_TO_RECT, size)
+ == fWriter.bytesWritten());
+ this->addPaintPtr(paint);
+ this->addBitmap(bitmap);
+ this->addRectPtr(src); // may be null
+ this->addRect(dst);
+ this->addInt(flags);
this->validate(initialOffset, size);
}
void SkPictureRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
const SkPaint* paint) {
- // id + paint index + bitmap index + matrix index
- uint32_t size = 4 * kUInt32Size;
+ if (bitmap.drawsNothing() && kBeClever) {
+ return;
+ }
+
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
+#endif
+
+ // id + paint index + bitmap index + matrix
+ size_t size = 3 * kUInt32Size + matrix.writeToMemory(NULL);
size_t initialOffset = this->addDraw(DRAW_BITMAP_MATRIX, &size);
SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP_MATRIX, size) == fWriter.bytesWritten());
- addPaintPtr(paint);
- addBitmap(bitmap);
- addMatrix(matrix);
+ this->addPaintPtr(paint);
+ this->addBitmap(bitmap);
+ this->addMatrix(matrix);
this->validate(initialOffset, size);
}
void SkPictureRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
const SkRect& dst, const SkPaint* paint) {
+ if (bitmap.drawsNothing() && kBeClever) {
+ return;
+ }
+
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
+#endif
+
// op + paint index + bitmap id + center + dst rect
- uint32_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst);
+ size_t size = 3 * kUInt32Size + sizeof(center) + sizeof(dst);
size_t initialOffset = this->addDraw(DRAW_BITMAP_NINE, &size);
SkASSERT(initialOffset+getPaintOffset(DRAW_BITMAP_NINE, size) == fWriter.bytesWritten());
- addPaintPtr(paint);
- addBitmap(bitmap);
- addIRect(center);
- addRect(dst);
+ this->addPaintPtr(paint);
+ this->addBitmap(bitmap);
+ this->addIRect(center);
+ this->addRect(dst);
this->validate(initialOffset, size);
}
void SkPictureRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
- const SkPaint* paint = NULL) {
+ const SkPaint* paint = NULL) {
+ if (bitmap.drawsNothing() && kBeClever) {
+ return;
+ }
+
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
+#endif
+
// op + paint index + bitmap index + left + top
- uint32_t size = 5 * kUInt32Size;
+ size_t size = 5 * kUInt32Size;
size_t initialOffset = this->addDraw(DRAW_SPRITE, &size);
SkASSERT(initialOffset+getPaintOffset(DRAW_SPRITE, size) == fWriter.bytesWritten());
- addPaintPtr(paint);
- addBitmap(bitmap);
- addInt(left);
- addInt(top);
+ this->addPaintPtr(paint);
+ this->addBitmap(bitmap);
+ this->addInt(left);
+ this->addInt(top);
this->validate(initialOffset, size);
}
@@ -1006,16 +1220,21 @@ void SkPictureRecord::ComputeFontMetricsTopBottom(const SkPaint& paint, SkScalar
void SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint, const SkFlatData& flat,
SkScalar minY, SkScalar maxY) {
WriteTopBot(paint, flat);
- addScalar(flat.topBot()[0] + minY);
- addScalar(flat.topBot()[1] + maxY);
+ this->addScalar(flat.topBot()[0] + minY);
+ this->addScalar(flat.topBot()[1] + maxY);
}
-void SkPictureRecord::drawText(const void* text, size_t byteLength, SkScalar x,
- SkScalar y, const SkPaint& paint) {
- bool fast = !paint.isVerticalText() && paint.canComputeFastBounds();
+void SkPictureRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
+ const SkPaint& paint) {
+
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
+#endif
+
+ bool fast = !paint.isVerticalText() && paint.canComputeFastBounds() && kBeClever;
// op + paint index + length + 'length' worth of chars + x + y
- uint32_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
+ size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * sizeof(SkScalar);
if (fast) {
size += 2 * sizeof(SkScalar); // + top & bottom
}
@@ -1025,18 +1244,23 @@ void SkPictureRecord::drawText(const void* text, size_t byteLength, SkScalar x,
SkASSERT(initialOffset+getPaintOffset(op, size) == fWriter.bytesWritten());
const SkFlatData* flatPaintData = addPaint(paint);
SkASSERT(flatPaintData);
- addText(text, byteLength);
- addScalar(x);
- addScalar(y);
+ this->addText(text, byteLength);
+ this->addScalar(x);
+ this->addScalar(y);
if (fast) {
- addFontMetricsTopBottom(paint, *flatPaintData, y, y);
+ this->addFontMetricsTopBottom(paint, *flatPaintData, y, y);
}
this->validate(initialOffset, size);
}
-void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
- const SkPoint pos[], const SkPaint& paint) {
- size_t points = paint.countText(text, byteLength);
+void SkPictureRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
+ const SkPaint& paint) {
+
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
+#endif
+
+ int points = paint.countText(text, byteLength);
if (0 == points)
return;
@@ -1046,7 +1270,7 @@ void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
// check if the caller really should have used drawPosTextH()
{
const SkScalar firstY = pos[0].fY;
- for (size_t index = 1; index < points; index++) {
+ for (int index = 1; index < points; index++) {
if (pos[index].fY != firstY) {
canUseDrawH = false;
if (pos[index].fY < minY) {
@@ -1058,11 +1282,11 @@ void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
}
}
- bool fastBounds = !paint.isVerticalText() && paint.canComputeFastBounds();
- bool fast = canUseDrawH && fastBounds;
+ bool fastBounds = !paint.isVerticalText() && paint.canComputeFastBounds() && kBeClever;
+ bool fast = canUseDrawH && fastBounds && kBeClever;
// op + paint index + length + 'length' worth of data + num points
- uint32_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
+ size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
if (canUseDrawH) {
if (fast) {
size += 2 * sizeof(SkScalar); // + top & bottom
@@ -1089,26 +1313,26 @@ void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
}
size_t initialOffset = this->addDraw(op, &size);
SkASSERT(initialOffset+getPaintOffset(op, size) == fWriter.bytesWritten());
- const SkFlatData* flatPaintData = addPaint(paint);
+ const SkFlatData* flatPaintData = this->addPaint(paint);
SkASSERT(flatPaintData);
- addText(text, byteLength);
- addInt(points);
+ this->addText(text, byteLength);
+ this->addInt(points);
#ifdef SK_DEBUG_SIZE
size_t start = fWriter.bytesWritten();
#endif
if (canUseDrawH) {
if (fast) {
- addFontMetricsTopBottom(paint, *flatPaintData, pos[0].fY, pos[0].fY);
+ this->addFontMetricsTopBottom(paint, *flatPaintData, pos[0].fY, pos[0].fY);
}
- addScalar(pos[0].fY);
+ this->addScalar(pos[0].fY);
SkScalar* xptr = (SkScalar*)fWriter.reserve(points * sizeof(SkScalar));
- for (size_t index = 0; index < points; index++)
+ for (int index = 0; index < points; index++)
*xptr++ = pos[index].fX;
} else {
fWriter.writeMul4(pos, points * sizeof(SkPoint));
if (fastBounds) {
- addFontMetricsTopBottom(paint, *flatPaintData, minY, maxY);
+ this->addFontMetricsTopBottom(paint, *flatPaintData, minY, maxY);
}
}
#ifdef SK_DEBUG_SIZE
@@ -1118,45 +1342,48 @@ void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
this->validate(initialOffset, size);
}
-void SkPictureRecord::drawPosTextH(const void* text, size_t byteLength,
- const SkScalar xpos[], SkScalar constY,
- const SkPaint& paint) {
+void SkPictureRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
+ SkScalar constY, const SkPaint& paint) {
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
+#endif
const SkFlatData* flatPaintData = this->getFlatPaintData(paint);
- drawPosTextHImpl(text, byteLength, xpos, constY, paint, flatPaintData);
+ this->drawPosTextHImpl(text, byteLength, xpos, constY, paint, flatPaintData);
}
void SkPictureRecord::drawPosTextHImpl(const void* text, size_t byteLength,
const SkScalar xpos[], SkScalar constY,
const SkPaint& paint, const SkFlatData* flatPaintData) {
- size_t points = paint.countText(text, byteLength);
- if (0 == points)
+ int points = paint.countText(text, byteLength);
+ if (0 == points && kBeClever) {
return;
+ }
- bool fast = !paint.isVerticalText() && paint.canComputeFastBounds();
+ bool fast = !paint.isVerticalText() && paint.canComputeFastBounds() && kBeClever;
// op + paint index + length + 'length' worth of data + num points
- uint32_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
+ size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 1 * kUInt32Size;
if (fast) {
size += 2 * sizeof(SkScalar); // + top & bottom
}
// + y + the actual points
size += 1 * kUInt32Size + points * sizeof(SkScalar);
size_t initialOffset = this->addDraw(fast ? DRAW_POS_TEXT_H_TOP_BOTTOM : DRAW_POS_TEXT_H,
- &size);
+ &size);
SkASSERT(flatPaintData);
- addFlatPaint(flatPaintData);
+ this->addFlatPaint(flatPaintData);
- addText(text, byteLength);
- addInt(points);
+ this->addText(text, byteLength);
+ this->addInt(points);
#ifdef SK_DEBUG_SIZE
size_t start = fWriter.bytesWritten();
#endif
if (fast) {
- addFontMetricsTopBottom(paint, *flatPaintData, constY, constY);
+ this->addFontMetricsTopBottom(paint, *flatPaintData, constY, constY);
}
- addScalar(constY);
+ this->addScalar(constY);
fWriter.writeMul4(xpos, points * sizeof(SkScalar));
#ifdef SK_DEBUG_SIZE
fPointBytes += fWriter.bytesWritten() - start;
@@ -1165,33 +1392,47 @@ void SkPictureRecord::drawPosTextHImpl(const void* text, size_t byteLength,
this->validate(initialOffset, size);
}
-void SkPictureRecord::drawTextOnPath(const void* text, size_t byteLength,
- const SkPath& path, const SkMatrix* matrix,
- const SkPaint& paint) {
- // op + paint index + length + 'length' worth of data + path index + matrix index
- uint32_t size = 3 * kUInt32Size + SkAlign4(byteLength) + 2 * kUInt32Size;
+void SkPictureRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
+ const SkMatrix* matrix, const SkPaint& paint) {
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
+#endif
+
+ // op + paint index + length + 'length' worth of data + path index + matrix
+ const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
+ size_t size = 3 * kUInt32Size + SkAlign4(byteLength) + kUInt32Size + m.writeToMemory(NULL);
size_t initialOffset = this->addDraw(DRAW_TEXT_ON_PATH, &size);
SkASSERT(initialOffset+getPaintOffset(DRAW_TEXT_ON_PATH, size) == fWriter.bytesWritten());
- addPaint(paint);
- addText(text, byteLength);
- addPath(path);
- addMatrixPtr(matrix);
+ this->addPaint(paint);
+ this->addText(text, byteLength);
+ this->addPath(path);
+ this->addMatrix(m);
this->validate(initialOffset, size);
}
-void SkPictureRecord::drawPicture(SkPicture& picture) {
+void SkPictureRecord::onDrawPicture(const SkPicture* picture) {
+
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
+#endif
+
// op + picture index
- uint32_t size = 2 * kUInt32Size;
+ size_t size = 2 * kUInt32Size;
size_t initialOffset = this->addDraw(DRAW_PICTURE, &size);
- addPicture(picture);
+ this->addPicture(picture);
this->validate(initialOffset, size);
}
void SkPictureRecord::drawVertices(VertexMode vmode, int vertexCount,
const SkPoint vertices[], const SkPoint texs[],
- const SkColor colors[], SkXfermode*,
+ const SkColor colors[], SkXfermode* xfer,
const uint16_t indices[], int indexCount,
const SkPaint& paint) {
+
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
+#endif
+
uint32_t flags = 0;
if (texs) {
flags |= DRAW_VERTICES_HAS_TEXS;
@@ -1202,9 +1443,15 @@ void SkPictureRecord::drawVertices(VertexMode vmode, int vertexCount,
if (indexCount > 0) {
flags |= DRAW_VERTICES_HAS_INDICES;
}
+ if (NULL != xfer) {
+ SkXfermode::Mode mode;
+ if (xfer->asMode(&mode) && SkXfermode::kModulate_Mode != mode) {
+ flags |= DRAW_VERTICES_HAS_XFER;
+ }
+ }
// op + paint index + flags + vmode + vCount + vertices
- uint32_t size = 5 * kUInt32Size + vertexCount * sizeof(SkPoint);
+ size_t size = 5 * kUInt32Size + vertexCount * sizeof(SkPoint);
if (flags & DRAW_VERTICES_HAS_TEXS) {
size += vertexCount * sizeof(SkPoint); // + uvs
}
@@ -1215,40 +1462,53 @@ void SkPictureRecord::drawVertices(VertexMode vmode, int vertexCount,
// + num indices + indices
size += 1 * kUInt32Size + SkAlign4(indexCount * sizeof(uint16_t));
}
+ if (flags & DRAW_VERTICES_HAS_XFER) {
+ size += kUInt32Size; // mode enum
+ }
size_t initialOffset = this->addDraw(DRAW_VERTICES, &size);
SkASSERT(initialOffset+getPaintOffset(DRAW_VERTICES, size) == fWriter.bytesWritten());
- addPaint(paint);
- addInt(flags);
- addInt(vmode);
- addInt(vertexCount);
- addPoints(vertices, vertexCount);
+ this->addPaint(paint);
+ this->addInt(flags);
+ this->addInt(vmode);
+ this->addInt(vertexCount);
+ this->addPoints(vertices, vertexCount);
if (flags & DRAW_VERTICES_HAS_TEXS) {
- addPoints(texs, vertexCount);
+ this->addPoints(texs, vertexCount);
}
if (flags & DRAW_VERTICES_HAS_COLORS) {
fWriter.writeMul4(colors, vertexCount * sizeof(SkColor));
}
if (flags & DRAW_VERTICES_HAS_INDICES) {
- addInt(indexCount);
+ this->addInt(indexCount);
fWriter.writePad(indices, indexCount * sizeof(uint16_t));
}
+ if (flags & DRAW_VERTICES_HAS_XFER) {
+ SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
+ (void)xfer->asMode(&mode);
+ this->addInt(mode);
+ }
this->validate(initialOffset, size);
}
void SkPictureRecord::drawData(const void* data, size_t length) {
+
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
+#endif
+
// op + length + 'length' worth of data
- uint32_t size = 2 * kUInt32Size + SkAlign4(length);
+ size_t size = 2 * kUInt32Size + SkAlign4(length);
size_t initialOffset = this->addDraw(DRAW_DATA, &size);
- addInt(length);
+ this->addInt(SkToInt(length));
fWriter.writePad(data, length);
this->validate(initialOffset, size);
}
void SkPictureRecord::beginCommentGroup(const char* description) {
// op/size + length of string + \0 terminated chars
- int length = strlen(description);
- uint32_t size = 2 * kUInt32Size + SkAlign4(length + 1);
+ size_t length = strlen(description);
+ size_t size = 2 * kUInt32Size + SkAlign4(length + 1);
size_t initialOffset = this->addDraw(BEGIN_COMMENT_GROUP, &size);
fWriter.writeString(description, length);
this->validate(initialOffset, size);
@@ -1256,9 +1516,9 @@ void SkPictureRecord::beginCommentGroup(const char* description) {
void SkPictureRecord::addComment(const char* kywd, const char* value) {
// op/size + 2x length of string + 2x \0 terminated chars
- int kywdLen = strlen(kywd);
- int valueLen = strlen(value);
- uint32_t size = 3 * kUInt32Size + SkAlign4(kywdLen + 1) + SkAlign4(valueLen + 1);
+ size_t kywdLen = strlen(kywd);
+ size_t valueLen = strlen(value);
+ size_t size = 3 * kUInt32Size + SkAlign4(kywdLen + 1) + SkAlign4(valueLen + 1);
size_t initialOffset = this->addDraw(COMMENT, &size);
fWriter.writeString(kywd, kywdLen);
fWriter.writeString(value, valueLen);
@@ -1267,28 +1527,67 @@ void SkPictureRecord::addComment(const char* kywd, const char* value) {
void SkPictureRecord::endCommentGroup() {
// op/size
- uint32_t size = 1 * kUInt32Size;
+ size_t size = 1 * kUInt32Size;
size_t initialOffset = this->addDraw(END_COMMENT_GROUP, &size);
this->validate(initialOffset, size);
}
+// [op/size] [rect] [skip offset]
+static const uint32_t kPushCullOpSize = 2 * kUInt32Size + sizeof(SkRect);
+void SkPictureRecord::onPushCull(const SkRect& cullRect) {
+ size_t size = kPushCullOpSize;
+ size_t initialOffset = this->addDraw(PUSH_CULL, &size);
+ // PUSH_CULL's size should stay constant (used to rewind).
+ SkASSERT(size == kPushCullOpSize);
+
+ this->addRect(cullRect);
+ fCullOffsetStack.push(SkToU32(fWriter.bytesWritten()));
+ this->addInt(0);
+ this->validate(initialOffset, size);
+}
+
+void SkPictureRecord::onPopCull() {
+ SkASSERT(!fCullOffsetStack.isEmpty());
+
+ uint32_t cullSkipOffset = fCullOffsetStack.top();
+ fCullOffsetStack.pop();
+
+ // Collapse empty push/pop pairs.
+ if ((size_t)(cullSkipOffset + kUInt32Size) == fWriter.bytesWritten() && kBeClever) {
+ SkASSERT(fWriter.bytesWritten() >= kPushCullOpSize);
+ SkASSERT(PUSH_CULL == peek_op(&fWriter, fWriter.bytesWritten() - kPushCullOpSize));
+ fWriter.rewindToOffset(fWriter.bytesWritten() - kPushCullOpSize);
+ return;
+ }
+
+ // op only
+ size_t size = kUInt32Size;
+ size_t initialOffset = this->addDraw(POP_CULL, &size);
+
+ // update the cull skip offset to point past this op.
+ fWriter.overwriteTAt<uint32_t>(cullSkipOffset, SkToU32(fWriter.bytesWritten()));
+
+ this->validate(initialOffset, size);
+}
+
///////////////////////////////////////////////////////////////////////////////
-void SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
+SkSurface* SkPictureRecord::onNewSurface(const SkImageInfo& info) {
+ return NULL;
+}
+
+int SkPictureRecord::addBitmap(const SkBitmap& bitmap) {
const int index = fBitmapHeap->insert(bitmap);
// In debug builds, a bad return value from insert() will crash, allowing for debugging. In
// release builds, the invalid value will be recorded so that the reader will know that there
// was a problem.
SkASSERT(index != SkBitmapHeap::INVALID_SLOT);
- addInt(index);
+ this->addInt(index);
+ return index;
}
void SkPictureRecord::addMatrix(const SkMatrix& matrix) {
- addMatrixPtr(&matrix);
-}
-
-void SkPictureRecord::addMatrixPtr(const SkMatrix* matrix) {
- this->addInt(matrix ? fMatrices.find(*matrix) : 0);
+ fWriter.writeMatrix(matrix);
}
const SkFlatData* SkPictureRecord::getFlatPaintData(const SkPaint& paint) {
@@ -1296,6 +1595,10 @@ const SkFlatData* SkPictureRecord::getFlatPaintData(const SkPaint& paint) {
}
const SkFlatData* SkPictureRecord::addPaintPtr(const SkPaint* paint) {
+ if (NULL != paint && NULL != paint->getPathEffect()) {
+ fContentInfo.incPaintWithPathEffectUses();
+ }
+
const SkFlatData* data = paint ? getFlatPaintData(*paint) : NULL;
this->addFlatPaint(data);
return data;
@@ -1306,22 +1609,30 @@ void SkPictureRecord::addFlatPaint(const SkFlatData* flatPaint) {
this->addInt(index);
}
-void SkPictureRecord::addPath(const SkPath& path) {
+int SkPictureRecord::addPathToHeap(const SkPath& path) {
if (NULL == fPathHeap) {
- fPathHeap = SkNEW(SkPathHeap);
+ fPathHeap.reset(SkNEW(SkPathHeap));
}
- addInt(fPathHeap->append(path));
+#ifdef SK_DEDUP_PICTURE_PATHS
+ return fPathHeap->insert(path);
+#else
+ return fPathHeap->append(path);
+#endif
+}
+
+void SkPictureRecord::addPath(const SkPath& path) {
+ this->addInt(this->addPathToHeap(path));
}
-void SkPictureRecord::addPicture(SkPicture& picture) {
- int index = fPictureRefs.find(&picture);
+void SkPictureRecord::addPicture(const SkPicture* picture) {
+ int index = fPictureRefs.find(picture);
if (index < 0) { // not found
index = fPictureRefs.count();
- *fPictureRefs.append() = &picture;
- picture.ref();
+ *fPictureRefs.append() = picture;
+ picture->ref();
}
// follow the convention of recording a 1-based index
- addInt(index + 1);
+ this->addInt(index + 1);
}
void SkPictureRecord::addPoint(const SkPoint& point) {
@@ -1343,6 +1654,11 @@ void SkPictureRecord::addPoints(const SkPoint pts[], int count) {
#endif
}
+void SkPictureRecord::addNoOp() {
+ size_t size = kUInt32Size; // op
+ this->addDraw(NOOP, &size);
+}
+
void SkPictureRecord::addRect(const SkRect& rect) {
#ifdef SK_DEBUG_SIZE
size_t start = fWriter.bytesWritten();
@@ -1375,14 +1691,14 @@ void SkPictureRecord::addRRect(const SkRRect& rrect) {
}
void SkPictureRecord::addRegion(const SkRegion& region) {
- addInt(fRegions.find(region));
+ fWriter.writeRegion(region);
}
void SkPictureRecord::addText(const void* text, size_t byteLength) {
#ifdef SK_DEBUG_SIZE
size_t start = fWriter.bytesWritten();
#endif
- addInt(byteLength);
+ addInt(SkToInt(byteLength));
fWriter.writePad(text, byteLength);
#ifdef SK_DEBUG_SIZE
fTextBytes += fWriter.bytesWritten() - start;
diff --git a/chromium/third_party/skia/src/core/SkPictureRecord.h b/chromium/third_party/skia/src/core/SkPictureRecord.h
index da79fc1bbb0..7e5c5c64109 100644
--- a/chromium/third_party/skia/src/core/SkPictureRecord.h
+++ b/chromium/third_party/skia/src/core/SkPictureRecord.h
@@ -1,23 +1,27 @@
-
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
+
#ifndef SkPictureRecord_DEFINED
#define SkPictureRecord_DEFINED
#include "SkCanvas.h"
#include "SkFlattenable.h"
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+#include "SkMatrixClipStateMgr.h"
+#endif
#include "SkPathHeap.h"
#include "SkPicture.h"
+#include "SkPicturePlayback.h"
#include "SkPictureFlat.h"
#include "SkTemplates.h"
#include "SkWriter32.h"
-class SkPictureStateTree;
class SkBBoxHierarchy;
+class SkPictureStateTree;
// These macros help with packing and unpacking a single byte value and
// a 3 byte value into/out of a uint32_t
@@ -30,24 +34,9 @@ class SkBBoxHierarchy;
class SkPictureRecord : public SkCanvas {
public:
- SkPictureRecord(uint32_t recordFlags, SkBaseDevice*);
+ SkPictureRecord(const SkISize& dimensions, uint32_t recordFlags);
virtual ~SkPictureRecord();
- virtual SkBaseDevice* setDevice(SkBaseDevice* device) SK_OVERRIDE;
-
- virtual int save(SaveFlags) SK_OVERRIDE;
- virtual int saveLayer(const SkRect* bounds, const SkPaint*, SaveFlags) SK_OVERRIDE;
- virtual void restore() SK_OVERRIDE;
- virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE;
- virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE;
- virtual bool rotate(SkScalar degrees) SK_OVERRIDE;
- virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE;
- virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE;
- virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE;
- virtual bool clipRect(const SkRect&, SkRegion::Op, bool) SK_OVERRIDE;
- virtual bool clipRRect(const SkRRect&, SkRegion::Op, bool) SK_OVERRIDE;
- virtual bool clipPath(const SkPath&, SkRegion::Op, bool) SK_OVERRIDE;
- virtual bool clipRegion(const SkRegion& region, SkRegion::Op op) SK_OVERRIDE;
virtual void clear(SkColor) SK_OVERRIDE;
virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
virtual void drawPoints(PointMode, size_t count, const SkPoint pts[],
@@ -67,16 +56,6 @@ public:
const SkRect& dst, const SkPaint*) SK_OVERRIDE;
virtual void drawSprite(const SkBitmap&, int left, int top,
const SkPaint*) SK_OVERRIDE;
- virtual void drawText(const void* text, size_t byteLength, SkScalar x,
- SkScalar y, const SkPaint&) SK_OVERRIDE;
- virtual void drawPosText(const void* text, size_t byteLength,
- const SkPoint pos[], const SkPaint&) SK_OVERRIDE;
- virtual void drawPosTextH(const void* text, size_t byteLength,
- const SkScalar xpos[], SkScalar constY, const SkPaint&) SK_OVERRIDE;
- virtual void drawTextOnPath(const void* text, size_t byteLength,
- const SkPath& path, const SkMatrix* matrix,
- const SkPaint&) SK_OVERRIDE;
- virtual void drawPicture(SkPicture& picture) SK_OVERRIDE;
virtual void drawVertices(VertexMode, int vertexCount,
const SkPoint vertices[], const SkPoint texs[],
const SkColor colors[], SkXfermode*,
@@ -91,10 +70,32 @@ public:
void addFontMetricsTopBottom(const SkPaint& paint, const SkFlatData&,
SkScalar minY, SkScalar maxY);
- const SkTDArray<SkPicture* >& getPictureRefs() const {
+ const SkTDArray<const SkPicture* >& getPictureRefs() const {
return fPictureRefs;
}
+ SkData* opData(bool deepCopy) const {
+ this->validate(fWriter.bytesWritten(), 0);
+
+ if (fWriter.bytesWritten() == 0) {
+ return SkData::NewEmpty();
+ }
+
+ if (deepCopy) {
+ return SkData::NewWithCopy(fWriter.contiguousArray(), fWriter.bytesWritten());
+ }
+
+ return fWriter.snapshotAsData();
+ }
+
+ const SkPathHeap* pathHeap() const {
+ return fPathHeap.get();
+ }
+
+ const SkPictureContentInfo& contentInfo() const {
+ return fContentInfo;
+ }
+
void setFlags(uint32_t recordFlags) {
fRecordFlags = recordFlags;
}
@@ -106,17 +107,27 @@ public:
void beginRecording();
void endRecording();
+ void internalOnly_EnableOpts(bool optsEnabled) {
+ fOptsEnabled = optsEnabled;
+ }
+
+protected:
+ void addNoOp();
+
private:
void handleOptimization(int opt);
- void recordRestoreOffsetPlaceholder(SkRegion::Op);
- void fillRestoreOffsetPlaceholdersForCurrentStackLevel(
- uint32_t restoreOffset);
+ size_t recordRestoreOffsetPlaceholder(SkRegion::Op);
+ void fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset);
+#ifndef SK_COLLAPSE_MATRIX_CLIP_STATE
SkTDArray<int32_t> fRestoreOffsetStack;
int fFirstSavedLayerIndex;
enum {
kNoSavedLayerIndex = -1
};
+#endif
+
+ SkTDArray<uint32_t> fCullOffsetStack;
/*
* Write the 'drawType' operation and chunk size to the skp. 'size'
@@ -130,7 +141,7 @@ private:
* end of blocks could go unused). Possibly add a second addDraw that
* operates in this manner.
*/
- size_t addDraw(DrawType drawType, uint32_t* size) {
+ size_t addDraw(DrawType drawType, size_t* size) {
size_t offset = fWriter.bytesWritten();
this->predrawNotify();
@@ -145,9 +156,9 @@ private:
if (0 != (*size & ~MASK_24) || *size == MASK_24) {
fWriter.writeInt(PACK_8_24(drawType, MASK_24));
*size += 1;
- fWriter.writeInt(*size);
+ fWriter.writeInt(SkToU32(*size));
} else {
- fWriter.writeInt(PACK_8_24(drawType, *size));
+ fWriter.writeInt(PACK_8_24(drawType, SkToU32(*size)));
}
return offset;
@@ -160,14 +171,14 @@ private:
fWriter.writeScalar(scalar);
}
- void addBitmap(const SkBitmap& bitmap);
+ // The command at 'offset' in the skp uses the specified bitmap
+ int addBitmap(const SkBitmap& bitmap);
void addMatrix(const SkMatrix& matrix);
- void addMatrixPtr(const SkMatrix* matrix);
const SkFlatData* addPaint(const SkPaint& paint) { return this->addPaintPtr(&paint); }
const SkFlatData* addPaintPtr(const SkPaint* paint);
void addFlatPaint(const SkFlatData* flatPaint);
void addPath(const SkPath& path);
- void addPicture(SkPicture& picture);
+ void addPicture(const SkPicture* picture);
void addPoint(const SkPoint& point);
void addPoints(const SkPoint pts[], int count);
void addRect(const SkRect& rect);
@@ -211,12 +222,44 @@ private:
void validateRegions() const;
#else
public:
- void validate(size_t initialOffset, uint32_t size) const {
+ void validate(size_t initialOffset, size_t size) const {
SkASSERT(fWriter.bytesWritten() == initialOffset + size);
}
#endif
protected:
+ virtual SkSurface* onNewSurface(const SkImageInfo&) SK_OVERRIDE;
+ const void* onPeekPixels(SkImageInfo*, size_t*) SK_OVERRIDE {
+ return NULL;
+ }
+
+ virtual void willSave(SaveFlags) SK_OVERRIDE;
+ virtual SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SaveFlags) SK_OVERRIDE;
+ virtual void willRestore() SK_OVERRIDE;
+
+ virtual void didConcat(const SkMatrix&) SK_OVERRIDE;
+ virtual void didSetMatrix(const SkMatrix&) SK_OVERRIDE;
+
+ virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) SK_OVERRIDE;
+ virtual void onPushCull(const SkRect&) SK_OVERRIDE;
+ virtual void onPopCull() SK_OVERRIDE;
+
+ virtual void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
+ const SkPaint&) SK_OVERRIDE;
+ virtual void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
+ const SkPaint&) SK_OVERRIDE;
+ virtual void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
+ SkScalar constY, const SkPaint&) SK_OVERRIDE;
+ virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
+ const SkMatrix* matrix, const SkPaint&) SK_OVERRIDE;
+
+ virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
+ virtual void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
+ virtual void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
+ virtual void onClipRegion(const SkRegion&, SkRegion::Op) SK_OVERRIDE;
+
+ virtual void onDrawPicture(const SkPicture* picture) SK_OVERRIDE;
+
// Return fontmetrics.fTop,fBottom in topbot[0,1], after they have been
// tweaked by paint.computeFastBounds().
static void ComputeFontMetricsTopBottom(const SkPaint& paint, SkScalar topbot[2]);
@@ -238,6 +281,22 @@ protected:
const SkScalar xpos[], SkScalar constY,
const SkPaint& paint, const SkFlatData* flatPaintData);
+ int addPathToHeap(const SkPath& path); // does not write to ops stream
+
+ // These entry points allow the writing of matrices, clips, saves &
+ // restores to be deferred (e.g., if the MC state is being collapsed and
+ // only written out as needed).
+ void recordConcat(const SkMatrix& matrix);
+ void recordTranslate(const SkMatrix& matrix);
+ void recordScale(const SkMatrix& matrix);
+ size_t recordClipRect(const SkRect& rect, SkRegion::Op op, bool doAA);
+ size_t recordClipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA);
+ size_t recordClipPath(int pathID, SkRegion::Op op, bool doAA);
+ size_t recordClipRegion(const SkRegion& region, SkRegion::Op op);
+ void recordSave(SaveFlags flags);
+ void recordSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags);
+ void recordRestore(bool fillInSkips = true);
+
// These are set to NULL in our constructor, but may be changed by
// subclasses, in which case they will be SkSafeUnref'd in our destructor.
SkBBoxHierarchy* fBoundingHierarchy;
@@ -247,24 +306,32 @@ protected:
SkBitmapHeap* fBitmapHeap;
private:
+ friend class MatrixClipState; // for access to *Impl methods
+ friend class SkMatrixClipStateMgr; // for access to *Impl methods
+
+ SkPictureContentInfo fContentInfo;
+ SkAutoTUnref<SkPathHeap> fPathHeap;
+
SkChunkFlatController fFlattenableHeap;
- SkMatrixDictionary fMatrices;
SkPaintDictionary fPaints;
- SkRegionDictionary fRegions;
- SkPathHeap* fPathHeap; // reference counted
SkWriter32 fWriter;
// we ref each item in these arrays
- SkTDArray<SkPicture*> fPictureRefs;
+ SkTDArray<const SkPicture*> fPictureRefs;
uint32_t fRecordFlags;
- int fInitialSaveCount;
+ bool fOptsEnabled;
+ int fInitialSaveCount;
friend class SkPicturePlayback;
friend class SkPictureTester; // for unit testing
+#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
+ SkMatrixClipStateMgr fMCMgr;
+#endif
+
typedef SkCanvas INHERITED;
};
diff --git a/chromium/third_party/skia/src/core/SkPictureRecorder.cpp b/chromium/third_party/skia/src/core/SkPictureRecorder.cpp
new file mode 100644
index 00000000000..f1423e3992e
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkPictureRecorder.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkBBoxHierarchyRecord.h"
+#include "SkPicturePlayback.h"
+#include "SkPictureRecord.h"
+#include "SkPictureRecorder.h"
+#include "SkRecord.h"
+#include "SkRecordDraw.h"
+#include "SkRecorder.h"
+#include "SkTypes.h"
+
+SkPictureRecorder::~SkPictureRecorder() {
+ this->reset();
+}
+
+void SkPictureRecorder::reset() {
+ SkSafeSetNull(fPictureRecord);
+ SkSafeSetNull(fRecorder);
+ SkDELETE(fRecord);
+ fRecord = NULL;
+}
+
+SkCanvas* SkPictureRecorder::beginRecording(int width, int height,
+ SkBBHFactory* bbhFactory /* = NULL */,
+ uint32_t recordFlags /* = 0 */) {
+ this->reset(); // terminate any prior recording(s)
+ fWidth = width;
+ fHeight = height;
+
+ const SkISize size = SkISize::Make(width, height);
+
+ if (NULL != bbhFactory) {
+ SkAutoTUnref<SkBBoxHierarchy> tree((*bbhFactory)(width, height));
+ SkASSERT(NULL != tree);
+ fPictureRecord = SkNEW_ARGS(SkBBoxHierarchyRecord, (size, recordFlags, tree.get()));
+ } else {
+ fPictureRecord = SkNEW_ARGS(SkPictureRecord, (size, recordFlags));
+ }
+
+ fPictureRecord->beginRecording();
+ return this->getRecordingCanvas();
+}
+
+SkCanvas* SkPictureRecorder::EXPERIMENTAL_beginRecording(int width, int height,
+ SkBBHFactory* bbhFactory /* = NULL */) {
+ this->reset();
+ fWidth = width;
+ fHeight = height;
+
+ // TODO: plumb bbhFactory through
+ fRecord = SkNEW(SkRecord);
+ fRecorder = SkNEW_ARGS(SkRecorder, (fRecord, width, height));
+ return this->getRecordingCanvas();
+}
+
+SkCanvas* SkPictureRecorder::getRecordingCanvas() {
+ if (NULL != fRecorder) {
+ return fRecorder;
+ }
+ return fPictureRecord;
+}
+
+SkPicture* SkPictureRecorder::endRecording() {
+ SkPicture* picture = NULL;
+
+ if (NULL != fRecorder) {
+ // TODO: picture = SkNEW_ARGS(SkPicture, (fWidth, fHeight, fRecord));
+ // fRecord = NULL;
+ }
+
+ if (NULL != fPictureRecord) {
+ fPictureRecord->endRecording();
+ const bool deepCopyOps = false;
+ picture = SkNEW_ARGS(SkPicture, (fWidth, fHeight, *fPictureRecord, deepCopyOps));
+ }
+
+ this->reset();
+ return picture;
+}
+
+void SkPictureRecorder::internalOnly_EnableOpts(bool enableOpts) {
+ if (NULL != fPictureRecord) {
+ fPictureRecord->internalOnly_EnableOpts(enableOpts);
+ }
+}
+
+void SkPictureRecorder::partialReplay(SkCanvas* canvas) const {
+ if (NULL == canvas) {
+ return;
+ }
+
+ if (NULL != fRecorder) {
+ SkRecordDraw(*fRecord, canvas);
+ }
+
+ if (NULL != fPictureRecord) {
+ const bool deepCopyOps = true;
+ SkPicture picture(fWidth, fHeight, *fPictureRecord, deepCopyOps);
+ picture.draw(canvas);
+ }
+}
diff --git a/chromium/third_party/skia/src/core/SkPictureShader.cpp b/chromium/third_party/skia/src/core/SkPictureShader.cpp
new file mode 100644
index 00000000000..2de8d4d4cb4
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkPictureShader.cpp
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkPictureShader.h"
+
+#include "SkBitmap.h"
+#include "SkBitmapProcShader.h"
+#include "SkCanvas.h"
+#include "SkMatrixUtils.h"
+#include "SkPicture.h"
+#include "SkReadBuffer.h"
+
+#if SK_SUPPORT_GPU
+#include "GrContext.h"
+#endif
+
+SkPictureShader::SkPictureShader(SkPicture* picture, TileMode tmx, TileMode tmy,
+ const SkMatrix* localMatrix)
+ : INHERITED(localMatrix)
+ , fPicture(SkRef(picture))
+ , fTmx(tmx)
+ , fTmy(tmy) { }
+
+SkPictureShader::SkPictureShader(SkReadBuffer& buffer)
+ : INHERITED(buffer) {
+ fTmx = static_cast<SkShader::TileMode>(buffer.read32());
+ fTmy = static_cast<SkShader::TileMode>(buffer.read32());
+ fPicture = SkPicture::CreateFromBuffer(buffer);
+}
+
+SkPictureShader::~SkPictureShader() {
+ fPicture->unref();
+}
+
+SkPictureShader* SkPictureShader::Create(SkPicture* picture, TileMode tmx, TileMode tmy,
+ const SkMatrix* localMatrix) {
+ if (!picture || 0 == picture->width() || 0 == picture->height()) {
+ return NULL;
+ }
+ return SkNEW_ARGS(SkPictureShader, (picture, tmx, tmy, localMatrix));
+}
+
+void SkPictureShader::flatten(SkWriteBuffer& buffer) const {
+ this->INHERITED::flatten(buffer);
+
+ buffer.write32(fTmx);
+ buffer.write32(fTmy);
+ fPicture->flatten(buffer);
+}
+
+SkShader* SkPictureShader::refBitmapShader(const SkMatrix& matrix, const SkMatrix* localM) const {
+ SkASSERT(fPicture && fPicture->width() > 0 && fPicture->height() > 0);
+
+ SkMatrix m;
+ m.setConcat(matrix, this->getLocalMatrix());
+ if (localM) {
+ m.preConcat(*localM);
+ }
+
+ // Use a rotation-invariant scale
+ SkPoint scale;
+ if (!SkDecomposeUpper2x2(m, NULL, &scale, NULL)) {
+ // Decomposition failed, use an approximation.
+ scale.set(SkScalarSqrt(m.getScaleX() * m.getScaleX() + m.getSkewX() * m.getSkewX()),
+ SkScalarSqrt(m.getScaleY() * m.getScaleY() + m.getSkewY() * m.getSkewY()));
+ }
+ SkSize scaledSize = SkSize::Make(scale.x() * fPicture->width(), scale.y() * fPicture->height());
+
+ SkISize tileSize = scaledSize.toRound();
+ if (tileSize.isEmpty()) {
+ return NULL;
+ }
+
+ // The actual scale, compensating for rounding.
+ SkSize tileScale = SkSize::Make(SkIntToScalar(tileSize.width()) / fPicture->width(),
+ SkIntToScalar(tileSize.height()) / fPicture->height());
+
+ SkAutoMutexAcquire ama(fCachedBitmapShaderMutex);
+
+ // TODO(fmalita): remove fCachedLocalMatrix from this key after getLocalMatrix is removed.
+ if (!fCachedBitmapShader || tileScale != fCachedTileScale ||
+ this->getLocalMatrix() != fCachedLocalMatrix) {
+ SkBitmap bm;
+ if (!bm.allocN32Pixels(tileSize.width(), tileSize.height())) {
+ return NULL;
+ }
+ bm.eraseColor(SK_ColorTRANSPARENT);
+
+ SkCanvas canvas(bm);
+ canvas.scale(tileScale.width(), tileScale.height());
+ canvas.drawPicture(fPicture);
+
+ fCachedTileScale = tileScale;
+ fCachedLocalMatrix = this->getLocalMatrix();
+
+ SkMatrix shaderMatrix = this->getLocalMatrix();
+ shaderMatrix.preScale(1 / tileScale.width(), 1 / tileScale.height());
+ fCachedBitmapShader.reset(CreateBitmapShader(bm, fTmx, fTmy, &shaderMatrix));
+ }
+
+ // Increment the ref counter inside the mutex to ensure the returned pointer is still valid.
+ // Otherwise, the pointer may have been overwritten on a different thread before the object's
+ // ref count was incremented.
+ fCachedBitmapShader.get()->ref();
+ return fCachedBitmapShader;
+}
+
+size_t SkPictureShader::contextSize() const {
+ return sizeof(PictureShaderContext);
+}
+
+SkShader::Context* SkPictureShader::onCreateContext(const ContextRec& rec, void* storage) const {
+ SkAutoTUnref<SkShader> bitmapShader(this->refBitmapShader(*rec.fMatrix, rec.fLocalMatrix));
+ if (NULL == bitmapShader.get()) {
+ return NULL;
+ }
+ return PictureShaderContext::Create(storage, *this, rec, bitmapShader);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+SkShader::Context* SkPictureShader::PictureShaderContext::Create(void* storage,
+ const SkPictureShader& shader, const ContextRec& rec, SkShader* bitmapShader) {
+ PictureShaderContext* ctx = SkNEW_PLACEMENT_ARGS(storage, PictureShaderContext,
+ (shader, rec, bitmapShader));
+ if (NULL == ctx->fBitmapShaderContext) {
+ ctx->~PictureShaderContext();
+ ctx = NULL;
+ }
+ return ctx;
+}
+
+SkPictureShader::PictureShaderContext::PictureShaderContext(
+ const SkPictureShader& shader, const ContextRec& rec, SkShader* bitmapShader)
+ : INHERITED(shader, rec)
+ , fBitmapShader(SkRef(bitmapShader))
+{
+ fBitmapShaderContextStorage = sk_malloc_throw(bitmapShader->contextSize());
+ fBitmapShaderContext = bitmapShader->createContext(rec, fBitmapShaderContextStorage);
+ //if fBitmapShaderContext is null, we are invalid
+}
+
+SkPictureShader::PictureShaderContext::~PictureShaderContext() {
+ if (fBitmapShaderContext) {
+ fBitmapShaderContext->~Context();
+ }
+ sk_free(fBitmapShaderContextStorage);
+}
+
+uint32_t SkPictureShader::PictureShaderContext::getFlags() const {
+ SkASSERT(fBitmapShaderContext);
+ return fBitmapShaderContext->getFlags();
+}
+
+SkShader::Context::ShadeProc SkPictureShader::PictureShaderContext::asAShadeProc(void** ctx) {
+ SkASSERT(fBitmapShaderContext);
+ return fBitmapShaderContext->asAShadeProc(ctx);
+}
+
+void SkPictureShader::PictureShaderContext::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
+ SkASSERT(fBitmapShaderContext);
+ fBitmapShaderContext->shadeSpan(x, y, dstC, count);
+}
+
+void SkPictureShader::PictureShaderContext::shadeSpan16(int x, int y, uint16_t dstC[], int count) {
+ SkASSERT(fBitmapShaderContext);
+ fBitmapShaderContext->shadeSpan16(x, y, dstC, count);
+}
+
+#ifndef SK_IGNORE_TO_STRING
+void SkPictureShader::toString(SkString* str) const {
+ static const char* gTileModeName[SkShader::kTileModeCount] = {
+ "clamp", "repeat", "mirror"
+ };
+
+ str->appendf("PictureShader: [%d:%d] ",
+ fPicture ? fPicture->width() : 0,
+ fPicture ? fPicture->height() : 0);
+
+ str->appendf("(%s, %s)", gTileModeName[fTmx], gTileModeName[fTmy]);
+
+ this->INHERITED::toString(str);
+}
+#endif
+
+#if SK_SUPPORT_GPU
+bool SkPictureShader::asNewEffect(GrContext* context, const SkPaint& paint,
+ const SkMatrix* localMatrix, GrColor* grColor,
+ GrEffectRef** grEffect) const {
+ SkAutoTUnref<SkShader> bitmapShader(this->refBitmapShader(context->getMatrix(), localMatrix));
+ if (!bitmapShader) {
+ return false;
+ }
+ return bitmapShader->asNewEffect(context, paint, NULL, grColor, grEffect);
+}
+#else
+bool SkPictureShader::asNewEffect(GrContext* context, const SkPaint& paint,
+ const SkMatrix* localMatrix, GrColor* grColor,
+ GrEffectRef** grEffect) const {
+ SkDEBUGFAIL("Should not call in GPU-less build");
+ return false;
+}
+#endif
diff --git a/chromium/third_party/skia/src/core/SkPictureShader.h b/chromium/third_party/skia/src/core/SkPictureShader.h
new file mode 100644
index 00000000000..294ffcd6b95
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkPictureShader.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPictureShader_DEFINED
+#define SkPictureShader_DEFINED
+
+#include "SkShader.h"
+
+class SkBitmap;
+class SkPicture;
+
+/*
+ * An SkPictureShader can be used to draw SkPicture-based patterns.
+ *
+ * The SkPicture is first rendered into a tile, which is then used to shade the area according
+ * to specified tiling rules.
+ */
+class SkPictureShader : public SkShader {
+public:
+ static SkPictureShader* Create(SkPicture*, TileMode, TileMode, const SkMatrix* = NULL);
+ virtual ~SkPictureShader();
+
+ virtual size_t contextSize() const SK_OVERRIDE;
+
+ SK_TO_STRING_OVERRIDE()
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPictureShader)
+
+ bool asNewEffect(GrContext*, const SkPaint&, const SkMatrix*, GrColor*, GrEffectRef**)
+ const SK_OVERRIDE;
+
+protected:
+ SkPictureShader(SkReadBuffer&);
+ virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
+ virtual Context* onCreateContext(const ContextRec&, void* storage) const SK_OVERRIDE;
+
+private:
+ SkPictureShader(SkPicture*, TileMode, TileMode, const SkMatrix* = NULL);
+
+ SkShader* refBitmapShader(const SkMatrix&, const SkMatrix* localMatrix) const;
+
+ SkPicture* fPicture;
+ TileMode fTmx, fTmy;
+
+ mutable SkMutex fCachedBitmapShaderMutex;
+ mutable SkAutoTUnref<SkShader> fCachedBitmapShader;
+ mutable SkSize fCachedTileScale;
+ mutable SkMatrix fCachedLocalMatrix;
+
+ class PictureShaderContext : public SkShader::Context {
+ public:
+ static Context* Create(void* storage, const SkPictureShader&, const ContextRec&,
+ SkShader* bitmapShader);
+
+ virtual ~PictureShaderContext();
+
+ virtual uint32_t getFlags() const SK_OVERRIDE;
+
+ virtual ShadeProc asAShadeProc(void** ctx) SK_OVERRIDE;
+ virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE;
+ virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count) SK_OVERRIDE;
+
+ private:
+ PictureShaderContext(const SkPictureShader&, const ContextRec&, SkShader* bitmapShader);
+
+ SkAutoTUnref<SkShader> fBitmapShader;
+ SkShader::Context* fBitmapShaderContext;
+ void* fBitmapShaderContextStorage;
+
+ typedef SkShader::Context INHERITED;
+ };
+
+ typedef SkShader INHERITED;
+};
+
+#endif // SkPictureShader_DEFINED
diff --git a/chromium/third_party/skia/src/core/SkPictureStateTree.cpp b/chromium/third_party/skia/src/core/SkPictureStateTree.cpp
index 2f3b943cddc..fdd86464a9e 100644
--- a/chromium/third_party/skia/src/core/SkPictureStateTree.cpp
+++ b/chromium/third_party/skia/src/core/SkPictureStateTree.cpp
@@ -27,10 +27,10 @@ SkPictureStateTree::SkPictureStateTree()
SkPictureStateTree::~SkPictureStateTree() {
}
-SkPictureStateTree::Draw* SkPictureStateTree::appendDraw(uint32_t offset) {
+SkPictureStateTree::Draw* SkPictureStateTree::appendDraw(size_t offset) {
Draw* draw = static_cast<Draw*>(fAlloc.allocThrow(sizeof(Draw)));
*draw = fCurrentState;
- draw->fOffset = offset;
+ draw->fOffset = SkToU32(offset);
return draw;
}
@@ -39,7 +39,7 @@ void SkPictureStateTree::appendSave() {
fCurrentState.fNode->fFlags |= Node::kSave_Flag;
}
-void SkPictureStateTree::appendSaveLayer(uint32_t offset) {
+void SkPictureStateTree::appendSaveLayer(size_t offset) {
*static_cast<Draw*>(fStateStack.push_back()) = fCurrentState;
this->appendNode(offset);
fCurrentState.fNode->fFlags |= Node::kSaveLayer_Flag;
@@ -69,7 +69,7 @@ void SkPictureStateTree::appendTransform(const SkMatrix& trans) {
fCurrentState.fMatrix = m;
}
-void SkPictureStateTree::appendClip(uint32_t offset) {
+void SkPictureStateTree::appendClip(size_t offset) {
this->appendNode(offset);
}
@@ -78,9 +78,9 @@ SkPictureStateTree::Iterator SkPictureStateTree::getIterator(const SkTDArray<voi
return Iterator(draws, canvas, &fRoot);
}
-void SkPictureStateTree::appendNode(uint32_t offset) {
+void SkPictureStateTree::appendNode(size_t offset) {
Node* n = static_cast<Node*>(fAlloc.allocThrow(sizeof(Node)));
- n->fOffset = offset;
+ n->fOffset = SkToU32(offset);
n->fFlags = 0;
n->fParent = fCurrentState.fNode;
n->fLevel = fCurrentState.fNode->fLevel + 1;
@@ -99,26 +99,53 @@ SkPictureStateTree::Iterator::Iterator(const SkTDArray<void*>& draws, SkCanvas*
, fValid(true) {
}
-uint32_t SkPictureStateTree::Iterator::draw() {
+void SkPictureStateTree::Iterator::setCurrentMatrix(const SkMatrix* matrix) {
+ SkASSERT(NULL != matrix);
+
+ if (matrix == fCurrentMatrix) {
+ return;
+ }
+
+ // The matrix is in recording space, but we also inherit
+ // a playback matrix from out target canvas.
+ SkMatrix m = *matrix;
+ m.postConcat(fPlaybackMatrix);
+ fCanvas->setMatrix(m);
+ fCurrentMatrix = matrix;
+}
+
+uint32_t SkPictureStateTree::Iterator::finish() {
+ if (fCurrentNode->fFlags & Node::kSaveLayer_Flag) {
+ fCanvas->restore();
+ }
+
+ for (fCurrentNode = fCurrentNode->fParent; fCurrentNode;
+ fCurrentNode = fCurrentNode->fParent) {
+ // Note: we call restore() twice when both flags are set.
+ if (fCurrentNode->fFlags & Node::kSave_Flag) {
+ fCanvas->restore();
+ }
+ if (fCurrentNode->fFlags & Node::kSaveLayer_Flag) {
+ fCanvas->restore();
+ }
+ }
+
+ fCanvas->setMatrix(fPlaybackMatrix);
+ fCurrentMatrix = NULL;
+ return kDrawComplete;
+}
+
+uint32_t SkPictureStateTree::Iterator::nextDraw() {
SkASSERT(this->isValid());
if (fPlaybackIndex >= fDraws->count()) {
- // restore back to where we started
- if (fCurrentNode->fFlags & Node::kSaveLayer_Flag) { fCanvas->restore(); }
- fCurrentNode = fCurrentNode->fParent;
- while (NULL != fCurrentNode) {
- if (fCurrentNode->fFlags & Node::kSave_Flag) { fCanvas->restore(); }
- if (fCurrentNode->fFlags & Node::kSaveLayer_Flag) { fCanvas->restore(); }
- fCurrentNode = fCurrentNode->fParent;
- }
- fCanvas->setMatrix(fPlaybackMatrix);
- return kDrawComplete;
+ return this->finish();
}
Draw* draw = static_cast<Draw*>((*fDraws)[fPlaybackIndex]);
Node* targetNode = draw->fNode;
if (fSave) {
- fCanvas->save(SkCanvas::kClip_SaveFlag);
+ fCanvas->save();
fSave = false;
}
@@ -137,8 +164,16 @@ uint32_t SkPictureStateTree::Iterator::draw() {
uint16_t currentLevel = tmp->fLevel;
uint16_t targetLevel = ancestor->fLevel;
if (currentLevel >= targetLevel) {
- if (tmp != fCurrentNode && tmp->fFlags & Node::kSave_Flag) { fCanvas->restore(); }
- if (tmp->fFlags & Node::kSaveLayer_Flag) { fCanvas->restore(); }
+ if (tmp != fCurrentNode && tmp->fFlags & Node::kSave_Flag) {
+ fCanvas->restore();
+ // restore() may change the matrix, so we need to reapply.
+ fCurrentMatrix = NULL;
+ }
+ if (tmp->fFlags & Node::kSaveLayer_Flag) {
+ fCanvas->restore();
+ // restore() may change the matrix, so we need to reapply.
+ fCurrentMatrix = NULL;
+ }
tmp = tmp->fParent;
}
if (currentLevel <= targetLevel) {
@@ -148,8 +183,14 @@ uint32_t SkPictureStateTree::Iterator::draw() {
}
if (ancestor->fFlags & Node::kSave_Flag) {
- if (fCurrentNode != ancestor) { fCanvas->restore(); }
- if (targetNode != ancestor) { fCanvas->save(SkCanvas::kClip_SaveFlag); }
+ if (fCurrentNode != ancestor) {
+ fCanvas->restore();
+ // restore() may change the matrix, so we need to reapply.
+ fCurrentMatrix = NULL;
+ }
+ if (targetNode != ancestor) {
+ fCanvas->save();
+ }
}
fCurrentNode = ancestor;
}
@@ -157,29 +198,18 @@ uint32_t SkPictureStateTree::Iterator::draw() {
// If we're not at the target node yet, we'll need to return an offset to make the caller
// apply the next clip or saveLayer.
if (fCurrentNode != targetNode) {
- if (fCurrentMatrix != fNodes.top()->fMatrix) {
- fCurrentMatrix = fNodes.top()->fMatrix;
- SkMatrix tmp = *fNodes.top()->fMatrix;
- tmp.postConcat(fPlaybackMatrix);
- fCanvas->setMatrix(tmp);
- }
uint32_t offset = fNodes.top()->fOffset;
fCurrentNode = fNodes.top();
fSave = fCurrentNode != targetNode && fCurrentNode->fFlags & Node::kSave_Flag;
fNodes.pop();
+ this->setCurrentMatrix(fCurrentNode->fMatrix);
return offset;
}
}
// If we got this far, the clip/saveLayer state is all set, so we can proceed to set the matrix
// for the draw, and return its offset.
-
- if (fCurrentMatrix != draw->fMatrix) {
- SkMatrix tmp = *draw->fMatrix;
- tmp.postConcat(fPlaybackMatrix);
- fCanvas->setMatrix(tmp);
- fCurrentMatrix = draw->fMatrix;
- }
+ this->setCurrentMatrix(draw->fMatrix);
++fPlaybackIndex;
return draw->fOffset;
diff --git a/chromium/third_party/skia/src/core/SkPictureStateTree.h b/chromium/third_party/skia/src/core/SkPictureStateTree.h
index 87529586d33..da51a5b954b 100644
--- a/chromium/third_party/skia/src/core/SkPictureStateTree.h
+++ b/chromium/third_party/skia/src/core/SkPictureStateTree.h
@@ -47,7 +47,7 @@ public:
/**
* Creates and returns a struct representing a draw at the given offset.
*/
- Draw* appendDraw(uint32_t offset);
+ Draw* appendDraw(size_t offset);
/**
* Given a list of draws, and a canvas, returns an iterator that produces the correct sequence
@@ -57,10 +57,10 @@ public:
Iterator getIterator(const SkTDArray<void*>& draws, SkCanvas* canvas);
void appendSave();
- void appendSaveLayer(uint32_t offset);
+ void appendSaveLayer(size_t offset);
void appendRestore();
void appendTransform(const SkMatrix& trans);
- void appendClip(uint32_t offset);
+ void appendClip(size_t offset);
/**
* Call this immediately after an appendRestore call that is associated
@@ -74,13 +74,23 @@ public:
*/
class Iterator {
public:
- /** Returns the next offset into the picture stream, or kDrawComplete if complete. */
- uint32_t draw();
+ /** Returns the next op offset needed to create the drawing state
+ required by the queued up draw operation or the offset of the queued
+ up draw operation itself. In the latter case, the next draw operation
+ will move into the queued up slot.
+ It retuns kDrawComplete when done.
+ TODO: this might be better named nextOp
+ */
+ uint32_t nextDraw();
static const uint32_t kDrawComplete = SK_MaxU32;
Iterator() : fPlaybackMatrix(), fValid(false) { }
bool isValid() const { return fValid; }
+
private:
Iterator(const SkTDArray<void*>& draws, SkCanvas* canvas, Node* root);
+
+ void setCurrentMatrix(const SkMatrix*);
+
// The draws this iterator is associated with
const SkTDArray<void*>* fDraws;
@@ -97,7 +107,7 @@ public:
const SkMatrix fPlaybackMatrix;
// Cache of current matrix, so we can avoid redundantly setting it
- SkMatrix* fCurrentMatrix;
+ const SkMatrix* fCurrentMatrix;
// current position in the array of draws
int fPlaybackIndex;
@@ -107,12 +117,14 @@ public:
// Whether or not this is a valid iterator (the default public constructor sets this false)
bool fValid;
+ uint32_t finish();
+
friend class SkPictureStateTree;
};
private:
- void appendNode(uint32_t offset);
+ void appendNode(size_t offset);
SkChunkAlloc fAlloc;
// Needed by saveCollapsed() because nodes do not currently store
diff --git a/chromium/third_party/skia/src/core/SkPixelRef.cpp b/chromium/third_party/skia/src/core/SkPixelRef.cpp
index 6cc67d89af9..bfa4ae24d94 100644
--- a/chromium/third_party/skia/src/core/SkPixelRef.cpp
+++ b/chromium/third_party/skia/src/core/SkPixelRef.cpp
@@ -6,31 +6,32 @@
* found in the LICENSE file.
*/
#include "SkPixelRef.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkThread.h"
#ifdef SK_USE_POSIX_THREADS
static SkBaseMutex gPixelRefMutexRing[] = {
- { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
- { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
- { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
- { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
-
- { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
- { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
- { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
- { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
-
- { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
- { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
- { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
- { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
-
- { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
- { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
- { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
- { PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
+ SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
+ SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
+ SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
+ SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
+
+ SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
+ SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
+ SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
+ SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
+
+ SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
+ SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
+ SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
+ SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
+
+ SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
+ SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
+ SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
+ SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
};
// must be a power-of-2. undef to just use 1 mutex
@@ -82,49 +83,37 @@ void SkPixelRef::setMutex(SkBaseMutex* mutex) {
// just need a > 0 value, so pick a funny one to aid in debugging
#define SKPIXELREF_PRELOCKED_LOCKCOUNT 123456789
-SkPixelRef::SkPixelRef(const SkImageInfo& info, SkBaseMutex* mutex) {
- this->setMutex(mutex);
- fInfo = info;
- fPixels = NULL;
- fColorTable = NULL; // we do not track ownership of this
- fLockCount = 0;
- this->needsNewGenID();
- fIsImmutable = false;
- fPreLocked = false;
-}
-
-SkPixelRef::SkPixelRef(const SkImageInfo& info) {
+SkPixelRef::SkPixelRef(const SkImageInfo& info) : fInfo(info) {
this->setMutex(NULL);
- fInfo = info;
- fPixels = NULL;
- fColorTable = NULL; // we do not track ownership of this
+ fRec.zero();
fLockCount = 0;
this->needsNewGenID();
fIsImmutable = false;
fPreLocked = false;
}
-#ifdef SK_SUPPORT_LEGACY_PIXELREF_CONSTRUCTOR
-// THIS GUY IS DEPRECATED -- don't use me!
-SkPixelRef::SkPixelRef(SkBaseMutex* mutex) {
+
+SkPixelRef::SkPixelRef(const SkImageInfo& info, SkBaseMutex* mutex) : fInfo(info) {
this->setMutex(mutex);
- // Fill with dummy values.
- sk_bzero(&fInfo, sizeof(fInfo));
- fPixels = NULL;
- fColorTable = NULL; // we do not track ownership of this
+ fRec.zero();
fLockCount = 0;
this->needsNewGenID();
fIsImmutable = false;
fPreLocked = false;
}
-#endif
-SkPixelRef::SkPixelRef(SkFlattenableReadBuffer& buffer, SkBaseMutex* mutex)
- : INHERITED(buffer) {
+static SkImageInfo read_info(SkReadBuffer& buffer) {
+ SkImageInfo info;
+ info.unflatten(buffer);
+ return info;
+}
+
+SkPixelRef::SkPixelRef(SkReadBuffer& buffer, SkBaseMutex* mutex)
+ : INHERITED(buffer)
+ , fInfo(read_info(buffer))
+{
this->setMutex(mutex);
- fInfo.unflatten(buffer);
- fPixels = NULL;
- fColorTable = NULL; // we do not track ownership of this
+ fRec.zero();
fLockCount = 0;
fIsImmutable = buffer.readBool();
fGenerationID = buffer.readUInt();
@@ -148,18 +137,19 @@ void SkPixelRef::cloneGenID(const SkPixelRef& that) {
that.fUniqueGenerationID = false;
}
-void SkPixelRef::setPreLocked(void* pixels, SkColorTable* ctable) {
+void SkPixelRef::setPreLocked(void* pixels, size_t rowBytes, SkColorTable* ctable) {
#ifndef SK_IGNORE_PIXELREF_SETPRELOCKED
// only call me in your constructor, otherwise fLockCount tracking can get
// out of sync.
- fPixels = pixels;
- fColorTable = ctable;
+ fRec.fPixels = pixels;
+ fRec.fColorTable = ctable;
+ fRec.fRowBytes = rowBytes;
fLockCount = SKPIXELREF_PRELOCKED_LOCKCOUNT;
fPreLocked = true;
#endif
}
-void SkPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkPixelRef::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
fInfo.flatten(buffer);
buffer.writeBool(fIsImmutable);
@@ -176,20 +166,30 @@ void SkPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
}
}
-void SkPixelRef::lockPixels() {
+bool SkPixelRef::lockPixels(LockRec* rec) {
SkASSERT(!fPreLocked || SKPIXELREF_PRELOCKED_LOCKCOUNT == fLockCount);
if (!fPreLocked) {
SkAutoMutexAcquire ac(*fMutex);
if (1 == ++fLockCount) {
- fPixels = this->onLockPixels(&fColorTable);
- // If onLockPixels failed, it will return NULL
- if (NULL == fPixels) {
- fColorTable = NULL;
+ SkASSERT(fRec.isZero());
+
+ LockRec rec;
+ if (!this->onNewLockPixels(&rec)) {
+ return false;
}
+ SkASSERT(!rec.isZero()); // else why did onNewLock return true?
+ fRec = rec;
}
}
+ *rec = fRec;
+ return true;
+}
+
+bool SkPixelRef::lockPixels() {
+ LockRec rec;
+ return this->lockPixels(&rec);
}
void SkPixelRef::unlockPixels() {
@@ -201,12 +201,11 @@ void SkPixelRef::unlockPixels() {
SkASSERT(fLockCount > 0);
if (0 == --fLockCount) {
// don't call onUnlockPixels unless onLockPixels succeeded
- if (fPixels) {
+ if (fRec.fPixels) {
this->onUnlockPixels();
- fPixels = NULL;
- fColorTable = NULL;
+ fRec.zero();
} else {
- SkASSERT(NULL == fColorTable);
+ SkASSERT(fRec.isZero());
}
}
}
@@ -266,6 +265,10 @@ void SkPixelRef::notifyPixelsChanged() {
this->needsNewGenID();
}
+void SkPixelRef::changeAlphaType(SkAlphaType at) {
+ *const_cast<SkAlphaType*>(&fInfo.fAlphaType) = at;
+}
+
void SkPixelRef::setImmutable() {
fIsImmutable = true;
}
diff --git a/chromium/third_party/skia/src/core/SkQuadTree.cpp b/chromium/third_party/skia/src/core/SkQuadTree.cpp
new file mode 100644
index 00000000000..a11613d08b0
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkQuadTree.cpp
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkQuadTree.h"
+#include "SkTSort.h"
+#include <stdio.h>
+
+static const int kSplitThreshold = 8;
+
+enum {
+ kTopLeft,
+ kTopRight,
+ kBottomLeft,
+ kBottomRight,
+};
+enum {
+ kTopLeft_Bit = 1 << kTopLeft,
+ kTopRight_Bit = 1 << kTopRight,
+ kBottomLeft_Bit = 1 << kBottomLeft,
+ kBottomRight_Bit = 1 << kBottomRight,
+};
+enum {
+ kMaskLeft = kTopLeft_Bit | kBottomLeft_Bit,
+ kMaskRight = kTopRight_Bit | kBottomRight_Bit,
+ kMaskTop = kTopLeft_Bit | kTopRight_Bit,
+ kMaskBottom = kBottomLeft_Bit | kBottomRight_Bit,
+};
+
+static U8CPU child_intersect(const SkIRect& query, const SkIPoint& split) {
+ // fast quadrant test
+ U8CPU intersect = 0xf;
+ if (query.fRight < split.fX) {
+ intersect &= ~kMaskRight;
+ } else if(query.fLeft >= split.fX) {
+ intersect &= ~kMaskLeft;
+ }
+ if (query.fBottom < split.fY) {
+ intersect &= ~kMaskBottom;
+ } else if(query.fTop >= split.fY) {
+ intersect &= ~kMaskTop;
+ }
+ return intersect;
+}
+
+SkQuadTree::SkQuadTree(const SkIRect& bounds) : fRoot(NULL) {
+ SkASSERT((bounds.width() * bounds.height()) > 0);
+ fRootBounds = bounds;
+}
+
+SkQuadTree::~SkQuadTree() {
+}
+
+void SkQuadTree::insert(Node* node, Entry* entry) {
+ // does it belong in a child?
+ if (NULL != node->fChildren[0]) {
+ switch(child_intersect(entry->fBounds, node->fSplitPoint)) {
+ case kTopLeft_Bit:
+ this->insert(node->fChildren[kTopLeft], entry);
+ return;
+ case kTopRight_Bit:
+ this->insert(node->fChildren[kTopRight], entry);
+ return;
+ case kBottomLeft_Bit:
+ this->insert(node->fChildren[kBottomLeft], entry);
+ return;
+ case kBottomRight_Bit:
+ this->insert(node->fChildren[kBottomRight], entry);
+ return;
+ default:
+ node->fEntries.push(entry);
+ return;
+ }
+ }
+ // No children yet, add to this node
+ node->fEntries.push(entry);
+ // should I split?
+ if (node->fEntries.getCount() > kSplitThreshold) {
+ this->split(node);
+ }
+}
+
+void SkQuadTree::split(Node* node) {
+ // Build all the children
+ node->fSplitPoint = SkIPoint::Make(node->fBounds.centerX(),
+ node->fBounds.centerY());
+ for(int index=0; index<kChildCount; ++index) {
+ node->fChildren[index] = fNodePool.acquire();
+ }
+ node->fChildren[0]->fBounds = SkIRect::MakeLTRB(
+ node->fBounds.fLeft, node->fBounds.fTop,
+ node->fSplitPoint.fX, node->fSplitPoint.fY);
+ node->fChildren[1]->fBounds = SkIRect::MakeLTRB(
+ node->fSplitPoint.fX, node->fBounds.fTop,
+ node->fBounds.fRight, node->fSplitPoint.fY);
+ node->fChildren[2]->fBounds = SkIRect::MakeLTRB(
+ node->fBounds.fLeft, node->fSplitPoint.fY,
+ node->fSplitPoint.fX, node->fBounds.fBottom);
+ node->fChildren[3]->fBounds = SkIRect::MakeLTRB(
+ node->fSplitPoint.fX, node->fSplitPoint.fY,
+ node->fBounds.fRight, node->fBounds.fBottom);
+ // reinsert all the entries of this node to allow child trickle
+ SkTInternalSList<Entry> entries;
+ entries.pushAll(&node->fEntries);
+ while(!entries.isEmpty()) {
+ this->insert(node, entries.pop());
+ }
+}
+
+void SkQuadTree::search(Node* node, const SkIRect& query,
+ SkTDArray<void*>* results) const {
+ for (Entry* entry = node->fEntries.head(); NULL != entry;
+ entry = entry->getSListNext()) {
+ if (SkIRect::IntersectsNoEmptyCheck(entry->fBounds, query)) {
+ results->push(entry->fData);
+ }
+ }
+ if (NULL == node->fChildren[0]) {
+ return;
+ }
+ U8CPU intersect = child_intersect(query, node->fSplitPoint);
+ for(int index=0; index<kChildCount; ++index) {
+ if (intersect & (1 << index)) {
+ this->search(node->fChildren[index], query, results);
+ }
+ }
+}
+
+void SkQuadTree::clear(Node* node) {
+ // first clear the entries of this node
+ fEntryPool.releaseAll(&node->fEntries);
+ // recurse into and clear all child nodes
+ for(int index=0; index<kChildCount; ++index) {
+ Node* child = node->fChildren[index];
+ node->fChildren[index] = NULL;
+ if (NULL != child) {
+ this->clear(child);
+ fNodePool.release(child);
+ }
+ }
+}
+
+int SkQuadTree::getDepth(Node* node) const {
+ int maxDepth = 0;
+ if (NULL != node) {
+ for(int index=0; index<kChildCount; ++index) {
+ maxDepth = SkMax32(maxDepth, getDepth(node->fChildren[index]));
+ }
+ }
+ return maxDepth + 1;
+}
+
+void SkQuadTree::insert(void* data, const SkIRect& bounds, bool) {
+ if (bounds.isEmpty()) {
+ SkASSERT(false);
+ return;
+ }
+ Entry* entry = fEntryPool.acquire();
+ entry->fData = data;
+ entry->fBounds = bounds;
+ if (NULL == fRoot) {
+ fDeferred.push(entry);
+ } else {
+ this->insert(fRoot, entry);
+ }
+}
+
+void SkQuadTree::search(const SkIRect& query, SkTDArray<void*>* results) {
+ SkASSERT(NULL != fRoot);
+ SkASSERT(NULL != results);
+ if (SkIRect::Intersects(fRootBounds, query)) {
+ this->search(fRoot, query, results);
+ }
+}
+
+void SkQuadTree::clear() {
+ this->flushDeferredInserts();
+ if (NULL != fRoot) {
+ this->clear(fRoot);
+ fNodePool.release(fRoot);
+ fRoot = NULL;
+ }
+ SkASSERT(fEntryPool.allocated() == fEntryPool.available());
+ SkASSERT(fNodePool.allocated() == fNodePool.available());
+}
+
+int SkQuadTree::getDepth() const {
+ return this->getDepth(fRoot);
+}
+
+void SkQuadTree::rewindInserts() {
+ SkASSERT(fClient);
+ // Currently only supports deferred inserts
+ SkASSERT(NULL == fRoot);
+ SkTInternalSList<Entry> entries;
+ entries.pushAll(&fDeferred);
+ while(!entries.isEmpty()) {
+ Entry* entry = entries.pop();
+ if (fClient->shouldRewind(entry->fData)) {
+ entry->fData = NULL;
+ fEntryPool.release(entry);
+ } else {
+ fDeferred.push(entry);
+ }
+ }
+}
+
+void SkQuadTree::flushDeferredInserts() {
+ if (NULL == fRoot) {
+ fRoot = fNodePool.acquire();
+ fRoot->fBounds = fRootBounds;
+ }
+ while(!fDeferred.isEmpty()) {
+ this->insert(fRoot, fDeferred.pop());
+ }
+}
diff --git a/chromium/third_party/skia/src/core/SkQuadTree.h b/chromium/third_party/skia/src/core/SkQuadTree.h
new file mode 100644
index 00000000000..bf1bc8ebbac
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkQuadTree.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkQuadTree_DEFINED
+#define SkQuadTree_DEFINED
+
+#include "SkRect.h"
+#include "SkTDArray.h"
+#include "SkBBoxHierarchy.h"
+#include "SkTInternalSList.h"
+#include "SkTObjectPool.h"
+
+/**
+ * A QuadTree implementation. In short, it is a tree containing a hierarchy of bounding rectangles
+ * in which each internal node has exactly four children.
+ *
+ * For more details see:
+ *
+ * http://en.wikipedia.org/wiki/Quadtree
+ */
+class SkQuadTree : public SkBBoxHierarchy {
+public:
+ SK_DECLARE_INST_COUNT(SkQuadTree)
+
+ /**
+ * Quad tree constructor.
+ * @param bounds The bounding box for the root of the quad tree.
+ * giving the quad tree bounds that fall outside the root
+ * bounds may result in pathological but correct behavior.
+ */
+ SkQuadTree(const SkIRect& bounds);
+
+ virtual ~SkQuadTree();
+
+ /**
+ * Insert a node, consisting of bounds and a data value into the tree, if we don't immediately
+ * need to use the tree; we may allow the insert to be deferred (this can allow us to bulk-load
+ * a large batch of nodes at once, which tends to be faster and produce a better tree).
+ * @param data The data value
+ * @param bounds The corresponding bounding box
+ * @param defer Can this insert be deferred? (this may be ignored)
+ */
+ virtual void insert(void* data, const SkIRect& bounds, bool defer = false) SK_OVERRIDE;
+
+ /**
+ * If any inserts have been deferred, this will add them into the tree
+ */
+ virtual void flushDeferredInserts() SK_OVERRIDE;
+
+ /**
+ * Given a query rectangle, populates the passed-in array with the elements it intersects
+ */
+ virtual void search(const SkIRect& query, SkTDArray<void*>* results) SK_OVERRIDE;
+
+ virtual void clear() SK_OVERRIDE;
+
+ /**
+ * Gets the depth of the tree structure
+ */
+ virtual int getDepth() const SK_OVERRIDE;
+
+ /**
+ * This gets the insertion count (rather than the node count)
+ */
+ virtual int getCount() const SK_OVERRIDE {
+ return fEntryPool.allocated() - fEntryPool.available();
+ }
+
+ virtual void rewindInserts() SK_OVERRIDE;
+
+private:
+ struct Entry {
+ Entry() : fData(NULL) {}
+ SkIRect fBounds;
+ void* fData;
+ SK_DECLARE_INTERNAL_SLIST_INTERFACE(Entry);
+ };
+
+ static const int kChildCount = 4;
+
+ struct Node {
+ Node() {
+ for (int index=0; index<kChildCount; ++index) {
+ fChildren[index] = NULL;
+ }
+ }
+ SkTInternalSList<Entry> fEntries;
+ SkIRect fBounds;
+ SkIPoint fSplitPoint; // Only valid if the node has children.
+ Node* fChildren[kChildCount];
+ SK_DECLARE_INTERNAL_SLIST_ADAPTER(Node, fChildren[0]);
+ };
+
+ SkTObjectPool<Entry> fEntryPool;
+ SkTObjectPool<Node> fNodePool;
+ Node* fRoot;
+ SkIRect fRootBounds;
+ SkTInternalSList<Entry> fDeferred;
+
+ void insert(Node* node, Entry* entry);
+ void split(Node* node);
+ void search(Node* node, const SkIRect& query, SkTDArray<void*>* results) const;
+ void clear(Node* node);
+ int getDepth(Node* node) const;
+
+ typedef SkBBoxHierarchy INHERITED;
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/core/SkRRect.cpp b/chromium/third_party/skia/src/core/SkRRect.cpp
index e5296d4e3a7..9bb6725deac 100644
--- a/chromium/third_party/skia/src/core/SkRRect.cpp
+++ b/chromium/third_party/skia/src/core/SkRRect.cpp
@@ -43,6 +43,61 @@ void SkRRect::setRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad) {
SkDEBUGCODE(this->validate();)
}
+void SkRRect::setNinePatch(const SkRect& rect, SkScalar leftRad, SkScalar topRad,
+ SkScalar rightRad, SkScalar bottomRad) {
+ if (rect.isEmpty()) {
+ this->setEmpty();
+ return;
+ }
+
+ leftRad = SkMaxScalar(leftRad, 0);
+ topRad = SkMaxScalar(topRad, 0);
+ rightRad = SkMaxScalar(rightRad, 0);
+ bottomRad = SkMaxScalar(bottomRad, 0);
+
+ SkScalar scale = SK_Scalar1;
+ if (leftRad + rightRad > rect.width()) {
+ scale = SkScalarDiv(rect.width(), leftRad + rightRad);
+ }
+ if (topRad + bottomRad > rect.height()) {
+ scale = SkMinScalar(scale, SkScalarDiv(rect.width(), leftRad + rightRad));
+ }
+
+ if (scale < SK_Scalar1) {
+ leftRad = SkScalarMul(leftRad, scale);
+ topRad = SkScalarMul(topRad, scale);
+ rightRad = SkScalarMul(rightRad, scale);
+ bottomRad = SkScalarMul(bottomRad, scale);
+ }
+
+ if (leftRad == rightRad && topRad == bottomRad) {
+ if (leftRad >= SkScalarHalf(rect.width()) && topRad >= SkScalarHalf(rect.height())) {
+ fType = kOval_Type;
+ } else if (0 == leftRad || 0 == topRad) {
+ // If the left and (by equality check above) right radii are zero then it is a rect.
+ // Same goes for top/bottom.
+ fType = kRect_Type;
+ leftRad = 0;
+ topRad = 0;
+ rightRad = 0;
+ bottomRad = 0;
+ } else {
+ fType = kSimple_Type;
+ }
+ } else {
+ fType = kNinePatch_Type;
+ }
+
+ fRect = rect;
+ fRadii[kUpperLeft_Corner].set(leftRad, topRad);
+ fRadii[kUpperRight_Corner].set(rightRad, topRad);
+ fRadii[kLowerRight_Corner].set(rightRad, bottomRad);
+ fRadii[kLowerLeft_Corner].set(leftRad, bottomRad);
+
+ SkDEBUGCODE(this->validate();)
+}
+
+
void SkRRect::setRectRadii(const SkRect& rect, const SkVector radii[4]) {
if (rect.isEmpty()) {
this->setEmpty();
@@ -172,6 +227,13 @@ bool SkRRect::checkCornerContainment(SkScalar x, SkScalar y) const {
return dist <= SkScalarSquare(SkScalarMul(fRadii[index].fX, fRadii[index].fY));
}
+bool SkRRect::allCornersCircular() const {
+ return fRadii[0].fX == fRadii[0].fY &&
+ fRadii[1].fX == fRadii[1].fY &&
+ fRadii[2].fX == fRadii[2].fY &&
+ fRadii[3].fX == fRadii[3].fY;
+}
+
bool SkRRect::contains(const SkRect& rect) const {
if (!this->getBounds().contains(rect)) {
// If 'rect' isn't contained by the RR's bounds then the
@@ -193,6 +255,13 @@ bool SkRRect::contains(const SkRect& rect) const {
this->checkCornerContainment(rect.fLeft, rect.fBottom);
}
+static bool radii_are_nine_patch(const SkVector radii[4]) {
+ return radii[SkRRect::kUpperLeft_Corner].fX == radii[SkRRect::kLowerLeft_Corner].fX &&
+ radii[SkRRect::kUpperLeft_Corner].fY == radii[SkRRect::kUpperRight_Corner].fY &&
+ radii[SkRRect::kUpperRight_Corner].fX == radii[SkRRect::kLowerRight_Corner].fX &&
+ radii[SkRRect::kLowerLeft_Corner].fY == radii[SkRRect::kLowerRight_Corner].fY;
+}
+
// There is a simplified version of this method in setRectXY
void SkRRect::computeType() const {
SkDEBUGCODE(this->validate();)
@@ -231,7 +300,11 @@ void SkRRect::computeType() const {
return;
}
- fType = kComplex_Type;
+ if (radii_are_nine_patch(fRadii)) {
+ fType = kNinePatch_Type;
+ } else {
+ fType = kComplex_Type;
+ }
}
static bool matrix_only_scale_and_translate(const SkMatrix& matrix) {
@@ -363,6 +436,18 @@ size_t SkRRect::readFromMemory(const void* buffer, size_t length) {
return kSizeInMemory;
}
+#ifdef SK_DEVELOPER
+void SkRRect::dump() const {
+ SkDebugf("Rect: ");
+ fRect.dump();
+ SkDebugf(" Corners: { TL: (%f, %f), TR: (%f, %f), BR: (%f, %f), BL: (%f, %f) }",
+ fRadii[kUpperLeft_Corner].fX, fRadii[kUpperLeft_Corner].fY,
+ fRadii[kUpperRight_Corner].fX, fRadii[kUpperRight_Corner].fY,
+ fRadii[kLowerRight_Corner].fX, fRadii[kLowerRight_Corner].fY,
+ fRadii[kLowerLeft_Corner].fX, fRadii[kLowerLeft_Corner].fY);
+}
+#endif
+
///////////////////////////////////////////////////////////////////////////////
#ifdef SK_DEBUG
@@ -384,14 +469,12 @@ void SkRRect::validate() const {
allCornersSquare = false;
}
}
+ bool patchesOfNine = radii_are_nine_patch(fRadii);
switch (fType) {
case kEmpty_Type:
SkASSERT(fRect.isEmpty());
SkASSERT(allRadiiZero && allRadiiSame && allCornersSquare);
-
- SkASSERT(0 == fRect.fLeft && 0 == fRect.fTop &&
- 0 == fRect.fRight && 0 == fRect.fBottom);
break;
case kRect_Type:
SkASSERT(!fRect.isEmpty());
@@ -410,9 +493,15 @@ void SkRRect::validate() const {
SkASSERT(!fRect.isEmpty());
SkASSERT(!allRadiiZero && allRadiiSame && !allCornersSquare);
break;
+ case kNinePatch_Type:
+ SkASSERT(!fRect.isEmpty());
+ SkASSERT(!allRadiiZero && !allRadiiSame && !allCornersSquare);
+ SkASSERT(patchesOfNine);
+ break;
case kComplex_Type:
SkASSERT(!fRect.isEmpty());
SkASSERT(!allRadiiZero && !allRadiiSame && !allCornersSquare);
+ SkASSERT(!patchesOfNine);
break;
case kUnknown_Type:
// no limits on this
diff --git a/chromium/third_party/skia/src/core/SkRTree.cpp b/chromium/third_party/skia/src/core/SkRTree.cpp
index 253a7ee1d44..fe08437da36 100644
--- a/chromium/third_party/skia/src/core/SkRTree.cpp
+++ b/chromium/third_party/skia/src/core/SkRTree.cpp
@@ -345,9 +345,9 @@ SkRTree::Branch SkRTree::bulkLoad(SkTDArray<Branch>* branches, int level) {
}
}
- int numStrips = SkScalarCeil(SkScalarSqrt(SkIntToScalar(numBranches) *
+ int numStrips = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(numBranches) *
SkScalarInvert(fAspectRatio)));
- int numTiles = SkScalarCeil(SkIntToScalar(numBranches) /
+ int numTiles = SkScalarCeilToInt(SkIntToScalar(numBranches) /
SkIntToScalar(numStrips));
int currentBranch = 0;
diff --git a/chromium/third_party/skia/src/core/SkRTree.h b/chromium/third_party/skia/src/core/SkRTree.h
index 2f905e7909b..d21b5f8d371 100644
--- a/chromium/third_party/skia/src/core/SkRTree.h
+++ b/chromium/third_party/skia/src/core/SkRTree.h
@@ -67,26 +67,32 @@ public:
* @param bounds The corresponding bounding box
* @param defer Can this insert be deferred? (this may be ignored)
*/
- virtual void insert(void* data, const SkIRect& bounds, bool defer = false);
+ virtual void insert(void* data, const SkIRect& bounds, bool defer = false) SK_OVERRIDE;
/**
* If any inserts have been deferred, this will add them into the tree
*/
- virtual void flushDeferredInserts();
+ virtual void flushDeferredInserts() SK_OVERRIDE;
/**
* Given a query rectangle, populates the passed-in array with the elements it intersects
*/
- virtual void search(const SkIRect& query, SkTDArray<void*>* results);
+ virtual void search(const SkIRect& query, SkTDArray<void*>* results) SK_OVERRIDE;
- virtual void clear();
+ virtual void clear() SK_OVERRIDE;
bool isEmpty() const { return 0 == fCount; }
- int getDepth() const { return this->isEmpty() ? 0 : fRoot.fChild.subtree->fLevel + 1; }
+
+ /**
+ * Gets the depth of the tree structure
+ */
+ virtual int getDepth() const SK_OVERRIDE {
+ return this->isEmpty() ? 0 : fRoot.fChild.subtree->fLevel + 1;
+ }
/**
* This gets the insertion count (rather than the node count)
*/
- virtual int getCount() const { return fCount; }
+ virtual int getCount() const SK_OVERRIDE { return fCount; }
virtual void rewindInserts() SK_OVERRIDE;
diff --git a/chromium/third_party/skia/src/core/SkOrderedReadBuffer.cpp b/chromium/third_party/skia/src/core/SkReadBuffer.cpp
index 31841182b9c..cacf989e204 100644
--- a/chromium/third_party/skia/src/core/SkOrderedReadBuffer.cpp
+++ b/chromium/third_party/skia/src/core/SkReadBuffer.cpp
@@ -8,11 +8,24 @@
#include "SkBitmap.h"
#include "SkErrorInternals.h"
-#include "SkOrderedReadBuffer.h"
+#include "SkReadBuffer.h"
#include "SkStream.h"
#include "SkTypeface.h"
-SkOrderedReadBuffer::SkOrderedReadBuffer() : INHERITED() {
+static uint32_t default_flags() {
+ uint32_t flags = 0;
+#ifdef SK_SCALAR_IS_FLOAT
+ flags |= SkReadBuffer::kScalarIsFloat_Flag;
+#endif
+ if (8 == sizeof(void*)) {
+ flags |= SkReadBuffer::kPtrIs64Bit_Flag;
+ }
+ return flags;
+}
+
+SkReadBuffer::SkReadBuffer() {
+ fFlags = default_flags();
+ fVersion = 0;
fMemoryPtr = NULL;
fBitmapStorage = NULL;
@@ -28,7 +41,9 @@ SkOrderedReadBuffer::SkOrderedReadBuffer() : INHERITED() {
#endif // DEBUG_NON_DETERMINISTIC_ASSERT
}
-SkOrderedReadBuffer::SkOrderedReadBuffer(const void* data, size_t size) : INHERITED() {
+SkReadBuffer::SkReadBuffer(const void* data, size_t size) {
+ fFlags = default_flags();
+ fVersion = 0;
fReader.setMemory(data, size);
fMemoryPtr = NULL;
@@ -45,7 +60,9 @@ SkOrderedReadBuffer::SkOrderedReadBuffer(const void* data, size_t size) : INHERI
#endif // DEBUG_NON_DETERMINISTIC_ASSERT
}
-SkOrderedReadBuffer::SkOrderedReadBuffer(SkStream* stream) {
+SkReadBuffer::SkReadBuffer(SkStream* stream) {
+ fFlags = default_flags();
+ fVersion = 0;
const size_t length = stream->getLength();
fMemoryPtr = sk_malloc_throw(length);
stream->read(fMemoryPtr, length);
@@ -64,46 +81,46 @@ SkOrderedReadBuffer::SkOrderedReadBuffer(SkStream* stream) {
#endif // DEBUG_NON_DETERMINISTIC_ASSERT
}
-SkOrderedReadBuffer::~SkOrderedReadBuffer() {
+SkReadBuffer::~SkReadBuffer() {
sk_free(fMemoryPtr);
SkSafeUnref(fBitmapStorage);
}
-bool SkOrderedReadBuffer::readBool() {
+bool SkReadBuffer::readBool() {
return fReader.readBool();
}
-SkColor SkOrderedReadBuffer::readColor() {
+SkColor SkReadBuffer::readColor() {
return fReader.readInt();
}
-SkFixed SkOrderedReadBuffer::readFixed() {
+SkFixed SkReadBuffer::readFixed() {
return fReader.readS32();
}
-int32_t SkOrderedReadBuffer::readInt() {
+int32_t SkReadBuffer::readInt() {
return fReader.readInt();
}
-SkScalar SkOrderedReadBuffer::readScalar() {
+SkScalar SkReadBuffer::readScalar() {
return fReader.readScalar();
}
-uint32_t SkOrderedReadBuffer::readUInt() {
+uint32_t SkReadBuffer::readUInt() {
return fReader.readU32();
}
-int32_t SkOrderedReadBuffer::read32() {
+int32_t SkReadBuffer::read32() {
return fReader.readInt();
}
-void SkOrderedReadBuffer::readString(SkString* string) {
+void SkReadBuffer::readString(SkString* string) {
size_t len;
const char* strContents = fReader.readString(&len);
string->set(strContents, len);
}
-void* SkOrderedReadBuffer::readEncodedString(size_t* length, SkPaint::TextEncoding encoding) {
+void* SkReadBuffer::readEncodedString(size_t* length, SkPaint::TextEncoding encoding) {
SkDEBUGCODE(int32_t encodingType = ) fReader.readInt();
SkASSERT(encodingType == encoding);
*length = fReader.readInt();
@@ -112,32 +129,32 @@ void* SkOrderedReadBuffer::readEncodedString(size_t* length, SkPaint::TextEncodi
return data;
}
-void SkOrderedReadBuffer::readPoint(SkPoint* point) {
+void SkReadBuffer::readPoint(SkPoint* point) {
point->fX = fReader.readScalar();
point->fY = fReader.readScalar();
}
-void SkOrderedReadBuffer::readMatrix(SkMatrix* matrix) {
+void SkReadBuffer::readMatrix(SkMatrix* matrix) {
fReader.readMatrix(matrix);
}
-void SkOrderedReadBuffer::readIRect(SkIRect* rect) {
+void SkReadBuffer::readIRect(SkIRect* rect) {
memcpy(rect, fReader.skip(sizeof(SkIRect)), sizeof(SkIRect));
}
-void SkOrderedReadBuffer::readRect(SkRect* rect) {
+void SkReadBuffer::readRect(SkRect* rect) {
memcpy(rect, fReader.skip(sizeof(SkRect)), sizeof(SkRect));
}
-void SkOrderedReadBuffer::readRegion(SkRegion* region) {
+void SkReadBuffer::readRegion(SkRegion* region) {
fReader.readRegion(region);
}
-void SkOrderedReadBuffer::readPath(SkPath* path) {
+void SkReadBuffer::readPath(SkPath* path) {
fReader.readPath(path);
}
-bool SkOrderedReadBuffer::readArray(void* value, size_t size, size_t elementSize) {
+bool SkReadBuffer::readArray(void* value, size_t size, size_t elementSize) {
const size_t count = this->getArrayCount();
if (count == size) {
(void)fReader.skip(sizeof(uint32_t)); // Skip array count
@@ -150,31 +167,31 @@ bool SkOrderedReadBuffer::readArray(void* value, size_t size, size_t elementSize
return false;
}
-bool SkOrderedReadBuffer::readByteArray(void* value, size_t size) {
+bool SkReadBuffer::readByteArray(void* value, size_t size) {
return readArray(static_cast<unsigned char*>(value), size, sizeof(unsigned char));
}
-bool SkOrderedReadBuffer::readColorArray(SkColor* colors, size_t size) {
+bool SkReadBuffer::readColorArray(SkColor* colors, size_t size) {
return readArray(colors, size, sizeof(SkColor));
}
-bool SkOrderedReadBuffer::readIntArray(int32_t* values, size_t size) {
+bool SkReadBuffer::readIntArray(int32_t* values, size_t size) {
return readArray(values, size, sizeof(int32_t));
}
-bool SkOrderedReadBuffer::readPointArray(SkPoint* points, size_t size) {
+bool SkReadBuffer::readPointArray(SkPoint* points, size_t size) {
return readArray(points, size, sizeof(SkPoint));
}
-bool SkOrderedReadBuffer::readScalarArray(SkScalar* values, size_t size) {
+bool SkReadBuffer::readScalarArray(SkScalar* values, size_t size) {
return readArray(values, size, sizeof(SkScalar));
}
-uint32_t SkOrderedReadBuffer::getArrayCount() {
+uint32_t SkReadBuffer::getArrayCount() {
return *(uint32_t*)fReader.peek();
}
-void SkOrderedReadBuffer::readBitmap(SkBitmap* bitmap) {
+bool SkReadBuffer::readBitmap(SkBitmap* bitmap) {
const int width = this->readInt();
const int height = this->readInt();
// The writer stored a boolean value to determine whether an SkBitmapHeap was used during
@@ -182,18 +199,18 @@ void SkOrderedReadBuffer::readBitmap(SkBitmap* bitmap) {
if (this->readBool()) {
// An SkBitmapHeap was used for writing. Read the index from the stream and find the
// corresponding SkBitmap in fBitmapStorage.
- const uint32_t index = fReader.readU32();
- fReader.readU32(); // bitmap generation ID (see SkOrderedWriteBuffer::writeBitmap)
+ const uint32_t index = this->readUInt();
+ this->readUInt(); // bitmap generation ID (see SkWriteBuffer::writeBitmap)
if (fBitmapStorage) {
*bitmap = *fBitmapStorage->getBitmap(index);
fBitmapStorage->releaseRef(index);
- return;
+ return true;
} else {
// The bitmap was stored in a heap, but there is no way to access it. Set an error and
// fall through to use a place holder bitmap.
- SkErrorInternals::SetError(kParseError_SkError, "SkOrderedWriteBuffer::writeBitmap "
+ SkErrorInternals::SetError(kParseError_SkError, "SkWriteBuffer::writeBitmap "
"stored the SkBitmap in an SkBitmapHeap, but "
- "SkOrderedReadBuffer has no SkBitmapHeapReader to "
+ "SkReadBuffer has no SkBitmapHeapReader to "
"retrieve the SkBitmap.");
}
} else {
@@ -206,13 +223,13 @@ void SkOrderedReadBuffer::readBitmap(SkBitmap* bitmap) {
// A non-zero size means the SkBitmap was encoded. Read the data and pixel
// offset.
const void* data = this->skip(length);
- const int32_t xOffset = fReader.readS32();
- const int32_t yOffset = fReader.readS32();
+ const int32_t xOffset = this->readInt();
+ const int32_t yOffset = this->readInt();
if (fBitmapDecoder != NULL && fBitmapDecoder(data, length, bitmap)) {
if (bitmap->width() == width && bitmap->height() == height) {
#ifdef DEBUG_NON_DETERMINISTIC_ASSERT
if (0 != xOffset || 0 != yOffset) {
- SkDebugf("SkOrderedReadBuffer::readBitmap: heights match,"
+ SkDebugf("SkReadBuffer::readBitmap: heights match,"
" but offset is not zero. \nInfo about the bitmap:"
"\n\tIndex: %d\n\tDimensions: [%d %d]\n\tEncoded"
" data size: %d\n\tOffset: (%d, %d)\n",
@@ -222,19 +239,23 @@ void SkOrderedReadBuffer::readBitmap(SkBitmap* bitmap) {
#endif // DEBUG_NON_DETERMINISTIC_ASSERT
// If the width and height match, there should be no offset.
SkASSERT(0 == xOffset && 0 == yOffset);
- return;
+ return true;
}
// This case can only be reached if extractSubset was called, so
- // the recorded width and height must be smaller than (or equal to
+ // the recorded width and height must be smaller than or equal to
// the encoded width and height.
- SkASSERT(width <= bitmap->width() && height <= bitmap->height());
+ // FIXME (scroggo): This assert assumes that our decoder and the
+ // sources encoder agree on the width and height which may not
+ // always be the case. Removing until it can be investigated
+ // further.
+ //SkASSERT(width <= bitmap->width() && height <= bitmap->height());
SkBitmap subsetBm;
SkIRect subset = SkIRect::MakeXYWH(xOffset, yOffset, width, height);
if (bitmap->extractSubset(&subsetBm, subset)) {
bitmap->swap(subsetBm);
- return;
+ return true;
}
}
// This bitmap was encoded when written, but we are unable to decode, possibly due to
@@ -243,17 +264,23 @@ void SkOrderedReadBuffer::readBitmap(SkBitmap* bitmap) {
"Could not decode bitmap. Resulting bitmap will be red.");
} else {
// A size of zero means the SkBitmap was simply flattened.
- bitmap->unflatten(*this);
- return;
+ if (this->isVersionLT(kNoMoreBitmapFlatten_Version)) {
+ SkBitmap tmp;
+ tmp.legacyUnflatten(*this);
+ // just throw this guy away
+ } else {
+ if (SkBitmap::ReadRawPixels(this, bitmap)) {
+ return true;
+ }
+ }
}
}
// Could not read the SkBitmap. Use a placeholder bitmap.
- bitmap->setConfig(SkBitmap::kARGB_8888_Config, width, height);
- bitmap->allocPixels();
- bitmap->eraseColor(SK_ColorRED);
+ bitmap->setInfo(SkImageInfo::MakeUnknown(width, height));
+ return false;
}
-SkTypeface* SkOrderedReadBuffer::readTypeface() {
+SkTypeface* SkReadBuffer::readTypeface() {
uint32_t index = fReader.readU32();
if (0 == index || index > (unsigned)fTFCount) {
@@ -267,7 +294,7 @@ SkTypeface* SkOrderedReadBuffer::readTypeface() {
}
}
-SkFlattenable* SkOrderedReadBuffer::readFlattenable(SkFlattenable::Type ft) {
+SkFlattenable* SkReadBuffer::readFlattenable(SkFlattenable::Type ft) {
//
// TODO: confirm that ft matches the factory we decide to use
//
@@ -301,10 +328,10 @@ SkFlattenable* SkOrderedReadBuffer::readFlattenable(SkFlattenable::Type ft) {
SkFlattenable* obj = NULL;
uint32_t sizeRecorded = fReader.readU32();
if (factory) {
- uint32_t offset = fReader.offset();
+ size_t offset = fReader.offset();
obj = (*factory)(*this);
// check that we read the amount we expected
- uint32_t sizeRead = fReader.offset() - offset;
+ size_t sizeRead = fReader.offset() - offset;
if (sizeRecorded != sizeRead) {
// we could try to fix up the offset...
sk_throw();
@@ -315,3 +342,25 @@ SkFlattenable* SkOrderedReadBuffer::readFlattenable(SkFlattenable::Type ft) {
}
return obj;
}
+
+/**
+ * Needs to follow the same pattern as readFlattenable(), but explicitly skip whatever data
+ * has been written.
+ */
+void SkReadBuffer::skipFlattenable() {
+ if (fFactoryCount > 0) {
+ if (0 == fReader.readU32()) {
+ return;
+ }
+ } else if (fFactoryTDArray) {
+ if (0 == fReader.readU32()) {
+ return;
+ }
+ } else {
+ if (NULL == this->readFunctionPtr()) {
+ return;
+ }
+ }
+ uint32_t sizeRecorded = fReader.readU32();
+ fReader.skip(sizeRecorded);
+}
diff --git a/chromium/third_party/skia/src/core/SkRecord.h b/chromium/third_party/skia/src/core/SkRecord.h
new file mode 100644
index 00000000000..6c5177eefb6
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkRecord.h
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkRecord_DEFINED
+#define SkRecord_DEFINED
+
+#include "SkChunkAlloc.h"
+#include "SkRecords.h"
+#include "SkTLogic.h"
+#include "SkTemplates.h"
+
+// SkRecord (REC-ord) represents a sequence of SkCanvas calls, saved for future use.
+// These future uses may include: replay, optimization, serialization, or combinations of those.
+//
+// Though an enterprising user may find calling alloc(), append(), visit(), and mutate() enough to
+// work with SkRecord, you probably want to look at SkRecorder which presents an SkCanvas interface
+// for creating an SkRecord, and SkRecordDraw which plays an SkRecord back into another SkCanvas.
+//
+// SkRecord often looks like it's compatible with any type T, but really it's compatible with any
+// type T which has a static const SkRecords::Type kType. That is to say, SkRecord is compatible
+// only with SkRecords::* structs defined in SkRecords.h. Your compiler will helpfully yell if you
+// get this wrong.
+
+class SkRecord : SkNoncopyable {
+public:
+ SkRecord(size_t chunkBytes = 4096, unsigned firstReserveCount = 64 / sizeof(void*))
+ : fAlloc(chunkBytes), fCount(0), fReserved(0), kFirstReserveCount(firstReserveCount) {}
+
+ ~SkRecord() {
+ Destroyer destroyer;
+ for (unsigned i = 0; i < this->count(); i++) {
+ this->mutate<void>(i, destroyer);
+ }
+ }
+
+ // Returns the number of canvas commands in this SkRecord.
+ unsigned count() const { return fCount; }
+
+ // Visit the i-th canvas command with a functor matching this interface:
+ // template <typename T>
+ // R operator()(const T& record) { ... }
+ // This operator() must be defined for at least all SkRecords::*.
+ template <typename R, typename F>
+ R visit(unsigned i, F& f) const {
+ SkASSERT(i < this->count());
+ return fRecords[i].visit<R>(fTypes[i], f);
+ }
+
+ // Mutate the i-th canvas command with a functor matching this interface:
+ // template <typename T>
+ // R operator()(T* record) { ... }
+ // This operator() must be defined for at least all SkRecords::*.
+ template <typename R, typename F>
+ R mutate(unsigned i, F& f) {
+ SkASSERT(i < this->count());
+ return fRecords[i].mutate<R>(fTypes[i], f);
+ }
+ // TODO: It'd be nice to infer R from F for visit and mutate if we ever get std::result_of.
+
+ // Allocate contiguous space for count Ts, to be freed when the SkRecord is destroyed.
+ // Here T can be any class, not just those from SkRecords. Throws on failure.
+ template <typename T>
+ T* alloc(unsigned count = 1) {
+ return (T*)fAlloc.allocThrow(sizeof(T) * count);
+ }
+
+ // Add a new command of type T to the end of this SkRecord.
+ // You are expected to placement new an object of type T onto this pointer.
+ template <typename T>
+ T* append() {
+ if (fCount == fReserved) {
+ fReserved = SkTMax(kFirstReserveCount, fReserved*2);
+ fRecords.realloc(fReserved);
+ fTypes.realloc(fReserved);
+ }
+
+ fTypes[fCount] = T::kType;
+ return fRecords[fCount++].set(this->allocCommand<T>());
+ }
+
+ // Replace the i-th command with a new command of type T.
+ // You are expected to placement new an object of type T onto this pointer.
+ // References to the original command are invalidated.
+ template <typename T>
+ T* replace(unsigned i) {
+ SkASSERT(i < this->count());
+
+ Destroyer destroyer;
+ this->mutate<void>(i, destroyer);
+
+ fTypes[i] = T::kType;
+ return fRecords[i].set(this->allocCommand<T>());
+ }
+
+ // Replace the i-th command with a new command of type T.
+ // You are expected to placement new an object of type T onto this pointer.
+ // You must show proof that you've already adopted the existing command.
+ template <typename T, typename Existing>
+ T* replace(unsigned i, const SkRecords::Adopted<Existing>& proofOfAdoption) {
+ SkASSERT(i < this->count());
+
+ SkASSERT(Existing::kType == fTypes[i]);
+ SkASSERT(proofOfAdoption == fRecords[i].ptr<Existing>());
+
+ fTypes[i] = T::kType;
+ return fRecords[i].set(this->allocCommand<T>());
+ }
+
+private:
+ // Implementation notes!
+ //
+ // Logically an SkRecord is structured as an array of pointers into a big chunk of memory where
+ // records representing each canvas draw call are stored:
+ //
+ // fRecords: [*][*][*]...
+ // | | |
+ // | | |
+ // | | +---------------------------------------+
+ // | +-----------------+ |
+ // | | |
+ // v v v
+ // fAlloc: [SkRecords::DrawRect][SkRecords::DrawPosTextH][SkRecords::DrawRect]...
+ //
+ // In the scheme above, the pointers in fRecords are void*: they have no type. The type is not
+ // stored in fAlloc either; we just write raw data there. But we need that type information.
+ // Here are some options:
+ // 1) use inheritance, virtuals, and vtables to make the fRecords pointers smarter
+ // 2) store the type data manually in fAlloc at the start of each record
+ // 3) store the type data manually somewhere with fRecords
+ //
+ // This code uses approach 3). The implementation feels very similar to 1), but it's
+ // devirtualized instead of using the language's polymorphism mechanisms. This lets us work
+ // with the types themselves (as SkRecords::Type), a sort of limited free RTTI; it lets us pay
+ // only 1 byte to store the type instead of a full pointer (4-8 bytes); and it leads to better
+ // decoupling between the SkRecords::* record types and the operations performed on them in
+ // visit() or mutate(). The recorded canvas calls don't have to have any idea about the
+ // operations performed on them.
+ //
+ // We store the types in a parallel fTypes array, mainly so that they can be tightly packed as
+ // single bytes. This has the side effect of allowing very fast analysis passes over an
+ // SkRecord looking for just patterns of draw commands (or using this as a quick reject
+ // mechanism) though there's admittedly not a very good API exposed publically for this.
+ //
+ // The cost to append a T into this structure is 1 + sizeof(void*) + sizeof(T).
+
+ // A mutator that can be used with replace to destroy canvas commands.
+ struct Destroyer {
+ template <typename T>
+ void operator()(T* record) { record->~T(); }
+ };
+
+ // Logically the same as SkRecords::Type, but packed into 8 bits.
+ struct Type8 {
+ public:
+ // This intentionally converts implicitly back and forth.
+ Type8(SkRecords::Type type) : fType(type) { SkASSERT(*this == type); }
+ operator SkRecords::Type () { return (SkRecords::Type)fType; }
+
+ private:
+ uint8_t fType;
+ };
+
+ // No point in allocating any more than one of an empty struct.
+ // We could just return NULL but it's sort of confusing to return NULL on success.
+ template <typename T>
+ SK_WHEN(SkTIsEmpty<T>, T*) allocCommand() {
+ static T singleton = {};
+ return &singleton;
+ }
+
+ template <typename T>
+ SK_WHEN(!SkTIsEmpty<T>, T*) allocCommand() { return this->alloc<T>(); }
+
+ // An untyped pointer to some bytes in fAlloc. This is the interface for polymorphic dispatch:
+ // visit() and mutate() work with the parallel fTypes array to do the work of a vtable.
+ struct Record {
+ public:
+ // Point this record to its data in fAlloc. Returns ptr for convenience.
+ template <typename T>
+ T* set(T* ptr) {
+ fPtr = ptr;
+ return ptr;
+ }
+
+ // Get the data in fAlloc, assuming it's of type T.
+ template <typename T>
+ T* ptr() const { return (T*)fPtr; }
+
+ // Visit this record with functor F (see public API above) assuming the record we're
+ // pointing to has this type.
+ template <typename R, typename F>
+ R visit(Type8 type, F& f) const {
+ #define CASE(T) case SkRecords::T##_Type: return f(*this->ptr<SkRecords::T>());
+ switch(type) { SK_RECORD_TYPES(CASE) }
+ #undef CASE
+ SkDEBUGFAIL("Unreachable");
+ return R();
+ }
+
+ // Mutate this record with functor F (see public API above) assuming the record we're
+ // pointing to has this type.
+ template <typename R, typename F>
+ R mutate(Type8 type, F& f) {
+ #define CASE(T) case SkRecords::T##_Type: return f(this->ptr<SkRecords::T>());
+ switch(type) { SK_RECORD_TYPES(CASE) }
+ #undef CASE
+ SkDEBUGFAIL("Unreachable");
+ return R();
+ }
+
+ private:
+ void* fPtr;
+ };
+
+ // fAlloc needs to be a data structure which can append variable length data in contiguous
+ // chunks, returning a stable handle to that data for later retrieval.
+ //
+ // fRecords and fTypes need to be data structures that can append fixed length data, and need to
+ // support efficient forward iteration. (They don't need to be contiguous or indexable.)
+
+ SkChunkAlloc fAlloc;
+ SkAutoTMalloc<Record> fRecords;
+ SkAutoTMalloc<Type8> fTypes;
+ // fCount and fReserved measure both fRecords and fTypes, which always grow in lock step.
+ unsigned fCount;
+ unsigned fReserved;
+ const unsigned kFirstReserveCount;
+};
+
+#endif//SkRecord_DEFINED
diff --git a/chromium/third_party/skia/src/core/SkRecordDraw.cpp b/chromium/third_party/skia/src/core/SkRecordDraw.cpp
new file mode 100644
index 00000000000..2bf7076bb05
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkRecordDraw.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkRecordDraw.h"
+
+void SkRecordDraw(const SkRecord& record, SkCanvas* canvas) {
+ for (SkRecords::Draw draw(canvas); draw.index() < record.count(); draw.next()) {
+ record.visit<void>(draw.index(), draw);
+ }
+}
+
+namespace SkRecords {
+
+bool Draw::skip(const PairedPushCull& r) {
+ if (fCanvas->quickReject(r.base->rect)) {
+ fIndex += r.skip;
+ return true;
+ }
+ return false;
+}
+
+bool Draw::skip(const BoundedDrawPosTextH& r) {
+ return fCanvas->quickRejectY(r.minY, r.maxY);
+}
+
+// NoOps draw nothing.
+template <> void Draw::draw(const NoOp&) {}
+
+#define DRAW(T, call) template <> void Draw::draw(const T& r) { fCanvas->call; }
+DRAW(Restore, restore());
+DRAW(Save, save(r.flags));
+DRAW(SaveLayer, saveLayer(r.bounds, r.paint, r.flags));
+DRAW(PopCull, popCull());
+DRAW(PushCull, pushCull(r.rect));
+DRAW(Clear, clear(r.color));
+DRAW(Concat, concat(r.matrix));
+DRAW(SetMatrix, setMatrix(SkMatrix::Concat(fInitialCTM, r.matrix)));
+
+DRAW(ClipPath, clipPath(r.path, r.op, r.doAA));
+DRAW(ClipRRect, clipRRect(r.rrect, r.op, r.doAA));
+DRAW(ClipRect, clipRect(r.rect, r.op, r.doAA));
+DRAW(ClipRegion, clipRegion(r.region, r.op));
+
+DRAW(DrawBitmap, drawBitmap(r.bitmap, r.left, r.top, r.paint));
+DRAW(DrawBitmapMatrix, drawBitmapMatrix(r.bitmap, r.matrix, r.paint));
+DRAW(DrawBitmapNine, drawBitmapNine(r.bitmap, r.center, r.dst, r.paint));
+DRAW(DrawBitmapRectToRect, drawBitmapRectToRect(r.bitmap, r.src, r.dst, r.paint, r.flags));
+DRAW(DrawDRRect, drawDRRect(r.outer, r.inner, r.paint));
+DRAW(DrawOval, drawOval(r.oval, r.paint));
+DRAW(DrawPaint, drawPaint(r.paint));
+DRAW(DrawPath, drawPath(r.path, r.paint));
+DRAW(DrawPoints, drawPoints(r.mode, r.count, r.pts, r.paint));
+DRAW(DrawPosText, drawPosText(r.text, r.byteLength, r.pos, r.paint));
+DRAW(DrawPosTextH, drawPosTextH(r.text, r.byteLength, r.xpos, r.y, r.paint));
+DRAW(DrawRRect, drawRRect(r.rrect, r.paint));
+DRAW(DrawRect, drawRect(r.rect, r.paint));
+DRAW(DrawSprite, drawSprite(r.bitmap, r.left, r.top, r.paint));
+DRAW(DrawText, drawText(r.text, r.byteLength, r.x, r.y, r.paint));
+DRAW(DrawTextOnPath, drawTextOnPath(r.text, r.byteLength, r.path, r.matrix, r.paint));
+DRAW(DrawVertices, drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.colors,
+ r.xmode.get(), r.indices, r.indexCount, r.paint));
+#undef DRAW
+
+template <> void Draw::draw(const PairedPushCull& r) { this->draw(*r.base); }
+template <> void Draw::draw(const BoundedDrawPosTextH& r) { this->draw(*r.base); }
+
+} // namespace SkRecords
diff --git a/chromium/third_party/skia/src/core/SkRecordDraw.h b/chromium/third_party/skia/src/core/SkRecordDraw.h
new file mode 100644
index 00000000000..359679a6d74
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkRecordDraw.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkRecordDraw_DEFINED
+#define SkRecordDraw_DEFINED
+
+#include "SkRecord.h"
+#include "SkCanvas.h"
+
+// Draw an SkRecord into an SkCanvas. A convenience wrapper around SkRecords::Draw.
+void SkRecordDraw(const SkRecord&, SkCanvas*);
+
+namespace SkRecords {
+
+// This is an SkRecord visitor that will draw that SkRecord to an SkCanvas.
+class Draw : SkNoncopyable {
+public:
+ explicit Draw(SkCanvas* canvas)
+ : fInitialCTM(canvas->getTotalMatrix()), fCanvas(canvas), fIndex(0) {}
+
+ unsigned index() const { return fIndex; }
+ void next() { ++fIndex; }
+
+ template <typename T> void operator()(const T& r) {
+ if (!this->skip(r)) {
+ this->draw(r);
+ }
+ }
+
+private:
+ // No base case, so we'll be compile-time checked that we implement all possibilities.
+ template <typename T> void draw(const T&);
+
+ // skip() should return true if we can skip this command, false if not.
+ // It may update fIndex directly to skip more than just this one command.
+
+ // Mostly we just blindly call fCanvas and let it handle quick rejects itself.
+ template <typename T> bool skip(const T&) { return false; }
+
+ // We add our own quick rejects for commands added by optimizations.
+ bool skip(const PairedPushCull&);
+ bool skip(const BoundedDrawPosTextH&);
+
+ const SkMatrix fInitialCTM;
+ SkCanvas* fCanvas;
+ unsigned fIndex;
+};
+
+} // namespace SkRecords
+
+#endif//SkRecordDraw_DEFINED
diff --git a/chromium/third_party/skia/src/core/SkRecordOpts.cpp b/chromium/third_party/skia/src/core/SkRecordOpts.cpp
new file mode 100644
index 00000000000..75f7c626056
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkRecordOpts.cpp
@@ -0,0 +1,303 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkRecordOpts.h"
+
+#include "SkRecordPattern.h"
+#include "SkRecords.h"
+#include "SkTDArray.h"
+
+using namespace SkRecords;
+
+void SkRecordOptimize(SkRecord* record) {
+ // TODO(mtklein): fuse independent optimizations to reduce number of passes?
+ SkRecordNoopCulls(record);
+ SkRecordNoopSaveRestores(record);
+ // TODO(mtklein): figure out why we draw differently and reenable
+ //SkRecordNoopSaveLayerDrawRestores(record);
+
+ SkRecordAnnotateCullingPairs(record);
+ SkRecordReduceDrawPosTextStrength(record); // Helpful to run this before BoundDrawPosTextH.
+ SkRecordBoundDrawPosTextH(record);
+}
+
+// Most of the optimizations in this file are pattern-based. These are all defined as structs with:
+// - a Pattern typedef
+// - a bool onMatch(SkRceord*, Pattern*, unsigned begin, unsigned end) method,
+// which returns true if it made changes and false if not.
+
+// Run a pattern-based optimization once across the SkRecord, returning true if it made any changes.
+// It looks for spans which match Pass::Pattern, and when found calls onMatch() with the pattern,
+// record, and [begin,end) span of the commands that matched.
+template <typename Pass>
+static bool apply(Pass* pass, SkRecord* record) {
+ typename Pass::Pattern pattern;
+ bool changed = false;
+ unsigned begin, end = 0;
+
+ while (pattern.search(record, &begin, &end)) {
+ changed |= pass->onMatch(record, &pattern, begin, end);
+ }
+ return changed;
+}
+
+struct CullNooper {
+ typedef Pattern3<Is<PushCull>, Star<Is<NoOp> >, Is<PopCull> > Pattern;
+
+ bool onMatch(SkRecord* record, Pattern* pattern, unsigned begin, unsigned end) {
+ record->replace<NoOp>(begin); // PushCull
+ record->replace<NoOp>(end-1); // PopCull
+ return true;
+ }
+};
+
+void SkRecordNoopCulls(SkRecord* record) {
+ CullNooper pass;
+ while (apply(&pass, record));
+}
+
+// Turns the logical NoOp Save and Restore in Save-Draw*-Restore patterns into actual NoOps.
+struct SaveOnlyDrawsRestoreNooper {
+ typedef Pattern3<Is<Save>,
+ Star<Or<Is<NoOp>, IsDraw> >,
+ Is<Restore> >
+ Pattern;
+
+ bool onMatch(SkRecord* record, Pattern* pattern, unsigned begin, unsigned end) {
+ record->replace<NoOp>(begin); // Save
+ record->replace<NoOp>(end-1); // Restore
+ return true;
+ }
+};
+// Turns logical no-op Save-[non-drawing command]*-Restore patterns into actual no-ops.
+struct SaveNoDrawsRestoreNooper {
+ // Star matches greedily, so we also have to exclude Save and Restore.
+ typedef Pattern3<Is<Save>,
+ Star<Not<Or3<Is<Save>,
+ Is<Restore>,
+ IsDraw> > >,
+ Is<Restore> >
+ Pattern;
+
+ bool onMatch(SkRecord* record, Pattern* pattern, unsigned begin, unsigned end) {
+ // If restore doesn't revert both matrix and clip, this isn't safe to noop away.
+ if (pattern->first<Save>()->flags != SkCanvas::kMatrixClip_SaveFlag) {
+ return false;
+ }
+
+ // The entire span between Save and Restore (inclusively) does nothing.
+ for (unsigned i = begin; i < end; i++) {
+ record->replace<NoOp>(i);
+ }
+ return true;
+ }
+};
+void SkRecordNoopSaveRestores(SkRecord* record) {
+ SaveOnlyDrawsRestoreNooper onlyDraws;
+ SaveNoDrawsRestoreNooper noDraws;
+
+ // Run until they stop changing things.
+ while (apply(&onlyDraws, record) || apply(&noDraws, record));
+}
+
+// For some SaveLayer-[drawing command]-Restore patterns, merge the SaveLayer's alpha into the
+// draw, and no-op the SaveLayer and Restore.
+struct SaveLayerDrawRestoreNooper {
+ typedef Pattern3<Is<SaveLayer>, IsDraw, Is<Restore> > Pattern;
+
+ bool onMatch(SkRecord* record, Pattern* pattern, unsigned begin, unsigned end) {
+ SaveLayer* saveLayer = pattern->first<SaveLayer>();
+ if (saveLayer->bounds != NULL) {
+ // SaveLayer with bounds is too tricky for us.
+ return false;
+ }
+
+ SkPaint* layerPaint = saveLayer->paint;
+ if (NULL == layerPaint) {
+ // There wasn't really any point to this SaveLayer at all.
+ return KillSaveLayerAndRestore(record, begin);
+ }
+
+ SkPaint* drawPaint = pattern->second<SkPaint>();
+ if (drawPaint == NULL) {
+ // We can just give the draw the SaveLayer's paint.
+ // TODO(mtklein): figure out how to do this clearly
+ return false;
+ }
+
+ const uint32_t layerColor = layerPaint->getColor();
+ const uint32_t drawColor = drawPaint->getColor();
+ if (!IsOnlyAlpha(layerColor) || !IsOpaque(drawColor) ||
+ HasAnyEffect(*layerPaint) || HasAnyEffect(*drawPaint)) {
+ // Too fancy for us. Actually, as long as layerColor is just an alpha
+ // we can blend it into drawColor's alpha; drawColor doesn't strictly have to be opaque.
+ return false;
+ }
+
+ drawPaint->setColor(SkColorSetA(drawColor, SkColorGetA(layerColor)));
+ return KillSaveLayerAndRestore(record, begin);
+ }
+
+ static bool KillSaveLayerAndRestore(SkRecord* record, unsigned saveLayerIndex) {
+ record->replace<NoOp>(saveLayerIndex); // SaveLayer
+ record->replace<NoOp>(saveLayerIndex+2); // Restore
+ return true;
+ }
+
+ static bool HasAnyEffect(const SkPaint& paint) {
+ return paint.getPathEffect() ||
+ paint.getShader() ||
+ paint.getXfermode() ||
+ paint.getMaskFilter() ||
+ paint.getColorFilter() ||
+ paint.getRasterizer() ||
+ paint.getLooper() ||
+ paint.getImageFilter();
+ }
+
+ static bool IsOpaque(SkColor color) {
+ return SkColorGetA(color) == SK_AlphaOPAQUE;
+ }
+ static bool IsOnlyAlpha(SkColor color) {
+ return SK_ColorTRANSPARENT == SkColorSetA(color, SK_AlphaTRANSPARENT);
+ }
+};
+void SkRecordNoopSaveLayerDrawRestores(SkRecord* record) {
+ SaveLayerDrawRestoreNooper pass;
+ apply(&pass, record);
+}
+
+
+// Replaces DrawPosText with DrawPosTextH when all Y coordinates are equal.
+struct StrengthReducer {
+ typedef Pattern1<Is<DrawPosText> > Pattern;
+
+ bool onMatch(SkRecord* record, Pattern* pattern, unsigned begin, unsigned end) {
+ SkASSERT(end == begin + 1);
+ DrawPosText* draw = pattern->first<DrawPosText>();
+
+ const unsigned points = draw->paint.countText(draw->text, draw->byteLength);
+ if (points == 0) {
+ return false; // No point (ha!).
+ }
+
+ const SkScalar firstY = draw->pos[0].fY;
+ for (unsigned i = 1; i < points; i++) {
+ if (draw->pos[i].fY != firstY) {
+ return false; // Needs full power of DrawPosText.
+ }
+ }
+ // All ys are the same. We can replace DrawPosText with DrawPosTextH.
+
+ // draw->pos is points SkPoints, [(x,y),(x,y),(x,y),(x,y), ... ].
+ // We're going to squint and look at that as 2*points SkScalars, [x,y,x,y,x,y,x,y, ...].
+ // Then we'll rearrange things so all the xs are in order up front, clobbering the ys.
+ SK_COMPILE_ASSERT(sizeof(SkPoint) == 2 * sizeof(SkScalar), SquintingIsNotSafe);
+ SkScalar* scalars = &draw->pos[0].fX;
+ for (unsigned i = 0; i < 2*points; i += 2) {
+ scalars[i/2] = scalars[i];
+ }
+
+ // Extend lifetime of draw to the end of the loop so we can copy its paint.
+ Adopted<DrawPosText> adopted(draw);
+ SkNEW_PLACEMENT_ARGS(record->replace<DrawPosTextH>(begin, adopted),
+ DrawPosTextH,
+ (draw->paint, draw->text, draw->byteLength, scalars, firstY));
+ return true;
+ }
+};
+void SkRecordReduceDrawPosTextStrength(SkRecord* record) {
+ StrengthReducer pass;
+ apply(&pass, record);
+}
+
+// Tries to replace DrawPosTextH with BoundedDrawPosTextH, which knows conservative upper and lower
+// bounds to use with SkCanvas::quickRejectY.
+struct TextBounder {
+ typedef Pattern1<Is<DrawPosTextH> > Pattern;
+
+ bool onMatch(SkRecord* record, Pattern* pattern, unsigned begin, unsigned end) {
+ SkASSERT(end == begin + 1);
+ DrawPosTextH* draw = pattern->first<DrawPosTextH>();
+
+ // If we're drawing vertical text, none of the checks we're about to do make any sense.
+ // We'll need to call SkPaint::computeFastBounds() later, so bail if that's not possible.
+ if (draw->paint.isVerticalText() || !draw->paint.canComputeFastBounds()) {
+ return false;
+ }
+
+ // Rather than checking the top and bottom font metrics, we guess. Actually looking up the
+ // top and bottom metrics is slow, and this overapproximation should be good enough.
+ const SkScalar buffer = draw->paint.getTextSize() * 1.5f;
+ SkDEBUGCODE(SkPaint::FontMetrics metrics;)
+ SkDEBUGCODE(draw->paint.getFontMetrics(&metrics);)
+ SkASSERT(-buffer <= metrics.fTop);
+ SkASSERT(+buffer >= metrics.fBottom);
+
+ // Let the paint adjust the text bounds. We don't care about left and right here, so we use
+ // 0 and 1 respectively just so the bounds rectangle isn't empty.
+ SkRect bounds;
+ bounds.set(0, draw->y - buffer, SK_Scalar1, draw->y + buffer);
+ SkRect adjusted = draw->paint.computeFastBounds(bounds, &bounds);
+
+ Adopted<DrawPosTextH> adopted(draw);
+ SkNEW_PLACEMENT_ARGS(record->replace<BoundedDrawPosTextH>(begin, adopted),
+ BoundedDrawPosTextH,
+ (&adopted, adjusted.fTop, adjusted.fBottom));
+ return true;
+ }
+};
+void SkRecordBoundDrawPosTextH(SkRecord* record) {
+ TextBounder pass;
+ apply(&pass, record);
+}
+
+// Replaces PushCull with PairedPushCull, which lets us skip to the paired PopCull when the canvas
+// can quickReject the cull rect.
+// There's no efficient way (yet?) to express this one as a pattern, so we write a custom pass.
+class CullAnnotator {
+public:
+ // Do nothing to most ops.
+ template <typename T> void operator()(T*) {}
+
+ void operator()(PushCull* push) {
+ Pair pair = { fIndex, push };
+ fPushStack.push(pair);
+ }
+
+ void operator()(PopCull* pop) {
+ Pair push = fPushStack.top();
+ fPushStack.pop();
+
+ SkASSERT(fIndex > push.index);
+ unsigned skip = fIndex - push.index;
+
+ Adopted<PushCull> adopted(push.command);
+ SkNEW_PLACEMENT_ARGS(fRecord->replace<PairedPushCull>(push.index, adopted),
+ PairedPushCull, (&adopted, skip));
+ }
+
+ void apply(SkRecord* record) {
+ for (fRecord = record, fIndex = 0; fIndex < record->count(); fIndex++) {
+ fRecord->mutate<void>(fIndex, *this);
+ }
+ }
+
+private:
+ struct Pair {
+ unsigned index;
+ PushCull* command;
+ };
+
+ SkTDArray<Pair> fPushStack;
+ SkRecord* fRecord;
+ unsigned fIndex;
+};
+void SkRecordAnnotateCullingPairs(SkRecord* record) {
+ CullAnnotator pass;
+ pass.apply(record);
+}
diff --git a/chromium/third_party/skia/src/core/SkRecordOpts.h b/chromium/third_party/skia/src/core/SkRecordOpts.h
new file mode 100644
index 00000000000..b535ec958ad
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkRecordOpts.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkRecordOpts_DEFINED
+#define SkRecordOpts_DEFINED
+
+#include "SkRecord.h"
+
+// Run all optimizations in recommended order.
+void SkRecordOptimize(SkRecord*);
+
+// NoOp away pointless PushCull/PopCull pairs with nothing between them.
+void SkRecordNoopCulls(SkRecord*);
+
+// Turns logical no-op Save-[non-drawing command]*-Restore patterns into actual no-ops.
+void SkRecordNoopSaveRestores(SkRecord*);
+
+// For some SaveLayer-[drawing command]-Restore patterns, merge the SaveLayer's alpha into the
+// draw, and no-op the SaveLayer and Restore.
+void SkRecordNoopSaveLayerDrawRestores(SkRecord*);
+
+// Annotates PushCull commands with the relative offset of their paired PopCull.
+void SkRecordAnnotateCullingPairs(SkRecord*);
+
+// Convert DrawPosText to DrawPosTextH when all the Y coordinates are equal.
+void SkRecordReduceDrawPosTextStrength(SkRecord*);
+
+// Calculate min and max Y bounds for DrawPosTextH commands, for use with SkCanvas::quickRejectY.
+void SkRecordBoundDrawPosTextH(SkRecord*);
+
+#endif//SkRecordOpts_DEFINED
diff --git a/chromium/third_party/skia/src/core/SkRecordPattern.h b/chromium/third_party/skia/src/core/SkRecordPattern.h
new file mode 100644
index 00000000000..57779ffd761
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkRecordPattern.h
@@ -0,0 +1,183 @@
+#ifndef SkRecordPattern_DEFINED
+#define SkRecordPattern_DEFINED
+
+#include "SkTLogic.h"
+
+namespace SkRecords {
+
+// First, some matchers. These match a single command in the SkRecord,
+// and may hang onto some data from it. If so, you can get the data by calling .get().
+
+// Matches a command of type T, and stores that command.
+template <typename T>
+class Is {
+public:
+ Is() : fPtr(NULL) {}
+
+ typedef T type;
+ type* get() { return fPtr; }
+
+ bool operator()(T* ptr) {
+ fPtr = ptr;
+ return true;
+ }
+
+ template <typename U>
+ bool operator()(U*) {
+ fPtr = NULL;
+ return false;
+ }
+
+private:
+ type* fPtr;
+};
+
+// Matches any command that draws, and stores its paint.
+class IsDraw {
+ SK_CREATE_MEMBER_DETECTOR(paint);
+public:
+ IsDraw() : fPaint(NULL) {}
+
+ typedef SkPaint type;
+ type* get() { return fPaint; }
+
+ template <typename T>
+ SK_WHEN(HasMember_paint<T>, bool) operator()(T* draw) {
+ fPaint = AsPtr(draw->paint);
+ return true;
+ }
+
+ template <typename T>
+ SK_WHEN(!HasMember_paint<T>, bool) operator()(T*) {
+ fPaint = NULL;
+ return false;
+ }
+
+ // SaveLayer has an SkPaint named paint, but it's not a draw.
+ bool operator()(SaveLayer*) {
+ fPaint = NULL;
+ return false;
+ }
+
+private:
+ // Abstracts away whether the paint is always part of the command or optional.
+ template <typename T> static T* AsPtr(SkRecords::Optional<T>& x) { return x; }
+ template <typename T> static T* AsPtr(T& x) { return &x; }
+
+ type* fPaint;
+};
+
+// Matches if Matcher doesn't. Stores nothing.
+template <typename Matcher>
+struct Not {
+ template <typename T>
+ bool operator()(T* ptr) { return !Matcher()(ptr); }
+};
+
+// Matches if either of A or B does. Stores nothing.
+template <typename A, typename B>
+struct Or {
+ template <typename T>
+ bool operator()(T* ptr) { return A()(ptr) || B()(ptr); }
+};
+
+// Matches if any of A, B or C does. Stores nothing.
+template <typename A, typename B, typename C>
+struct Or3 : Or<A, Or<B, C> > {};
+
+// Star is a special matcher that greedily matches Matcher 0 or more times. Stores nothing.
+template <typename Matcher>
+struct Star {
+ template <typename T>
+ bool operator()(T* ptr) { return Matcher()(ptr); }
+};
+
+// Cons builds a list of Matchers.
+// It first matches Matcher (something from above), then Pattern (another Cons or Nil).
+//
+// This is the main entry point to pattern matching, and so provides a couple of extra API bits:
+// - search scans through the record to look for matches;
+// - first, second, and third return the data stored by their respective matchers in the pattern.
+//
+// These Cons build lists analogously to Lisp's "cons". See Pattern# for the "list" equivalent.
+template <typename Matcher, typename Pattern>
+class Cons {
+public:
+ // If this pattern matches the SkRecord starting at i,
+ // return the index just past the end of the pattern, otherwise return 0.
+ SK_ALWAYS_INLINE unsigned match(SkRecord* record, unsigned i) {
+ i = this->matchHead(&fHead, record, i);
+ return i == 0 ? 0 : fTail.match(record, i);
+ }
+
+ // Starting from *end, walk through the SkRecord to find the first span matching this pattern.
+ // If there is no such span, return false. If there is, return true and set [*begin, *end).
+ SK_ALWAYS_INLINE bool search(SkRecord* record, unsigned* begin, unsigned* end) {
+ for (*begin = *end; *begin < record->count(); ++(*begin)) {
+ *end = this->match(record, *begin);
+ if (*end != 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Once either match or search has succeeded, access the stored data of the first, second,
+ // or third matcher in this pattern. Add as needed for longer patterns.
+ // T is checked statically at compile time; no casting is involved. It's just an API wart.
+ template <typename T> T* first() { return fHead.get(); }
+ template <typename T> T* second() { return fTail.fHead.get(); }
+ template <typename T> T* third() { return fTail.fTail.fHead.get(); }
+
+private:
+ // If head isn't a Star, try to match at i once.
+ template <typename T>
+ unsigned matchHead(T*, SkRecord* record, unsigned i) {
+ if (i < record->count()) {
+ if (record->mutate<bool>(i, fHead)) {
+ return i+1;
+ }
+ }
+ return 0;
+ }
+
+ // If head is a Star, walk i until it doesn't match.
+ template <typename T>
+ unsigned matchHead(Star<T>*, SkRecord* record, unsigned i) {
+ while (i < record->count()) {
+ if (!record->mutate<bool>(i, fHead)) {
+ return i;
+ }
+ i++;
+ }
+ return 0;
+ }
+
+ Matcher fHead;
+ Pattern fTail;
+
+ // All Cons are friends with each other. This lets first, second, and third work.
+ template <typename, typename> friend class Cons;
+};
+
+// Nil is the end of every pattern Cons chain.
+struct Nil {
+ // Bottoms out recursion down the fTail chain. Just return whatever i the front decided on.
+ unsigned match(SkRecord*, unsigned i) { return i; }
+};
+
+// These Pattern# types are syntax sugar over Cons and Nil, just to help eliminate some of the
+// template noise. Use these if you can. Feel free to add more for longer patterns.
+// All types A, B, C, ... are Matchers.
+template <typename A>
+struct Pattern1 : Cons<A, Nil> {};
+
+template <typename A, typename B>
+struct Pattern2 : Cons<A, Pattern1<B> > {};
+
+template <typename A, typename B, typename C>
+struct Pattern3 : Cons<A, Pattern2<B, C> > {};
+
+} // namespace SkRecords
+
+#endif//SkRecordPattern_DEFINED
diff --git a/chromium/third_party/skia/src/core/SkRecorder.cpp b/chromium/third_party/skia/src/core/SkRecorder.cpp
new file mode 100644
index 00000000000..8581257c4ae
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkRecorder.cpp
@@ -0,0 +1,263 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkRecorder.h"
+#include "SkPicture.h"
+
+// SkCanvas will fail in mysterious ways if it doesn't know the real width and height.
+SkRecorder::SkRecorder(SkRecord* record, int width, int height)
+ : SkCanvas(width, height), fRecord(record) {}
+
+void SkRecorder::forgetRecord() {
+ fRecord = NULL;
+}
+
+// To make appending to fRecord a little less verbose.
+#define APPEND(T, ...) \
+ SkNEW_PLACEMENT_ARGS(fRecord->append<SkRecords::T>(), SkRecords::T, (__VA_ARGS__))
+
+// For methods which must call back into SkCanvas.
+#define INHERITED(method, ...) this->SkCanvas::method(__VA_ARGS__)
+
+// The structs we're creating all copy their constructor arguments. Given the way the SkRecords
+// framework works, sometimes they happen to technically be copied twice, which is fine and elided
+// into a single copy unless the class has a non-trivial copy constructor. For classes with
+// non-trivial copy constructors, we skip the first copy (and its destruction) by wrapping the value
+// with delay_copy(), forcing the argument to be passed by const&.
+//
+// This is used below for SkBitmap, SkPaint, SkPath, and SkRegion, which all have non-trivial copy
+// constructors and destructors. You'll know you've got a good candidate T if you see ~T() show up
+// unexpectedly on a profile of record time. Otherwise don't bother.
+template <typename T>
+class Reference {
+public:
+ Reference(const T& x) : fX(x) {}
+ operator const T&() const { return fX; }
+private:
+ const T& fX;
+};
+
+template <typename T>
+static Reference<T> delay_copy(const T& x) { return Reference<T>(x); }
+
+// Use copy() only for optional arguments, to be copied if present or skipped if not.
+// (For most types we just pass by value and let copy constructors do their thing.)
+template <typename T>
+T* SkRecorder::copy(const T* src) {
+ if (NULL == src) {
+ return NULL;
+ }
+ return SkNEW_PLACEMENT_ARGS(fRecord->alloc<T>(), T, (*src));
+}
+
+// This copy() is for arrays.
+// It will work with POD or non-POD, though currently we only use it for POD.
+template <typename T>
+T* SkRecorder::copy(const T src[], unsigned count) {
+ if (NULL == src) {
+ return NULL;
+ }
+ T* dst = fRecord->alloc<T>(count);
+ for (unsigned i = 0; i < count; i++) {
+ SkNEW_PLACEMENT_ARGS(dst + i, T, (src[i]));
+ }
+ return dst;
+}
+
+// Specialization for copying strings, using memcpy.
+// This measured around 2x faster for copying code points,
+// but I found no corresponding speedup for other arrays.
+template <>
+char* SkRecorder::copy(const char src[], unsigned count) {
+ if (NULL == src) {
+ return NULL;
+ }
+ char* dst = fRecord->alloc<char>(count);
+ memcpy(dst, src, count);
+ return dst;
+}
+
+void SkRecorder::clear(SkColor color) {
+ APPEND(Clear, color);
+}
+
+void SkRecorder::drawPaint(const SkPaint& paint) {
+ APPEND(DrawPaint, delay_copy(paint));
+}
+
+void SkRecorder::drawPoints(PointMode mode,
+ size_t count,
+ const SkPoint pts[],
+ const SkPaint& paint) {
+ APPEND(DrawPoints, delay_copy(paint), mode, count, this->copy(pts, count));
+}
+
+void SkRecorder::drawRect(const SkRect& rect, const SkPaint& paint) {
+ APPEND(DrawRect, delay_copy(paint), rect);
+}
+
+void SkRecorder::drawOval(const SkRect& oval, const SkPaint& paint) {
+ APPEND(DrawOval, delay_copy(paint), oval);
+}
+
+void SkRecorder::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
+ APPEND(DrawRRect, delay_copy(paint), rrect);
+}
+
+void SkRecorder::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
+ APPEND(DrawDRRect, delay_copy(paint), outer, inner);
+}
+
+void SkRecorder::drawPath(const SkPath& path, const SkPaint& paint) {
+ APPEND(DrawPath, delay_copy(paint), delay_copy(path));
+}
+
+void SkRecorder::drawBitmap(const SkBitmap& bitmap,
+ SkScalar left,
+ SkScalar top,
+ const SkPaint* paint) {
+ APPEND(DrawBitmap, this->copy(paint), delay_copy(bitmap), left, top);
+}
+
+void SkRecorder::drawBitmapRectToRect(const SkBitmap& bitmap,
+ const SkRect* src,
+ const SkRect& dst,
+ const SkPaint* paint,
+ DrawBitmapRectFlags flags) {
+ APPEND(DrawBitmapRectToRect,
+ this->copy(paint), delay_copy(bitmap), this->copy(src), dst, flags);
+}
+
+void SkRecorder::drawBitmapMatrix(const SkBitmap& bitmap,
+ const SkMatrix& matrix,
+ const SkPaint* paint) {
+ APPEND(DrawBitmapMatrix, this->copy(paint), delay_copy(bitmap), matrix);
+}
+
+void SkRecorder::drawBitmapNine(const SkBitmap& bitmap,
+ const SkIRect& center,
+ const SkRect& dst,
+ const SkPaint* paint) {
+ APPEND(DrawBitmapNine, this->copy(paint), delay_copy(bitmap), center, dst);
+}
+
+void SkRecorder::drawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint* paint) {
+ APPEND(DrawSprite, this->copy(paint), delay_copy(bitmap), left, top);
+}
+
+void SkRecorder::onDrawText(const void* text, size_t byteLength,
+ SkScalar x, SkScalar y, const SkPaint& paint) {
+ APPEND(DrawText,
+ delay_copy(paint), this->copy((const char*)text, byteLength), byteLength, x, y);
+}
+
+void SkRecorder::onDrawPosText(const void* text, size_t byteLength,
+ const SkPoint pos[], const SkPaint& paint) {
+ const unsigned points = paint.countText(text, byteLength);
+ APPEND(DrawPosText,
+ delay_copy(paint),
+ this->copy((const char*)text, byteLength),
+ byteLength,
+ this->copy(pos, points));
+}
+
+void SkRecorder::onDrawPosTextH(const void* text, size_t byteLength,
+ const SkScalar xpos[], SkScalar constY, const SkPaint& paint) {
+ const unsigned points = paint.countText(text, byteLength);
+ APPEND(DrawPosTextH,
+ delay_copy(paint),
+ this->copy((const char*)text, byteLength),
+ byteLength,
+ this->copy(xpos, points),
+ constY);
+}
+
+void SkRecorder::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
+ const SkMatrix* matrix, const SkPaint& paint) {
+ APPEND(DrawTextOnPath,
+ delay_copy(paint),
+ this->copy((const char*)text, byteLength),
+ byteLength,
+ delay_copy(path),
+ this->copy(matrix));
+}
+
+void SkRecorder::onDrawPicture(const SkPicture* picture) {
+ picture->draw(this);
+}
+
+void SkRecorder::drawVertices(VertexMode vmode,
+ int vertexCount, const SkPoint vertices[],
+ const SkPoint texs[], const SkColor colors[],
+ SkXfermode* xmode,
+ const uint16_t indices[], int indexCount, const SkPaint& paint) {
+ APPEND(DrawVertices, delay_copy(paint),
+ vmode,
+ vertexCount,
+ this->copy(vertices, vertexCount),
+ texs ? this->copy(texs, vertexCount) : NULL,
+ colors ? this->copy(colors, vertexCount) : NULL,
+ xmode,
+ this->copy(indices, indexCount),
+ indexCount);
+}
+
+void SkRecorder::willSave(SkCanvas::SaveFlags flags) {
+ APPEND(Save, flags);
+ INHERITED(willSave, flags);
+}
+
+SkCanvas::SaveLayerStrategy SkRecorder::willSaveLayer(const SkRect* bounds,
+ const SkPaint* paint,
+ SkCanvas::SaveFlags flags) {
+ APPEND(SaveLayer, this->copy(bounds), this->copy(paint), flags);
+ INHERITED(willSaveLayer, bounds, paint, flags);
+ return SkCanvas::kNoLayer_SaveLayerStrategy;
+}
+
+void SkRecorder::willRestore() {
+ APPEND(Restore);
+ INHERITED(willRestore);
+}
+
+void SkRecorder::onPushCull(const SkRect& rect) {
+ APPEND(PushCull, rect);
+}
+
+void SkRecorder::onPopCull() {
+ APPEND(PopCull);
+}
+
+void SkRecorder::didConcat(const SkMatrix& matrix) {
+ APPEND(Concat, matrix);
+ INHERITED(didConcat, matrix);
+}
+
+void SkRecorder::didSetMatrix(const SkMatrix& matrix) {
+ APPEND(SetMatrix, matrix);
+ INHERITED(didSetMatrix, matrix);
+}
+
+void SkRecorder::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
+ APPEND(ClipRect, rect, op, edgeStyle == kSoft_ClipEdgeStyle);
+ INHERITED(onClipRect, rect, op, edgeStyle);
+}
+
+void SkRecorder::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
+ APPEND(ClipRRect, rrect, op, edgeStyle == kSoft_ClipEdgeStyle);
+ INHERITED(updateClipConservativelyUsingBounds, rrect.getBounds(), op, false);
+}
+
+void SkRecorder::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
+ APPEND(ClipPath, delay_copy(path), op, edgeStyle == kSoft_ClipEdgeStyle);
+ INHERITED(updateClipConservativelyUsingBounds, path.getBounds(), op, path.isInverseFillType());
+}
+
+void SkRecorder::onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op) {
+ APPEND(ClipRegion, delay_copy(deviceRgn), op);
+ INHERITED(onClipRegion, deviceRgn, op);
+}
diff --git a/chromium/third_party/skia/src/core/SkRecorder.h b/chromium/third_party/skia/src/core/SkRecorder.h
new file mode 100644
index 00000000000..3e2932d42e9
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkRecorder.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkRecorder_DEFINED
+#define SkRecorder_DEFINED
+
+#include "SkCanvas.h"
+#include "SkRecord.h"
+#include "SkRecords.h"
+
+// SkRecorder provides an SkCanvas interface for recording into an SkRecord.
+
+class SkRecorder : public SkCanvas {
+public:
+ // Does not take ownership of the SkRecord.
+ SkRecorder(SkRecord*, int width, int height);
+
+ // Make SkRecorder forget entirely about its SkRecord*; all calls to SkRecorder will fail.
+ void forgetRecord();
+
+ void clear(SkColor) SK_OVERRIDE;
+ void drawPaint(const SkPaint& paint) SK_OVERRIDE;
+ void drawPoints(PointMode mode,
+ size_t count,
+ const SkPoint pts[],
+ const SkPaint& paint) SK_OVERRIDE;
+ void drawRect(const SkRect& rect, const SkPaint& paint) SK_OVERRIDE;
+ void drawOval(const SkRect& oval, const SkPaint&) SK_OVERRIDE;
+ void drawRRect(const SkRRect& rrect, const SkPaint& paint) SK_OVERRIDE;
+ void drawPath(const SkPath& path, const SkPaint& paint) SK_OVERRIDE;
+ void drawBitmap(const SkBitmap& bitmap,
+ SkScalar left,
+ SkScalar top,
+ const SkPaint* paint = NULL) SK_OVERRIDE;
+ void drawBitmapRectToRect(const SkBitmap& bitmap,
+ const SkRect* src,
+ const SkRect& dst,
+ const SkPaint* paint = NULL,
+ DrawBitmapRectFlags flags = kNone_DrawBitmapRectFlag) SK_OVERRIDE;
+ void drawBitmapMatrix(const SkBitmap& bitmap,
+ const SkMatrix& m,
+ const SkPaint* paint = NULL) SK_OVERRIDE;
+ void drawBitmapNine(const SkBitmap& bitmap,
+ const SkIRect& center,
+ const SkRect& dst,
+ const SkPaint* paint = NULL) SK_OVERRIDE;
+ void drawSprite(const SkBitmap& bitmap,
+ int left,
+ int top,
+ const SkPaint* paint = NULL) SK_OVERRIDE;
+ void drawVertices(VertexMode vmode,
+ int vertexCount,
+ const SkPoint vertices[],
+ const SkPoint texs[],
+ const SkColor colors[],
+ SkXfermode* xmode,
+ const uint16_t indices[],
+ int indexCount,
+ const SkPaint& paint) SK_OVERRIDE;
+
+ void willSave(SkCanvas::SaveFlags) SK_OVERRIDE;
+ SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SkCanvas::SaveFlags) SK_OVERRIDE;
+ void willRestore() SK_OVERRIDE;
+
+ void didConcat(const SkMatrix&) SK_OVERRIDE;
+ void didSetMatrix(const SkMatrix&) SK_OVERRIDE;
+
+ void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) SK_OVERRIDE;
+ void onDrawText(const void* text,
+ size_t byteLength,
+ SkScalar x,
+ SkScalar y,
+ const SkPaint& paint) SK_OVERRIDE;
+ void onDrawPosText(const void* text,
+ size_t byteLength,
+ const SkPoint pos[],
+ const SkPaint& paint) SK_OVERRIDE;
+ void onDrawPosTextH(const void* text,
+ size_t byteLength,
+ const SkScalar xpos[],
+ SkScalar constY,
+ const SkPaint& paint) SK_OVERRIDE;
+ void onDrawTextOnPath(const void* text,
+ size_t byteLength,
+ const SkPath& path,
+ const SkMatrix* matrix,
+ const SkPaint& paint) SK_OVERRIDE;
+ void onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) SK_OVERRIDE;
+ void onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) SK_OVERRIDE;
+ void onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) SK_OVERRIDE;
+ void onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op) SK_OVERRIDE;
+
+ void onDrawPicture(const SkPicture* picture) SK_OVERRIDE;
+
+ void onPushCull(const SkRect& cullRect) SK_OVERRIDE;
+ void onPopCull() SK_OVERRIDE;
+
+private:
+ template <typename T>
+ T* copy(const T*);
+
+ template <typename T>
+ T* copy(const T[], unsigned count);
+
+ SkRecord* fRecord;
+};
+
+#endif//SkRecorder_DEFINED
diff --git a/chromium/third_party/skia/src/core/SkRecording.cpp b/chromium/third_party/skia/src/core/SkRecording.cpp
new file mode 100644
index 00000000000..94fabce9121
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkRecording.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "../../include/record/SkRecording.h"
+
+#include "SkRecord.h"
+#include "SkRecordOpts.h"
+#include "SkRecordDraw.h"
+#include "SkRecorder.h"
+
+namespace EXPERIMENTAL {
+
+SkPlayback::SkPlayback(const SkRecord* record) : fRecord(record) {}
+
+SkPlayback::~SkPlayback() {}
+
+void SkPlayback::draw(SkCanvas* canvas) const {
+ SkASSERT(fRecord.get() != NULL);
+ SkRecordDraw(*fRecord, canvas);
+}
+
+SkRecording::SkRecording(int width, int height)
+ : fRecord(SkNEW(SkRecord))
+ , fRecorder(SkNEW_ARGS(SkRecorder, (fRecord.get(), width, height)))
+ {}
+
+SkPlayback* SkRecording::releasePlayback() {
+ SkASSERT(fRecorder->unique());
+ fRecorder->forgetRecord();
+ SkRecordOptimize(fRecord.get());
+ return SkNEW_ARGS(SkPlayback, (fRecord.detach()));
+}
+
+SkRecording::~SkRecording() {}
+
+SkCanvas* SkRecording::canvas() {
+ return fRecord.get() ? fRecorder.get() : NULL;
+}
+
+} // namespace EXPERIMENTAL
diff --git a/chromium/third_party/skia/src/core/SkRecords.h b/chromium/third_party/skia/src/core/SkRecords.h
new file mode 100644
index 00000000000..581ae21e053
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkRecords.h
@@ -0,0 +1,291 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkRecords_DEFINED
+#define SkRecords_DEFINED
+
+#include "SkCanvas.h"
+
+namespace SkRecords {
+
+// A list of all the types of canvas calls we can record.
+// Each of these is reified into a struct below.
+//
+// (We're using the macro-of-macro trick here to do several different things with the same list.)
+//
+// We leave this SK_RECORD_TYPES macro defined for use by code that wants to operate on SkRecords
+// types polymorphically. (See SkRecord::Record::{visit,mutate} for an example.)
+//
+// Order doesn't technically matter here, but the compiler can generally generate better code if
+// you keep them semantically grouped, especially the Draws. It's also nice to leave NoOp at 0.
+#define SK_RECORD_TYPES(M) \
+ M(NoOp) \
+ M(Restore) \
+ M(Save) \
+ M(SaveLayer) \
+ M(PushCull) \
+ M(PopCull) \
+ M(PairedPushCull) /*From SkRecordAnnotateCullingPairs*/ \
+ M(Concat) \
+ M(SetMatrix) \
+ M(ClipPath) \
+ M(ClipRRect) \
+ M(ClipRect) \
+ M(ClipRegion) \
+ M(Clear) \
+ M(DrawBitmap) \
+ M(DrawBitmapMatrix) \
+ M(DrawBitmapNine) \
+ M(DrawBitmapRectToRect) \
+ M(DrawDRRect) \
+ M(DrawOval) \
+ M(DrawPaint) \
+ M(DrawPath) \
+ M(DrawPoints) \
+ M(DrawPosText) \
+ M(DrawPosTextH) \
+ M(DrawRRect) \
+ M(DrawRect) \
+ M(DrawSprite) \
+ M(DrawText) \
+ M(DrawTextOnPath) \
+ M(DrawVertices) \
+ M(BoundedDrawPosTextH) /*From SkRecordBoundDrawPosTextH*/
+
+// Defines SkRecords::Type, an enum of all record types.
+#define ENUM(T) T##_Type,
+enum Type { SK_RECORD_TYPES(ENUM) };
+#undef ENUM
+
+// Macros to make it easier to define a record for a draw call with 0 args, 1 args, 2 args, etc.
+// These should be clearer when you look at their use below.
+#define RECORD0(T) \
+struct T { \
+ static const Type kType = T##_Type; \
+};
+
+// We try to be flexible about the types the constructors take. Instead of requring the exact type
+// A here, we take any type Z which implicitly casts to A. This allows the delay_copy() trick to
+// work, allowing the caller to decide whether to pass by value or by const&.
+
+#define RECORD1(T, A, a) \
+struct T { \
+ static const Type kType = T##_Type; \
+ template <typename Z> \
+ T(Z a) : a(a) {} \
+ A a; \
+};
+
+#define RECORD2(T, A, a, B, b) \
+struct T { \
+ static const Type kType = T##_Type; \
+ template <typename Z, typename Y> \
+ T(Z a, Y b) : a(a), b(b) {} \
+ A a; B b; \
+};
+
+#define RECORD3(T, A, a, B, b, C, c) \
+struct T { \
+ static const Type kType = T##_Type; \
+ template <typename Z, typename Y, typename X> \
+ T(Z a, Y b, X c) : a(a), b(b), c(c) {} \
+ A a; B b; C c; \
+};
+
+#define RECORD4(T, A, a, B, b, C, c, D, d) \
+struct T { \
+ static const Type kType = T##_Type; \
+ template <typename Z, typename Y, typename X, typename W> \
+ T(Z a, Y b, X c, W d) : a(a), b(b), c(c), d(d) {} \
+ A a; B b; C c; D d; \
+};
+
+#define RECORD5(T, A, a, B, b, C, c, D, d, E, e) \
+struct T { \
+ static const Type kType = T##_Type; \
+ template <typename Z, typename Y, typename X, typename W, typename V> \
+ T(Z a, Y b, X c, W d, V e) : a(a), b(b), c(c), d(d), e(e) {} \
+ A a; B b; C c; D d; E e; \
+};
+
+#define ACT_AS_PTR(ptr) \
+ operator T*() { return ptr; } \
+ operator const T*() const { return ptr; } \
+ T* operator->() { return ptr; } \
+ const T* operator->() const { return ptr; }
+
+// An Optional doesn't own the pointer's memory, but may need to destroy non-POD data.
+template <typename T>
+class Optional : SkNoncopyable {
+public:
+ Optional(T* ptr) : fPtr(ptr) {}
+ ~Optional() { if (fPtr) fPtr->~T(); }
+
+ ACT_AS_PTR(fPtr);
+private:
+ T* fPtr;
+};
+
+// Like Optional, but ptr must not be NULL.
+template <typename T>
+class Adopted : SkNoncopyable {
+public:
+ Adopted(T* ptr) : fPtr(ptr) { SkASSERT(fPtr); }
+ Adopted(Adopted* source) {
+ // Transfer ownership from source to this.
+ fPtr = source->fPtr;
+ source->fPtr = NULL;
+ }
+ ~Adopted() { if (fPtr) fPtr->~T(); }
+
+ ACT_AS_PTR(fPtr);
+private:
+ T* fPtr;
+};
+
+// PODArray doesn't own the pointer's memory, and we assume the data is POD.
+template <typename T>
+class PODArray {
+public:
+ PODArray(T* ptr) : fPtr(ptr) {}
+ // Default copy and assign.
+
+ ACT_AS_PTR(fPtr);
+private:
+ T* fPtr;
+};
+
+#undef ACT_AS_PTR
+
+// Like SkBitmap, but deep copies pixels if they're not immutable.
+// Using this, we guarantee the immutability of all bitmaps we record.
+class ImmutableBitmap {
+public:
+ explicit ImmutableBitmap(const SkBitmap& bitmap) {
+ if (bitmap.isImmutable()) {
+ fBitmap = bitmap;
+ } else {
+ bitmap.copyTo(&fBitmap);
+ }
+ fBitmap.setImmutable();
+ }
+
+ operator const SkBitmap& () const { return fBitmap; }
+
+private:
+ SkBitmap fBitmap;
+};
+
+RECORD0(NoOp);
+
+RECORD0(Restore);
+RECORD1(Save, SkCanvas::SaveFlags, flags);
+RECORD3(SaveLayer, Optional<SkRect>, bounds, Optional<SkPaint>, paint, SkCanvas::SaveFlags, flags);
+
+RECORD1(PushCull, SkRect, rect);
+RECORD0(PopCull);
+
+RECORD1(Concat, SkMatrix, matrix);
+RECORD1(SetMatrix, SkMatrix, matrix);
+
+RECORD3(ClipPath, SkPath, path, SkRegion::Op, op, bool, doAA);
+RECORD3(ClipRRect, SkRRect, rrect, SkRegion::Op, op, bool, doAA);
+RECORD3(ClipRect, SkRect, rect, SkRegion::Op, op, bool, doAA);
+RECORD2(ClipRegion, SkRegion, region, SkRegion::Op, op);
+
+RECORD1(Clear, SkColor, color);
+// While not strictly required, if you have an SkPaint, it's fastest to put it first.
+RECORD4(DrawBitmap, Optional<SkPaint>, paint,
+ ImmutableBitmap, bitmap,
+ SkScalar, left,
+ SkScalar, top);
+RECORD3(DrawBitmapMatrix, Optional<SkPaint>, paint, ImmutableBitmap, bitmap, SkMatrix, matrix);
+RECORD4(DrawBitmapNine, Optional<SkPaint>, paint,
+ ImmutableBitmap, bitmap,
+ SkIRect, center,
+ SkRect, dst);
+RECORD5(DrawBitmapRectToRect, Optional<SkPaint>, paint,
+ ImmutableBitmap, bitmap,
+ Optional<SkRect>, src,
+ SkRect, dst,
+ SkCanvas::DrawBitmapRectFlags, flags);
+RECORD3(DrawDRRect, SkPaint, paint, SkRRect, outer, SkRRect, inner);
+RECORD2(DrawOval, SkPaint, paint, SkRect, oval);
+RECORD1(DrawPaint, SkPaint, paint);
+RECORD2(DrawPath, SkPaint, paint, SkPath, path);
+RECORD4(DrawPoints, SkPaint, paint, SkCanvas::PointMode, mode, size_t, count, SkPoint*, pts);
+RECORD4(DrawPosText, SkPaint, paint,
+ PODArray<char>, text,
+ size_t, byteLength,
+ PODArray<SkPoint>, pos);
+RECORD5(DrawPosTextH, SkPaint, paint,
+ PODArray<char>, text,
+ size_t, byteLength,
+ PODArray<SkScalar>, xpos,
+ SkScalar, y);
+RECORD2(DrawRRect, SkPaint, paint, SkRRect, rrect);
+RECORD2(DrawRect, SkPaint, paint, SkRect, rect);
+RECORD4(DrawSprite, Optional<SkPaint>, paint, ImmutableBitmap, bitmap, int, left, int, top);
+RECORD5(DrawText, SkPaint, paint,
+ PODArray<char>, text,
+ size_t, byteLength,
+ SkScalar, x,
+ SkScalar, y);
+RECORD5(DrawTextOnPath, SkPaint, paint,
+ PODArray<char>, text,
+ size_t, byteLength,
+ SkPath, path,
+ Optional<SkMatrix>, matrix);
+
+// This guy is so ugly we just write it manually.
+struct DrawVertices {
+ static const Type kType = DrawVertices_Type;
+
+ DrawVertices(const SkPaint& paint,
+ SkCanvas::VertexMode vmode,
+ int vertexCount,
+ SkPoint* vertices,
+ SkPoint* texs,
+ SkColor* colors,
+ SkXfermode* xmode,
+ uint16_t* indices,
+ int indexCount)
+ : paint(paint)
+ , vmode(vmode)
+ , vertexCount(vertexCount)
+ , vertices(vertices)
+ , texs(texs)
+ , colors(colors)
+ , xmode(SkSafeRef(xmode))
+ , indices(indices)
+ , indexCount(indexCount) {}
+
+ SkPaint paint;
+ SkCanvas::VertexMode vmode;
+ int vertexCount;
+ PODArray<SkPoint> vertices;
+ PODArray<SkPoint> texs;
+ PODArray<SkColor> colors;
+ SkAutoTUnref<SkXfermode> xmode;
+ PODArray<uint16_t> indices;
+ int indexCount;
+};
+
+// Records added by optimizations.
+RECORD2(PairedPushCull, Adopted<PushCull>, base, unsigned, skip);
+RECORD3(BoundedDrawPosTextH, Adopted<DrawPosTextH>, base, SkScalar, minY, SkScalar, maxY);
+
+#undef RECORD0
+#undef RECORD1
+#undef RECORD2
+#undef RECORD3
+#undef RECORD4
+#undef RECORD5
+
+} // namespace SkRecords
+
+#endif//SkRecords_DEFINED
diff --git a/chromium/third_party/skia/src/core/SkRect.cpp b/chromium/third_party/skia/src/core/SkRect.cpp
index c62f2f3cf6d..3cff5d81e5a 100644
--- a/chromium/third_party/skia/src/core/SkRect.cpp
+++ b/chromium/third_party/skia/src/core/SkRect.cpp
@@ -55,21 +55,6 @@ void SkRect::toQuad(SkPoint quad[4]) const {
quad[3].set(fLeft, fBottom);
}
-#ifdef SK_SCALAR_IS_FLOAT
- #define SkFLOATCODE(code) code
-#else
- #define SkFLOATCODE(code)
-#endif
-
-// For float compares (at least on x86, by removing the else from the min/max
-// computation, we get MAXSS and MINSS instructions, and no branches.
-// Fixed point has no such opportunity (afaik), so we leave the else in that case
-#ifdef SK_SCALAR_IS_FLOAT
- #define MINMAX_ELSE
-#else
- #define MINMAX_ELSE else
-#endif
-
bool SkRect::setBoundsCheck(const SkPoint pts[], int count) {
SkASSERT((pts && count > 0) || count == 0);
@@ -78,24 +63,6 @@ bool SkRect::setBoundsCheck(const SkPoint pts[], int count) {
if (count <= 0) {
sk_bzero(this, sizeof(SkRect));
} else {
-#ifdef SK_SCALAR_SLOW_COMPARES
- int32_t l, t, r, b;
-
- l = r = SkScalarAs2sCompliment(pts[0].fX);
- t = b = SkScalarAs2sCompliment(pts[0].fY);
-
- for (int i = 1; i < count; i++) {
- int32_t x = SkScalarAs2sCompliment(pts[i].fX);
- int32_t y = SkScalarAs2sCompliment(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(Sk2sComplimentAsScalar(l),
- Sk2sComplimentAsScalar(t),
- Sk2sComplimentAsScalar(r),
- Sk2sComplimentAsScalar(b));
-#else
SkScalar l, t, r, b;
l = r = pts[0].fX;
@@ -103,28 +70,30 @@ bool SkRect::setBoundsCheck(const SkPoint pts[], int count) {
// If all of the points are finite, accum should stay 0. If we encounter
// a NaN or infinity, then accum should become NaN.
- SkFLOATCODE(float accum = 0;)
- SkFLOATCODE(accum *= l; accum *= t;)
+ float accum = 0;
+ accum *= l; accum *= t;
for (int i = 1; i < count; i++) {
SkScalar x = pts[i].fX;
SkScalar y = pts[i].fY;
- SkFLOATCODE(accum *= x; accum *= y;)
+ accum *= x; accum *= y;
- if (x < l) l = x; MINMAX_ELSE if (x > r) r = x;
- if (y < t) t = y; MINMAX_ELSE if (y > b) b = y;
+ // we use if instead of if/else, so we can generate min/max
+ // float instructions (at least on SSE)
+ if (x < l) l = x;
+ if (x > r) r = x;
+
+ if (y < t) t = y;
+ if (y > b) b = y;
}
-#ifdef SK_SCALAR_IS_FLOAT
SkASSERT(!accum || !SkScalarIsFinite(accum));
if (accum) {
l = t = r = b = 0;
isFinite = false;
}
-#endif
this->set(l, t, r, b);
-#endif
}
return isFinite;
@@ -149,6 +118,22 @@ bool SkRect::intersect(const SkRect& r) {
return this->intersect(r.fLeft, r.fTop, r.fRight, r.fBottom);
}
+bool SkRect::intersect2(const SkRect& r) {
+ SkASSERT(&r);
+ SkScalar L = SkMaxScalar(fLeft, r.fLeft);
+ SkScalar R = SkMinScalar(fRight, r.fRight);
+ if (L >= R) {
+ return false;
+ }
+ SkScalar T = SkMaxScalar(fTop, r.fTop);
+ SkScalar B = SkMinScalar(fBottom, r.fBottom);
+ if (T >= B) {
+ return false;
+ }
+ this->set(L, T, R, B);
+ return true;
+}
+
bool SkRect::intersect(const SkRect& a, const SkRect& b) {
SkASSERT(&a && &b);
diff --git a/chromium/third_party/skia/src/core/SkRegion.cpp b/chromium/third_party/skia/src/core/SkRegion.cpp
index baedf2aea82..24d7248582f 100644
--- a/chromium/third_party/skia/src/core/SkRegion.cpp
+++ b/chromium/third_party/skia/src/core/SkRegion.cpp
@@ -212,12 +212,6 @@ char* SkRegion::toString() {
///////////////////////////////////////////////////////////////////////////////
int SkRegion::count_runtype_values(int* itop, int* ibot) const {
- if (this == NULL) {
- *itop = SK_MinS32;
- *ibot = SK_MaxS32;
- return 0;
- }
-
int maxT;
if (this->isRect()) {
@@ -796,7 +790,7 @@ public:
fTop = (SkRegion::RunType)(bottom); // just update our bottom
} else {
start[-2] = (SkRegion::RunType)(bottom);
- start[-1] = len >> 1;
+ start[-1] = SkToS32(len >> 1);
fPrevDst = start;
fPrevLen = len;
}
@@ -1212,7 +1206,7 @@ static void compute_bounds(const SkRegion::RunType runs[],
const SkRegion::RunType* prev = runs;
runs = skip_intervals_slow(runs);
- int intervals = (runs - prev) >> 1;
+ int intervals = SkToInt((runs - prev) >> 1);
SkASSERT(prev[-1] == intervals);
intervalCount += intervals;
diff --git a/chromium/third_party/skia/src/core/SkRegionPriv.h b/chromium/third_party/skia/src/core/SkRegionPriv.h
index f299f3a9d69..c8f000df35e 100644
--- a/chromium/third_party/skia/src/core/SkRegionPriv.h
+++ b/chromium/third_party/skia/src/core/SkRegionPriv.h
@@ -29,7 +29,7 @@ static int compute_intervalcount(const SkRegion::RunType runs[]) {
SkASSERT(curr[1] < SkRegion::kRunTypeSentinel);
curr += 2;
}
- return (curr - runs) >> 1;
+ return SkToInt((curr - runs) >> 1);
}
#endif
@@ -213,7 +213,7 @@ public:
#ifdef SK_DEBUG
// +1 to skip the last Y-sentinel
- int runCount = runs - this->writable_runs() + 1;
+ int runCount = SkToInt(runs - this->writable_runs() + 1);
SkASSERT(runCount == fRunCount);
#endif
diff --git a/chromium/third_party/skia/src/core/SkRegion_path.cpp b/chromium/third_party/skia/src/core/SkRegion_path.cpp
index 98e937cbed2..03830e6ce54 100644
--- a/chromium/third_party/skia/src/core/SkRegion_path.cpp
+++ b/chromium/third_party/skia/src/core/SkRegion_path.cpp
@@ -112,8 +112,6 @@ bool SkRgnBuilder::init(int maxHeight, int maxTransitions, bool pathIsInverse) {
return false;
}
- Sk64 count, size;
-
if (pathIsInverse) {
// allow for additional X transitions to "invert" each scanline
// [ L' ... normal transitions ... R' ]
@@ -122,25 +120,25 @@ bool SkRgnBuilder::init(int maxHeight, int maxTransitions, bool pathIsInverse) {
}
// compute the count with +1 and +3 slop for the working buffer
- count.setMul(maxHeight + 1, 3 + maxTransitions);
+ int64_t count = sk_64_mul(maxHeight + 1, 3 + maxTransitions);
if (pathIsInverse) {
// allow for two "empty" rows for the top and bottom
// [ Y, 1, L, R, S] == 5 (*2 for top and bottom)
- count.add(10);
+ count += 10;
}
- if (!count.is32() || count.isNeg()) {
+ if (count < 0 || !sk_64_isS32(count)) {
return false;
}
- fStorageCount = count.get32();
+ fStorageCount = sk_64_asS32(count);
- size.setMul(fStorageCount, sizeof(SkRegion::RunType));
- if (!size.is32() || size.isNeg()) {
+ int64_t size = sk_64_mul(fStorageCount, sizeof(SkRegion::RunType));
+ if (size < 0 || !sk_64_isS32(size)) {
return false;
}
- fStorage = (SkRegion::RunType*)sk_malloc_flags(size.get32(), 0);
+ fStorage = (SkRegion::RunType*)sk_malloc_flags(sk_64_asS32(size), 0);
if (NULL == fStorage) {
return false;
}
@@ -295,8 +293,8 @@ static int count_path_runtype_values(const SkPath& path, int* itop, int* ibot) {
}
SkASSERT(top <= bot);
- *itop = SkScalarRound(top);
- *ibot = SkScalarRound(bot);
+ *itop = SkScalarRoundToInt(top);
+ *ibot = SkScalarRoundToInt(bot);
return maxEdges;
}
diff --git a/chromium/third_party/skia/src/core/SkRegion_rects.cpp b/chromium/third_party/skia/src/core/SkRegion_rects.cpp
deleted file mode 100644
index 4121080c417..00000000000
--- a/chromium/third_party/skia/src/core/SkRegion_rects.cpp
+++ /dev/null
@@ -1,290 +0,0 @@
-
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "SkRegion.h"
-#include "SkChunkAlloc.h"
-#include "SkTDArray.h"
-#include "SkTemplates.h"
-
-#if 0
-
-struct VEdge {
- VEdge* fPrev;
- VEdge* fNext;
-
- SkRegion::RunType fX;
- SkRegion::RunType fTop;
- SkRegion::RunType fBottom;
- int fWinding;
-
- void removeFromList() {
- fPrev->fNext = fNext;
- fNext->fPrev = fPrev;
- }
-
- void backwardsInsert() {
- while (fPrev->fX > fX) {
- VEdge* prev = fPrev;
- VEdge* next = this;
-
- // remove prev from the list
- prev->fPrev->fNext = next;
- next->fPrev = prev->fPrev;
-
- // insert prev after next
- prev->fNext = next->fNext;
- next->fNext->fPrev = prev;
- next->fNext = prev;
- prev->fPrev = next;
- }
- }
-
- static void SetFromRect(VEdge edges[], const SkIRect& r) {
- edges[0].fX = r.fLeft;
- edges[0].fTop = r.fTop;
- edges[0].fBottom = r.fBottom;
- edges[0].fWinding = -1;
-
- edges[1].fX = r.fRight;
- edges[1].fTop = r.fTop;
- edges[1].fBottom = r.fBottom;
- edges[1].fWinding = 1;
- }
-};
-
-class Accumulator {
-public:
- Accumulator(SkRegion::RunType top, int numRects);
- ~Accumulator() {}
-
- SkRegion::RunType append(SkRegion::RunType top, const VEdge* edge);
-
- int count() const { return fTotalCount; }
- void copyTo(SkRegion::RunType dst[]);
-
-private:
- struct Row {
- SkRegion::RunType* fPtr;
- SkRegion::RunType fBottom;
- int fCount; // just [L R] count
- };
- SkChunkAlloc fAlloc;
- SkTDArray<Row> fRows;
- SkRegion::RunType fTop;
- int fTotalCount;
- int fRectCount;
-};
-
-Accumulator::Accumulator(SkRegion::RunType top, int numRects)
- : fAlloc((1 + numRects * 2 + 1) * sizeof(int32_t)) {
- fRectCount = numRects;
- fTop = top;
- fTotalCount = 2; // Top + final sentinel
-}
-
-//#define TRACE_ROW(code) code
-#define TRACE_ROW(code)
-
-SkRegion::RunType Accumulator::append(SkRegion::RunType currY, const VEdge* edge) {
- // worst-case size
- size_t size = fRectCount * 2 * sizeof(SkRegion::RunType);
- SkRegion::RunType* row = (SkRegion::RunType*)fAlloc.allocThrow(size);
- SkRegion::RunType* rowHead = row;
-
- SkRegion::RunType nextY = SkRegion::kRunTypeSentinel;
- int winding = edge->fWinding;
-
- // record the L R values for this row
-
- if (edge->fTop > currY) {
- nextY = SkMin32(nextY, edge->fTop);
- TRACE_ROW(SkDebugf("Y %d\n", currY);)
- } else {
- SkRegion::RunType currR;
- *row++ = edge->fX;
- TRACE_ROW(SkDebugf("Y %d [%d", currY, edge->fX);)
- edge = edge->fNext;
- for (;;) {
- if (edge->fTop > currY) {
- nextY = SkMin32(nextY, edge->fTop);
- break;
- }
-
- int prevWinding = winding;
- winding += edge->fWinding;
- if (0 == winding) { // we finished an interval
- currR = edge->fX;
- } else if (0 == prevWinding && edge->fX > currR) {
- *row++ = currR;
- *row++ = edge->fX;
- TRACE_ROW(SkDebugf(" %d] [%d", currR, edge->fX);)
- }
-
- nextY = SkMin32(nextY, edge->fBottom);
- edge = edge->fNext;
- }
- SkASSERT(0 == winding);
- *row++ = currR;
- TRACE_ROW(SkDebugf(" %d]\n", currR);)
- }
- int rowCount = row - rowHead;
-
- // now see if we have already seen this row, or if its unique
-
- Row* r = fRows.count() ? &fRows[fRows.count() - 1] : NULL;
- if (r && (r->fCount == rowCount) &&
- !memcmp(r->fPtr, rowHead,
- rowCount * sizeof(SkRegion::RunType))) {
- r->fBottom = nextY; // update bottom
- fAlloc.unalloc(rowHead);
- } else {
- Row* r = fRows.append();
- r->fPtr = rowHead;
- r->fBottom = nextY;
- r->fCount = rowCount;
- fTotalCount += 1 + rowCount + 1;
- }
-
- return nextY;
-}
-
-void Accumulator::copyTo(SkRegion::RunType dst[]) {
- SkDEBUGCODE(SkRegion::RunType* startDst = dst;)
-
- *dst++ = fTop;
-
- const Row* curr = fRows.begin();
- const Row* stop = fRows.end();
- while (curr < stop) {
- *dst++ = curr->fBottom;
- memcpy(dst, curr->fPtr, curr->fCount * sizeof(SkRegion::RunType));
- dst += curr->fCount;
- *dst++ = SkRegion::kRunTypeSentinel;
- curr += 1;
- }
- *dst++ = SkRegion::kRunTypeSentinel;
- SkASSERT(dst - startDst == fTotalCount);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-template <typename T> int SkTCmp2Int(const T& a, const T& b) {
- return (a < b) ? -1 : ((b < a) ? 1 : 0);
-}
-
-static inline int SkCmp32(int32_t a, int32_t b) {
- return (a < b) ? -1 : ((b < a) ? 1 : 0);
-}
-
-static int compare_edgeptr(const void* p0, const void* p1) {
- const VEdge* e0 = *static_cast<VEdge*const*>(p0);
- const VEdge* e1 = *static_cast<VEdge*const*>(p1);
-
- SkRegion::RunType v0 = e0->fTop;
- SkRegion::RunType v1 = e1->fTop;
-
- if (v0 == v1) {
- v0 = e0->fX;
- v1 = e1->fX;
- }
- return SkCmp32(v0, v1);
-}
-
-// fillout edge[] from rects[], sorted. Return the head, and set the tail
-//
-static VEdge* sort_edges(VEdge** edgePtr, VEdge edge[], const SkIRect rects[],
- int rectCount, VEdge** edgeTail) {
- int i;
- VEdge** ptr = edgePtr;
- for (int i = 0; i < rectCount; i++) {
- if (!rects[i].isEmpty()) {
- VEdge::SetFromRect(edge, rects[i]);
- *ptr++ = edge++;
- *ptr++ = edge++;
- }
- }
-
- int edgeCount = ptr - edgePtr;
- if (0 == edgeCount) {
- // all the rects[] were empty
- return NULL;
- }
-
- qsort(edgePtr, edgeCount, sizeof(*edgePtr), compare_edgeptr);
- for (i = 1; i < edgeCount; i++) {
- edgePtr[i - 1]->fNext = edgePtr[i];
- edgePtr[i]->fPrev = edgePtr[i - 1];
- }
- *edgeTail = edgePtr[edgeCount - 1];
- return edgePtr[0];
-}
-
-bool SkRegion::setRects(const SkIRect rects[], int rectCount) {
- if (0 == rectCount) {
- return this->setEmpty();
- }
- if (1 == rectCount) {
- return this->setRect(rects[0]);
- }
-
- int edgeCount = rectCount * 2;
- SkAutoMalloc memory((sizeof(VEdge) + sizeof(VEdge*)) * edgeCount);
- VEdge** edgePtr = (VEdge**)memory.get();
- VEdge* tail, *head = (VEdge*)(edgePtr + edgeCount);
- head = sort_edges(edgePtr, head, rects, rectCount, &tail);
- // check if we have no edges
- if (NULL == head) {
- return this->setEmpty();
- }
-
- // at this stage, we don't really care about edgeCount, or if rectCount is
- // larger that it should be (since sort_edges might have skipped some
- // empty rects[]). rectCount now is just used for worst-case allocations
-
- VEdge headEdge, tailEdge;
- headEdge.fPrev = NULL;
- headEdge.fNext = head;
- headEdge.fTop = SK_MinS32;
- headEdge.fX = SK_MinS32;
- head->fPrev = &headEdge;
-
- tailEdge.fPrev = tail;
- tailEdge.fNext = NULL;
- tailEdge.fTop = SK_MaxS32;
- tail->fNext = &tailEdge;
-
- int32_t currY = head->fTop;
- Accumulator accum(currY, rectCount);
-
- while (head->fNext) {
- VEdge* edge = head;
- // accumulate the current
- SkRegion::RunType nextY = accum.append(currY, edge);
- // remove the old
- while (edge->fTop <= currY) {
- VEdge* next = edge->fNext;
- if (edge->fBottom <= nextY) {
- edge->removeFromList();
- }
- edge = next;
- }
- // insert (sorted) the new
- while (edge->fTop == nextY) {
- VEdge* next = edge->fNext;
- edge->backwardsInsert();
- edge = next;
- }
- currY = nextY;
- head = headEdge.fNext;
- }
-
- SkAutoTArray<RunType> runs(accum.count());
- accum.copyTo(runs.get());
- return this->setRuns(runs.get(), accum.count());
-}
-
-#endif
diff --git a/chromium/third_party/skia/src/core/SkScaledImageCache.cpp b/chromium/third_party/skia/src/core/SkScaledImageCache.cpp
index 2529b5f8ec6..a030248197a 100644
--- a/chromium/third_party/skia/src/core/SkScaledImageCache.cpp
+++ b/chromium/third_party/skia/src/core/SkScaledImageCache.cpp
@@ -7,7 +7,6 @@
#include "SkScaledImageCache.h"
#include "SkMipMap.h"
-#include "SkOnce.h"
#include "SkPixelRef.h"
#include "SkRect.h"
@@ -116,6 +115,9 @@ struct SkScaledImageCache::Rec {
SkSafeUnref(fMip);
}
+ static const Key& GetKey(const Rec& rec) { return rec.fKey; }
+ static uint32_t Hash(const Key& key) { return key.fHash; }
+
size_t bytesUsed() const {
return fMip ? fMip->getSize() : fBitmap.getSize();
}
@@ -135,25 +137,9 @@ struct SkScaledImageCache::Rec {
#include "SkTDynamicHash.h"
-namespace { // can't use static functions w/ template parameters
-const SkScaledImageCache::Key& key_from_rec(const SkScaledImageCache::Rec& rec) {
- return rec.fKey;
-}
-
-uint32_t hash_from_key(const SkScaledImageCache::Key& key) {
- return key.fHash;
-}
-
-bool eq_rec_key(const SkScaledImageCache::Rec& rec, const SkScaledImageCache::Key& key) {
- return rec.fKey == key;
-}
-}
+class SkScaledImageCache::Hash :
+ public SkTDynamicHash<SkScaledImageCache::Rec, SkScaledImageCache::Key> {};
-class SkScaledImageCache::Hash : public SkTDynamicHash<SkScaledImageCache::Rec,
- SkScaledImageCache::Key,
- key_from_rec,
- hash_from_key,
- eq_rec_key> {};
///////////////////////////////////////////////////////////////////////////////
@@ -192,6 +178,7 @@ void SkScaledImageCache::init() {
class SkOneShotDiscardablePixelRef : public SkPixelRef {
public:
+ SK_DECLARE_INST_COUNT(SkOneShotDiscardablePixelRef)
// Ownership of the discardablememory is transfered to the pixelref
SkOneShotDiscardablePixelRef(const SkImageInfo&, SkDiscardableMemory*, size_t rowBytes);
~SkOneShotDiscardablePixelRef();
@@ -199,13 +186,11 @@ public:
SK_DECLARE_UNFLATTENABLE_OBJECT()
protected:
- virtual void* onLockPixels(SkColorTable**) SK_OVERRIDE;
+ virtual bool onNewLockPixels(LockRec*) SK_OVERRIDE;
virtual void onUnlockPixels() SK_OVERRIDE;
virtual size_t getAllocatedSizeInBytes() const SK_OVERRIDE;
private:
- SkImageInfo fInfo; // remove when SkPixelRef gets this in baseclass
-
SkDiscardableMemory* fDM;
size_t fRB;
bool fFirstTime;
@@ -220,8 +205,6 @@ SkOneShotDiscardablePixelRef::SkOneShotDiscardablePixelRef(const SkImageInfo& in
, fDM(dm)
, fRB(rowBytes)
{
- fInfo = info; // remove this redundant field when SkPixelRef has info
-
SkASSERT(dm->data());
fFirstTime = true;
}
@@ -230,26 +213,31 @@ SkOneShotDiscardablePixelRef::~SkOneShotDiscardablePixelRef() {
SkDELETE(fDM);
}
-void* SkOneShotDiscardablePixelRef::onLockPixels(SkColorTable** ctable) {
+bool SkOneShotDiscardablePixelRef::onNewLockPixels(LockRec* rec) {
if (fFirstTime) {
// we're already locked
SkASSERT(fDM->data());
fFirstTime = false;
- return fDM->data();
+ goto SUCCESS;
}
// A previous call to onUnlock may have deleted our DM, so check for that
if (NULL == fDM) {
- return NULL;
+ return false;
}
if (!fDM->lock()) {
// since it failed, we delete it now, to free-up the resource
delete fDM;
fDM = NULL;
- return NULL;
+ return false;
}
- return fDM->data();
+
+SUCCESS:
+ rec->fPixels = fDM->data();
+ rec->fColorTable = NULL;
+ rec->fRowBytes = fRB;
+ return true;
}
void SkOneShotDiscardablePixelRef::onUnlockPixels() {
@@ -258,7 +246,7 @@ void SkOneShotDiscardablePixelRef::onUnlockPixels() {
}
size_t SkOneShotDiscardablePixelRef::getAllocatedSizeInBytes() const {
- return fInfo.fHeight * fRB;
+ return this->info().getSafeSize(fRB);
}
class SkScaledImageCacheDiscardableAllocator : public SkBitmap::Allocator {
@@ -278,7 +266,8 @@ private:
bool SkScaledImageCacheDiscardableAllocator::allocPixelRef(SkBitmap* bitmap,
SkColorTable* ctable) {
size_t size = bitmap->getSize();
- if (0 == size) {
+ uint64_t size64 = bitmap->computeSize64();
+ if (0 == size || size64 > (uint64_t)size) {
return false;
}
@@ -287,18 +276,12 @@ bool SkScaledImageCacheDiscardableAllocator::allocPixelRef(SkBitmap* bitmap,
return false;
}
- // can relax when we have bitmap::asImageInfo
- if (SkBitmap::kARGB_8888_Config != bitmap->config()) {
+ // can we relax this?
+ if (kN32_SkColorType != bitmap->colorType()) {
return false;
}
- SkImageInfo info = {
- bitmap->width(),
- bitmap->height(),
- kPMColor_SkColorType,
- bitmap->alphaType()
- };
-
+ SkImageInfo info = bitmap->info();
bitmap->setPixelRef(SkNEW_ARGS(SkOneShotDiscardablePixelRef,
(info, dm, bitmap->rowBytes())))->unref();
bitmap->lockPixels();
@@ -368,10 +351,8 @@ static SkIRect get_bounds_from_bitmap(const SkBitmap& bm) {
if (!(bm.pixelRef())) {
return SkIRect::MakeEmpty();
}
- size_t x, y;
- SkTDivMod(bm.pixelRefOffset(), bm.rowBytes(), &y, &x);
- x >>= bm.shiftPerPixel();
- return SkIRect::MakeXYWH(x, y, bm.width(), bm.height());
+ SkIPoint origin = bm.pixelRefOrigin();
+ return SkIRect::MakeXYWH(origin.fX, origin.fY, bm.width(), bm.height());
}
@@ -428,7 +409,11 @@ SkScaledImageCache::ID* SkScaledImageCache::addAndLock(SkScaledImageCache::Rec*
SkASSERT(rec);
// See if we already have this key (racy inserts, etc.)
Rec* existing = this->findAndLock(rec->fKey);
- if (existing != NULL) {
+ if (NULL != existing) {
+ // Since we already have a matching entry, just delete the new one and return.
+ // Call sites cannot assume the passed in object will live past this call.
+ existing->fBitmap = rec->fBitmap;
+ SkDELETE(rec);
return rec_to_id(existing);
}
@@ -685,21 +670,30 @@ void SkScaledImageCache::dump() const {
#include "SkThread.h"
SK_DECLARE_STATIC_MUTEX(gMutex);
-
-static void create_cache(SkScaledImageCache** cache) {
-#ifdef SK_USE_DISCARDABLE_SCALEDIMAGECACHE
- *cache = SkNEW_ARGS(SkScaledImageCache, (SkDiscardableMemory::Create));
-#else
- *cache = SkNEW_ARGS(SkScaledImageCache, (SK_DEFAULT_IMAGE_CACHE_LIMIT));
+static SkScaledImageCache* gScaledImageCache = NULL;
+static void cleanup_gScaledImageCache() {
+ // We'll clean this up in our own tests, but disable for clients.
+ // Chrome seems to have funky multi-process things going on in unit tests that
+ // makes this unsafe to delete when the main process atexit()s.
+ // SkLazyPtr does the same sort of thing.
+#if SK_DEVELOPER
+ SkDELETE(gScaledImageCache);
#endif
}
+/** Must hold gMutex when calling. */
static SkScaledImageCache* get_cache() {
- static SkScaledImageCache* gCache(NULL);
- SK_DECLARE_STATIC_ONCE(create_cache_once);
- SkOnce(&create_cache_once, create_cache, &gCache);
- SkASSERT(NULL != gCache);
- return gCache;
+ // gMutex is always held when this is called, so we don't need to be fancy in here.
+ gMutex.assertHeld();
+ if (NULL == gScaledImageCache) {
+#ifdef SK_USE_DISCARDABLE_SCALEDIMAGECACHE
+ gScaledImageCache = SkNEW_ARGS(SkScaledImageCache, (SkDiscardableMemory::Create));
+#else
+ gScaledImageCache = SkNEW_ARGS(SkScaledImageCache, (SK_DEFAULT_IMAGE_CACHE_LIMIT));
+#endif
+ atexit(cleanup_gScaledImageCache);
+ }
+ return gScaledImageCache;
}
diff --git a/chromium/third_party/skia/src/core/SkScalerContext.cpp b/chromium/third_party/skia/src/core/SkScalerContext.cpp
index 04ef2a92221..3e20bf69ed6 100644
--- a/chromium/third_party/skia/src/core/SkScalerContext.cpp
+++ b/chromium/third_party/skia/src/core/SkScalerContext.cpp
@@ -15,8 +15,8 @@
#include "SkGlyph.h"
#include "SkMaskFilter.h"
#include "SkMaskGamma.h"
-#include "SkOrderedReadBuffer.h"
-#include "SkOrderedWriteBuffer.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkPathEffect.h"
#include "SkRasterizer.h"
#include "SkRasterClip.h"
@@ -73,7 +73,7 @@ static SkFlattenable* load_flattenable(const SkDescriptor* desc, uint32_t tag,
const void* data = desc->findEntry(tag, &len);
if (data) {
- SkOrderedReadBuffer buffer(data, len);
+ SkReadBuffer buffer(data, len);
obj = buffer.readFlattenable(ft);
SkASSERT(buffer.offset() == buffer.size());
}
@@ -102,7 +102,7 @@ SkScalerContext::SkScalerContext(SkTypeface* typeface, const SkDescriptor* desc)
{
#ifdef DUMP_REC
desc->assertChecksum();
- SkDebugf("SkScalarContext checksum %x count %d length %d\n",
+ SkDebugf("SkScalerContext checksum %x count %d length %d\n",
desc->getChecksum(), desc->getCount(), desc->getLength());
SkDebugf(" textsize %g prescale %g preskew %g post [%g %g %g %g]\n",
rec->fTextSize, rec->fPreScaleX, rec->fPreSkewX, rec->fPost2x2[0][0],
@@ -118,7 +118,7 @@ SkScalerContext::SkScalerContext(SkTypeface* typeface, const SkDescriptor* desc)
uint32_t len;
const void* data = desc->findEntry(kAndroidOpts_SkDescriptorTag, &len);
if (data) {
- SkOrderedReadBuffer buffer(data, len);
+ SkReadBuffer buffer(data, len);
fPaintOptionsAndroid.unflatten(buffer);
SkASSERT(buffer.offset() == buffer.size());
}
@@ -147,10 +147,11 @@ SkScalerContext* SkScalerContext::allocNextContext() const {
SkAutoTUnref<SkTypeface> aur(newFace);
uint32_t newFontID = newFace->uniqueID();
- SkOrderedWriteBuffer androidBuffer(128);
+ SkWriteBuffer androidBuffer;
fPaintOptionsAndroid.flatten(androidBuffer);
- SkAutoDescriptor ad(sizeof(fRec) + androidBuffer.size() + SkDescriptor::ComputeOverhead(2));
+ SkAutoDescriptor ad(sizeof(fRec) + androidBuffer.bytesWritten()
+ + SkDescriptor::ComputeOverhead(2));
SkDescriptor* desc = ad.getDesc();
desc->init();
@@ -158,7 +159,7 @@ SkScalerContext* SkScalerContext::allocNextContext() const {
(SkScalerContext::Rec*)desc->addEntry(kRec_SkDescriptorTag,
sizeof(fRec), &fRec);
androidBuffer.writeToMemory(desc->addEntry(kAndroidOpts_SkDescriptorTag,
- androidBuffer.size(), NULL));
+ androidBuffer.bytesWritten(), NULL));
newRec->fFontID = newFontID;
desc->computeChecksum();
@@ -427,7 +428,7 @@ static void pack4xHToLCD16(const SkBitmap& src, const SkMask& dst,
const SkMaskGamma::PreBlend& maskPreBlend) {
#define SAMPLES_PER_PIXEL 4
#define LCD_PER_PIXEL 3
- SkASSERT(SkBitmap::kA8_Config == src.config());
+ SkASSERT(kAlpha_8_SkColorType == src.colorType());
SkASSERT(SkMask::kLCD16_Format == dst.fFormat);
const int sample_width = src.width();
@@ -501,7 +502,7 @@ static void pack4xHToLCD16(const SkBitmap& src, const SkMask& dst,
template<bool APPLY_PREBLEND>
static void pack4xHToLCD32(const SkBitmap& src, const SkMask& dst,
const SkMaskGamma::PreBlend& maskPreBlend) {
- SkASSERT(SkBitmap::kA8_Config == src.config());
+ SkASSERT(kAlpha_8_SkColorType == src.colorType());
SkASSERT(SkMask::kLCD32_Format == dst.fFormat);
const int width = dst.fBounds.width();
@@ -547,8 +548,9 @@ static void packA8ToA1(const SkMask& mask, const uint8_t* src, size_t srcRB) {
const int dstPad = mask.fRowBytes - SkAlign8(width)/8;
SkASSERT(dstPad >= 0);
- const int srcPad = srcRB - width;
- SkASSERT(srcPad >= 0);
+ SkASSERT(width >= 0);
+ SkASSERT(srcRB >= (size_t)width);
+ const size_t srcPad = srcRB - width;
for (int y = 0; y < height; ++y) {
for (int i = 0; i < octs; ++i) {
@@ -582,7 +584,6 @@ static void generateMask(const SkMask& mask, const SkPath& path,
matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft),
-SkIntToScalar(mask.fBounds.fTop));
- SkBitmap::Config config = SkBitmap::kA8_Config;
paint.setAntiAlias(SkMask::kBW_Format != mask.fFormat);
switch (mask.fFormat) {
case SkMask::kBW_Format:
@@ -606,18 +607,17 @@ static void generateMask(const SkMask& mask, const SkPath& path,
SkRasterClip clip;
clip.setRect(SkIRect::MakeWH(dstW, dstH));
+ const SkImageInfo info = SkImageInfo::MakeA8(dstW, dstH);
SkBitmap bm;
- bm.setConfig(config, dstW, dstH, dstRB);
if (0 == dstRB) {
- if (!bm.allocPixels()) {
+ if (!bm.allocPixels(info)) {
// can't allocate offscreen, so empty the mask and return
sk_bzero(mask.fImage, mask.computeImageSize());
return;
}
- bm.lockPixels();
} else {
- bm.setPixels(mask.fImage);
+ bm.installPixels(info, mask.fImage, dstRB);
}
sk_bzero(bm.getPixels(), bm.getSafeSize());
diff --git a/chromium/third_party/skia/src/core/SkScalerContext.h b/chromium/third_party/skia/src/core/SkScalerContext.h
index e4950edee3b..af83685eb69 100644
--- a/chromium/third_party/skia/src/core/SkScalerContext.h
+++ b/chromium/third_party/skia/src/core/SkScalerContext.h
@@ -122,7 +122,7 @@ public:
kEmbeddedBitmapText_Flag = 0x0004,
kEmbolden_Flag = 0x0008,
kSubpixelPositioning_Flag = 0x0010,
- kAutohinting_Flag = 0x0020,
+ kForceAutohinting_Flag = 0x0020, // Use auto instead of bytcode hinting if hinting.
kVertical_Flag = 0x0040,
// together, these two flags resulting in a two bit value which matches
@@ -184,6 +184,17 @@ public:
void getPath(const SkGlyph&, SkPath*);
void getFontMetrics(SkPaint::FontMetrics*);
+ /** Return the size in bytes of the associated gamma lookup table
+ */
+ static size_t GetGammaLUTSize(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma,
+ int* width, int* height);
+
+ /** Get the associated gamma lookup table. The 'data' pointer must point to pre-allocated
+ memory, with size in bytes greater than or equal to the return value of getGammaLUTSize().
+ */
+ static void GetGammaLUTData(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma,
+ void* data);
+
#ifdef SK_BUILD_FOR_ANDROID
unsigned getBaseGlyphCount(SkUnichar charCode);
@@ -192,8 +203,8 @@ public:
SkFontID findTypefaceIdForChar(SkUnichar uni);
#endif
- static inline void MakeRec(const SkPaint&, const SkDeviceProperties* deviceProperties,
- const SkMatrix*, Rec* rec);
+ static void MakeRec(const SkPaint&, const SkDeviceProperties* deviceProperties,
+ const SkMatrix*, Rec* rec);
static inline void PostMakeRec(const SkPaint&, Rec*);
static SkMaskGamma::PreBlend GetMaskPreBlend(const Rec& rec);
diff --git a/chromium/third_party/skia/src/core/SkScan.cpp b/chromium/third_party/skia/src/core/SkScan.cpp
index 44968bd9ec0..b21dd6bf9c6 100644
--- a/chromium/third_party/skia/src/core/SkScan.cpp
+++ b/chromium/third_party/skia/src/core/SkScan.cpp
@@ -53,8 +53,6 @@ void SkScan::FillXRect(const SkXRect& xr, const SkRegion* clip,
SkScan::FillIRect(r, clip, blitter);
}
-#ifdef SK_SCALAR_IS_FLOAT
-
void SkScan::FillRect(const SkRect& r, const SkRegion* clip,
SkBlitter* blitter) {
SkIRect ir;
@@ -63,8 +61,6 @@ void SkScan::FillRect(const SkRect& r, const SkRegion* clip,
SkScan::FillIRect(ir, clip, blitter);
}
-#endif
-
///////////////////////////////////////////////////////////////////////////////
void SkScan::FillIRect(const SkIRect& r, const SkRasterClip& clip,
@@ -97,8 +93,6 @@ void SkScan::FillXRect(const SkXRect& xr, const SkRasterClip& clip,
FillXRect(xr, &wrapper.getRgn(), wrapper.getBlitter());
}
-#ifdef SK_SCALAR_IS_FLOAT
-
void SkScan::FillRect(const SkRect& r, const SkRasterClip& clip,
SkBlitter* blitter) {
if (clip.isEmpty() || r.isEmpty()) {
@@ -113,5 +107,3 @@ void SkScan::FillRect(const SkRect& r, const SkRasterClip& clip,
SkAAClipBlitterWrapper wrapper(clip, blitter);
FillRect(r, &wrapper.getRgn(), wrapper.getBlitter());
}
-
-#endif
diff --git a/chromium/third_party/skia/src/core/SkScan.h b/chromium/third_party/skia/src/core/SkScan.h
index 5989435d298..46a81073ead 100644
--- a/chromium/third_party/skia/src/core/SkScan.h
+++ b/chromium/third_party/skia/src/core/SkScan.h
@@ -31,19 +31,8 @@ public:
static void FillIRect(const SkIRect&, const SkRasterClip&, SkBlitter*);
static void FillXRect(const SkXRect&, const SkRasterClip&, SkBlitter*);
-#ifdef SK_SCALAR_IS_FIXED
- static void FillRect(const SkRect& rect, const SkRasterClip& clip,
- SkBlitter* blitter) {
- SkScan::FillXRect(*(const SkXRect*)&rect, clip, blitter);
- }
- static void AntiFillRect(const SkRect& rect, const SkRasterClip& clip,
- SkBlitter* blitter) {
- SkScan::AntiFillXRect(*(const SkXRect*)&rect, clip, blitter);
- }
-#else
static void FillRect(const SkRect&, const SkRasterClip&, SkBlitter*);
static void AntiFillRect(const SkRect&, const SkRasterClip&, SkBlitter*);
-#endif
static void AntiFillXRect(const SkXRect&, const SkRasterClip&, SkBlitter*);
static void FillPath(const SkPath&, const SkRasterClip&, SkBlitter*);
static void AntiFillPath(const SkPath&, const SkRasterClip&, SkBlitter*);
@@ -67,19 +56,8 @@ private:
static void FillIRect(const SkIRect&, const SkRegion* clip, SkBlitter*);
static void FillXRect(const SkXRect&, const SkRegion* clip, SkBlitter*);
-#ifdef SK_SCALAR_IS_FIXED
- static void FillRect(const SkRect& rect, const SkRegion* clip,
- SkBlitter* blitter) {
- SkScan::FillXRect(*(const SkXRect*)&rect, clip, blitter);
- }
- static void AntiFillRect(const SkRect& rect, const SkRegion* clip,
- SkBlitter* blitter) {
- SkScan::AntiFillXRect(*(const SkXRect*)&rect, clip, blitter);
- }
-#else
static void FillRect(const SkRect&, const SkRegion* clip, SkBlitter*);
static void AntiFillRect(const SkRect&, const SkRegion* clip, SkBlitter*);
-#endif
static void AntiFillXRect(const SkXRect&, const SkRegion*, SkBlitter*);
static void FillPath(const SkPath&, const SkRegion& clip, SkBlitter*);
static void AntiFillPath(const SkPath&, const SkRegion& clip, SkBlitter*,
@@ -119,20 +97,20 @@ static inline void XRect_set(SkXRect* xr, const SkRect& src) {
/** Round the SkXRect coordinates, and store the result in the SkIRect.
*/
static inline void XRect_round(const SkXRect& xr, SkIRect* dst) {
- dst->fLeft = SkFixedRound(xr.fLeft);
- dst->fTop = SkFixedRound(xr.fTop);
- dst->fRight = SkFixedRound(xr.fRight);
- dst->fBottom = SkFixedRound(xr.fBottom);
+ dst->fLeft = SkFixedRoundToInt(xr.fLeft);
+ dst->fTop = SkFixedRoundToInt(xr.fTop);
+ dst->fRight = SkFixedRoundToInt(xr.fRight);
+ dst->fBottom = SkFixedRoundToInt(xr.fBottom);
}
/** Round the SkXRect coordinates out (i.e. use floor for left/top, and ceiling
for right/bottom), and store the result in the SkIRect.
*/
static inline void XRect_roundOut(const SkXRect& xr, SkIRect* dst) {
- dst->fLeft = SkFixedFloor(xr.fLeft);
- dst->fTop = SkFixedFloor(xr.fTop);
- dst->fRight = SkFixedCeil(xr.fRight);
- dst->fBottom = SkFixedCeil(xr.fBottom);
+ dst->fLeft = SkFixedFloorToInt(xr.fLeft);
+ dst->fTop = SkFixedFloorToInt(xr.fTop);
+ dst->fRight = SkFixedCeilToInt(xr.fRight);
+ dst->fBottom = SkFixedCeilToInt(xr.fBottom);
}
#endif
diff --git a/chromium/third_party/skia/src/core/SkScan_AntiPath.cpp b/chromium/third_party/skia/src/core/SkScan_AntiPath.cpp
index 0d2152c7c15..e5c67a958af 100644
--- a/chromium/third_party/skia/src/core/SkScan_AntiPath.cpp
+++ b/chromium/third_party/skia/src/core/SkScan_AntiPath.cpp
@@ -589,13 +589,8 @@ static int rect_overflows_short_shift(SkIRect rect, int shift) {
}
static bool safeRoundOut(const SkRect& src, SkIRect* dst, int32_t maxInt) {
-#ifdef SK_SCALAR_IS_FIXED
- // the max-int (shifted) is exactly what we want to compare against, to know
- // if we can survive shifting our fixed-point coordinates
- const SkFixed maxScalar = maxInt;
-#else
const SkScalar maxScalar = SkIntToScalar(maxInt);
-#endif
+
if (fitsInsideLimit(src, maxScalar)) {
src.roundOut(dst);
return true;
diff --git a/chromium/third_party/skia/src/core/SkScan_Antihair.cpp b/chromium/third_party/skia/src/core/SkScan_Antihair.cpp
index a6a0869f224..1ad68e50759 100644
--- a/chromium/third_party/skia/src/core/SkScan_Antihair.cpp
+++ b/chromium/third_party/skia/src/core/SkScan_Antihair.cpp
@@ -466,11 +466,11 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1,
// now test if our Y values are completely inside the clip
int top, bottom;
if (slope >= 0) { // T2B
- top = SkFixedFloor(fstart - SK_FixedHalf);
- bottom = SkFixedCeil(fstart + (istop - istart - 1) * slope + SK_FixedHalf);
+ top = SkFixedFloorToInt(fstart - SK_FixedHalf);
+ bottom = SkFixedCeilToInt(fstart + (istop - istart - 1) * slope + SK_FixedHalf);
} else { // B2T
- bottom = SkFixedCeil(fstart + SK_FixedHalf);
- top = SkFixedFloor(fstart + (istop - istart - 1) * slope - SK_FixedHalf);
+ bottom = SkFixedCeilToInt(fstart + SK_FixedHalf);
+ top = SkFixedFloorToInt(fstart + (istop - istart - 1) * slope - SK_FixedHalf);
}
#ifdef OUTSET_BEFORE_CLIP_TEST
top -= 1;
@@ -542,11 +542,11 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1,
// now test if our X values are completely inside the clip
int left, right;
if (slope >= 0) { // L2R
- left = SkFixedFloor(fstart - SK_FixedHalf);
- right = SkFixedCeil(fstart + (istop - istart - 1) * slope + SK_FixedHalf);
+ left = SkFixedFloorToInt(fstart - SK_FixedHalf);
+ right = SkFixedCeilToInt(fstart + (istop - istart - 1) * slope + SK_FixedHalf);
} else { // R2L
- right = SkFixedCeil(fstart + SK_FixedHalf);
- left = SkFixedFloor(fstart + (istop - istart - 1) * slope - SK_FixedHalf);
+ right = SkFixedCeilToInt(fstart + SK_FixedHalf);
+ left = SkFixedFloorToInt(fstart + (istop - istart - 1) * slope - SK_FixedHalf);
}
#ifdef OUTSET_BEFORE_CLIP_TEST
left -= 1;
@@ -602,7 +602,6 @@ void SkScan::AntiHairLineRgn(const SkPoint& pt0, const SkPoint& pt1,
SkPoint pts[2] = { pt0, pt1 };
-#ifdef SK_SCALAR_IS_FLOAT
// We have to pre-clip the line to fit in a SkFixed, so we just chop
// the line. TODO find a way to actually draw beyond that range.
{
@@ -613,7 +612,6 @@ void SkScan::AntiHairLineRgn(const SkPoint& pt0, const SkPoint& pt1,
return;
}
}
-#endif
if (clip) {
SkRect clipBounds;
@@ -828,8 +826,6 @@ void SkScan::AntiFillXRect(const SkXRect& xr, const SkRasterClip& clip,
}
}
-#ifdef SK_SCALAR_IS_FLOAT
-
/* This guy takes a float-rect, but with the key improvement that it has
already been clipped, so we know that it is safe to convert it into a
XRect (fixedpoint), as it won't overflow.
@@ -888,8 +884,6 @@ void SkScan::AntiFillRect(const SkRect& r, const SkRasterClip& clip,
}
}
-#endif // SK_SCALAR_IS_FLOAT
-
///////////////////////////////////////////////////////////////////////////////
#define SkAlphaMulRound(a, b) SkMulDiv255Round(a, b)
@@ -902,11 +896,7 @@ static void fillcheckrect(int L, int T, int R, int B, SkBlitter* blitter) {
}
static inline FDot8 SkScalarToFDot8(SkScalar x) {
-#ifdef SK_SCALAR_IS_FLOAT
return (int)(x * 256);
-#else
- return x >> 8;
-#endif
}
static inline int FDot8Floor(FDot8 x) {
diff --git a/chromium/third_party/skia/src/core/SkScan_Hairline.cpp b/chromium/third_party/skia/src/core/SkScan_Hairline.cpp
index f440d32613d..1e7e762b5a8 100644
--- a/chromium/third_party/skia/src/core/SkScan_Hairline.cpp
+++ b/chromium/third_party/skia/src/core/SkScan_Hairline.cpp
@@ -47,7 +47,6 @@ void SkScan::HairLineRgn(const SkPoint& pt0, const SkPoint& pt1,
SkIRect clipR, ptsR;
SkPoint pts[2] = { pt0, pt1 };
-#ifdef SK_SCALAR_IS_FLOAT
// We have to pre-clip the line to fit in a SkFixed, so we just chop
// the line. TODO find a way to actually draw beyond that range.
{
@@ -58,7 +57,6 @@ void SkScan::HairLineRgn(const SkPoint& pt0, const SkPoint& pt1,
return;
}
}
-#endif
if (clip) {
// Perform a clip in scalar space, so we catch huge values which might
@@ -202,8 +200,8 @@ static int compute_int_quad_dist(const SkPoint pts[3]) {
dx = SkScalarAbs(dx);
dy = SkScalarAbs(dy);
// convert to whole pixel values (use ceiling to be conservative)
- int idx = SkScalarCeil(dx);
- int idy = SkScalarCeil(dy);
+ int idx = SkScalarCeilToInt(dx);
+ int idy = SkScalarCeilToInt(dy);
// use the cheap approx for distance
if (idx > idy) {
return idx + (idy >> 1);
diff --git a/chromium/third_party/skia/src/core/SkScan_Path.cpp b/chromium/third_party/skia/src/core/SkScan_Path.cpp
index 66e9507678d..b32d68e7341 100644
--- a/chromium/third_party/skia/src/core/SkScan_Path.cpp
+++ b/chromium/third_party/skia/src/core/SkScan_Path.cpp
@@ -602,7 +602,11 @@ void SkScan::FillPath(const SkPath& path, const SkRegion& origClip,
// don't reference "origClip" any more, just use clipPtr
SkIRect ir;
- path.getBounds().round(&ir);
+ // We deliberately call dround() instead of round(), since we can't afford to generate a
+ // bounds that is tighter than the corresponding SkEdges. The edge code basically converts
+ // the floats to fixed, and then "rounds". If we called round() instead of dround() here,
+ // we could generate the wrong ir for values like 0.4999997.
+ path.getBounds().dround(&ir);
if (ir.isEmpty()) {
if (path.isInverseFillType()) {
blitter->blitRegion(*clipPtr);
diff --git a/chromium/third_party/skia/src/core/SkShader.cpp b/chromium/third_party/skia/src/core/SkShader.cpp
index 33fddb1183f..18fb0d2584a 100644
--- a/chromium/third_party/skia/src/core/SkShader.cpp
+++ b/chromium/third_party/skia/src/core/SkShader.cpp
@@ -5,76 +5,115 @@
* found in the LICENSE file.
*/
-
+#include "SkBitmapProcShader.h"
+#include "SkEmptyShader.h"
+#include "SkReadBuffer.h"
+#include "SkMallocPixelRef.h"
+#include "SkPaint.h"
+#include "SkPicture.h"
+#include "SkPictureShader.h"
#include "SkScalar.h"
#include "SkShader.h"
-#include "SkFlattenableBuffers.h"
-#include "SkPaint.h"
-#include "SkMallocPixelRef.h"
+#include "SkThread.h"
+#include "SkWriteBuffer.h"
+
+//#define SK_TRACK_SHADER_LIFETIME
+
+#ifdef SK_TRACK_SHADER_LIFETIME
+ static int32_t gShaderCounter;
+#endif
-SkShader::SkShader() {
- fLocalMatrix.reset();
- SkDEBUGCODE(fInSetContext = false;)
+static inline void inc_shader_counter() {
+#ifdef SK_TRACK_SHADER_LIFETIME
+ int32_t prev = sk_atomic_inc(&gShaderCounter);
+ SkDebugf("+++ shader counter %d\n", prev + 1);
+#endif
+}
+static inline void dec_shader_counter() {
+#ifdef SK_TRACK_SHADER_LIFETIME
+ int32_t prev = sk_atomic_dec(&gShaderCounter);
+ SkDebugf("--- shader counter %d\n", prev - 1);
+#endif
}
-SkShader::SkShader(SkFlattenableReadBuffer& buffer)
- : INHERITED(buffer) {
+SkShader::SkShader(const SkMatrix* localMatrix) {
+ inc_shader_counter();
+ if (localMatrix) {
+ fLocalMatrix = *localMatrix;
+ } else {
+ fLocalMatrix.reset();
+ }
+}
+
+SkShader::SkShader(SkReadBuffer& buffer) : INHERITED(buffer) {
+ inc_shader_counter();
if (buffer.readBool()) {
buffer.readMatrix(&fLocalMatrix);
} else {
fLocalMatrix.reset();
}
-
- SkDEBUGCODE(fInSetContext = false;)
}
SkShader::~SkShader() {
- SkASSERT(!fInSetContext);
+ dec_shader_counter();
}
-void SkShader::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkShader::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
- bool hasLocalM = this->hasLocalMatrix();
+ bool hasLocalM = !fLocalMatrix.isIdentity();
buffer.writeBool(hasLocalM);
if (hasLocalM) {
buffer.writeMatrix(fLocalMatrix);
}
}
-bool SkShader::setContext(const SkBitmap& device,
- const SkPaint& paint,
- const SkMatrix& matrix) {
- SkASSERT(!this->setContextHasBeenCalled());
+bool SkShader::computeTotalInverse(const ContextRec& rec, SkMatrix* totalInverse) const {
+ SkMatrix total;
+ total.setConcat(*rec.fMatrix, fLocalMatrix);
- const SkMatrix* m = &matrix;
- SkMatrix total;
-
- fDeviceConfig = SkToU8(device.config());
- fPaintAlpha = paint.getAlpha();
- if (this->hasLocalMatrix()) {
- total.setConcat(matrix, this->getLocalMatrix());
+ const SkMatrix* m = &total;
+ if (rec.fLocalMatrix) {
+ total.setConcat(*m, *rec.fLocalMatrix);
m = &total;
}
- if (m->invert(&fTotalInverse)) {
- fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse);
- SkDEBUGCODE(fInSetContext = true;)
- return true;
+ return m->invert(totalInverse);
+}
+
+SkShader::Context* SkShader::createContext(const ContextRec& rec, void* storage) const {
+ if (!this->computeTotalInverse(rec, NULL)) {
+ return NULL;
}
- return false;
+ return this->onCreateContext(rec, storage);
+}
+
+SkShader::Context* SkShader::onCreateContext(const ContextRec& rec, void*) const {
+ return NULL;
+}
+
+size_t SkShader::contextSize() const {
+ return 0;
}
-void SkShader::endContext() {
- SkASSERT(fInSetContext);
- SkDEBUGCODE(fInSetContext = false;)
+SkShader::Context::Context(const SkShader& shader, const ContextRec& rec)
+ : fShader(shader), fCTM(*rec.fMatrix)
+{
+ // Because the context parameters must be valid at this point, we know that the matrix is
+ // invertible.
+ SkAssertResult(fShader.computeTotalInverse(rec, &fTotalInverse));
+ fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse);
+
+ fPaintAlpha = rec.fPaint->getAlpha();
}
-SkShader::ShadeProc SkShader::asAShadeProc(void** ctx) {
+SkShader::Context::~Context() {}
+
+SkShader::Context::ShadeProc SkShader::Context::asAShadeProc(void** ctx) {
return NULL;
}
#include "SkColorPriv.h"
-void SkShader::shadeSpan16(int x, int y, uint16_t span16[], int count) {
+void SkShader::Context::shadeSpan16(int x, int y, uint16_t span16[], int count) {
SkASSERT(span16);
SkASSERT(count > 0);
SkASSERT(this->canCallShadeSpan16());
@@ -92,7 +131,7 @@ void SkShader::shadeSpan16(int x, int y, uint16_t span16[], int count) {
#define SkU32BitShiftToByteOffset(shift) ((shift) >> 3)
#endif
-void SkShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
+void SkShader::Context::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
SkASSERT(count > 0);
SkPMColor colors[kTempColorCount];
@@ -146,7 +185,7 @@ void SkShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
#endif
}
-SkShader::MatrixClass SkShader::ComputeMatrixClass(const SkMatrix& mat) {
+SkShader::Context::MatrixClass SkShader::Context::ComputeMatrixClass(const SkMatrix& mat) {
MatrixClass mc = kLinear_MatrixClass;
if (mat.hasPerspective()) {
@@ -161,8 +200,7 @@ SkShader::MatrixClass SkShader::ComputeMatrixClass(const SkMatrix& mat) {
//////////////////////////////////////////////////////////////////////////////
-SkShader::BitmapType SkShader::asABitmap(SkBitmap*, SkMatrix*,
- TileMode*) const {
+SkShader::BitmapType SkShader::asABitmap(SkBitmap*, SkMatrix*, TileMode*) const {
return kNone_BitmapType;
}
@@ -170,20 +208,35 @@ SkShader::GradientType SkShader::asAGradient(GradientInfo* info) const {
return kNone_GradientType;
}
-GrEffectRef* SkShader::asNewEffect(GrContext*, const SkPaint&) const {
+bool SkShader::asNewEffect(GrContext* context, const SkPaint& paint,
+ const SkMatrix* localMatrixOrNull, GrColor* grColor,
+ GrEffectRef** grEffect) const {
+ return false;
+}
+
+SkShader* SkShader::refAsALocalMatrixShader(SkMatrix*) const {
return NULL;
}
-SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
- TileMode tmx, TileMode tmy) {
- return SkShader::CreateBitmapShader(src, tmx, tmy, NULL, 0);
+SkShader* SkShader::CreateEmptyShader() {
+ return SkNEW(SkEmptyShader);
+}
+
+SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, TileMode tmx, TileMode tmy,
+ const SkMatrix* localMatrix) {
+ return ::CreateBitmapShader(src, tmx, tmy, localMatrix, NULL);
+}
+
+SkShader* SkShader::CreatePictureShader(SkPicture* src, TileMode tmx, TileMode tmy,
+ const SkMatrix* localMatrix) {
+ return SkPictureShader::Create(src, tmx, tmy, localMatrix);
}
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkShader::toString(SkString* str) const {
- if (this->hasLocalMatrix()) {
+ if (!fLocalMatrix.isIdentity()) {
str->append(" ");
- this->getLocalMatrix().toString(str);
+ fLocalMatrix.toString(str);
}
}
#endif
@@ -193,71 +246,54 @@ void SkShader::toString(SkString* str) const {
#include "SkColorShader.h"
#include "SkUtils.h"
-SkColorShader::SkColorShader() {
- fFlags = 0;
- fInheritColor = true;
+SkColorShader::SkColorShader(SkColor c)
+ : fColor(c) {
}
-SkColorShader::SkColorShader(SkColor c) {
- fFlags = 0;
- fColor = c;
- fInheritColor = false;
-}
-
-SkColorShader::~SkColorShader() {}
-
bool SkColorShader::isOpaque() const {
- if (fInheritColor) {
- return true; // using paint's alpha
- }
return SkColorGetA(fColor) == 255;
}
-SkColorShader::SkColorShader(SkFlattenableReadBuffer& b) : INHERITED(b) {
- fFlags = 0; // computed in setContext
-
- fInheritColor = b.readBool();
- if (fInheritColor) {
- return;
+SkColorShader::SkColorShader(SkReadBuffer& b) : INHERITED(b) {
+ // V25_COMPATIBILITY_CODE We had a boolean to make the color shader inherit the paint's
+ // color. We don't support that any more.
+ if (b.isVersionLT(SkReadBuffer::kColorShaderNoBool_Version)) {
+ if (b.readBool()) {
+ SkDEBUGFAIL("We shouldn't have pictures that recorded the inherited case.");
+ fColor = SK_ColorWHITE;
+ return;
+ }
}
fColor = b.readColor();
}
-void SkColorShader::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkColorShader::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
- buffer.writeBool(fInheritColor);
- if (fInheritColor) {
- return;
- }
buffer.writeColor(fColor);
}
-uint32_t SkColorShader::getFlags() {
+uint32_t SkColorShader::ColorShaderContext::getFlags() const {
return fFlags;
}
-uint8_t SkColorShader::getSpan16Alpha() const {
+uint8_t SkColorShader::ColorShaderContext::getSpan16Alpha() const {
return SkGetPackedA32(fPMColor);
}
-bool SkColorShader::setContext(const SkBitmap& device, const SkPaint& paint,
- const SkMatrix& matrix) {
- if (!this->INHERITED::setContext(device, paint, matrix)) {
- return false;
- }
-
- unsigned a;
+SkShader::Context* SkColorShader::onCreateContext(const ContextRec& rec, void* storage) const {
+ return SkNEW_PLACEMENT_ARGS(storage, ColorShaderContext, (*this, rec));
+}
- if (fInheritColor) {
- fColor = paint.getColor();
- a = SkColorGetA(fColor);
- } else {
- a = SkAlphaMul(SkColorGetA(fColor), SkAlpha255To256(paint.getAlpha()));
- }
+SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shader,
+ const ContextRec& rec)
+ : INHERITED(shader, rec)
+{
+ SkColor color = shader.fColor;
+ unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(rec.fPaint->getAlpha()));
- unsigned r = SkColorGetR(fColor);
- unsigned g = SkColorGetG(fColor);
- unsigned b = SkColorGetB(fColor);
+ unsigned r = SkColorGetR(color);
+ unsigned g = SkColorGetG(color);
+ unsigned b = SkColorGetB(color);
// we want this before we apply any alpha
fColor16 = SkPack888ToRGB16(r, g, b);
@@ -272,23 +308,21 @@ bool SkColorShader::setContext(const SkBitmap& device, const SkPaint& paint,
fFlags = kConstInY32_Flag;
if (255 == a) {
fFlags |= kOpaqueAlpha_Flag;
- if (paint.isDither() == false) {
+ if (rec.fPaint->isDither() == false) {
fFlags |= kHasSpan16_Flag;
}
}
-
- return true;
}
-void SkColorShader::shadeSpan(int x, int y, SkPMColor span[], int count) {
+void SkColorShader::ColorShaderContext::shadeSpan(int x, int y, SkPMColor span[], int count) {
sk_memset32(span, fPMColor, count);
}
-void SkColorShader::shadeSpan16(int x, int y, uint16_t span[], int count) {
+void SkColorShader::ColorShaderContext::shadeSpan16(int x, int y, uint16_t span[], int count) {
sk_memset16(span, fColor16, count);
}
-void SkColorShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
+void SkColorShader::ColorShaderContext::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
memset(alpha, SkGetPackedA32(fPMColor), count);
}
@@ -309,16 +343,37 @@ SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const {
return kColor_GradientType;
}
-#ifdef SK_DEVELOPER
+#if SK_SUPPORT_GPU
+
+#include "SkGr.h"
+
+bool SkColorShader::asNewEffect(GrContext* context, const SkPaint& paint,
+ const SkMatrix* localMatrix, GrColor* grColor,
+ GrEffectRef** grEffect) const {
+ *grEffect = NULL;
+ SkColor skColor = fColor;
+ U8CPU newA = SkMulDiv255Round(SkColorGetA(fColor), paint.getAlpha());
+ *grColor = SkColor2GrColor(SkColorSetA(skColor, newA));
+ return true;
+}
+
+#else
+
+bool SkColorShader::asNewEffect(GrContext* context, const SkPaint& paint,
+ const SkMatrix* localMatrix, GrColor* grColor,
+ GrEffectRef** grEffect) const {
+ SkDEBUGFAIL("Should not call in GPU-less build");
+ return false;
+}
+
+#endif
+
+#ifndef SK_IGNORE_TO_STRING
void SkColorShader::toString(SkString* str) const {
str->append("SkColorShader: (");
- if (fInheritColor) {
- str->append("Color: inherited from paint");
- } else {
- str->append("Color: ");
- str->appendHex(fColor);
- }
+ str->append("Color: ");
+ str->appendHex(fColor);
this->INHERITED::toString(str);
@@ -328,27 +383,9 @@ void SkColorShader::toString(SkString* str) const {
///////////////////////////////////////////////////////////////////////////////
+#ifndef SK_IGNORE_TO_STRING
#include "SkEmptyShader.h"
-uint32_t SkEmptyShader::getFlags() { return 0; }
-uint8_t SkEmptyShader::getSpan16Alpha() const { return 0; }
-
-bool SkEmptyShader::setContext(const SkBitmap&, const SkPaint&,
- const SkMatrix&) { return false; }
-
-void SkEmptyShader::shadeSpan(int x, int y, SkPMColor span[], int count) {
- SkDEBUGFAIL("should never get called, since setContext() returned false");
-}
-
-void SkEmptyShader::shadeSpan16(int x, int y, uint16_t span[], int count) {
- SkDEBUGFAIL("should never get called, since setContext() returned false");
-}
-
-void SkEmptyShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
- SkDEBUGFAIL("should never get called, since setContext() returned false");
-}
-
-#ifdef SK_DEVELOPER
void SkEmptyShader::toString(SkString* str) const {
str->append("SkEmptyShader: (");
diff --git a/chromium/third_party/skia/src/core/SkSmallAllocator.h b/chromium/third_party/skia/src/core/SkSmallAllocator.h
new file mode 100644
index 00000000000..018705f974f
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkSmallAllocator.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2014 Google, Inc
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSmallAllocator_DEFINED
+#define SkSmallAllocator_DEFINED
+
+#include "SkTDArray.h"
+#include "SkTypes.h"
+
+// Used by SkSmallAllocator to call the destructor for objects it has
+// allocated.
+template<typename T> void destroyT(void* ptr) {
+ static_cast<T*>(ptr)->~T();
+}
+
+/*
+ * Template class for allocating small objects without additional heap memory
+ * allocations. kMaxObjects is a hard limit on the number of objects that can
+ * be allocated using this class. After that, attempts to create more objects
+ * with this class will assert and return NULL.
+ * kTotalBytes is the total number of bytes provided for storage for all
+ * objects created by this allocator. If an object to be created is larger
+ * than the storage (minus storage already used), it will be allocated on the
+ * heap. This class's destructor will handle calling the destructor for each
+ * object it allocated and freeing its memory.
+ */
+template<uint32_t kMaxObjects, size_t kTotalBytes>
+class SkSmallAllocator : SkNoncopyable {
+public:
+ SkSmallAllocator()
+ : fStorageUsed(0)
+ , fNumObjects(0)
+ {}
+
+ ~SkSmallAllocator() {
+ // Destruct in reverse order, in case an earlier object points to a
+ // later object.
+ while (fNumObjects > 0) {
+ fNumObjects--;
+ Rec* rec = &fRecs[fNumObjects];
+ rec->fKillProc(rec->fObj);
+ // Safe to do if fObj is in fStorage, since fHeapStorage will
+ // point to NULL.
+ sk_free(rec->fHeapStorage);
+ }
+ }
+
+ /*
+ * Create a new object of type T. Its lifetime will be handled by this
+ * SkSmallAllocator.
+ * Each version behaves the same but takes a different number of
+ * arguments.
+ * Note: If kMaxObjects have been created by this SkSmallAllocator, NULL
+ * will be returned.
+ */
+ template<typename T>
+ T* createT() {
+ void* buf = this->reserveT<T>();
+ if (NULL == buf) {
+ return NULL;
+ }
+ SkNEW_PLACEMENT(buf, T);
+ return static_cast<T*>(buf);
+ }
+
+ template<typename T, typename A1> T* createT(const A1& a1) {
+ void* buf = this->reserveT<T>();
+ if (NULL == buf) {
+ return NULL;
+ }
+ SkNEW_PLACEMENT_ARGS(buf, T, (a1));
+ return static_cast<T*>(buf);
+ }
+
+ template<typename T, typename A1, typename A2>
+ T* createT(const A1& a1, const A2& a2) {
+ void* buf = this->reserveT<T>();
+ if (NULL == buf) {
+ return NULL;
+ }
+ SkNEW_PLACEMENT_ARGS(buf, T, (a1, a2));
+ return static_cast<T*>(buf);
+ }
+
+ template<typename T, typename A1, typename A2, typename A3>
+ T* createT(const A1& a1, const A2& a2, const A3& a3) {
+ void* buf = this->reserveT<T>();
+ if (NULL == buf) {
+ return NULL;
+ }
+ SkNEW_PLACEMENT_ARGS(buf, T, (a1, a2, a3));
+ return static_cast<T*>(buf);
+ }
+
+ template<typename T, typename A1, typename A2, typename A3, typename A4>
+ T* createT(const A1& a1, const A2& a2, const A3& a3, const A4& a4) {
+ void* buf = this->reserveT<T>();
+ if (NULL == buf) {
+ return NULL;
+ }
+ SkNEW_PLACEMENT_ARGS(buf, T, (a1, a2, a3, a4));
+ return static_cast<T*>(buf);
+ }
+
+ /*
+ * Reserve a specified amount of space (must be enough space for one T).
+ * The space will be in fStorage if there is room, or on the heap otherwise.
+ * Either way, this class will call ~T() in its destructor and free the heap
+ * allocation if necessary.
+ * Unlike createT(), this method will not call the constructor of T.
+ */
+ template<typename T> void* reserveT(size_t storageRequired = sizeof(T)) {
+ SkASSERT(fNumObjects < kMaxObjects);
+ SkASSERT(storageRequired >= sizeof(T));
+ if (kMaxObjects == fNumObjects) {
+ return NULL;
+ }
+ const size_t storageRemaining = SkAlign4(kTotalBytes) - fStorageUsed;
+ storageRequired = SkAlign4(storageRequired);
+ Rec* rec = &fRecs[fNumObjects];
+ if (storageRequired > storageRemaining) {
+ // Allocate on the heap. Ideally we want to avoid this situation,
+ // but we're not sure we can catch all callers, so handle it but
+ // assert false in debug mode.
+ SkASSERT(false);
+ rec->fStorageSize = 0;
+ rec->fHeapStorage = sk_malloc_throw(storageRequired);
+ rec->fObj = static_cast<void*>(rec->fHeapStorage);
+ } else {
+ // There is space in fStorage.
+ rec->fStorageSize = storageRequired;
+ rec->fHeapStorage = NULL;
+ SkASSERT(SkIsAlign4(fStorageUsed));
+ rec->fObj = static_cast<void*>(fStorage + (fStorageUsed / 4));
+ fStorageUsed += storageRequired;
+ }
+ rec->fKillProc = destroyT<T>;
+ fNumObjects++;
+ return rec->fObj;
+ }
+
+ /*
+ * Free the memory reserved last without calling the destructor.
+ * Can be used in a nested way, i.e. after reserving A and B, calling
+ * freeLast once will free B and calling it again will free A.
+ */
+ void freeLast() {
+ SkASSERT(fNumObjects > 0);
+ Rec* rec = &fRecs[fNumObjects - 1];
+ sk_free(rec->fHeapStorage);
+ fStorageUsed -= rec->fStorageSize;
+
+ fNumObjects--;
+ }
+
+private:
+ struct Rec {
+ size_t fStorageSize; // 0 if allocated on heap
+ void* fObj;
+ void* fHeapStorage;
+ void (*fKillProc)(void*);
+ };
+
+ // Number of bytes used so far.
+ size_t fStorageUsed;
+ // Pad the storage size to be 4-byte aligned.
+ uint32_t fStorage[SkAlign4(kTotalBytes) >> 2];
+ uint32_t fNumObjects;
+ Rec fRecs[kMaxObjects];
+};
+
+#endif // SkSmallAllocator_DEFINED
diff --git a/chromium/third_party/skia/src/core/SkSpriteBlitter.h b/chromium/third_party/skia/src/core/SkSpriteBlitter.h
index ae79afe1d8e..f69a55a2a0b 100644
--- a/chromium/third_party/skia/src/core/SkSpriteBlitter.h
+++ b/chromium/third_party/skia/src/core/SkSpriteBlitter.h
@@ -10,8 +10,11 @@
#ifndef SkSpriteBlitter_DEFINED
#define SkSpriteBlitter_DEFINED
-#include "SkBlitter.h"
#include "SkBitmap.h"
+#include "SkBitmapProcShader.h"
+#include "SkBlitter.h"
+#include "SkShader.h"
+#include "SkSmallAllocator.h"
class SkPaint;
@@ -32,9 +35,9 @@ public:
#endif
static SkSpriteBlitter* ChooseD16(const SkBitmap& source, const SkPaint&,
- void* storage, size_t storageSize);
+ SkTBlitterAllocator*);
static SkSpriteBlitter* ChooseD32(const SkBitmap& source, const SkPaint&,
- void* storage, size_t storageSize);
+ SkTBlitterAllocator*);
protected:
const SkBitmap* fDevice;
diff --git a/chromium/third_party/skia/src/core/SkSpriteBlitter_ARGB32.cpp b/chromium/third_party/skia/src/core/SkSpriteBlitter_ARGB32.cpp
index 8255336c659..a4ae41c689b 100644
--- a/chromium/third_party/skia/src/core/SkSpriteBlitter_ARGB32.cpp
+++ b/chromium/third_party/skia/src/core/SkSpriteBlitter_ARGB32.cpp
@@ -20,7 +20,7 @@
class Sprite_D32_S32 : public SkSpriteBlitter {
public:
Sprite_D32_S32(const SkBitmap& src, U8CPU alpha) : INHERITED(src) {
- SkASSERT(src.config() == SkBitmap::kARGB_8888_Config);
+ SkASSERT(src.colorType() == kN32_SkColorType);
unsigned flags32 = 0;
if (255 != alpha) {
@@ -263,11 +263,10 @@ public:
///////////////////////////////////////////////////////////////////////////////
-#include "SkTemplatesPriv.h"
+SkSpriteBlitter* SkSpriteBlitter::ChooseD32(const SkBitmap& source, const SkPaint& paint,
+ SkTBlitterAllocator* allocator) {
+ SkASSERT(allocator != NULL);
-SkSpriteBlitter* SkSpriteBlitter::ChooseD32(const SkBitmap& source,
- const SkPaint& paint,
- void* storage, size_t storageSize) {
if (paint.getMaskFilter() != NULL) {
return NULL;
}
@@ -277,33 +276,28 @@ SkSpriteBlitter* SkSpriteBlitter::ChooseD32(const SkBitmap& source,
SkColorFilter* filter = paint.getColorFilter();
SkSpriteBlitter* blitter = NULL;
- switch (source.config()) {
- case SkBitmap::kARGB_4444_Config:
+ switch (source.colorType()) {
+ case kARGB_4444_SkColorType:
if (alpha != 0xFF) {
return NULL; // we only have opaque sprites
}
if (xfermode || filter) {
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S4444_XferFilter,
- storage, storageSize, (source, paint));
+ blitter = allocator->createT<Sprite_D32_S4444_XferFilter>(source, paint);
} else if (source.isOpaque()) {
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S4444_Opaque,
- storage, storageSize, (source));
+ blitter = allocator->createT<Sprite_D32_S4444_Opaque>(source);
} else {
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S4444,
- storage, storageSize, (source));
+ blitter = allocator->createT<Sprite_D32_S4444>(source);
}
break;
- case SkBitmap::kARGB_8888_Config:
+ case kN32_SkColorType:
if (xfermode || filter) {
if (255 == alpha) {
// this can handle xfermode or filter, but not alpha
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S32A_XferFilter,
- storage, storageSize, (source, paint));
+ blitter = allocator->createT<Sprite_D32_S32A_XferFilter>(source, paint);
}
} else {
// this can handle alpha, but not xfermode or filter
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S32,
- storage, storageSize, (source, alpha));
+ blitter = allocator->createT<Sprite_D32_S32>(source, alpha);
}
break;
default:
diff --git a/chromium/third_party/skia/src/core/SkSpriteBlitter_RGB16.cpp b/chromium/third_party/skia/src/core/SkSpriteBlitter_RGB16.cpp
index 2bce41e993b..1ba3ee22fcb 100644
--- a/chromium/third_party/skia/src/core/SkSpriteBlitter_RGB16.cpp
+++ b/chromium/third_party/skia/src/core/SkSpriteBlitter_RGB16.cpp
@@ -278,7 +278,7 @@ public:
if (paint.isDither()) {
flags |= SkBlitRow::kDither_Flag;
}
- fProc = SkBlitRow::Factory(flags, SkBitmap::kRGB_565_Config);
+ fProc = SkBlitRow::Factory(flags, kRGB_565_SkColorType);
}
virtual void blitRect(int x, int y, int width, int height) {
@@ -306,11 +306,11 @@ private:
///////////////////////////////////////////////////////////////////////////////
-#include "SkTemplatesPriv.h"
+SkSpriteBlitter* SkSpriteBlitter::ChooseD16(const SkBitmap& source, const SkPaint& paint,
+ SkTBlitterAllocator* allocator) {
+
+ SkASSERT(allocator != NULL);
-SkSpriteBlitter* SkSpriteBlitter::ChooseD16(const SkBitmap& source,
- const SkPaint& paint,
- void* storage, size_t storageSize) {
if (paint.getMaskFilter() != NULL) { // may add cases for this
return NULL;
}
@@ -324,49 +324,41 @@ SkSpriteBlitter* SkSpriteBlitter::ChooseD16(const SkBitmap& source,
SkSpriteBlitter* blitter = NULL;
unsigned alpha = paint.getAlpha();
- switch (source.config()) {
- case SkBitmap::kARGB_8888_Config:
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S32_BlitRowProc,
- storage, storageSize, (source));
+ switch (source.colorType()) {
+ case kN32_SkColorType: {
+ blitter = allocator->createT<Sprite_D16_S32_BlitRowProc>(source);
break;
- case SkBitmap::kARGB_4444_Config:
+ }
+ case kARGB_4444_SkColorType:
if (255 == alpha) {
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S4444_Opaque,
- storage, storageSize, (source));
+ blitter = allocator->createT<Sprite_D16_S4444_Opaque>(source);
} else {
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S4444_Blend,
- storage, storageSize, (source, alpha >> 4));
+ blitter = allocator->createT<Sprite_D16_S4444_Blend>(source, alpha >> 4);
}
break;
- case SkBitmap::kRGB_565_Config:
+ case kRGB_565_SkColorType:
if (255 == alpha) {
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S16_Opaque,
- storage, storageSize, (source));
+ blitter = allocator->createT<Sprite_D16_S16_Opaque>(source);
} else {
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S16_Blend,
- storage, storageSize, (source, alpha));
+ blitter = allocator->createT<Sprite_D16_S16_Blend>(source, alpha);
}
break;
- case SkBitmap::kIndex8_Config:
+ case kIndex_8_SkColorType:
if (paint.isDither()) {
// we don't support dither yet in these special cases
break;
}
if (source.isOpaque()) {
if (255 == alpha) {
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8_Opaque,
- storage, storageSize, (source));
+ blitter = allocator->createT<Sprite_D16_SIndex8_Opaque>(source);
} else {
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8_Blend,
- storage, storageSize, (source, alpha));
+ blitter = allocator->createT<Sprite_D16_SIndex8_Blend>(source, alpha);
}
} else {
if (255 == alpha) {
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8A_Opaque,
- storage, storageSize, (source));
+ blitter = allocator->createT<Sprite_D16_SIndex8A_Opaque>(source);
} else {
- SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8A_Blend,
- storage, storageSize, (source, alpha));
+ blitter = allocator->createT<Sprite_D16_SIndex8A_Blend>(source, alpha);
}
}
break;
diff --git a/chromium/third_party/skia/src/core/SkStream.cpp b/chromium/third_party/skia/src/core/SkStream.cpp
index 3350f82fc18..ebaac9ab150 100644
--- a/chromium/third_party/skia/src/core/SkStream.cpp
+++ b/chromium/third_party/skia/src/core/SkStream.cpp
@@ -140,6 +140,15 @@ bool SkWStream::writeScalar(SkScalar value) {
return this->write(&value, sizeof(value));
}
+int SkWStream::SizeOfPackedUInt(size_t value) {
+ if (value <= SK_MAX_BYTE_FOR_U8) {
+ return 1;
+ } else if (value <= 0xFFFF) {
+ return 3;
+ }
+ return 5;
+}
+
bool SkWStream::writePackedUInt(size_t value) {
uint8_t data[5];
size_t len = 1;
@@ -152,7 +161,7 @@ bool SkWStream::writePackedUInt(size_t value) {
memcpy(&data[1], &value16, 2);
len = 3;
} else {
- uint32_t value32 = value;
+ uint32_t value32 = SkToU32(value);
data[0] = SK_BYTE_SENTINEL_FOR_U32;
memcpy(&data[1], &value32, 4);
len = 5;
@@ -180,7 +189,7 @@ bool SkWStream::writeStream(SkStream* stream, size_t length) {
bool SkWStream::writeData(const SkData* data) {
if (data) {
- this->write32(data->size());
+ this->write32(SkToU32(data->size()));
this->write(data->data(), data->size());
} else {
this->write32(0);
@@ -433,14 +442,20 @@ SkFILEWStream::SkFILEWStream(const char path[])
SkFILEWStream::~SkFILEWStream()
{
- if (fFILE)
+ if (fFILE) {
sk_fclose(fFILE);
+ }
+}
+
+size_t SkFILEWStream::bytesWritten() const {
+ return sk_ftell(fFILE);
}
bool SkFILEWStream::write(const void* buffer, size_t size)
{
- if (fFILE == NULL)
+ if (fFILE == NULL) {
return false;
+ }
if (sk_fwrite(buffer, size, fFILE) != size)
{
@@ -454,8 +469,9 @@ bool SkFILEWStream::write(const void* buffer, size_t size)
void SkFILEWStream::flush()
{
- if (fFILE)
+ if (fFILE) {
sk_fflush(fFILE);
+ }
}
////////////////////////////////////////////////////////////////////////
@@ -465,11 +481,9 @@ SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
{
}
-bool SkMemoryWStream::write(const void* buffer, size_t size)
-{
- size = SkMin32(size, fMaxLength - fBytesWritten);
- if (size > 0)
- {
+bool SkMemoryWStream::write(const void* buffer, size_t size) {
+ size = SkTMin(size, fMaxLength - fBytesWritten);
+ if (size > 0) {
memcpy(fBuffer + fBytesWritten, buffer, size);
fBytesWritten += size;
return true;
@@ -542,7 +556,7 @@ bool SkDynamicMemoryWStream::write(const void* buffer, size_t count)
size_t size;
if (fTail != NULL && fTail->avail() > 0) {
- size = SkMin32(fTail->avail(), count);
+ size = SkTMin(fTail->avail(), count);
buffer = fTail->append(buffer, size);
SkASSERT(count >= size);
count -= size;
@@ -550,7 +564,7 @@ bool SkDynamicMemoryWStream::write(const void* buffer, size_t count)
return true;
}
- size = SkMax32(count, SkDynamicMemoryWStream_MinBlockSize);
+ size = SkTMax<size_t>(count, SkDynamicMemoryWStream_MinBlockSize);
Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
block->init(size);
block->append(buffer, count);
@@ -687,10 +701,10 @@ public:
size_t bytesLeftToRead = count;
while (fCurrent != NULL) {
size_t bytesLeftInCurrent = fCurrent->written() - fCurrentOffset;
- size_t bytesFromCurrent = bytesLeftToRead <= bytesLeftInCurrent
- ? bytesLeftToRead : bytesLeftInCurrent;
+ size_t bytesFromCurrent = SkTMin(bytesLeftToRead, bytesLeftInCurrent);
if (buffer) {
memcpy(buffer, fCurrent->start() + fCurrentOffset, bytesFromCurrent);
+ buffer = SkTAddOffset<void>(buffer, bytesFromCurrent);
}
if (bytesLeftToRead <= bytesFromCurrent) {
fCurrentOffset += bytesFromCurrent;
@@ -698,7 +712,6 @@ public:
return count;
}
bytesLeftToRead -= bytesFromCurrent;
- buffer = SkTAddOffset<void>(buffer, bytesFromCurrent);
fCurrent = fCurrent->fNext;
fCurrentOffset = 0;
}
@@ -791,6 +804,7 @@ void SkDebugWStream::newline()
{
#if defined(SK_DEBUG) || defined(SK_DEVELOPER)
SkDebugf("\n");
+ fBytesWritten++;
#endif
}
@@ -802,6 +816,7 @@ bool SkDebugWStream::write(const void* buffer, size_t size)
s[size] = 0;
SkDebugf("%s", s);
delete[] s;
+ fBytesWritten += size;
#endif
return true;
}
diff --git a/chromium/third_party/skia/src/core/SkString.cpp b/chromium/third_party/skia/src/core/SkString.cpp
index 643dfb13727..ba1da413689 100644
--- a/chromium/third_party/skia/src/core/SkString.cpp
+++ b/chromium/third_party/skia/src/core/SkString.cpp
@@ -162,7 +162,7 @@ char* SkStrAppendFixed(char string[], SkFixed x) {
static const uint16_t gTens[] = { 1000, 100, 10, 1 };
const uint16_t* tens = gTens;
- x = SkFixedRound(frac * 10000);
+ x = SkFixedRoundToInt(frac * 10000);
SkASSERT(x <= 10000);
if (x == 10000) {
x -= 1;
diff --git a/chromium/third_party/skia/src/core/SkStringUtils.h b/chromium/third_party/skia/src/core/SkStringUtils.h
new file mode 100644
index 00000000000..aa5c809f2cb
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkStringUtils.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkStringUtils_DEFINED
+#define SkStringUtils_DEFINED
+
+class SkString;
+
+/**
+ * Add 'flagStr' to 'string' and set 'needSeparator' to true only if 'flag' is
+ * true. If 'needSeparator' is true append a '|' before 'flagStr'. This method
+ * is used to streamline the creation of ASCII flag strings within the toString
+ * methods.
+ */
+void SkAddFlagToString(SkString* string, bool flag,
+ const char* flagStr, bool* needSeparator);
+
+
+#endif
diff --git a/chromium/third_party/skia/src/core/SkStrokeRec.cpp b/chromium/third_party/skia/src/core/SkStrokeRec.cpp
index ce744e501b8..a4c73af2c5a 100644
--- a/chromium/third_party/skia/src/core/SkStrokeRec.cpp
+++ b/chromium/third_party/skia/src/core/SkStrokeRec.cpp
@@ -24,7 +24,15 @@ SkStrokeRec::SkStrokeRec(const SkStrokeRec& src) {
}
SkStrokeRec::SkStrokeRec(const SkPaint& paint) {
- switch (paint.getStyle()) {
+ this->init(paint, paint.getStyle());
+}
+
+SkStrokeRec::SkStrokeRec(const SkPaint& paint, SkPaint::Style styleOverride) {
+ this->init(paint, styleOverride);
+}
+
+void SkStrokeRec::init(const SkPaint& paint, SkPaint::Style style) {
+ switch (style) {
case SkPaint::kFill_Style:
fWidth = kStrokeRec_FillStyleWidth;
fStrokeAndFill = false;
diff --git a/chromium/third_party/skia/src/core/SkStrokerPriv.cpp b/chromium/third_party/skia/src/core/SkStrokerPriv.cpp
index 269ebd3dbd4..ad9c0c4d6fd 100644
--- a/chromium/third_party/skia/src/core/SkStrokerPriv.cpp
+++ b/chromium/third_party/skia/src/core/SkStrokerPriv.cpp
@@ -153,11 +153,7 @@ static void RoundJoiner(SkPath* outer, SkPath* inner, const SkVector& beforeUnit
}
}
-#ifdef SK_SCALAR_IS_FLOAT
- #define kOneOverSqrt2 (0.707106781f)
-#else
- #define kOneOverSqrt2 (46341)
-#endif
+#define kOneOverSqrt2 (0.707106781f)
static void MiterJoiner(SkPath* outer, SkPath* inner, const SkVector& beforeUnitNormal,
const SkPoint& pivot, const SkVector& afterUnitNormal,
diff --git a/chromium/third_party/skia/src/core/SkTDynamicHash.h b/chromium/third_party/skia/src/core/SkTDynamicHash.h
index 4cb44204c85..c9a0b3ed01c 100644
--- a/chromium/third_party/skia/src/core/SkTDynamicHash.h
+++ b/chromium/third_party/skia/src/core/SkTDynamicHash.h
@@ -8,21 +8,21 @@
#ifndef SkTDynamicHash_DEFINED
#define SkTDynamicHash_DEFINED
-#include "SkTypes.h"
#include "SkMath.h"
+#include "SkTemplates.h"
+#include "SkTypes.h"
+// Traits requires:
+// static const Key& GetKey(const T&) { ... }
+// static uint32_t Hash(const Key&) { ... }
+// We'll look on T for these by default, or you can pass a custom Traits type.
template <typename T,
typename Key,
- const Key& (GetKey)(const T&),
- uint32_t (Hash)(const Key&),
- bool (Equal)(const T&, const Key&),
- int kGrowPercent = 75, // Larger -> more memory efficient, but slower.
- int kShrinkPercent = 25>
+ typename Traits = T,
+ int kGrowPercent = 75> // Larger -> more memory efficient, but slower.
class SkTDynamicHash {
- static const int kMinCapacity = 4; // Smallest capacity we allow.
public:
- SkTDynamicHash(int initialCapacity=64/sizeof(T*)) {
- this->reset(SkNextPow2(initialCapacity > kMinCapacity ? initialCapacity : kMinCapacity));
+ SkTDynamicHash() : fCount(0), fDeleted(0), fCapacity(0), fArray(NULL) {
SkASSERT(this->validate());
}
@@ -30,6 +30,33 @@ public:
sk_free(fArray);
}
+ class Iter {
+ public:
+ explicit Iter(SkTDynamicHash* hash) : fHash(hash), fCurrentIndex(-1) {
+ SkASSERT(hash);
+ ++(*this);
+ }
+ bool done() const {
+ SkASSERT(fCurrentIndex <= fHash->fCapacity);
+ return fCurrentIndex == fHash->fCapacity;
+ }
+ T& operator*() const {
+ SkASSERT(!this->done());
+ return *this->current();
+ }
+ void operator++() {
+ do {
+ fCurrentIndex++;
+ } while (!this->done() && (this->current() == Empty() || this->current() == Deleted()));
+ }
+
+ private:
+ T* current() const { return fHash->fArray[fCurrentIndex]; }
+
+ SkTDynamicHash* fHash;
+ int fCurrentIndex;
+ };
+
int count() const { return fCount; }
// Return the entry with this key if we have it, otherwise NULL.
@@ -40,12 +67,12 @@ public:
if (Empty() == candidate) {
return NULL;
}
- if (Deleted() != candidate && Equal(*candidate, key)) {
+ if (Deleted() != candidate && GetKey(*candidate) == key) {
return candidate;
}
index = this->nextIndex(index, round);
}
- SkASSERT(0); // find: should be unreachable
+ SkASSERT(fCapacity == 0);
return NULL;
}
@@ -53,7 +80,6 @@ public:
void add(T* newEntry) {
SkASSERT(NULL == this->find(GetKey(*newEntry)));
this->maybeGrow();
- SkASSERT(this->validate());
this->innerAdd(newEntry);
SkASSERT(this->validate());
}
@@ -63,8 +89,6 @@ public:
SkASSERT(NULL != this->find(key));
this->innerRemove(key);
SkASSERT(this->validate());
- this->maybeShrink();
- SkASSERT(this->validate());
}
protected:
@@ -77,13 +101,13 @@ protected:
int index = this->firstIndex(key);
for (int round = 0; round < fCapacity; round++) {
const T* candidate = fArray[index];
- if (Empty() == candidate || Deleted() == candidate || Equal(*candidate, key)) {
+ if (Empty() == candidate || Deleted() == candidate || GetKey(*candidate) == key) {
return round;
}
index = this->nextIndex(index, round);
}
- SkASSERT(0); // countCollisions: should be unreachable
- return -1;
+ SkASSERT(fCapacity == 0);
+ return 0;
}
private:
@@ -91,62 +115,44 @@ private:
static T* Empty() { return reinterpret_cast<T*>(0); } // i.e. NULL
static T* Deleted() { return reinterpret_cast<T*>(1); } // Also an invalid pointer.
- static T** AllocArray(int capacity) {
- return (T**)sk_calloc_throw(sizeof(T*) * capacity); // All cells == Empty().
- }
-
- void reset(int capacity) {
- fCount = 0;
- fDeleted = 0;
- fCapacity = capacity;
- fArray = AllocArray(fCapacity);
- }
-
bool validate() const {
#define SKTDYNAMICHASH_CHECK(x) SkASSERT((x)); if (!(x)) return false
+ static const int kLarge = 50; // Arbitrary, tweak to suit your patience.
+ // O(1) checks, always done.
// Is capacity sane?
SKTDYNAMICHASH_CHECK(SkIsPow2(fCapacity));
- SKTDYNAMICHASH_CHECK(fCapacity >= kMinCapacity);
- // Is fCount correct?
- int count = 0;
- for (int i = 0; i < fCapacity; i++) {
- if (Empty() != fArray[i] && Deleted() != fArray[i]) {
- count++;
- }
- }
- SKTDYNAMICHASH_CHECK(count == fCount);
-
- // Is fDeleted correct?
- int deleted = 0;
- for (int i = 0; i < fCapacity; i++) {
- if (Deleted() == fArray[i]) {
- deleted++;
- }
- }
- SKTDYNAMICHASH_CHECK(deleted == fDeleted);
-
- // Are all entries findable?
- for (int i = 0; i < fCapacity; i++) {
- if (Empty() == fArray[i] || Deleted() == fArray[i]) {
- continue;
+ // O(N) checks, skipped when very large.
+ if (fCount < kLarge * kLarge) {
+ // Are fCount and fDeleted correct, and are all elements findable?
+ int count = 0, deleted = 0;
+ for (int i = 0; i < fCapacity; i++) {
+ if (Deleted() == fArray[i]) {
+ deleted++;
+ } else if (Empty() != fArray[i]) {
+ count++;
+ SKTDYNAMICHASH_CHECK(NULL != this->find(GetKey(*fArray[i])));
+ }
}
- SKTDYNAMICHASH_CHECK(NULL != this->find(GetKey(*fArray[i])));
+ SKTDYNAMICHASH_CHECK(count == fCount);
+ SKTDYNAMICHASH_CHECK(deleted == fDeleted);
}
- // Are all entries unique?
- for (int i = 0; i < fCapacity; i++) {
- if (Empty() == fArray[i] || Deleted() == fArray[i]) {
- continue;
- }
- for (int j = i+1; j < fCapacity; j++) {
- if (Empty() == fArray[j] || Deleted() == fArray[j]) {
+ // O(N^2) checks, skipped when large.
+ if (fCount < kLarge) {
+ // Are all entries unique?
+ for (int i = 0; i < fCapacity; i++) {
+ if (Empty() == fArray[i] || Deleted() == fArray[i]) {
continue;
}
- SKTDYNAMICHASH_CHECK(fArray[i] != fArray[j]);
- SKTDYNAMICHASH_CHECK(!Equal(*fArray[i], GetKey(*fArray[j])));
- SKTDYNAMICHASH_CHECK(!Equal(*fArray[j], GetKey(*fArray[i])));
+ for (int j = i+1; j < fCapacity; j++) {
+ if (Empty() == fArray[j] || Deleted() == fArray[j]) {
+ continue;
+ }
+ SKTDYNAMICHASH_CHECK(fArray[i] != fArray[j]);
+ SKTDYNAMICHASH_CHECK(!(GetKey(*fArray[i]) == GetKey(*fArray[j])));
+ }
}
}
#undef SKTDYNAMICHASH_CHECK
@@ -168,7 +174,7 @@ private:
}
index = this->nextIndex(index, round);
}
- SkASSERT(0); // add: should be unreachable
+ SkASSERT(fCapacity == 0);
}
void innerRemove(const Key& key) {
@@ -176,7 +182,7 @@ private:
int index = firstIndex;
for (int round = 0; round < fCapacity; round++) {
const T* candidate = fArray[index];
- if (Deleted() != candidate && Equal(*candidate, key)) {
+ if (Deleted() != candidate && GetKey(*candidate) == key) {
fDeleted++;
fCount--;
fArray[index] = Deleted();
@@ -184,37 +190,31 @@ private:
}
index = this->nextIndex(index, round);
}
- SkASSERT(0); // innerRemove: should be unreachable
+ SkASSERT(fCapacity == 0);
}
void maybeGrow() {
- if (fCount + fDeleted + 1 > (fCapacity * kGrowPercent) / 100) {
- resize(fCapacity * 2);
- }
- }
-
- void maybeShrink() {
- if (fCount < (fCapacity * kShrinkPercent) / 100 && fCapacity / 2 > kMinCapacity) {
- resize(fCapacity / 2);
+ if (100 * (fCount + fDeleted + 1) > fCapacity * kGrowPercent) {
+ this->resize(fCapacity > 0 ? fCapacity * 2 : 4);
}
}
void resize(int newCapacity) {
SkDEBUGCODE(int oldCount = fCount;)
int oldCapacity = fCapacity;
- T** oldArray = fArray;
+ SkAutoTMalloc<T*> oldArray(fArray);
- reset(newCapacity);
+ fCount = fDeleted = 0;
+ fCapacity = newCapacity;
+ fArray = (T**)sk_calloc_throw(sizeof(T*) * fCapacity);
for (int i = 0; i < oldCapacity; i++) {
T* entry = oldArray[i];
if (Empty() != entry && Deleted() != entry) {
- this->add(entry);
+ this->innerAdd(entry);
}
}
SkASSERT(oldCount == fCount);
-
- sk_free(oldArray);
}
// fCapacity is always a power of 2, so this masks the correct low bits to index into our hash.
@@ -230,6 +230,9 @@ private:
return (index + round + 1) & this->hashMask();
}
+ static const Key& GetKey(const T& t) { return Traits::GetKey(t); }
+ static uint32_t Hash(const Key& key) { return Traits::Hash(key); }
+
int fCount; // Number of non Empty(), non Deleted() entries in fArray.
int fDeleted; // Number of Deleted() entries in fArray.
int fCapacity; // Number of entries in fArray. Always a power of 2.
diff --git a/chromium/third_party/skia/src/core/SkTInternalSList.h b/chromium/third_party/skia/src/core/SkTInternalSList.h
new file mode 100644
index 00000000000..4695e5af292
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkTInternalSList.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkTInternalSList_DEFINED
+#define SkTInternalSList_DEFINED
+
+#include "SkTInternalLList.h" // for SkPtrWrapper
+
+/**
+ * This macro creates the methods required by the SkTInternalSList class.
+ * It should be instantiated in the private block of the class you want to put
+ * into an SkTInternalSList.
+ * For most use cases you should use SK_DECLARE_INTERNAL_SLIST_INTERFACE and not
+ * this macro. If you care about the field name, or want to re-use an existing
+ * field, then you can use this macro to declare the methods pointing to a
+ * specific field.
+ * Unlike SK_DECLARE_INTERNAL_SLIST_INTERFACE this does not declare the field
+ * itself.
+ * It also makes SkTInternalSList<ClassName> a friend to give it access to the
+ * methods.
+ */
+#define SK_DECLARE_INTERNAL_SLIST_ADAPTER(ClassName, field) \
+ ClassName* getSListNext() { \
+ return this->field; \
+ } \
+ void setSListNext(ClassName* next) { \
+ this->field = next; \
+ } \
+ friend class SkTInternalSList<ClassName>
+
+/**
+ * This macro declares an fSListNext that auto initializes to NULL and then
+ * uses SK_DECLARE_INTERNAL_SLIST_ADAPTER to add the methods needed by
+ * SkTInternalSList.
+ * It should be instantiated in the private block of the class you want to put
+ * into an SkTInternalSList.
+ */
+#define SK_DECLARE_INTERNAL_SLIST_INTERFACE(ClassName) \
+ SK_DECLARE_INTERNAL_SLIST_ADAPTER(ClassName, fSListNext); \
+ SkPtrWrapper<ClassName> fSListNext
+
+/**
+ * An implementation of an intrusive singly linked list.
+ * The type T must have a methods getSListNext and setSListNext that are visible
+ * to the list. The easiest way to do this is with
+ * SK_DECLARE_INTERNAL_SLIST_INTERFACE.
+ * The list does not maintain ownership of any of its elements, or ever delete
+ * them.
+ */
+template<typename T> class SkTInternalSList {
+public:
+ SkTInternalSList() : fHead(NULL), fCount(0) {}
+
+ /**
+ * Push an item onto the head of the list.
+ * This method is *not* thread safe.
+ */
+ void push(T* entry) {
+ SkASSERT(entry->getSListNext() == NULL);
+ entry->setSListNext(fHead);
+ fHead = entry;
+ ++fCount;
+ }
+
+ /**
+ * Takes all the items from another list and pushes them into this list.
+ * No ordering guarantees are made, the other list will be emptied.
+ * This method is *not* thread safe.
+ */
+ void pushAll(SkTInternalSList<T>* other) {
+ if (this->isEmpty()) {
+ this->swap(other);
+ return;
+ }
+ while (!other->isEmpty()) {
+ this->push(other->pop());
+ }
+ }
+
+ /**
+ * Pop an item from the head of the list.
+ * Returns NULL if the list is empty.
+ * This method is *not* thread safe.
+ */
+ T* pop() {
+ if (NULL == fHead) {
+ return NULL;
+ }
+ T* result = fHead;
+ fHead = result->getSListNext();
+ result->setSListNext(NULL);
+ --fCount;
+ return result;
+ }
+
+ T* head() const {
+ return fHead;
+ }
+
+ /**
+ * Returns true if the list has no elements.
+ */
+ bool isEmpty() const {
+ return NULL == fHead;
+ }
+
+ /**
+ * Swaps the contents of this list with another one.
+ * This method is *not* thread safe.
+ */
+ void swap(SkTInternalSList<T>* other) {
+ SkTSwap(fHead, other->fHead);
+ SkTSwap(fCount, other->fCount);
+ }
+
+ /**
+ * Returns the count of elements in the list.
+ */
+ int getCount() const {
+ return fCount;
+ }
+private:
+ T* fHead;
+ int fCount;
+};
+
+
+#endif
diff --git a/chromium/third_party/skia/src/core/SkTLList.h b/chromium/third_party/skia/src/core/SkTLList.h
index 298ce516cc0..e2b9691430a 100644
--- a/chromium/third_party/skia/src/core/SkTLList.h
+++ b/chromium/third_party/skia/src/core/SkTLList.h
@@ -28,7 +28,7 @@ inline void* operator new(size_t, SkTLList<T>* list,
constructor arguments for type_name. These macros behave like addBefore() and addAfter().
*/
template <typename T>
-class SkTLList : public SkNoncopyable {
+class SkTLList : SkNoncopyable {
private:
struct Block;
struct Node {
@@ -75,6 +75,15 @@ public:
return reinterpret_cast<T*>(node->fObj);
}
+ T* addToHead() {
+ this->validate();
+ Node* node = this->createNode();
+ fList.addToHead(node);
+ SkNEW_PLACEMENT(node->fObj, T);
+ this->validate();
+ return reinterpret_cast<T*>(node->fObj);
+ }
+
T* addToTail(const T& t) {
this->validate();
Node* node = this->createNode();
@@ -84,6 +93,15 @@ public:
return reinterpret_cast<T*>(node->fObj);
}
+ T* addToTail() {
+ this->validate();
+ Node* node = this->createNode();
+ fList.addToTail(node);
+ SkNEW_PLACEMENT(node->fObj, T);
+ this->validate();
+ return reinterpret_cast<T*>(node->fObj);
+ }
+
/** Adds a new element to the list before the location indicated by the iterator. If the
iterator refers to a NULL location then the new element is added at the tail */
T* addBefore(const T& t, const Iter& location) {
@@ -180,11 +198,11 @@ public:
Iter() {}
- Iter(const SkTLList& list, IterStart start) {
+ Iter(const SkTLList& list, IterStart start = kHead_IterStart) {
INHERITED::init(list.fList, start);
}
- T* init(const SkTLList& list, IterStart start) {
+ T* init(const SkTLList& list, IterStart start = kHead_IterStart) {
return this->nodeToObj(INHERITED::init(list.fList, start));
}
diff --git a/chromium/third_party/skia/src/core/SkTObjectPool.h b/chromium/third_party/skia/src/core/SkTObjectPool.h
new file mode 100644
index 00000000000..f2a471f634a
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkTObjectPool.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFreeList_DEFINED
+#define SkFreeList_DEFINED
+
+#include "SkTInternalSList.h"
+
+/**
+ * An implementation of a self growing pool of objects.
+ * It maintains a pool of fully initialized objects. If an attempt is made to
+ * acquire one, and there are none left, it makes some more.
+ * It does not automatically reclaim them, they have to be given back to it.
+ * Constructors will be called on objects allocated by the pool at allocation
+ * time.
+ * All allocated objects will be destroyed and memory will be reclaimed when
+ * the pool is destroyed, so the pool must survive longer than you are using
+ * any item taken from it.
+ */
+template<typename T, int numItemsPerBlock = 4096/sizeof(T)> class SkTObjectPool {
+public:
+ SkTObjectPool() {}
+ ~SkTObjectPool() {
+ while (!fBlocks.isEmpty()) {
+ SkDELETE(fBlocks.pop());
+ }
+ }
+
+ /**
+ * Get an item from the pool.
+ * If the pool has no free items, it will allocate and construct some more.
+ * The returned item is only valid as long as the pool has not been
+ * destroyed, at that point all memory allocated by grow will have been
+ * reclaimed.
+ * This method is *not* thread safe.
+ */
+ T* acquire() {
+ if (fAvailable.isEmpty()) {
+ grow();
+ }
+ return fAvailable.pop();
+ }
+
+ /**
+ * Release an item into the pool.
+ * The item does not have to have come from the pool, but if it did not
+ * it must have a lifetime greater than the pool does.
+ * This method is *not* thread safe.
+ */
+ void release(T* entry) {
+ fAvailable.push(entry);
+ }
+
+ /**
+ * Takes all the items from an SkTInternalSList and adds them back to this
+ * pool. The other list will be left empty.
+ */
+ void releaseAll(SkTInternalSList<T>* other) {
+ fAvailable.pushAll(other);
+ }
+
+ /**
+ * Returns the number of items immediately available without having to
+ * construct any new ones.
+ */
+ int available() const { return fAvailable.getCount(); }
+
+ /**
+ * Returns the number of blocks of items the pool has allocated so far.
+ */
+ int blocks() const { return fBlocks.getCount(); }
+
+ /**
+ * Returns the number of items allocated by the pool in total.
+ */
+ int allocated() const { return fBlocks.getCount() * numItemsPerBlock; }
+
+private:
+ /**
+ * The type for a new block of entries for the list.
+ */
+ struct Block {
+ T entries[numItemsPerBlock];
+ SK_DECLARE_INTERNAL_SLIST_INTERFACE(Block);
+ };
+ SkTInternalSList<Block> fBlocks;
+ SkTInternalSList<T> fAvailable;
+
+ /**
+ * When the free list runs out of items, this method is called to allocate
+ * a new block of them.
+ * It calls the constructors and then pushes the nodes into the available
+ * list.
+ */
+ void grow() {
+ Block* block = SkNEW(Block);
+ fBlocks.push(block);
+ for(int index = 0; index < numItemsPerBlock; ++index) {
+ fAvailable.push(&block->entries[index]);
+ }
+ }
+
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/core/SkTRefArray.h b/chromium/third_party/skia/src/core/SkTRefArray.h
index c4bca241d77..c4bca241d77 100755..100644
--- a/chromium/third_party/skia/src/core/SkTRefArray.h
+++ b/chromium/third_party/skia/src/core/SkTRefArray.h
diff --git a/chromium/third_party/skia/src/core/SkTemplatesPriv.h b/chromium/third_party/skia/src/core/SkTemplatesPriv.h
deleted file mode 100644
index 79ae6093358..00000000000
--- a/chromium/third_party/skia/src/core/SkTemplatesPriv.h
+++ /dev/null
@@ -1,76 +0,0 @@
-
-/*
- * Copyright 2006 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#ifndef SkTemplatesPriv_DEFINED
-#define SkTemplatesPriv_DEFINED
-
-#include "SkTemplates.h"
-
-////////////////////////////////////////////////////////////////////////////////
-
-#ifdef SK_BUILD_FOR_WIN32
- #define SK_PLACEMENT_NEW(result, classname, storage, storageSize) \
- result = SkNEW(classname)
-
- #define SK_PLACEMENT_NEW_ARGS(result, classname, storage, storageSize, args) \
- result = SkNEW_ARGS(classname, args)
-#else
- #include <new>
- #define SK_PLACEMENT_NEW(result, classname, storage, storagesize) \
- do { \
- if (storagesize) \
- { \
- SkASSERT(storageSize >= sizeof(classname)); \
- result = new(storage) classname; \
- } \
- else \
- result = SkNEW(classname); \
- } while (0)
-
- #define SK_PLACEMENT_NEW_ARGS(result, classname, storage, storagesize, args) \
- do { \
- if (storagesize) \
- { \
- SkASSERT(storageSize >= sizeof(classname)); \
- result = new(storage) classname args; \
- } \
- else \
- result = SkNEW_ARGS(classname, args); \
- } while (0)
-#endif
-
-////////////////////////////////////////////////////////////////////////////////
-
-template <class T> class SkAutoTPlacementDelete {
-public:
- SkAutoTPlacementDelete(T* obj, void* storage) : fObj(obj), fStorage(storage)
- {
- }
- ~SkAutoTPlacementDelete()
- {
- if (fObj)
- {
- if (fObj == fStorage)
- fObj->~T();
- else
- delete fObj;
- }
- }
- T* detach()
- {
- T* obj = fObj;
- fObj = NULL;
- return obj;
- }
-private:
- T* fObj;
- void* fStorage;
-};
-
-#endif
diff --git a/chromium/third_party/skia/src/core/SkTextMapStateProc.h b/chromium/third_party/skia/src/core/SkTextMapStateProc.h
new file mode 100644
index 00000000000..5a8dcaa3b1a
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkTextMapStateProc.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkTextMapStateProc_DEFINED
+#define SkTextMapStateProc_DEFINED
+
+#include "SkPoint.h"
+#include "SkMatrix.h"
+
+class SkTextMapStateProc {
+public:
+ SkTextMapStateProc(const SkMatrix& matrix, SkScalar y, int scalarsPerPosition)
+ : fMatrix(matrix)
+ , fProc(matrix.getMapXYProc())
+ , fY(y)
+ , fScaleX(fMatrix.getScaleX())
+ , fTransX(fMatrix.getTranslateX()) {
+ SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
+ if (1 == scalarsPerPosition) {
+ unsigned mtype = fMatrix.getType();
+ if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) {
+ fMapCase = kX;
+ } else {
+ fY = SkScalarMul(y, fMatrix.getScaleY()) +
+ fMatrix.getTranslateY();
+ if (mtype & SkMatrix::kScale_Mask) {
+ fMapCase = kOnlyScaleX;
+ } else {
+ fMapCase = kOnlyTransX;
+ }
+ }
+ } else {
+ fMapCase = kXY;
+ }
+ }
+
+ void operator()(const SkScalar pos[], SkPoint* loc) const;
+
+private:
+ const SkMatrix& fMatrix;
+ enum {
+ kXY,
+ kOnlyScaleX,
+ kOnlyTransX,
+ kX
+ } fMapCase;
+ const SkMatrix::MapXYProc fProc;
+ SkScalar fY; // Ignored by kXY case.
+ SkScalar fScaleX, fTransX; // These are only used by Only... cases.
+};
+
+inline void SkTextMapStateProc::operator()(const SkScalar pos[], SkPoint* loc) const {
+ switch(fMapCase) {
+ case kXY:
+ fProc(fMatrix, pos[0], pos[1], loc);
+ break;
+ case kOnlyScaleX:
+ loc->set(SkScalarMul(fScaleX, *pos) + fTransX, fY);
+ break;
+ case kOnlyTransX:
+ loc->set(*pos + fTransX, fY);
+ break;
+ default:
+ SkASSERT(false);
+ case kX:
+ fProc(fMatrix, *pos, fY, loc);
+ break;
+ }
+}
+
+#endif
+
diff --git a/chromium/third_party/skia/src/core/SkThreadPriv.h b/chromium/third_party/skia/src/core/SkThreadPriv.h
new file mode 100644
index 00000000000..c44cca53509
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkThreadPriv.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkThreadPriv_DEFINED
+#define SkThreadPriv_DEFINED
+
+#include "SkTypes.h"
+
+// SK_ATOMICS_PLATFORM_H must provide inline implementations for the following declarations.
+
+/** Atomic compare and set, for pointers.
+ * If *addr == before, set *addr to after. Always returns previous value of *addr.
+ * This must issue a release barrier on success, acquire on failure, and always a compiler barrier.
+ */
+static void* sk_atomic_cas(void** addr, void* before, void* after);
+
+#include SK_ATOMICS_PLATFORM_H
+
+#endif//SkThreadPriv_DEFINED
diff --git a/chromium/third_party/skia/src/core/SkTileGrid.cpp b/chromium/third_party/skia/src/core/SkTileGrid.cpp
index bbed00603dc..35f85d26c96 100644
--- a/chromium/third_party/skia/src/core/SkTileGrid.cpp
+++ b/chromium/third_party/skia/src/core/SkTileGrid.cpp
@@ -8,9 +8,8 @@
#include "SkTileGrid.h"
-SkTileGrid::SkTileGrid(int xTileCount, int yTileCount, const SkTileGridPicture::TileGridInfo& info,
- SkTileGridNextDatumFunctionPtr nextDatumFunction)
-{
+SkTileGrid::SkTileGrid(int xTileCount, int yTileCount, const SkTileGridFactory::TileGridInfo& info,
+ SkTileGridNextDatumFunctionPtr nextDatumFunction) {
fXTileCount = xTileCount;
fYTileCount = yTileCount;
fInfo = info;
@@ -30,6 +29,10 @@ SkTileGrid::~SkTileGrid() {
SkDELETE_ARRAY(fTileData);
}
+int SkTileGrid::tileCount(int x, int y) {
+ return this->tile(x, y).count();
+}
+
SkTDArray<void *>& SkTileGrid::tile(int x, int y) {
return fTileData[y * fXTileCount + x];
}
diff --git a/chromium/third_party/skia/src/core/SkTileGrid.h b/chromium/third_party/skia/src/core/SkTileGrid.h
index 77d972850fe..0ec5c2c3932 100644
--- a/chromium/third_party/skia/src/core/SkTileGrid.h
+++ b/chromium/third_party/skia/src/core/SkTileGrid.h
@@ -9,9 +9,9 @@
#ifndef SkTileGrid_DEFINED
#define SkTileGrid_DEFINED
+#include "SkBBHFactory.h"
#include "SkBBoxHierarchy.h"
#include "SkPictureStateTree.h"
-#include "SkTileGridPicture.h" // for TileGridInfo
/**
* Subclass of SkBBoxHierarchy that stores elements in buckets that correspond
@@ -35,7 +35,7 @@ public:
typedef void* (*SkTileGridNextDatumFunctionPtr)(SkTDArray<void*>** tileData, SkAutoSTArray<kStackAllocationTileCount, int>& tileIndices);
- SkTileGrid(int xTileCount, int yTileCount, const SkTileGridPicture::TileGridInfo& info,
+ SkTileGrid(int xTileCount, int yTileCount, const SkTileGridFactory::TileGridInfo& info,
SkTileGridNextDatumFunctionPtr nextDatumFunction);
virtual ~SkTileGrid();
@@ -63,23 +63,27 @@ public:
*/
virtual int getCount() const SK_OVERRIDE;
+ virtual int getDepth() const SK_OVERRIDE { return -1; }
+
virtual void rewindInserts() SK_OVERRIDE;
// Used by search() and in SkTileGridHelper implementations
enum {
kTileFinished = -1,
};
+
+ int tileCount(int x, int y); // For testing only.
+
private:
SkTDArray<void*>& tile(int x, int y);
int fXTileCount, fYTileCount, fTileCount;
- SkTileGridPicture::TileGridInfo fInfo;
+ SkTileGridFactory::TileGridInfo fInfo;
SkTDArray<void*>* fTileData;
int fInsertionCount;
SkIRect fGridBounds;
SkTileGridNextDatumFunctionPtr fNextDatumFunction;
- friend class TileGridTest;
typedef SkBBoxHierarchy INHERITED;
};
diff --git a/chromium/third_party/skia/src/core/SkTileGridPicture.cpp b/chromium/third_party/skia/src/core/SkTileGridPicture.cpp
deleted file mode 100644
index 7a8d5932ace..00000000000
--- a/chromium/third_party/skia/src/core/SkTileGridPicture.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkTileGridPicture.h"
-
-#include "SkPictureStateTree.h"
-#include "SkTileGrid.h"
-
-SkTileGridPicture::SkTileGridPicture(int width, int height, const TileGridInfo& info) {
- SkASSERT(info.fMargin.width() >= 0);
- SkASSERT(info.fMargin.height() >= 0);
- fInfo = info;
- // Note: SkIRects are non-inclusive of the right() column and bottom() row.
- // For example, an SkIRect at 0,0 with a size of (1,1) will only have
- // content at pixel (0,0) and will report left=0 and right=1, hence the
- // "-1"s below.
- fXTileCount = (width + info.fTileInterval.width() - 1) / info.fTileInterval.width();
- fYTileCount = (height + info.fTileInterval.height() - 1) / info.fTileInterval.height();
-}
-
-SkBBoxHierarchy* SkTileGridPicture::createBBoxHierarchy() const {
- return SkNEW_ARGS(SkTileGrid, (fXTileCount, fYTileCount, fInfo,
- SkTileGridNextDatum<SkPictureStateTree::Draw>));
-}
diff --git a/chromium/third_party/skia/src/core/SkTraceEvent.h b/chromium/third_party/skia/src/core/SkTraceEvent.h
new file mode 100644
index 00000000000..0c7989fb1a7
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkTraceEvent.h
@@ -0,0 +1,1245 @@
+// Copyright (c) 2014 Google Inc.
+//
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This header file defines the set of trace_event macros without specifying
+// how the events actually get collected and stored. If you need to expose trace
+// events to some other universe, you can copy-and-paste this file as well as
+// trace_event.h, modifying the macros contained there as necessary for the
+// target platform. The end result is that multiple libraries can funnel events
+// through to a shared trace event collector.
+
+// Trace events are for tracking application performance and resource usage.
+// Macros are provided to track:
+// Begin and end of function calls
+// Counters
+//
+// Events are issued against categories. Whereas LOG's
+// categories are statically defined, TRACE categories are created
+// implicitly with a string. For example:
+// TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent",
+// TRACE_EVENT_SCOPE_THREAD)
+//
+// It is often the case that one trace may belong in multiple categories at the
+// same time. The first argument to the trace can be a comma-separated list of
+// categories, forming a category group, like:
+//
+// TRACE_EVENT_INSTANT0("input,views", "OnMouseOver", TRACE_EVENT_SCOPE_THREAD)
+//
+// We can enable/disable tracing of OnMouseOver by enabling/disabling either
+// category.
+//
+// Events can be INSTANT, or can be pairs of BEGIN and END in the same scope:
+// TRACE_EVENT_BEGIN0("MY_SUBSYSTEM", "SomethingCostly")
+// doSomethingCostly()
+// TRACE_EVENT_END0("MY_SUBSYSTEM", "SomethingCostly")
+// Note: our tools can't always determine the correct BEGIN/END pairs unless
+// these are used in the same scope. Use ASYNC_BEGIN/ASYNC_END macros if you
+// need them to be in separate scopes.
+//
+// A common use case is to trace entire function scopes. This
+// issues a trace BEGIN and END automatically:
+// void doSomethingCostly() {
+// TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly");
+// ...
+// }
+//
+// Additional parameters can be associated with an event:
+// void doSomethingCostly2(int howMuch) {
+// TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly",
+// "howMuch", howMuch);
+// ...
+// }
+//
+// The trace system will automatically add to this information the
+// current process id, thread id, and a timestamp in microseconds.
+//
+// To trace an asynchronous procedure such as an IPC send/receive, use
+// ASYNC_BEGIN and ASYNC_END:
+// [single threaded sender code]
+// static int send_count = 0;
+// ++send_count;
+// TRACE_EVENT_ASYNC_BEGIN0("ipc", "message", send_count);
+// Send(new MyMessage(send_count));
+// [receive code]
+// void OnMyMessage(send_count) {
+// TRACE_EVENT_ASYNC_END0("ipc", "message", send_count);
+// }
+// The third parameter is a unique ID to match ASYNC_BEGIN/ASYNC_END pairs.
+// ASYNC_BEGIN and ASYNC_END can occur on any thread of any traced process.
+// Pointers can be used for the ID parameter, and they will be mangled
+// internally so that the same pointer on two different processes will not
+// match. For example:
+// class MyTracedClass {
+// public:
+// MyTracedClass() {
+// TRACE_EVENT_ASYNC_BEGIN0("category", "MyTracedClass", this);
+// }
+// ~MyTracedClass() {
+// TRACE_EVENT_ASYNC_END0("category", "MyTracedClass", this);
+// }
+// }
+//
+// Trace event also supports counters, which is a way to track a quantity
+// as it varies over time. Counters are created with the following macro:
+// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter", g_myCounterValue);
+//
+// Counters are process-specific. The macro itself can be issued from any
+// thread, however.
+//
+// Sometimes, you want to track two counters at once. You can do this with two
+// counter macros:
+// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter0", g_myCounterValue[0]);
+// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter1", g_myCounterValue[1]);
+// Or you can do it with a combined macro:
+// TRACE_COUNTER2("MY_SUBSYSTEM", "myCounter",
+// "bytesPinned", g_myCounterValue[0],
+// "bytesAllocated", g_myCounterValue[1]);
+// This indicates to the tracing UI that these counters should be displayed
+// in a single graph, as a summed area chart.
+//
+// Since counters are in a global namespace, you may want to disambiguate with a
+// unique ID, by using the TRACE_COUNTER_ID* variations.
+//
+// By default, trace collection is compiled in, but turned off at runtime.
+// Collecting trace data is the responsibility of the embedding
+// application. In Chrome's case, navigating to about:tracing will turn on
+// tracing and display data collected across all active processes.
+//
+//
+// Memory scoping note:
+// Tracing copies the pointers, not the string content, of the strings passed
+// in for category_group, name, and arg_names. Thus, the following code will
+// cause problems:
+// char* str = strdup("importantName");
+// TRACE_EVENT_INSTANT0("SUBSYSTEM", str); // BAD!
+// free(str); // Trace system now has dangling pointer
+//
+// To avoid this issue with the |name| and |arg_name| parameters, use the
+// TRACE_EVENT_COPY_XXX overloads of the macros at additional runtime overhead.
+// Notes: The category must always be in a long-lived char* (i.e. static const).
+// The |arg_values|, when used, are always deep copied with the _COPY
+// macros.
+//
+// When are string argument values copied:
+// const char* arg_values are only referenced by default:
+// TRACE_EVENT1("category", "name",
+// "arg1", "literal string is only referenced");
+// Use TRACE_STR_COPY to force copying of a const char*:
+// TRACE_EVENT1("category", "name",
+// "arg1", TRACE_STR_COPY("string will be copied"));
+// std::string arg_values are always copied:
+// TRACE_EVENT1("category", "name",
+// "arg1", std::string("string will be copied"));
+//
+//
+// Thread Safety:
+// A thread safe singleton and mutex are used for thread safety. Category
+// enabled flags are used to limit the performance impact when the system
+// is not enabled.
+//
+// TRACE_EVENT macros first cache a pointer to a category. The categories are
+// statically allocated and safe at all times, even after exit. Fetching a
+// category is protected by the TraceLog::lock_. Multiple threads initializing
+// the static variable is safe, as they will be serialized by the lock and
+// multiple calls will return the same pointer to the category.
+//
+// Then the category_group_enabled flag is checked. This is a unsigned char, and
+// not intended to be multithread safe. It optimizes access to AddTraceEvent
+// which is threadsafe internally via TraceLog::lock_. The enabled flag may
+// cause some threads to incorrectly call or skip calling AddTraceEvent near
+// the time of the system being enabled or disabled. This is acceptable as
+// we tolerate some data loss while the system is being enabled/disabled and
+// because AddTraceEvent is threadsafe internally and checks the enabled state
+// again under lock.
+//
+// Without the use of these static category pointers and enabled flags all
+// trace points would carry a significant performance cost of acquiring a lock
+// and resolving the category.
+
+#ifndef SkTraceEvent_DEFINED
+#define SkTraceEvent_DEFINED
+
+#include "SkEventTracer.h"
+
+// By default, const char* argument values are assumed to have long-lived scope
+// and will not be copied. Use this macro to force a const char* to be copied.
+#define TRACE_STR_COPY(str) \
+ skia::tracing_internals::TraceStringWithCopy(str)
+
+// By default, uint64 ID argument values are not mangled with the Process ID in
+// TRACE_EVENT_ASYNC macros. Use this macro to force Process ID mangling.
+#define TRACE_ID_MANGLE(id) \
+ skia::tracing_internals::TraceID::ForceMangle(id)
+
+// By default, pointers are mangled with the Process ID in TRACE_EVENT_ASYNC
+// macros. Use this macro to prevent Process ID mangling.
+#define TRACE_ID_DONT_MANGLE(id) \
+ skia::tracing_internals::TraceID::DontMangle(id)
+
+// Records a pair of begin and end events called "name" for the current
+// scope, with 0, 1 or 2 associated arguments. If the category is not
+// enabled, then this does nothing.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+#define TRACE_EVENT0(category_group, name) \
+ INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name)
+#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, arg1_name, arg1_val)
+#define TRACE_EVENT2( \
+ category_group, name, arg1_name, arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_SCOPED( \
+ category_group, name, arg1_name, arg1_val, arg2_name, arg2_val)
+
+// Records events like TRACE_EVENT2 but uses |memory_tag| for memory tracing.
+// Use this where |name| is too generic to accurately aggregate allocations.
+#define TRACE_EVENT_WITH_MEMORY_TAG2( \
+ category, name, memory_tag, arg1_name, arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_SCOPED( \
+ category, name, arg1_name, arg1_val, arg2_name, arg2_val)
+
+// UNSHIPPED_TRACE_EVENT* are like TRACE_EVENT* except that they are not
+// included in official builds.
+
+#if OFFICIAL_BUILD
+#undef TRACING_IS_OFFICIAL_BUILD
+#define TRACING_IS_OFFICIAL_BUILD 1
+#elif !defined(TRACING_IS_OFFICIAL_BUILD)
+#define TRACING_IS_OFFICIAL_BUILD 0
+#endif
+
+#if TRACING_IS_OFFICIAL_BUILD
+#define UNSHIPPED_TRACE_EVENT0(category_group, name) (void)0
+#define UNSHIPPED_TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \
+ (void)0
+#define UNSHIPPED_TRACE_EVENT2(category_group, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val) (void)0
+#define UNSHIPPED_TRACE_EVENT_INSTANT0(category_group, name, scope) (void)0
+#define UNSHIPPED_TRACE_EVENT_INSTANT1(category_group, name, scope, \
+ arg1_name, arg1_val) (void)0
+#define UNSHIPPED_TRACE_EVENT_INSTANT2(category_group, name, scope, \
+ arg1_name, arg1_val, \
+ arg2_name, arg2_val) (void)0
+#else
+#define UNSHIPPED_TRACE_EVENT0(category_group, name) \
+ TRACE_EVENT0(category_group, name)
+#define UNSHIPPED_TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \
+ TRACE_EVENT1(category_group, name, arg1_name, arg1_val)
+#define UNSHIPPED_TRACE_EVENT2(category_group, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ TRACE_EVENT2(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val)
+#define UNSHIPPED_TRACE_EVENT_INSTANT0(category_group, name, scope) \
+ TRACE_EVENT_INSTANT0(category_group, name, scope)
+#define UNSHIPPED_TRACE_EVENT_INSTANT1(category_group, name, scope, \
+ arg1_name, arg1_val) \
+ TRACE_EVENT_INSTANT1(category_group, name, scope, arg1_name, arg1_val)
+#define UNSHIPPED_TRACE_EVENT_INSTANT2(category_group, name, scope, \
+ arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ TRACE_EVENT_INSTANT2(category_group, name, scope, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+#endif
+
+// Records a single event called "name" immediately, with 0, 1 or 2
+// associated arguments. If the category is not enabled, then this
+// does nothing.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+#define TRACE_EVENT_INSTANT0(category_group, name, scope) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+ category_group, name, TRACE_EVENT_FLAG_NONE | scope)
+#define TRACE_EVENT_INSTANT1(category_group, name, scope, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+ category_group, name, TRACE_EVENT_FLAG_NONE | scope, \
+ arg1_name, arg1_val)
+#define TRACE_EVENT_INSTANT2(category_group, name, scope, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+ category_group, name, TRACE_EVENT_FLAG_NONE | scope, \
+ arg1_name, arg1_val, arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_INSTANT0(category_group, name, scope) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+ category_group, name, TRACE_EVENT_FLAG_COPY | scope)
+#define TRACE_EVENT_COPY_INSTANT1(category_group, name, scope, \
+ arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+ category_group, name, TRACE_EVENT_FLAG_COPY | scope, arg1_name, \
+ arg1_val)
+#define TRACE_EVENT_COPY_INSTANT2(category_group, name, scope, \
+ arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+ category_group, name, TRACE_EVENT_FLAG_COPY | scope, \
+ arg1_name, arg1_val, arg2_name, arg2_val)
+
+// Sets the current sample state to the given category and name (both must be
+// constant strings). These states are intended for a sampling profiler.
+// Implementation note: we store category and name together because we don't
+// want the inconsistency/expense of storing two pointers.
+// |thread_bucket| is [0..2] and is used to statically isolate samples in one
+// thread from others.
+#define TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET( \
+ bucket_number, category, name) \
+ skia::tracing_internals:: \
+ TraceEventSamplingStateScope<bucket_number>::Set(category "\0" name)
+
+// Returns a current sampling state of the given bucket.
+#define TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(bucket_number) \
+ skia::tracing_internals::TraceEventSamplingStateScope<bucket_number>::Current()
+
+// Creates a scope of a sampling state of the given bucket.
+//
+// { // The sampling state is set within this scope.
+// TRACE_EVENT_SAMPLING_STATE_SCOPE_FOR_BUCKET(0, "category", "name");
+// ...;
+// }
+#define TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET( \
+ bucket_number, category, name) \
+ skia::tracing_internals::TraceEventSamplingStateScope<bucket_number> \
+ traceEventSamplingScope(category "\0" name);
+
+// Syntactic sugars for the sampling tracing in the main thread.
+#define TRACE_EVENT_SCOPED_SAMPLING_STATE(category, name) \
+ TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(0, category, name)
+#define TRACE_EVENT_GET_SAMPLING_STATE() \
+ TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(0)
+#define TRACE_EVENT_SET_SAMPLING_STATE(category, name) \
+ TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(0, category, name)
+
+
+// Records a single BEGIN event called "name" immediately, with 0, 1 or 2
+// associated arguments. If the category is not enabled, then this
+// does nothing.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+#define TRACE_EVENT_BEGIN0(category_group, name) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+ category_group, name, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_BEGIN1(category_group, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+ category_group, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_BEGIN2(category_group, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+ category_group, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_BEGIN0(category_group, name) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+ category_group, name, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_BEGIN1(category_group, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+ category_group, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_BEGIN2(category_group, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+ category_group, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+
+// Similar to TRACE_EVENT_BEGINx but with a custom |at| timestamp provided.
+// - |id| is used to match the _BEGIN event with the _END event.
+// Events are considered to match if their category_group, name and id values
+// all match. |id| must either be a pointer or an integer value up to 64 bits.
+// If it's a pointer, the bits will be xored with a hash of the process ID so
+// that the same pointer on two different processes will not collide.
+#define TRACE_EVENT_BEGIN_WITH_ID_TID_AND_TIMESTAMP0(category_group, \
+ name, id, thread_id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, thread_id, \
+ timestamp, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP0( \
+ category_group, name, id, thread_id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, thread_id, \
+ timestamp, TRACE_EVENT_FLAG_COPY)
+
+// Records a single END event for "name" immediately. If the category
+// is not enabled, then this does nothing.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+#define TRACE_EVENT_END0(category_group, name) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+ category_group, name, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_END1(category_group, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+ category_group, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_END2(category_group, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+ category_group, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_END0(category_group, name) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+ category_group, name, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_END1(category_group, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+ category_group, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_END2(category_group, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+ category_group, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+
+// Similar to TRACE_EVENT_ENDx but with a custom |at| timestamp provided.
+// - |id| is used to match the _BEGIN event with the _END event.
+// Events are considered to match if their category_group, name and id values
+// all match. |id| must either be a pointer or an integer value up to 64 bits.
+// If it's a pointer, the bits will be xored with a hash of the process ID so
+// that the same pointer on two different processes will not collide.
+#define TRACE_EVENT_END_WITH_ID_TID_AND_TIMESTAMP0(category_group, \
+ name, id, thread_id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, thread_id, \
+ timestamp, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP0( \
+ category_group, name, id, thread_id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, thread_id, \
+ timestamp, TRACE_EVENT_FLAG_COPY)
+
+// Records the value of a counter called "name" immediately. Value
+// must be representable as a 32 bit integer.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+#define TRACE_COUNTER1(category_group, name, value) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
+ category_group, name, TRACE_EVENT_FLAG_NONE, \
+ "value", static_cast<int>(value))
+#define TRACE_COPY_COUNTER1(category_group, name, value) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
+ category_group, name, TRACE_EVENT_FLAG_COPY, \
+ "value", static_cast<int>(value))
+
+// Records the values of a multi-parted counter called "name" immediately.
+// The UI will treat value1 and value2 as parts of a whole, displaying their
+// values as a stacked-bar chart.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+#define TRACE_COUNTER2(category_group, name, value1_name, value1_val, \
+ value2_name, value2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
+ category_group, name, TRACE_EVENT_FLAG_NONE, \
+ value1_name, static_cast<int>(value1_val), \
+ value2_name, static_cast<int>(value2_val))
+#define TRACE_COPY_COUNTER2(category_group, name, value1_name, value1_val, \
+ value2_name, value2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
+ category_group, name, TRACE_EVENT_FLAG_COPY, \
+ value1_name, static_cast<int>(value1_val), \
+ value2_name, static_cast<int>(value2_val))
+
+// Records the value of a counter called "name" immediately. Value
+// must be representable as a 32 bit integer.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+// - |id| is used to disambiguate counters with the same name. It must either
+// be a pointer or an integer value up to 64 bits. If it's a pointer, the bits
+// will be xored with a hash of the process ID so that the same pointer on
+// two different processes will not collide.
+#define TRACE_COUNTER_ID1(category_group, name, id, value) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
+ category_group, name, id, TRACE_EVENT_FLAG_NONE, \
+ "value", static_cast<int>(value))
+#define TRACE_COPY_COUNTER_ID1(category_group, name, id, value) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
+ category_group, name, id, TRACE_EVENT_FLAG_COPY, \
+ "value", static_cast<int>(value))
+
+// Records the values of a multi-parted counter called "name" immediately.
+// The UI will treat value1 and value2 as parts of a whole, displaying their
+// values as a stacked-bar chart.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+// - |id| is used to disambiguate counters with the same name. It must either
+// be a pointer or an integer value up to 64 bits. If it's a pointer, the bits
+// will be xored with a hash of the process ID so that the same pointer on
+// two different processes will not collide.
+#define TRACE_COUNTER_ID2(category_group, name, id, value1_name, value1_val, \
+ value2_name, value2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
+ category_group, name, id, TRACE_EVENT_FLAG_NONE, \
+ value1_name, static_cast<int>(value1_val), \
+ value2_name, static_cast<int>(value2_val))
+#define TRACE_COPY_COUNTER_ID2(category_group, name, id, value1_name, \
+ value1_val, value2_name, value2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
+ category_group, name, id, TRACE_EVENT_FLAG_COPY, \
+ value1_name, static_cast<int>(value1_val), \
+ value2_name, static_cast<int>(value2_val))
+
+
+// Records a single ASYNC_BEGIN event called "name" immediately, with 0, 1 or 2
+// associated arguments. If the category is not enabled, then this
+// does nothing.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+// - |id| is used to match the ASYNC_BEGIN event with the ASYNC_END event. ASYNC
+// events are considered to match if their category_group, name and id values
+// all match. |id| must either be a pointer or an integer value up to 64 bits.
+// If it's a pointer, the bits will be xored with a hash of the process ID so
+// that the same pointer on two different processes will not collide.
+//
+// An asynchronous operation can consist of multiple phases. The first phase is
+// defined by the ASYNC_BEGIN calls. Additional phases can be defined using the
+// ASYNC_STEP_INTO or ASYNC_STEP_PAST macros. The ASYNC_STEP_INTO macro will
+// annotate the block following the call. The ASYNC_STEP_PAST macro will
+// annotate the block prior to the call. Note that any particular event must use
+// only STEP_INTO or STEP_PAST macros; they can not mix and match. When the
+// operation completes, call ASYNC_END.
+//
+// An ASYNC trace typically occurs on a single thread (if not, they will only be
+// drawn on the thread defined in the ASYNC_BEGIN event), but all events in that
+// operation must use the same |name| and |id|. Each step can have its own
+// args.
+#define TRACE_EVENT_ASYNC_BEGIN0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+ category_group, name, id, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_ASYNC_BEGIN1(category_group, name, id, arg1_name, \
+ arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+ category_group, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_ASYNC_BEGIN2(category_group, name, id, arg1_name, \
+ arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+ category_group, name, id, TRACE_EVENT_FLAG_NONE, \
+ arg1_name, arg1_val, arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_ASYNC_BEGIN0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+ category_group, name, id, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_ASYNC_BEGIN1(category_group, name, id, arg1_name, \
+ arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+ category_group, name, id, TRACE_EVENT_FLAG_COPY, \
+ arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_ASYNC_BEGIN2(category_group, name, id, arg1_name, \
+ arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+ category_group, name, id, TRACE_EVENT_FLAG_COPY, \
+ arg1_name, arg1_val, arg2_name, arg2_val)
+
+// Records a single ASYNC_STEP_INTO event for |step| immediately. If the
+// category is not enabled, then this does nothing. The |name| and |id| must
+// match the ASYNC_BEGIN event above. The |step| param identifies this step
+// within the async event. This should be called at the beginning of the next
+// phase of an asynchronous operation. The ASYNC_BEGIN event must not have any
+// ASYNC_STEP_PAST events.
+#define TRACE_EVENT_ASYNC_STEP_INTO0(category_group, name, id, step) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_INTO, \
+ category_group, name, id, TRACE_EVENT_FLAG_NONE, "step", step)
+#define TRACE_EVENT_ASYNC_STEP_INTO1(category_group, name, id, step, \
+ arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_INTO, \
+ category_group, name, id, TRACE_EVENT_FLAG_NONE, "step", step, \
+ arg1_name, arg1_val)
+
+// Records a single ASYNC_STEP_PAST event for |step| immediately. If the
+// category is not enabled, then this does nothing. The |name| and |id| must
+// match the ASYNC_BEGIN event above. The |step| param identifies this step
+// within the async event. This should be called at the beginning of the next
+// phase of an asynchronous operation. The ASYNC_BEGIN event must not have any
+// ASYNC_STEP_INTO events.
+#define TRACE_EVENT_ASYNC_STEP_PAST0(category_group, name, id, step) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_PAST, \
+ category_group, name, id, TRACE_EVENT_FLAG_NONE, "step", step)
+#define TRACE_EVENT_ASYNC_STEP_PAST1(category_group, name, id, step, \
+ arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_PAST, \
+ category_group, name, id, TRACE_EVENT_FLAG_NONE, "step", step, \
+ arg1_name, arg1_val)
+
+// Records a single ASYNC_END event for "name" immediately. If the category
+// is not enabled, then this does nothing.
+#define TRACE_EVENT_ASYNC_END0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+ category_group, name, id, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_ASYNC_END1(category_group, name, id, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+ category_group, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_ASYNC_END2(category_group, name, id, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+ category_group, name, id, TRACE_EVENT_FLAG_NONE, \
+ arg1_name, arg1_val, arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_ASYNC_END0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+ category_group, name, id, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_ASYNC_END1(category_group, name, id, arg1_name, \
+ arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+ category_group, name, id, TRACE_EVENT_FLAG_COPY, \
+ arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_ASYNC_END2(category_group, name, id, arg1_name, \
+ arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+ category_group, name, id, TRACE_EVENT_FLAG_COPY, \
+ arg1_name, arg1_val, arg2_name, arg2_val)
+
+
+// Records a single FLOW_BEGIN event called "name" immediately, with 0, 1 or 2
+// associated arguments. If the category is not enabled, then this
+// does nothing.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+// - |id| is used to match the FLOW_BEGIN event with the FLOW_END event. FLOW
+// events are considered to match if their category_group, name and id values
+// all match. |id| must either be a pointer or an integer value up to 64 bits.
+// If it's a pointer, the bits will be xored with a hash of the process ID so
+// that the same pointer on two different processes will not collide.
+// FLOW events are different from ASYNC events in how they are drawn by the
+// tracing UI. A FLOW defines asynchronous data flow, such as posting a task
+// (FLOW_BEGIN) and later executing that task (FLOW_END). Expect FLOWs to be
+// drawn as lines or arrows from FLOW_BEGIN scopes to FLOW_END scopes. Similar
+// to ASYNC, a FLOW can consist of multiple phases. The first phase is defined
+// by the FLOW_BEGIN calls. Additional phases can be defined using the FLOW_STEP
+// macros. When the operation completes, call FLOW_END. An async operation can
+// span threads and processes, but all events in that operation must use the
+// same |name| and |id|. Each event can have its own args.
+#define TRACE_EVENT_FLOW_BEGIN0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \
+ category_group, name, id, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_FLOW_BEGIN1(category_group, name, id, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \
+ category_group, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_FLOW_BEGIN2(category_group, name, id, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \
+ category_group, name, id, TRACE_EVENT_FLAG_NONE, \
+ arg1_name, arg1_val, arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_FLOW_BEGIN0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \
+ category_group, name, id, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_FLOW_BEGIN1(category_group, name, id, arg1_name, \
+ arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \
+ category_group, name, id, TRACE_EVENT_FLAG_COPY, \
+ arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_FLOW_BEGIN2(category_group, name, id, arg1_name, \
+ arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \
+ category_group, name, id, TRACE_EVENT_FLAG_COPY, \
+ arg1_name, arg1_val, arg2_name, arg2_val)
+
+// Records a single FLOW_STEP event for |step| immediately. If the category
+// is not enabled, then this does nothing. The |name| and |id| must match the
+// FLOW_BEGIN event above. The |step| param identifies this step within the
+// async event. This should be called at the beginning of the next phase of an
+// asynchronous operation.
+#define TRACE_EVENT_FLOW_STEP0(category_group, name, id, step) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_STEP, \
+ category_group, name, id, TRACE_EVENT_FLAG_NONE, "step", step)
+#define TRACE_EVENT_FLOW_STEP1(category_group, name, id, step, \
+ arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_STEP, \
+ category_group, name, id, TRACE_EVENT_FLAG_NONE, "step", step, \
+ arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_FLOW_STEP0(category_group, name, id, step) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_STEP, \
+ category_group, name, id, TRACE_EVENT_FLAG_COPY, "step", step)
+#define TRACE_EVENT_COPY_FLOW_STEP1(category_group, name, id, step, \
+ arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_STEP, \
+ category_group, name, id, TRACE_EVENT_FLAG_COPY, "step", step, \
+ arg1_name, arg1_val)
+
+// Records a single FLOW_END event for "name" immediately. If the category
+// is not enabled, then this does nothing.
+#define TRACE_EVENT_FLOW_END0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, \
+ category_group, name, id, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_FLOW_END1(category_group, name, id, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, \
+ category_group, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_FLOW_END2(category_group, name, id, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, \
+ category_group, name, id, TRACE_EVENT_FLAG_NONE, \
+ arg1_name, arg1_val, arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_FLOW_END0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, \
+ category_group, name, id, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_FLOW_END1(category_group, name, id, arg1_name, \
+ arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, \
+ category_group, name, id, TRACE_EVENT_FLAG_COPY, \
+ arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_FLOW_END2(category_group, name, id, arg1_name, \
+ arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, \
+ category_group, name, id, TRACE_EVENT_FLAG_COPY, \
+ arg1_name, arg1_val, arg2_name, arg2_val)
+
+// Macros to track the life time and value of arbitrary client objects.
+// See also TraceTrackableObject.
+#define TRACE_EVENT_OBJECT_CREATED_WITH_ID(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_CREATE_OBJECT, \
+ category_group, name, TRACE_ID_DONT_MANGLE(id), TRACE_EVENT_FLAG_NONE)
+
+#define TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(category_group, name, id, snapshot) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_SNAPSHOT_OBJECT, \
+ category_group, name, TRACE_ID_DONT_MANGLE(id), TRACE_EVENT_FLAG_NONE,\
+ "snapshot", snapshot)
+
+#define TRACE_EVENT_OBJECT_DELETED_WITH_ID(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_DELETE_OBJECT, \
+ category_group, name, TRACE_ID_DONT_MANGLE(id), TRACE_EVENT_FLAG_NONE)
+
+#define INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE() \
+ *INTERNAL_TRACE_EVENT_UID(category_group_enabled) & \
+ (SkEventTracer::kEnabledForRecording_CategoryGroupEnabledFlags | \
+ SkEventTracer::kEnabledForEventCallback_CategoryGroupEnabledFlags)
+
+// Macro to efficiently determine if a given category group is enabled.
+#define TRACE_EVENT_CATEGORY_GROUP_ENABLED(category_group, ret) \
+ do { \
+ INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
+ if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
+ *ret = true; \
+ } else { \
+ *ret = false; \
+ } \
+ } while (0)
+
+// Macro to efficiently determine, through polling, if a new trace has begun.
+#define TRACE_EVENT_IS_NEW_TRACE(ret) \
+ do { \
+ static int INTERNAL_TRACE_EVENT_UID(lastRecordingNumber) = 0; \
+ int num_traces_recorded = TRACE_EVENT_API_GET_NUM_TRACES_RECORDED(); \
+ if (num_traces_recorded != -1 && \
+ num_traces_recorded != \
+ INTERNAL_TRACE_EVENT_UID(lastRecordingNumber)) { \
+ INTERNAL_TRACE_EVENT_UID(lastRecordingNumber) = \
+ num_traces_recorded; \
+ *ret = true; \
+ } else { \
+ *ret = false; \
+ } \
+ } while (0)
+
+////////////////////////////////////////////////////////////////////////////////
+// Implementation specific tracing API definitions.
+
+// Get a pointer to the enabled state of the given trace category. Only
+// long-lived literal strings should be given as the category group. The
+// returned pointer can be held permanently in a local static for example. If
+// the unsigned char is non-zero, tracing is enabled. If tracing is enabled,
+// TRACE_EVENT_API_ADD_TRACE_EVENT can be called. It's OK if tracing is disabled
+// between the load of the tracing state and the call to
+// TRACE_EVENT_API_ADD_TRACE_EVENT, because this flag only provides an early out
+// for best performance when tracing is disabled.
+// const uint8_t*
+// TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(const char* category_group)
+#define TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED \
+ SkEventTracer::GetInstance()->getCategoryGroupEnabled
+
+// Get the number of times traces have been recorded. This is used to implement
+// the TRACE_EVENT_IS_NEW_TRACE facility.
+// unsigned int TRACE_EVENT_API_GET_NUM_TRACES_RECORDED()
+#define TRACE_EVENT_API_GET_NUM_TRACES_RECORDED \
+ SkEventTracer::GetInstance()->getNumTracesRecorded
+
+// Add a trace event to the platform tracing system.
+// SkEventTracer::Handle TRACE_EVENT_API_ADD_TRACE_EVENT(
+// char phase,
+// const uint8_t* category_group_enabled,
+// const char* name,
+// uint64_t id,
+// int num_args,
+// const char** arg_names,
+// const uint8_t* arg_types,
+// const uint64_t* arg_values,
+// unsigned char flags)
+#define TRACE_EVENT_API_ADD_TRACE_EVENT \
+ SkEventTracer::GetInstance()->addTraceEvent
+
+// Set the duration field of a COMPLETE trace event.
+// void TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(
+// const uint8_t* category_group_enabled,
+// const char* name,
+// SkEventTracer::Handle id)
+#define TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION \
+ SkEventTracer::GetInstance()->updateTraceEventDuration
+
+// These operations are atomic in the Chrome tracing implementation
+// to cater to ARM's weak memory consistency; we're just doing read/
+// write here because it's not strictly needed for correctness.
+// So says Nat.
+// FIXME
+
+#define TRACE_EVENT_API_ATOMIC_WORD intptr_t
+#define TRACE_EVENT_API_ATOMIC_LOAD(var) (*(&var))
+#define TRACE_EVENT_API_ATOMIC_STORE(var, value) (var=value)
+
+// Defines visibility for classes in trace_event.h
+#define TRACE_EVENT_API_CLASS_EXPORT SK_API
+
+// The thread buckets for the sampling profiler.
+TRACE_EVENT_API_CLASS_EXPORT extern \
+ TRACE_EVENT_API_ATOMIC_WORD g_trace_state[3];
+
+#define TRACE_EVENT_API_THREAD_BUCKET(thread_bucket) \
+ g_trace_state[thread_bucket]
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Implementation detail: trace event macros create temporary variables
+// to keep instrumentation overhead low. These macros give each temporary
+// variable a unique name based on the line number to prevent name collisions.
+#define INTERNAL_TRACE_EVENT_UID3(a,b) \
+ trace_event_unique_##a##b
+#define INTERNAL_TRACE_EVENT_UID2(a,b) \
+ INTERNAL_TRACE_EVENT_UID3(a,b)
+#define INTERNAL_TRACE_EVENT_UID(name_prefix) \
+ INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__)
+
+// Implementation detail: internal macro to create static category.
+// No barriers are needed, because this code is designed to operate safely
+// even when the unsigned char* points to garbage data (which may be the case
+// on processors without cache coherency).
+#define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES( \
+ category_group, atomic, category_group_enabled) \
+ category_group_enabled = \
+ reinterpret_cast<const uint8_t*>(TRACE_EVENT_API_ATOMIC_LOAD( \
+ atomic)); \
+ if (!category_group_enabled) { \
+ category_group_enabled = \
+ TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_group); \
+ TRACE_EVENT_API_ATOMIC_STORE(atomic, \
+ reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>( \
+ category_group_enabled)); \
+ }
+
+#define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group) \
+ static TRACE_EVENT_API_ATOMIC_WORD INTERNAL_TRACE_EVENT_UID(atomic) = 0; \
+ const uint8_t* INTERNAL_TRACE_EVENT_UID(category_group_enabled); \
+ INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES(category_group, \
+ INTERNAL_TRACE_EVENT_UID(atomic), \
+ INTERNAL_TRACE_EVENT_UID(category_group_enabled));
+
+// Implementation detail: internal macro to create static category and add
+// event if the category is enabled.
+#define INTERNAL_TRACE_EVENT_ADD(phase, category_group, name, flags, ...) \
+ do { \
+ INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
+ if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
+ skia::tracing_internals::AddTraceEvent( \
+ phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
+ skia::tracing_internals::kNoEventId, flags, ##__VA_ARGS__); \
+ } \
+ } while (0)
+
+// Implementation detail: internal macro to create static category and add begin
+// event if the category is enabled. Also adds the end event when the scope
+// ends.
+#define INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, ...) \
+ INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
+ skia::tracing_internals::ScopedTracer INTERNAL_TRACE_EVENT_UID(tracer); \
+ if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
+ SkEventTracer::Handle h = skia::tracing_internals::AddTraceEvent( \
+ TRACE_EVENT_PHASE_COMPLETE, \
+ INTERNAL_TRACE_EVENT_UID(category_group_enabled), \
+ name, skia::tracing_internals::kNoEventId, \
+ TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__); \
+ INTERNAL_TRACE_EVENT_UID(tracer).Initialize( \
+ INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, h); \
+ }
+
+// Implementation detail: internal macro to create static category and add
+// event if the category is enabled.
+#define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category_group, name, id, \
+ flags, ...) \
+ do { \
+ INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
+ if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
+ unsigned char trace_event_flags = flags | TRACE_EVENT_FLAG_HAS_ID; \
+ skia::tracing_internals::TraceID trace_event_trace_id( \
+ id, &trace_event_flags); \
+ skia::tracing_internals::AddTraceEvent( \
+ phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), \
+ name, trace_event_trace_id.data(), trace_event_flags, \
+ ##__VA_ARGS__); \
+ } \
+ } while (0)
+
+// Implementation detail: internal macro to create static category and add
+// event if the category is enabled.
+#define INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP(phase, \
+ category_group, name, id, thread_id, flags, ...) \
+ do { \
+ INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
+ if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
+ unsigned char trace_event_flags = flags | TRACE_EVENT_FLAG_HAS_ID; \
+ skia::tracing_internals::TraceID trace_event_trace_id( \
+ id, &trace_event_flags); \
+ skia::tracing_internals::AddTraceEventWithThreadIdAndTimestamp( \
+ phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), \
+ name, trace_event_trace_id.data(), \
+ thread_id, base::TimeTicks::FromInternalValue(timestamp), \
+ trace_event_flags, ##__VA_ARGS__); \
+ } \
+ } while (0)
+
+// Notes regarding the following definitions:
+// New values can be added and propagated to third party libraries, but existing
+// definitions must never be changed, because third party libraries may use old
+// definitions.
+
+// Phase indicates the nature of an event entry. E.g. part of a begin/end pair.
+#define TRACE_EVENT_PHASE_BEGIN ('B')
+#define TRACE_EVENT_PHASE_END ('E')
+#define TRACE_EVENT_PHASE_COMPLETE ('X')
+#define TRACE_EVENT_PHASE_INSTANT ('i')
+#define TRACE_EVENT_PHASE_ASYNC_BEGIN ('S')
+#define TRACE_EVENT_PHASE_ASYNC_STEP_INTO ('T')
+#define TRACE_EVENT_PHASE_ASYNC_STEP_PAST ('p')
+#define TRACE_EVENT_PHASE_ASYNC_END ('F')
+#define TRACE_EVENT_PHASE_FLOW_BEGIN ('s')
+#define TRACE_EVENT_PHASE_FLOW_STEP ('t')
+#define TRACE_EVENT_PHASE_FLOW_END ('f')
+#define TRACE_EVENT_PHASE_METADATA ('M')
+#define TRACE_EVENT_PHASE_COUNTER ('C')
+#define TRACE_EVENT_PHASE_SAMPLE ('P')
+#define TRACE_EVENT_PHASE_CREATE_OBJECT ('N')
+#define TRACE_EVENT_PHASE_SNAPSHOT_OBJECT ('O')
+#define TRACE_EVENT_PHASE_DELETE_OBJECT ('D')
+
+// Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT.
+#define TRACE_EVENT_FLAG_NONE (static_cast<unsigned char>(0))
+#define TRACE_EVENT_FLAG_COPY (static_cast<unsigned char>(1 << 0))
+#define TRACE_EVENT_FLAG_HAS_ID (static_cast<unsigned char>(1 << 1))
+#define TRACE_EVENT_FLAG_MANGLE_ID (static_cast<unsigned char>(1 << 2))
+#define TRACE_EVENT_FLAG_SCOPE_OFFSET (static_cast<unsigned char>(1 << 3))
+
+#define TRACE_EVENT_FLAG_SCOPE_MASK (static_cast<unsigned char>( \
+ TRACE_EVENT_FLAG_SCOPE_OFFSET | (TRACE_EVENT_FLAG_SCOPE_OFFSET << 1)))
+
+// Type values for identifying types in the TraceValue union.
+#define TRACE_VALUE_TYPE_BOOL (static_cast<unsigned char>(1))
+#define TRACE_VALUE_TYPE_UINT (static_cast<unsigned char>(2))
+#define TRACE_VALUE_TYPE_INT (static_cast<unsigned char>(3))
+#define TRACE_VALUE_TYPE_DOUBLE (static_cast<unsigned char>(4))
+#define TRACE_VALUE_TYPE_POINTER (static_cast<unsigned char>(5))
+#define TRACE_VALUE_TYPE_STRING (static_cast<unsigned char>(6))
+#define TRACE_VALUE_TYPE_COPY_STRING (static_cast<unsigned char>(7))
+#define TRACE_VALUE_TYPE_CONVERTABLE (static_cast<unsigned char>(8))
+
+// Enum reflecting the scope of an INSTANT event. Must fit within
+// TRACE_EVENT_FLAG_SCOPE_MASK.
+#define TRACE_EVENT_SCOPE_GLOBAL (static_cast<unsigned char>(0 << 3))
+#define TRACE_EVENT_SCOPE_PROCESS (static_cast<unsigned char>(1 << 3))
+#define TRACE_EVENT_SCOPE_THREAD (static_cast<unsigned char>(2 << 3))
+
+#define TRACE_EVENT_SCOPE_NAME_GLOBAL ('g')
+#define TRACE_EVENT_SCOPE_NAME_PROCESS ('p')
+#define TRACE_EVENT_SCOPE_NAME_THREAD ('t')
+
+namespace skia {
+namespace tracing_internals {
+
+// Specify these values when the corresponding argument of AddTraceEvent is not
+// used.
+const int kZeroNumArgs = 0;
+const uint64_t kNoEventId = 0;
+
+// TraceID encapsulates an ID that can either be an integer or pointer. Pointers
+// are by default mangled with the Process ID so that they are unlikely to
+// collide when the same pointer is used on different processes.
+class TraceID {
+ public:
+ class DontMangle {
+ public:
+ explicit DontMangle(const void* id)
+ : data_(static_cast<uint64_t>(
+ reinterpret_cast<unsigned long>(id))) {}
+ explicit DontMangle(uint64_t id) : data_(id) {}
+ explicit DontMangle(unsigned int id) : data_(id) {}
+ explicit DontMangle(unsigned short id) : data_(id) {}
+ explicit DontMangle(unsigned char id) : data_(id) {}
+ explicit DontMangle(long long id)
+ : data_(static_cast<uint64_t>(id)) {}
+ explicit DontMangle(long id)
+ : data_(static_cast<uint64_t>(id)) {}
+ explicit DontMangle(int id)
+ : data_(static_cast<uint64_t>(id)) {}
+ explicit DontMangle(short id)
+ : data_(static_cast<uint64_t>(id)) {}
+ explicit DontMangle(signed char id)
+ : data_(static_cast<uint64_t>(id)) {}
+ uint64_t data() const { return data_; }
+ private:
+ uint64_t data_;
+ };
+
+ class ForceMangle {
+ public:
+ explicit ForceMangle(uint64_t id) : data_(id) {}
+ explicit ForceMangle(unsigned int id) : data_(id) {}
+ explicit ForceMangle(unsigned short id) : data_(id) {}
+ explicit ForceMangle(unsigned char id) : data_(id) {}
+ explicit ForceMangle(long long id)
+ : data_(static_cast<uint64_t>(id)) {}
+ explicit ForceMangle(long id)
+ : data_(static_cast<uint64_t>(id)) {}
+ explicit ForceMangle(int id)
+ : data_(static_cast<uint64_t>(id)) {}
+ explicit ForceMangle(short id)
+ : data_(static_cast<uint64_t>(id)) {}
+ explicit ForceMangle(signed char id)
+ : data_(static_cast<uint64_t>(id)) {}
+ uint64_t data() const { return data_; }
+ private:
+ uint64_t data_;
+ };
+
+ TraceID(const void* id, unsigned char* flags)
+ : data_(static_cast<uint64_t>(
+ reinterpret_cast<unsigned long>(id))) {
+ *flags |= TRACE_EVENT_FLAG_MANGLE_ID;
+ }
+ TraceID(ForceMangle id, unsigned char* flags) : data_(id.data()) {
+ *flags |= TRACE_EVENT_FLAG_MANGLE_ID;
+ }
+ TraceID(DontMangle id, unsigned char* flags) : data_(id.data()) {
+ }
+ TraceID(uint64_t id, unsigned char* flags)
+ : data_(id) { (void)flags; }
+ TraceID(unsigned int id, unsigned char* flags)
+ : data_(id) { (void)flags; }
+ TraceID(unsigned short id, unsigned char* flags)
+ : data_(id) { (void)flags; }
+ TraceID(unsigned char id, unsigned char* flags)
+ : data_(id) { (void)flags; }
+ TraceID(long long id, unsigned char* flags)
+ : data_(static_cast<uint64_t>(id)) { (void)flags; }
+ TraceID(long id, unsigned char* flags)
+ : data_(static_cast<uint64_t>(id)) { (void)flags; }
+ TraceID(int id, unsigned char* flags)
+ : data_(static_cast<uint64_t>(id)) { (void)flags; }
+ TraceID(short id, unsigned char* flags)
+ : data_(static_cast<uint64_t>(id)) { (void)flags; }
+ TraceID(signed char id, unsigned char* flags)
+ : data_(static_cast<uint64_t>(id)) { (void)flags; }
+
+ uint64_t data() const { return data_; }
+
+ private:
+ uint64_t data_;
+};
+
+// Simple union to store various types as uint64_t.
+union TraceValueUnion {
+ bool as_bool;
+ uint64_t as_uint;
+ long long as_int;
+ double as_double;
+ const void* as_pointer;
+ const char* as_string;
+};
+
+// Simple container for const char* that should be copied instead of retained.
+class TraceStringWithCopy {
+ public:
+ explicit TraceStringWithCopy(const char* str) : str_(str) {}
+ operator const char* () const { return str_; }
+ private:
+ const char* str_;
+};
+
+// Define SetTraceValue for each allowed type. It stores the type and
+// value in the return arguments. This allows this API to avoid declaring any
+// structures so that it is portable to third_party libraries.
+#define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, \
+ union_member, \
+ value_type_id) \
+ static inline void SetTraceValue( \
+ actual_type arg, \
+ unsigned char* type, \
+ uint64_t* value) { \
+ TraceValueUnion type_value; \
+ type_value.union_member = arg; \
+ *type = value_type_id; \
+ *value = type_value.as_uint; \
+ }
+// Simpler form for int types that can be safely casted.
+#define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, \
+ value_type_id) \
+ static inline void SetTraceValue( \
+ actual_type arg, \
+ unsigned char* type, \
+ uint64_t* value) { \
+ *type = value_type_id; \
+ *value = static_cast<uint64_t>(arg); \
+ }
+
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(uint64_t, TRACE_VALUE_TYPE_UINT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned int, TRACE_VALUE_TYPE_UINT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned short, TRACE_VALUE_TYPE_UINT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long long, TRACE_VALUE_TYPE_INT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long, TRACE_VALUE_TYPE_INT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(short, TRACE_VALUE_TYPE_INT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT)
+INTERNAL_DECLARE_SET_TRACE_VALUE(bool, as_bool, TRACE_VALUE_TYPE_BOOL)
+INTERNAL_DECLARE_SET_TRACE_VALUE(double, as_double, TRACE_VALUE_TYPE_DOUBLE)
+INTERNAL_DECLARE_SET_TRACE_VALUE(const void*, as_pointer,
+ TRACE_VALUE_TYPE_POINTER)
+INTERNAL_DECLARE_SET_TRACE_VALUE(const char*, as_string,
+ TRACE_VALUE_TYPE_STRING)
+INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy&, as_string,
+ TRACE_VALUE_TYPE_COPY_STRING)
+
+#undef INTERNAL_DECLARE_SET_TRACE_VALUE
+#undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT
+
+// These AddTraceEvent and AddTraceEvent template
+// functions are defined here instead of in the macro, because the arg_values
+// could be temporary objects, such as std::string. In order to store
+// pointers to the internal c_str and pass through to the tracing API,
+// the arg_values must live throughout these procedures.
+
+static inline SkEventTracer::Handle
+AddTraceEvent(
+ char phase,
+ const uint8_t* category_group_enabled,
+ const char* name,
+ uint64_t id,
+ unsigned char flags) {
+ return TRACE_EVENT_API_ADD_TRACE_EVENT(
+ phase, category_group_enabled, name, id,
+ kZeroNumArgs, NULL, NULL, NULL, flags);
+}
+
+template<class ARG1_TYPE>
+static inline SkEventTracer::Handle
+AddTraceEvent(
+ char phase,
+ const uint8_t* category_group_enabled,
+ const char* name,
+ uint64_t id,
+ unsigned char flags,
+ const char* arg1_name,
+ const ARG1_TYPE& arg1_val) {
+ const int num_args = 1;
+ uint8_t arg_types[1];
+ uint64_t arg_values[1];
+ SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]);
+ return TRACE_EVENT_API_ADD_TRACE_EVENT(
+ phase, category_group_enabled, name, id,
+ num_args, &arg1_name, arg_types, arg_values, flags);
+}
+
+template<class ARG1_TYPE, class ARG2_TYPE>
+static inline SkEventTracer::Handle
+AddTraceEvent(
+ char phase,
+ const uint8_t* category_group_enabled,
+ const char* name,
+ uint64_t id,
+ unsigned char flags,
+ const char* arg1_name,
+ const ARG1_TYPE& arg1_val,
+ const char* arg2_name,
+ const ARG2_TYPE& arg2_val) {
+ const int num_args = 2;
+ const char* arg_names[2] = { arg1_name, arg2_name };
+ unsigned char arg_types[2];
+ uint64_t arg_values[2];
+ SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]);
+ SetTraceValue(arg2_val, &arg_types[1], &arg_values[1]);
+ return TRACE_EVENT_API_ADD_TRACE_EVENT(
+ phase, category_group_enabled, name, id,
+ num_args, arg_names, arg_types, arg_values, flags);
+}
+
+// Used by TRACE_EVENTx macros. Do not use directly.
+class TRACE_EVENT_API_CLASS_EXPORT ScopedTracer {
+ public:
+ // Note: members of data_ intentionally left uninitialized. See Initialize.
+ ScopedTracer() : p_data_(NULL) {}
+
+ ~ScopedTracer() {
+ if (p_data_ && *data_.category_group_enabled)
+ TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(
+ data_.category_group_enabled, data_.name, data_.event_handle);
+ }
+
+ void Initialize(const uint8_t* category_group_enabled,
+ const char* name,
+ SkEventTracer::Handle event_handle) {
+ data_.category_group_enabled = category_group_enabled;
+ data_.name = name;
+ data_.event_handle = event_handle;
+ p_data_ = &data_;
+ }
+
+ private:
+ // This Data struct workaround is to avoid initializing all the members
+ // in Data during construction of this object, since this object is always
+ // constructed, even when tracing is disabled. If the members of Data were
+ // members of this class instead, compiler warnings occur about potential
+ // uninitialized accesses.
+ struct Data {
+ const uint8_t* category_group_enabled;
+ const char* name;
+ SkEventTracer::Handle event_handle;
+ };
+ Data* p_data_;
+ Data data_;
+};
+
+// Used by TRACE_EVENT_BINARY_EFFICIENTx macro. Do not use directly.
+class TRACE_EVENT_API_CLASS_EXPORT ScopedTraceBinaryEfficient {
+ public:
+ ScopedTraceBinaryEfficient(const char* category_group, const char* name);
+ ~ScopedTraceBinaryEfficient();
+
+ private:
+ const uint8_t* category_group_enabled_;
+ const char* name_;
+ SkEventTracer::Handle event_handle_;
+};
+
+// This macro generates less code then TRACE_EVENT0 but is also
+// slower to execute when tracing is off. It should generally only be
+// used with code that is seldom executed or conditionally executed
+// when debugging.
+// For now the category_group must be "gpu".
+#define TRACE_EVENT_BINARY_EFFICIENT0(category_group, name) \
+ skia::tracing_internals::ScopedTraceBinaryEfficient \
+ INTERNAL_TRACE_EVENT_UID(scoped_trace)(category_group, name);
+
+// TraceEventSamplingStateScope records the current sampling state
+// and sets a new sampling state. When the scope exists, it restores
+// the sampling state having recorded.
+template<size_t BucketNumber>
+class TraceEventSamplingStateScope {
+ public:
+ TraceEventSamplingStateScope(const char* category_and_name) {
+ previous_state_ = TraceEventSamplingStateScope<BucketNumber>::Current();
+ TraceEventSamplingStateScope<BucketNumber>::Set(category_and_name);
+ }
+
+ ~TraceEventSamplingStateScope() {
+ TraceEventSamplingStateScope<BucketNumber>::Set(previous_state_);
+ }
+
+ static inline const char* Current() {
+ return reinterpret_cast<const char*>(TRACE_EVENT_API_ATOMIC_LOAD(
+ g_trace_state[BucketNumber]));
+ }
+
+ static inline void Set(const char* category_and_name) {
+ TRACE_EVENT_API_ATOMIC_STORE(
+ g_trace_state[BucketNumber],
+ reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>(
+ const_cast<char*>(category_and_name)));
+ }
+
+ private:
+ const char* previous_state_;
+};
+
+} // namespace tracing_internals
+} // namespace skia
+
+#endif
diff --git a/chromium/third_party/skia/src/core/SkTypeface.cpp b/chromium/third_party/skia/src/core/SkTypeface.cpp
index 09a64324af2..48be651fd6a 100644
--- a/chromium/third_party/skia/src/core/SkTypeface.cpp
+++ b/chromium/third_party/skia/src/core/SkTypeface.cpp
@@ -6,8 +6,11 @@
*/
#include "SkAdvancedTypefaceMetrics.h"
+#include "SkEndian.h"
#include "SkFontDescriptor.h"
#include "SkFontHost.h"
+#include "SkLazyPtr.h"
+#include "SkOTTable_OS_2.h"
#include "SkStream.h"
#include "SkTypeface.h"
@@ -36,8 +39,12 @@ SkTypeface::~SkTypeface() {
class SkEmptyTypeface : public SkTypeface {
public:
- SkEmptyTypeface() : SkTypeface(SkTypeface::kNormal, 0, true) { }
+ static SkEmptyTypeface* Create() {
+ return SkNEW(SkEmptyTypeface);
+ }
protected:
+ SkEmptyTypeface() : SkTypeface(SkTypeface::kNormal, 0, true) { }
+
virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { return NULL; }
virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK_OVERRIDE {
return NULL;
@@ -69,25 +76,30 @@ protected:
}
};
+SkTypeface* SkTypeface::CreateDefault(int style) {
+ // If backed by fontconfig, it's not safe to call SkFontHost::CreateTypeface concurrently.
+ // To be safe, we serialize here with a mutex so only one call to
+ // CreateTypeface is happening at any given time.
+ // TODO(bungeman, mtklein): This is sad. Make our fontconfig code safe?
+ SK_DECLARE_STATIC_MUTEX(mutex);
+ SkAutoMutexAcquire lock(&mutex);
+
+ SkTypeface* t = SkFontHost::CreateTypeface(NULL, NULL, (Style)style);
+ return t ? t : SkEmptyTypeface::Create();
+}
+
+void SkTypeface::DeleteDefault(SkTypeface* t) {
+ // The SkTypeface returned by SkFontHost::CreateTypeface may _itself_ be a
+ // cleverly-shared singleton. This is less than ideal. This means we
+ // cannot just assert our ownership and SkDELETE(t) like we'd want to.
+ SkSafeUnref(t);
+}
+
SkTypeface* SkTypeface::GetDefaultTypeface(Style style) {
- // we keep a reference to this guy for all time, since if we return its
- // fontID, the font cache may later on ask to resolve that back into a
- // typeface object.
- static const uint32_t FONT_STYLE_COUNT = 4;
- static SkTypeface* gDefaultTypefaces[FONT_STYLE_COUNT];
- SkASSERT((unsigned)style < FONT_STYLE_COUNT);
-
- // mask off any other bits to avoid a crash in SK_RELEASE
- style = (Style)(style & 0x03);
-
- if (NULL == gDefaultTypefaces[style]) {
- gDefaultTypefaces[style] = SkFontHost::CreateTypeface(NULL, NULL, style);
- }
- if (NULL == gDefaultTypefaces[style]) {
- gDefaultTypefaces[style] = SkNEW(SkEmptyTypeface);
- }
+ SK_DECLARE_STATIC_LAZY_PTR_ARRAY(SkTypeface, defaults, 4, CreateDefault, DeleteDefault);
- return gDefaultTypefaces[style];
+ SkASSERT((int)style < 4);
+ return defaults[style];
}
SkTypeface* SkTypeface::RefDefault(Style style) {
@@ -259,7 +271,28 @@ SkAdvancedTypefaceMetrics* SkTypeface::getAdvancedTypefaceMetrics(
SkAdvancedTypefaceMetrics::PerGlyphInfo info,
const uint32_t* glyphIDs,
uint32_t glyphIDsCount) const {
- return this->onGetAdvancedTypefaceMetrics(info, glyphIDs, glyphIDsCount);
+ SkAdvancedTypefaceMetrics* result =
+ this->onGetAdvancedTypefaceMetrics(info, glyphIDs, glyphIDsCount);
+ if (result && result->fType == SkAdvancedTypefaceMetrics::kTrueType_Font) {
+ struct SkOTTableOS2 os2table;
+ if (this->getTableData(SkTEndian_SwapBE32(SkOTTableOS2::TAG), 0,
+ sizeof(os2table), &os2table) > 0) {
+ if (os2table.version.v2.fsType.field.Bitmap ||
+ (os2table.version.v2.fsType.field.Restricted &&
+ !(os2table.version.v2.fsType.field.PreviewPrint ||
+ os2table.version.v2.fsType.field.Editable))) {
+ result->fFlags = SkTBitOr<SkAdvancedTypefaceMetrics::FontFlags>(
+ result->fFlags,
+ SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag);
+ }
+ if (os2table.version.v2.fsType.field.NoSubsetting) {
+ result->fFlags = SkTBitOr<SkAdvancedTypefaceMetrics::FontFlags>(
+ result->fFlags,
+ SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag);
+ }
+ }
+ }
+ return result;
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/third_party/skia/src/core/SkUnPreMultiply.cpp b/chromium/third_party/skia/src/core/SkUnPreMultiply.cpp
index ad87f8af144..6245e96429c 100644
--- a/chromium/third_party/skia/src/core/SkUnPreMultiply.cpp
+++ b/chromium/third_party/skia/src/core/SkUnPreMultiply.cpp
@@ -17,6 +17,15 @@ SkColor SkUnPreMultiply::PMColorToColor(SkPMColor c) {
ApplyScale(scale, SkGetPackedB32(c)));
}
+uint32_t SkUnPreMultiply::UnPreMultiplyPreservingByteOrder(SkPMColor c) {
+ const U8CPU a = SkGetPackedA32(c);
+ const Scale scale = GetScale(a);
+ return SkPackARGB32NoCheck(a,
+ ApplyScale(scale, SkGetPackedR32(c)),
+ ApplyScale(scale, SkGetPackedG32(c)),
+ ApplyScale(scale, SkGetPackedB32(c)));
+}
+
const uint32_t SkUnPreMultiply::gTable[] = {
0x00000000, 0xFF000000, 0x7F800000, 0x55000000, 0x3FC00000, 0x33000000, 0x2A800000, 0x246DB6DB,
0x1FE00000, 0x1C555555, 0x19800000, 0x172E8BA3, 0x15400000, 0x139D89D9, 0x1236DB6E, 0x11000000,
diff --git a/chromium/third_party/skia/src/core/SkUtils.cpp b/chromium/third_party/skia/src/core/SkUtils.cpp
index e460ac8f6e9..eff718b20fb 100644
--- a/chromium/third_party/skia/src/core/SkUtils.cpp
+++ b/chromium/third_party/skia/src/core/SkUtils.cpp
@@ -8,6 +8,7 @@
#include "SkUtils.h"
+#include "SkLazyFnPtr.h"
#if 0
#define assign_16_longs(dst, value) \
@@ -37,7 +38,7 @@
///////////////////////////////////////////////////////////////////////////////
-void sk_memset16_portable(uint16_t dst[], uint16_t value, int count) {
+static void sk_memset16_portable(uint16_t dst[], uint16_t value, int count) {
SkASSERT(dst != NULL && count >= 0);
if (count <= 0) {
@@ -90,7 +91,7 @@ void sk_memset16_portable(uint16_t dst[], uint16_t value, int count) {
}
}
-void sk_memset32_portable(uint32_t dst[], uint32_t value, int count) {
+static void sk_memset32_portable(uint32_t dst[], uint32_t value, int count) {
SkASSERT(dst != NULL && count >= 0);
int sixteenlongs = count >> 4;
@@ -108,21 +109,45 @@ void sk_memset32_portable(uint32_t dst[], uint32_t value, int count) {
}
}
-static void sk_memset16_stub(uint16_t dst[], uint16_t value, int count) {
- SkMemset16Proc proc = SkMemset16GetPlatformProc();
- sk_memset16 = proc ? proc : sk_memset16_portable;
- sk_memset16(dst, value, count);
+static void sk_memcpy32_portable(uint32_t dst[], const uint32_t src[], int count) {
+ memcpy(dst, src, count * sizeof(uint32_t));
}
-SkMemset16Proc sk_memset16 = sk_memset16_stub;
+namespace {
+// These three methods technically need external linkage to be passed as template parameters.
+// Since they can't be static, we hide them in an anonymous namespace instead.
+
+SkMemset16Proc choose_memset16() {
+ SkMemset16Proc proc = SkMemset16GetPlatformProc();
+ return proc ? proc : sk_memset16_portable;
+}
-static void sk_memset32_stub(uint32_t dst[], uint32_t value, int count) {
+SkMemset32Proc choose_memset32() {
SkMemset32Proc proc = SkMemset32GetPlatformProc();
- sk_memset32 = proc ? proc : sk_memset32_portable;
- sk_memset32(dst, value, count);
+ return proc ? proc : sk_memset32_portable;
+}
+
+SkMemcpy32Proc choose_memcpy32() {
+ SkMemcpy32Proc proc = SkMemcpy32GetPlatformProc();
+ return proc ? proc : sk_memcpy32_portable;
}
-SkMemset32Proc sk_memset32 = sk_memset32_stub;
+} // namespace
+
+void sk_memset16(uint16_t dst[], uint16_t value, int count) {
+ SK_DECLARE_STATIC_LAZY_FN_PTR(SkMemset16Proc, proc, choose_memset16);
+ proc.get()(dst, value, count);
+}
+
+void sk_memset32(uint32_t dst[], uint32_t value, int count) {
+ SK_DECLARE_STATIC_LAZY_FN_PTR(SkMemset32Proc, proc, choose_memset32);
+ proc.get()(dst, value, count);
+}
+
+void sk_memcpy32(uint32_t dst[], const uint32_t src[], int count) {
+ SK_DECLARE_STATIC_LAZY_FN_PTR(SkMemcpy32Proc, proc, choose_memcpy32);
+ proc.get()(dst, src, count);
+}
///////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/third_party/skia/src/core/SkUtilsArm.cpp b/chromium/third_party/skia/src/core/SkUtilsArm.cpp
index 87a4a7fb0ad..58cf1157c30 100644
--- a/chromium/third_party/skia/src/core/SkUtilsArm.cpp
+++ b/chromium/third_party/skia/src/core/SkUtilsArm.cpp
@@ -20,10 +20,12 @@
// cpu-features helper library to detect NEON at runtime. See
// http://crbug.com/164154 to see why this is needed in Chromium
// for Android.
-#if defined(SK_BUILD_FOR_ANDROID)
-# define USE_ANDROID_NDK_CPU_FEATURES 1
-#else
-# define USE_ANDROID_NDK_CPU_FEATURES 0
+#if !defined(USE_ANDROID_NDK_CPU_FEATURES)
+# if defined(SK_BUILD_FOR_ANDROID)
+# define USE_ANDROID_NDK_CPU_FEATURES 1
+# else
+# define USE_ANDROID_NDK_CPU_FEATURES 0
+# endif
#endif
#if USE_ANDROID_NDK_CPU_FEATURES
diff --git a/chromium/third_party/skia/src/core/SkUtilsArm.h b/chromium/third_party/skia/src/core/SkUtilsArm.h
index b9a26143ee8..09ddaf39466 100644
--- a/chromium/third_party/skia/src/core/SkUtilsArm.h
+++ b/chromium/third_party/skia/src/core/SkUtilsArm.h
@@ -21,9 +21,9 @@
#define SK_ARM_NEON_MODE_ALWAYS 1
#define SK_ARM_NEON_MODE_DYNAMIC 2
-#if defined(SK_CPU_ARM) && defined(__ARM_HAVE_OPTIONAL_NEON_SUPPORT)
+#if defined(SK_CPU_ARM32) && defined(__ARM_HAVE_OPTIONAL_NEON_SUPPORT)
# define SK_ARM_NEON_MODE SK_ARM_NEON_MODE_DYNAMIC
-#elif defined(SK_CPU_ARM) && defined(__ARM_HAVE_NEON)
+#elif defined(SK_CPU_ARM32) && defined(__ARM_HAVE_NEON) || defined(SK_CPU_ARM64)
# define SK_ARM_NEON_MODE SK_ARM_NEON_MODE_ALWAYS
#else
# define SK_ARM_NEON_MODE SK_ARM_NEON_MODE_NONE
diff --git a/chromium/third_party/skia/src/core/SkValidatingReadBuffer.cpp b/chromium/third_party/skia/src/core/SkValidatingReadBuffer.cpp
index 692d0dd4d18..037a99465b2 100644
--- a/chromium/third_party/skia/src/core/SkValidatingReadBuffer.cpp
+++ b/chromium/third_party/skia/src/core/SkValidatingReadBuffer.cpp
@@ -14,7 +14,7 @@
SkValidatingReadBuffer::SkValidatingReadBuffer(const void* data, size_t size) :
fError(false) {
this->setMemory(data, size);
- this->setFlags(SkFlattenableReadBuffer::kValidation_Flag);
+ this->setFlags(SkReadBuffer::kValidation_Flag);
}
SkValidatingReadBuffer::~SkValidatingReadBuffer() {
@@ -91,7 +91,7 @@ int32_t SkValidatingReadBuffer::read32() {
}
void SkValidatingReadBuffer::readString(SkString* string) {
- const size_t len = this->readInt();
+ const size_t len = this->readUInt();
const void* ptr = fReader.peek();
const char* cptr = (const char*)ptr;
@@ -210,24 +210,15 @@ uint32_t SkValidatingReadBuffer::getArrayCount() {
return fError ? 0 : *(uint32_t*)fReader.peek();
}
-void SkValidatingReadBuffer::readBitmap(SkBitmap* bitmap) {
- const int width = this->readInt();
- const int height = this->readInt();
- const size_t length = this->readUInt();
- // A size of zero means the SkBitmap was simply flattened.
- this->validate(length == 0);
- if (fError) {
- return;
- }
- bitmap->unflatten(*this);
- this->validate((bitmap->width() == width) && (bitmap->height() == height));
-}
-
SkTypeface* SkValidatingReadBuffer::readTypeface() {
// TODO: Implement this (securely) when needed
return NULL;
}
+bool SkValidatingReadBuffer::validateAvailable(size_t size) {
+ return this->validate((size <= SK_MaxU32) && fReader.isAvailable(static_cast<uint32_t>(size)));
+}
+
SkFlattenable* SkValidatingReadBuffer::readFlattenable(SkFlattenable::Type type) {
SkString name;
this->readString(&name);
@@ -252,10 +243,10 @@ SkFlattenable* SkValidatingReadBuffer::readFlattenable(SkFlattenable::Type type)
SkFlattenable* obj = NULL;
uint32_t sizeRecorded = this->readUInt();
if (factory) {
- uint32_t offset = fReader.offset();
+ size_t offset = fReader.offset();
obj = (*factory)(*this);
// check that we read the amount we expected
- uint32_t sizeRead = fReader.offset() - offset;
+ size_t sizeRead = fReader.offset() - offset;
this->validate(sizeRecorded == sizeRead);
if (fError) {
// we could try to fix up the offset...
@@ -269,3 +260,13 @@ SkFlattenable* SkValidatingReadBuffer::readFlattenable(SkFlattenable::Type type)
}
return obj;
}
+
+void SkValidatingReadBuffer::skipFlattenable() {
+ SkString name;
+ this->readString(&name);
+ if (fError) {
+ return;
+ }
+ uint32_t sizeRecorded = this->readUInt();
+ this->skip(sizeRecorded);
+}
diff --git a/chromium/third_party/skia/src/core/SkValidatingReadBuffer.h b/chromium/third_party/skia/src/core/SkValidatingReadBuffer.h
index febf0c0b42f..5cf3abed68f 100644
--- a/chromium/third_party/skia/src/core/SkValidatingReadBuffer.h
+++ b/chromium/third_party/skia/src/core/SkValidatingReadBuffer.h
@@ -10,19 +10,20 @@
#include "SkRefCnt.h"
#include "SkBitmapHeap.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkPath.h"
#include "SkPicture.h"
#include "SkReader32.h"
class SkBitmap;
-class SkValidatingReadBuffer : public SkFlattenableReadBuffer {
+class SkValidatingReadBuffer : public SkReadBuffer {
public:
SkValidatingReadBuffer(const void* data, size_t size);
virtual ~SkValidatingReadBuffer();
- const void* skip(size_t size);
+ virtual const void* skip(size_t size) SK_OVERRIDE;
// primitives
virtual bool readBool() SK_OVERRIDE;
@@ -39,6 +40,7 @@ public:
// common data structures
virtual SkFlattenable* readFlattenable(SkFlattenable::Type type) SK_OVERRIDE;
+ virtual void skipFlattenable() SK_OVERRIDE;
virtual void readPoint(SkPoint* point) SK_OVERRIDE;
virtual void readMatrix(SkMatrix* matrix) SK_OVERRIDE;
virtual void readIRect(SkIRect* rect) SK_OVERRIDE;
@@ -56,13 +58,14 @@ public:
// helpers to get info about arrays and binary data
virtual uint32_t getArrayCount() SK_OVERRIDE;
- virtual void readBitmap(SkBitmap* bitmap) SK_OVERRIDE;
// TODO: Implement this (securely) when needed
virtual SkTypeface* readTypeface() SK_OVERRIDE;
virtual bool validate(bool isValid) SK_OVERRIDE;
virtual bool isValid() const SK_OVERRIDE;
+ virtual bool validateAvailable(size_t size) SK_OVERRIDE;
+
private:
bool readArray(void* value, size_t size, size_t elementSize);
@@ -72,10 +75,9 @@ private:
return SkIsAlign4((uintptr_t)ptr);
}
- SkReader32 fReader;
bool fError;
- typedef SkFlattenableReadBuffer INHERITED;
+ typedef SkReadBuffer INHERITED;
};
#endif // SkValidatingReadBuffer_DEFINED
diff --git a/chromium/third_party/skia/src/core/SkValidationUtils.h b/chromium/third_party/skia/src/core/SkValidationUtils.h
index 683da29c187..e9e59866ca9 100644
--- a/chromium/third_party/skia/src/core/SkValidationUtils.h
+++ b/chromium/third_party/skia/src/core/SkValidationUtils.h
@@ -23,12 +23,6 @@ static inline bool SkIsValidMode(SkXfermode::Mode mode) {
return (mode >= 0) && (mode <= SkXfermode::kLastMode);
}
-/** Returns true if config's value is in the SkBitmap::Config enum.
- */
-static inline bool SkIsValidConfig(SkBitmap::Config config) {
- return (config >= 0) && (config <= static_cast<int>(SkBitmap::kConfigCount));
-}
-
/** Returns true if the rect's dimensions are between 0 and SK_MaxS32
*/
static inline bool SkIsValidIRect(const SkIRect& rect) {
diff --git a/chromium/third_party/skia/src/core/SkVertState.cpp b/chromium/third_party/skia/src/core/SkVertState.cpp
new file mode 100644
index 00000000000..f23b1083fee
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkVertState.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkVertState.h"
+
+bool VertState::Triangles(VertState* state) {
+ int index = state->fCurrIndex;
+ if (index + 3 > state->fCount) {
+ return false;
+ }
+ state->f0 = index + 0;
+ state->f1 = index + 1;
+ state->f2 = index + 2;
+ state->fCurrIndex = index + 3;
+ return true;
+}
+
+bool VertState::TrianglesX(VertState* state) {
+ const uint16_t* indices = state->fIndices;
+ int index = state->fCurrIndex;
+ if (index + 3 > state->fCount) {
+ return false;
+ }
+ state->f0 = indices[index + 0];
+ state->f1 = indices[index + 1];
+ state->f2 = indices[index + 2];
+ state->fCurrIndex = index + 3;
+ return true;
+}
+
+bool VertState::TriangleStrip(VertState* state) {
+ int index = state->fCurrIndex;
+ if (index + 3 > state->fCount) {
+ return false;
+ }
+ state->f2 = index + 2;
+ if (index & 1) {
+ state->f0 = index + 1;
+ state->f1 = index + 0;
+ } else {
+ state->f0 = index + 0;
+ state->f1 = index + 1;
+ }
+ state->fCurrIndex = index + 1;
+ return true;
+}
+
+bool VertState::TriangleStripX(VertState* state) {
+ const uint16_t* indices = state->fIndices;
+ int index = state->fCurrIndex;
+ if (index + 3 > state->fCount) {
+ return false;
+ }
+ state->f2 = indices[index + 2];
+ if (index & 1) {
+ state->f0 = indices[index + 1];
+ state->f1 = indices[index + 0];
+ } else {
+ state->f0 = indices[index + 0];
+ state->f1 = indices[index + 1];
+ }
+ state->fCurrIndex = index + 1;
+ return true;
+}
+
+bool VertState::TriangleFan(VertState* state) {
+ int index = state->fCurrIndex;
+ if (index + 3 > state->fCount) {
+ return false;
+ }
+ state->f0 = 0;
+ state->f1 = index + 1;
+ state->f2 = index + 2;
+ state->fCurrIndex = index + 1;
+ return true;
+}
+
+bool VertState::TriangleFanX(VertState* state) {
+ const uint16_t* indices = state->fIndices;
+ int index = state->fCurrIndex;
+ if (index + 3 > state->fCount) {
+ return false;
+ }
+ state->f0 = indices[0];
+ state->f1 = indices[index + 1];
+ state->f2 = indices[index + 2];
+ state->fCurrIndex = index + 1;
+ return true;
+}
+
+VertState::Proc VertState::chooseProc(SkCanvas::VertexMode mode) {
+ switch (mode) {
+ case SkCanvas::kTriangles_VertexMode:
+ return fIndices ? TrianglesX : Triangles;
+ case SkCanvas::kTriangleStrip_VertexMode:
+ return fIndices ? TriangleStripX : TriangleStrip;
+ case SkCanvas::kTriangleFan_VertexMode:
+ return fIndices ? TriangleFanX : TriangleFan;
+ default:
+ return NULL;
+ }
+}
diff --git a/chromium/third_party/skia/src/core/SkVertState.h b/chromium/third_party/skia/src/core/SkVertState.h
new file mode 100644
index 00000000000..ecf1773dc7a
--- /dev/null
+++ b/chromium/third_party/skia/src/core/SkVertState.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkVertState_DEFINED
+#define SkVertState_DEFINED
+
+#include "SkCanvas.h"
+
+/** \struct VertState
+ This is a helper for drawVertices(). It is used to iterate over the triangles
+ that are to be rendered based on an SkCanvas::VertexMode and (optionally) an
+ index array. It does not copy the index array and the client must ensure it
+ remains valid for the lifetime of the VertState object.
+*/
+
+struct VertState {
+ int f0, f1, f2;
+
+ /**
+ * Construct a VertState from a vertex count, index array, and index count.
+ * If the vertices are unindexed pass NULL for indices.
+ */
+ VertState(int vCount, const uint16_t indices[], int indexCount)
+ : fIndices(indices) {
+ fCurrIndex = 0;
+ if (indices) {
+ fCount = indexCount;
+ } else {
+ fCount = vCount;
+ }
+ }
+
+ typedef bool (*Proc)(VertState*);
+
+ /**
+ * Choose an appropriate function to traverse the vertices.
+ * @param mode Specifies the SkCanvas::VertexMode.
+ */
+ Proc chooseProc(SkCanvas::VertexMode mode);
+
+private:
+ int fCount;
+ int fCurrIndex;
+ const uint16_t* fIndices;
+
+ static bool Triangles(VertState*);
+ static bool TrianglesX(VertState*);
+ static bool TriangleStrip(VertState*);
+ static bool TriangleStripX(VertState*);
+ static bool TriangleFan(VertState*);
+ static bool TriangleFanX(VertState*);
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/core/SkOrderedWriteBuffer.cpp b/chromium/third_party/skia/src/core/SkWriteBuffer.cpp
index 25ca769168d..f2be41b266b 100644
--- a/chromium/third_party/skia/src/core/SkOrderedWriteBuffer.cpp
+++ b/chromium/third_party/skia/src/core/SkWriteBuffer.cpp
@@ -6,132 +6,132 @@
* found in the LICENSE file.
*/
-#include "SkOrderedWriteBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkBitmap.h"
#include "SkData.h"
+#include "SkPixelRef.h"
#include "SkPtrRecorder.h"
#include "SkStream.h"
#include "SkTypeface.h"
-SkOrderedWriteBuffer::SkOrderedWriteBuffer(size_t minSize)
- : INHERITED()
+SkWriteBuffer::SkWriteBuffer(uint32_t flags)
+ : fFlags(flags)
, fFactorySet(NULL)
, fNamedFactorySet(NULL)
- , fWriter(minSize)
, fBitmapHeap(NULL)
, fTFSet(NULL)
, fBitmapEncoder(NULL) {
}
-SkOrderedWriteBuffer::SkOrderedWriteBuffer(size_t minSize, void* storage, size_t storageSize)
- : INHERITED()
+SkWriteBuffer::SkWriteBuffer(void* storage, size_t storageSize, uint32_t flags)
+ : fFlags(flags)
, fFactorySet(NULL)
, fNamedFactorySet(NULL)
- , fWriter(minSize, storage, storageSize)
+ , fWriter(storage, storageSize)
, fBitmapHeap(NULL)
, fTFSet(NULL)
, fBitmapEncoder(NULL) {
}
-SkOrderedWriteBuffer::~SkOrderedWriteBuffer() {
+SkWriteBuffer::~SkWriteBuffer() {
SkSafeUnref(fFactorySet);
SkSafeUnref(fNamedFactorySet);
SkSafeUnref(fBitmapHeap);
SkSafeUnref(fTFSet);
}
-void SkOrderedWriteBuffer::writeByteArray(const void* data, size_t size) {
- fWriter.write32(size);
+void SkWriteBuffer::writeByteArray(const void* data, size_t size) {
+ fWriter.write32(SkToU32(size));
fWriter.writePad(data, size);
}
-void SkOrderedWriteBuffer::writeBool(bool value) {
+void SkWriteBuffer::writeBool(bool value) {
fWriter.writeBool(value);
}
-void SkOrderedWriteBuffer::writeFixed(SkFixed value) {
+void SkWriteBuffer::writeFixed(SkFixed value) {
fWriter.write32(value);
}
-void SkOrderedWriteBuffer::writeScalar(SkScalar value) {
+void SkWriteBuffer::writeScalar(SkScalar value) {
fWriter.writeScalar(value);
}
-void SkOrderedWriteBuffer::writeScalarArray(const SkScalar* value, uint32_t count) {
+void SkWriteBuffer::writeScalarArray(const SkScalar* value, uint32_t count) {
fWriter.write32(count);
fWriter.write(value, count * sizeof(SkScalar));
}
-void SkOrderedWriteBuffer::writeInt(int32_t value) {
+void SkWriteBuffer::writeInt(int32_t value) {
fWriter.write32(value);
}
-void SkOrderedWriteBuffer::writeIntArray(const int32_t* value, uint32_t count) {
+void SkWriteBuffer::writeIntArray(const int32_t* value, uint32_t count) {
fWriter.write32(count);
fWriter.write(value, count * sizeof(int32_t));
}
-void SkOrderedWriteBuffer::writeUInt(uint32_t value) {
+void SkWriteBuffer::writeUInt(uint32_t value) {
fWriter.write32(value);
}
-void SkOrderedWriteBuffer::write32(int32_t value) {
+void SkWriteBuffer::write32(int32_t value) {
fWriter.write32(value);
}
-void SkOrderedWriteBuffer::writeString(const char* value) {
+void SkWriteBuffer::writeString(const char* value) {
fWriter.writeString(value);
}
-void SkOrderedWriteBuffer::writeEncodedString(const void* value, size_t byteLength,
+void SkWriteBuffer::writeEncodedString(const void* value, size_t byteLength,
SkPaint::TextEncoding encoding) {
fWriter.writeInt(encoding);
- fWriter.writeInt(byteLength);
+ fWriter.writeInt(SkToU32(byteLength));
fWriter.write(value, byteLength);
}
-void SkOrderedWriteBuffer::writeColor(const SkColor& color) {
+void SkWriteBuffer::writeColor(const SkColor& color) {
fWriter.write32(color);
}
-void SkOrderedWriteBuffer::writeColorArray(const SkColor* color, uint32_t count) {
+void SkWriteBuffer::writeColorArray(const SkColor* color, uint32_t count) {
fWriter.write32(count);
fWriter.write(color, count * sizeof(SkColor));
}
-void SkOrderedWriteBuffer::writePoint(const SkPoint& point) {
+void SkWriteBuffer::writePoint(const SkPoint& point) {
fWriter.writeScalar(point.fX);
fWriter.writeScalar(point.fY);
}
-void SkOrderedWriteBuffer::writePointArray(const SkPoint* point, uint32_t count) {
+void SkWriteBuffer::writePointArray(const SkPoint* point, uint32_t count) {
fWriter.write32(count);
fWriter.write(point, count * sizeof(SkPoint));
}
-void SkOrderedWriteBuffer::writeMatrix(const SkMatrix& matrix) {
+void SkWriteBuffer::writeMatrix(const SkMatrix& matrix) {
fWriter.writeMatrix(matrix);
}
-void SkOrderedWriteBuffer::writeIRect(const SkIRect& rect) {
+void SkWriteBuffer::writeIRect(const SkIRect& rect) {
fWriter.write(&rect, sizeof(SkIRect));
}
-void SkOrderedWriteBuffer::writeRect(const SkRect& rect) {
+void SkWriteBuffer::writeRect(const SkRect& rect) {
fWriter.writeRect(rect);
}
-void SkOrderedWriteBuffer::writeRegion(const SkRegion& region) {
+void SkWriteBuffer::writeRegion(const SkRegion& region) {
fWriter.writeRegion(region);
}
-void SkOrderedWriteBuffer::writePath(const SkPath& path) {
+void SkWriteBuffer::writePath(const SkPath& path) {
fWriter.writePath(path);
}
-size_t SkOrderedWriteBuffer::writeStream(SkStream* stream, size_t length) {
- fWriter.write32(length);
+size_t SkWriteBuffer::writeStream(SkStream* stream, size_t length) {
+ fWriter.write32(SkToU32(length));
size_t bytesWritten = fWriter.readFromStream(stream, length);
if (bytesWritten < length) {
fWriter.reservePad(length - bytesWritten);
@@ -139,15 +139,19 @@ size_t SkOrderedWriteBuffer::writeStream(SkStream* stream, size_t length) {
return bytesWritten;
}
-bool SkOrderedWriteBuffer::writeToStream(SkWStream* stream) {
+bool SkWriteBuffer::writeToStream(SkWStream* stream) {
return fWriter.writeToStream(stream);
}
-// Defined in SkBitmap.cpp
-bool get_upper_left_from_offset(SkBitmap::Config config, size_t offset, size_t rowBytes,
- int32_t* x, int32_t* y);
+static void write_encoded_bitmap(SkWriteBuffer* buffer, SkData* data,
+ const SkIPoint& origin) {
+ buffer->writeUInt(SkToU32(data->size()));
+ buffer->getWriter32()->writePad(data->data(), data->size());
+ buffer->write32(origin.fX);
+ buffer->write32(origin.fY);
+}
-void SkOrderedWriteBuffer::writeBitmap(const SkBitmap& bitmap) {
+void SkWriteBuffer::writeBitmap(const SkBitmap& bitmap) {
// Record the width and height. This way if readBitmap fails a dummy bitmap can be drawn at the
// right size.
this->writeInt(bitmap.width());
@@ -179,33 +183,34 @@ void SkOrderedWriteBuffer::writeBitmap(const SkBitmap& bitmap) {
fWriter.write32(bitmap.getGenerationID());
return;
}
+
+ // see if the pixelref already has an encoded version
+ if (bitmap.pixelRef()) {
+ SkAutoDataUnref data(bitmap.pixelRef()->refEncodedData());
+ if (data.get() != NULL) {
+ write_encoded_bitmap(this, data, bitmap.pixelRefOrigin());
+ return;
+ }
+ }
+
+ // see if the caller wants to manually encode
if (fBitmapEncoder != NULL) {
SkASSERT(NULL == fBitmapHeap);
- size_t offset = 0;
+ size_t offset = 0; // this parameter is deprecated/ignored
+ // if we have to "encode" the bitmap, then we assume there is no
+ // offset to share, since we are effectively creating a new pixelref
SkAutoDataUnref data(fBitmapEncoder(&offset, bitmap));
if (data.get() != NULL) {
- // Write the length to indicate that the bitmap was encoded successfully, followed
- // by the actual data.
- this->writeUInt(SkToU32(data->size()));
- fWriter.writePad(data->data(), data->size());
- // Store the coordinate of the offset, rather than fPixelRefOffset, which may be
- // different depending on the decoder.
- int32_t x, y;
- if (0 == offset || !get_upper_left_from_offset(bitmap.config(), offset,
- bitmap.rowBytes(), &x, &y)) {
- x = y = 0;
- }
- this->write32(x);
- this->write32(y);
+ write_encoded_bitmap(this, data, SkIPoint::Make(0, 0));
return;
}
}
- // Bitmap was not encoded. Record a zero, implying that the reader need not decode.
- this->writeUInt(0);
- bitmap.flatten(*this);
+
+ this->writeUInt(0); // signal raw pixels
+ SkBitmap::WriteRawPixels(this, bitmap);
}
-void SkOrderedWriteBuffer::writeTypeface(SkTypeface* obj) {
+void SkWriteBuffer::writeTypeface(SkTypeface* obj) {
if (NULL == obj || NULL == fTFSet) {
fWriter.write32(0);
} else {
@@ -213,7 +218,7 @@ void SkOrderedWriteBuffer::writeTypeface(SkTypeface* obj) {
}
}
-SkFactorySet* SkOrderedWriteBuffer::setFactoryRecorder(SkFactorySet* rec) {
+SkFactorySet* SkWriteBuffer::setFactoryRecorder(SkFactorySet* rec) {
SkRefCnt_SafeAssign(fFactorySet, rec);
if (fNamedFactorySet != NULL) {
fNamedFactorySet->unref();
@@ -222,7 +227,7 @@ SkFactorySet* SkOrderedWriteBuffer::setFactoryRecorder(SkFactorySet* rec) {
return rec;
}
-SkNamedFactorySet* SkOrderedWriteBuffer::setNamedFactoryRecorder(SkNamedFactorySet* rec) {
+SkNamedFactorySet* SkWriteBuffer::setNamedFactoryRecorder(SkNamedFactorySet* rec) {
SkRefCnt_SafeAssign(fNamedFactorySet, rec);
if (fFactorySet != NULL) {
fFactorySet->unref();
@@ -231,12 +236,12 @@ SkNamedFactorySet* SkOrderedWriteBuffer::setNamedFactoryRecorder(SkNamedFactoryS
return rec;
}
-SkRefCntSet* SkOrderedWriteBuffer::setTypefaceRecorder(SkRefCntSet* rec) {
+SkRefCntSet* SkWriteBuffer::setTypefaceRecorder(SkRefCntSet* rec) {
SkRefCnt_SafeAssign(fTFSet, rec);
return rec;
}
-void SkOrderedWriteBuffer::setBitmapHeap(SkBitmapHeap* bitmapHeap) {
+void SkWriteBuffer::setBitmapHeap(SkBitmapHeap* bitmapHeap) {
SkRefCnt_SafeAssign(fBitmapHeap, bitmapHeap);
if (bitmapHeap != NULL) {
SkASSERT(NULL == fBitmapEncoder);
@@ -244,7 +249,7 @@ void SkOrderedWriteBuffer::setBitmapHeap(SkBitmapHeap* bitmapHeap) {
}
}
-void SkOrderedWriteBuffer::setBitmapEncoder(SkPicture::EncodeBitmap bitmapEncoder) {
+void SkWriteBuffer::setBitmapEncoder(SkPicture::EncodeBitmap bitmapEncoder) {
fBitmapEncoder = bitmapEncoder;
if (bitmapEncoder != NULL) {
SkASSERT(NULL == fBitmapHeap);
@@ -253,7 +258,7 @@ void SkOrderedWriteBuffer::setBitmapEncoder(SkPicture::EncodeBitmap bitmapEncode
}
}
-void SkOrderedWriteBuffer::writeFlattenable(const SkFlattenable* flattenable) {
+void SkWriteBuffer::writeFlattenable(const SkFlattenable* flattenable) {
/*
* If we have a factoryset, then the first 32bits tell us...
* 0: failure to write the flattenable
@@ -264,15 +269,9 @@ void SkOrderedWriteBuffer::writeFlattenable(const SkFlattenable* flattenable) {
* The distinction is important, since 0-index is 32bits (always), but a
* 0-functionptr might be 32 or 64 bits.
*/
-
- SkFlattenable::Factory factory = NULL;
- if (flattenable) {
- factory = flattenable->getFactory();
- }
- if (NULL == factory) {
+ if (NULL == flattenable) {
if (this->isValidating()) {
this->writeString("");
- SkASSERT(NULL == flattenable); // We shouldn't get in here in this scenario
} else if (fFactorySet != NULL || fNamedFactorySet != NULL) {
this->write32(0);
} else {
@@ -281,6 +280,9 @@ void SkOrderedWriteBuffer::writeFlattenable(const SkFlattenable* flattenable) {
return;
}
+ SkFlattenable::Factory factory = flattenable->getFactory();
+ SkASSERT(factory != NULL);
+
/*
* We can write 1 of 3 versions of the flattenable:
* 1. function-ptr : this is the fastest for the reader, but assumes that
@@ -310,10 +312,10 @@ void SkOrderedWriteBuffer::writeFlattenable(const SkFlattenable* flattenable) {
// make room for the size of the flattened object
(void)fWriter.reserve(sizeof(uint32_t));
// record the current size, so we can subtract after the object writes.
- uint32_t offset = fWriter.bytesWritten();
+ size_t offset = fWriter.bytesWritten();
// now flatten the object
- flattenObject(flattenable, *this);
- uint32_t objSize = fWriter.bytesWritten() - offset;
+ flattenable->flatten(*this);
+ size_t objSize = fWriter.bytesWritten() - offset;
// record the obj's size
- *fWriter.peek32(offset - sizeof(uint32_t)) = objSize;
+ fWriter.overwriteTAt(offset - sizeof(uint32_t), SkToU32(objSize));
}
diff --git a/chromium/third_party/skia/src/core/SkWriter32.cpp b/chromium/third_party/skia/src/core/SkWriter32.cpp
index e5befbafb40..00c46368b60 100644
--- a/chromium/third_party/skia/src/core/SkWriter32.cpp
+++ b/chromium/third_party/skia/src/core/SkWriter32.cpp
@@ -5,249 +5,19 @@
* found in the LICENSE file.
*/
-#include "SkWriter32.h"
-
-SkWriter32::SkWriter32(size_t minSize, void* storage, size_t storageSize) {
- fMinSize = minSize;
- fSize = 0;
- fWrittenBeforeLastBlock = 0;
- fHead = fTail = NULL;
-
- if (storageSize) {
- this->reset(storage, storageSize);
- }
-}
-
-SkWriter32::~SkWriter32() {
- this->reset();
-}
-
-void SkWriter32::reset() {
- Block* block = fHead;
-
- if (this->isHeadExternallyAllocated()) {
- SkASSERT(block);
- // don't 'free' the first block, since it is owned by the caller
- block = block->fNext;
- }
- while (block) {
- Block* next = block->fNext;
- sk_free(block);
- block = next;
- }
-
- fSize = 0;
- fWrittenBeforeLastBlock = 0;
- fHead = fTail = NULL;
-}
-
-void SkWriter32::reset(void* storage, size_t storageSize) {
- this->reset();
-
- storageSize &= ~3; // trunc down to multiple of 4
- if (storageSize > 0 && SkIsAlign4((intptr_t)storage)) {
- fHead = fTail = fExternalBlock.initFromStorage(storage, storageSize);
- }
-}
-
-SkWriter32::Block* SkWriter32::doReserve(size_t size) {
- SkASSERT(SkAlign4(size) == size);
-
- Block* block = fTail;
- SkASSERT(NULL == block || block->available() < size);
-
- if (NULL == block) {
- SkASSERT(NULL == fHead);
- fHead = fTail = block = Block::Create(SkMax32(size, fMinSize));
- SkASSERT(0 == fWrittenBeforeLastBlock);
- } else {
- fWrittenBeforeLastBlock = fSize;
-
- fTail = Block::Create(SkMax32(size, fMinSize));
- block->fNext = fTail;
- block = fTail;
- }
- return block;
-}
-
-uint32_t* SkWriter32::peek32(size_t offset) {
- SkDEBUGCODE(this->validate();)
-
- SkASSERT(SkAlign4(offset) == offset);
- SkASSERT(offset <= fSize);
-
- // try the fast case, where offset is within fTail
- if (offset >= fWrittenBeforeLastBlock) {
- return fTail->peek32(offset - fWrittenBeforeLastBlock);
- }
-
- Block* block = fHead;
- SkASSERT(NULL != block);
-
- while (offset >= block->fAllocatedSoFar) {
- offset -= block->fAllocatedSoFar;
- block = block->fNext;
- SkASSERT(NULL != block);
- }
- return block->peek32(offset);
-}
-
-void SkWriter32::rewindToOffset(size_t offset) {
- if (offset >= fSize) {
- return;
- }
- if (0 == offset) {
- this->reset();
- return;
- }
-
- SkDEBUGCODE(this->validate();)
-
- SkASSERT(SkAlign4(offset) == offset);
- SkASSERT(offset <= fSize);
- fSize = offset;
-
- // Try the fast case, where offset is within fTail
- if (offset >= fWrittenBeforeLastBlock) {
- fTail->fAllocatedSoFar = offset - fWrittenBeforeLastBlock;
- } else {
- // Similar to peek32, except that we free up any following blocks.
- // We have to re-compute fWrittenBeforeLastBlock as well.
-
- size_t globalOffset = offset;
- Block* block = fHead;
- SkASSERT(NULL != block);
- while (offset >= block->fAllocatedSoFar) {
- offset -= block->fAllocatedSoFar;
- block = block->fNext;
- SkASSERT(NULL != block);
- }
-
- // this has to be recomputed, since we may free up fTail
- fWrittenBeforeLastBlock = globalOffset - offset;
-
- // update the size on the "last" block
- block->fAllocatedSoFar = offset;
- // end our list
- fTail = block;
- Block* next = block->fNext;
- block->fNext = NULL;
- // free up any trailing blocks
- block = next;
- while (block) {
- Block* next = block->fNext;
- sk_free(block);
- block = next;
- }
- }
- SkDEBUGCODE(this->validate();)
-}
-
-void SkWriter32::flatten(void* dst) const {
- const Block* block = fHead;
- SkDEBUGCODE(size_t total = 0;)
-
- while (block) {
- size_t allocated = block->fAllocatedSoFar;
- memcpy(dst, block->base(), allocated);
- dst = (char*)dst + allocated;
- block = block->fNext;
-
- SkDEBUGCODE(total += allocated;)
- SkASSERT(total <= fSize);
- }
- SkASSERT(total == fSize);
-}
-
-uint32_t* SkWriter32::reservePad(size_t size) {
- if (size > 0) {
- size_t alignedSize = SkAlign4(size);
- char* dst = (char*)this->reserve(alignedSize);
- // Pad the last four bytes with zeroes in one step.
- uint32_t* padding = (uint32_t*)(dst + (alignedSize - 4));
- *padding = 0;
- return (uint32_t*) dst;
- }
- return this->reserve(0);
-}
-
-void SkWriter32::writePad(const void* src, size_t size) {
- if (size > 0) {
- char* dst = (char*)this->reservePad(size);
- // Copy the actual data.
- memcpy(dst, src, size);
- }
-}
-
-#include "SkStream.h"
-
-size_t SkWriter32::readFromStream(SkStream* stream, size_t length) {
- char scratch[1024];
- const size_t MAX = sizeof(scratch);
- size_t remaining = length;
-
- while (remaining != 0) {
- size_t n = remaining;
- if (n > MAX) {
- n = MAX;
- }
- size_t bytes = stream->read(scratch, n);
- this->writePad(scratch, bytes);
- remaining -= bytes;
- if (bytes != n) {
- break;
- }
- }
- return length - remaining;
-}
-
-bool SkWriter32::writeToStream(SkWStream* stream) {
- const Block* block = fHead;
- while (block) {
- if (!stream->write(block->base(), block->fAllocatedSoFar)) {
- return false;
- }
- block = block->fNext;
- }
- return true;
-}
-
-#ifdef SK_DEBUG
-void SkWriter32::validate() const {
- SkASSERT(SkIsAlign4(fSize));
-
- size_t accum = 0;
- const Block* block = fHead;
- while (block) {
- SkASSERT(SkIsAlign4(block->fSizeOfBlock));
- SkASSERT(SkIsAlign4(block->fAllocatedSoFar));
- SkASSERT(block->fAllocatedSoFar <= block->fSizeOfBlock);
- if (NULL == block->fNext) {
- SkASSERT(fTail == block);
- SkASSERT(fWrittenBeforeLastBlock == accum);
- }
- accum += block->fAllocatedSoFar;
- SkASSERT(accum <= fSize);
- block = block->fNext;
- }
- SkASSERT(accum == fSize);
-}
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-
#include "SkReader32.h"
#include "SkString.h"
+#include "SkWriter32.h"
/*
* Strings are stored as: length[4-bytes] + string_data + '\0' + pad_to_mul_4
*/
const char* SkReader32::readString(size_t* outLen) {
- size_t len = this->readInt();
+ size_t len = this->readU32();
const void* ptr = this->peek();
- // skip over teh string + '\0' and then pad to a multiple of 4
+ // skip over the string + '\0' and then pad to a multiple of 4
size_t alignedSize = SkAlign4(len + 1);
this->skip(alignedSize);
@@ -274,17 +44,13 @@ void SkWriter32::writeString(const char str[], size_t len) {
if ((long)len < 0) {
len = strlen(str);
}
- this->write32(len);
- // add 1 since we also write a terminating 0
- size_t alignedLen = SkAlign4(len + 1);
- char* ptr = (char*)this->reserve(alignedLen);
- {
- // Write the terminating 0 and fill in the rest with zeroes
- uint32_t* padding = (uint32_t*)(ptr + (alignedLen - 4));
- *padding = 0;
- }
- // Copy the string itself.
- memcpy(ptr, str, len);
+
+ // [ 4 byte len ] [ str ... ] [1 - 4 \0s]
+ uint32_t* ptr = this->reservePad(sizeof(uint32_t) + len + 1);
+ *ptr = SkToU32(len);
+ char* chars = (char*)(ptr + 1);
+ memcpy(chars, str, len);
+ chars[len] = '\0';
}
size_t SkWriter32::WriteStringSize(const char* str, size_t len) {
@@ -296,3 +62,44 @@ size_t SkWriter32::WriteStringSize(const char* str, size_t len) {
// add 1 since we also write a terminating 0
return SkAlign4(lenBytes + len + 1);
}
+
+void SkWriter32::growToAtLeast(size_t size) {
+ const bool wasExternal = (fExternal != NULL) && (fData == fExternal);
+
+ fCapacity = 4096 + SkTMax(size, fCapacity + (fCapacity / 2));
+ fInternal.realloc(fCapacity);
+ fData = fInternal.get();
+
+ if (wasExternal) {
+ // we were external, so copy in the data
+ memcpy(fData, fExternal, fUsed);
+ }
+ // Invalidate the snapshot, we know it is no longer useful.
+ fSnapshot.reset(NULL);
+}
+
+SkData* SkWriter32::snapshotAsData() const {
+ // get a non const version of this, we are only conceptually const
+ SkWriter32& mutable_this = *const_cast<SkWriter32*>(this);
+ // we use size change detection to invalidate the cached data
+ if ((fSnapshot.get() != NULL) && (fSnapshot->size() != fUsed)) {
+ mutable_this.fSnapshot.reset(NULL);
+ }
+ if (fSnapshot.get() == NULL) {
+ uint8_t* buffer = NULL;
+ if ((fExternal != NULL) && (fData == fExternal)) {
+ // We need to copy to an allocated buffer before returning.
+ buffer = (uint8_t*)sk_malloc_throw(fUsed);
+ memcpy(buffer, fData, fUsed);
+ } else {
+ buffer = mutable_this.fInternal.detach();
+ // prepare us to do copy on write, by pretending the data buffer
+ // is external and size limited
+ mutable_this.fData = buffer;
+ mutable_this.fCapacity = fUsed;
+ mutable_this.fExternal = buffer;
+ }
+ mutable_this.fSnapshot.reset(SkData::NewFromMalloc(buffer, fUsed));
+ }
+ return SkRef(fSnapshot.get()); // Take an extra ref for the caller.
+}
diff --git a/chromium/third_party/skia/src/core/SkXfermode.cpp b/chromium/third_party/skia/src/core/SkXfermode.cpp
index 176bcb50ea7..b5f95dad51b 100644
--- a/chromium/third_party/skia/src/core/SkXfermode.cpp
+++ b/chromium/third_party/skia/src/core/SkXfermode.cpp
@@ -8,12 +8,15 @@
#include "SkXfermode.h"
+#include "SkXfermode_opts_SSE2.h"
#include "SkXfermode_proccoeff.h"
#include "SkColorPriv.h"
-#include "SkFlattenableBuffers.h"
+#include "SkLazyPtr.h"
#include "SkMathPriv.h"
+#include "SkReadBuffer.h"
#include "SkString.h"
#include "SkUtilsArm.h"
+#include "SkWriteBuffer.h"
#if !SK_ARM_NEON_IS_NONE
#include "SkXfermode_opts_arm_neon.h"
@@ -771,116 +774,6 @@ void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
}
}
-///////////////////////////////////////////////////////////////////////////////
-
-void SkProcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
- const SkPMColor* SK_RESTRICT src, int count,
- const SkAlpha* SK_RESTRICT aa) const {
- SkASSERT(dst && src && count >= 0);
-
- SkXfermodeProc proc = fProc;
-
- if (NULL != proc) {
- if (NULL == aa) {
- for (int i = count - 1; i >= 0; --i) {
- dst[i] = proc(src[i], dst[i]);
- }
- } else {
- for (int i = count - 1; i >= 0; --i) {
- unsigned a = aa[i];
- if (0 != a) {
- SkPMColor dstC = dst[i];
- SkPMColor C = proc(src[i], dstC);
- if (a != 0xFF) {
- C = SkFourByteInterp(C, dstC, a);
- }
- dst[i] = C;
- }
- }
- }
- }
-}
-
-void SkProcXfermode::xfer16(uint16_t* SK_RESTRICT dst,
- const SkPMColor* SK_RESTRICT src, int count,
- const SkAlpha* SK_RESTRICT aa) const {
- SkASSERT(dst && src && count >= 0);
-
- SkXfermodeProc proc = fProc;
-
- if (NULL != proc) {
- if (NULL == aa) {
- for (int i = count - 1; i >= 0; --i) {
- SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
- dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
- }
- } else {
- for (int i = count - 1; i >= 0; --i) {
- unsigned a = aa[i];
- if (0 != a) {
- SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
- SkPMColor C = proc(src[i], dstC);
- if (0xFF != a) {
- C = SkFourByteInterp(C, dstC, a);
- }
- dst[i] = SkPixel32ToPixel16_ToU16(C);
- }
- }
- }
- }
-}
-
-void SkProcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
- const SkPMColor* SK_RESTRICT src, int count,
- const SkAlpha* SK_RESTRICT aa) const {
- SkASSERT(dst && src && count >= 0);
-
- SkXfermodeProc proc = fProc;
-
- if (NULL != proc) {
- if (NULL == aa) {
- for (int i = count - 1; i >= 0; --i) {
- SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
- dst[i] = SkToU8(SkGetPackedA32(res));
- }
- } else {
- for (int i = count - 1; i >= 0; --i) {
- unsigned a = aa[i];
- if (0 != a) {
- SkAlpha dstA = dst[i];
- SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
- unsigned A = SkGetPackedA32(res);
- if (0xFF != a) {
- A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
- }
- dst[i] = SkToU8(A);
- }
- }
- }
- }
-}
-
-SkProcXfermode::SkProcXfermode(SkFlattenableReadBuffer& buffer)
- : SkXfermode(buffer) {
- fProc = NULL;
- if (!buffer.isCrossProcess()) {
- fProc = (SkXfermodeProc)buffer.readFunctionPtr();
- }
-}
-
-void SkProcXfermode::flatten(SkFlattenableWriteBuffer& buffer) const {
- this->INHERITED::flatten(buffer);
- if (!buffer.isCrossProcess()) {
- buffer.writeFunctionPtr((void*)fProc);
- }
-}
-
-#ifdef SK_DEVELOPER
-void SkProcXfermode::toString(SkString* str) const {
- str->appendf("SkProcXfermode: %p", fProc);
-}
-#endif
-
//////////////////////////////////////////////////////////////////////////////
#if SK_SUPPORT_GPU
@@ -1071,13 +964,16 @@ public:
break;
}
default:
- GrCrash("Unknown XferEffect mode.");
+ SkFAIL("Unknown XferEffect mode.");
break;
}
}
static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
- return drawEffect.castEffect<XferEffect>().mode();
+ // The background may come from the dst or from a texture.
+ int numTextures = (*drawEffect.effect())->numTextures();
+ SkASSERT(numTextures <= 1);
+ return (drawEffect.castEffect<XferEffect>().mode() << 1) | numTextures;
}
private:
@@ -1343,7 +1239,7 @@ GrEffectRef* XferEffect::TestCreate(SkRandom* rand,
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
-SkProcCoeffXfermode::SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
+SkProcCoeffXfermode::SkProcCoeffXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {
uint32_t mode32 = buffer.read32() % SK_ARRAY_COUNT(gProcCoeffs);
if (mode32 >= SK_ARRAY_COUNT(gProcCoeffs)) {
// out of range, just set to something harmless
@@ -1352,11 +1248,10 @@ SkProcCoeffXfermode::SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer) : INHE
fMode = (SkXfermode::Mode)mode32;
const ProcCoeff& rec = gProcCoeffs[fMode];
+ fProc = rec.fProc;
// these may be valid, or may be CANNOT_USE_COEFF
fSrcCoeff = rec.fSC;
fDstCoeff = rec.fDC;
- // now update our function-ptr in the super class
- this->INHERITED::setProc(rec.fProc);
}
bool SkProcCoeffXfermode::asMode(Mode* mode) const {
@@ -1380,6 +1275,93 @@ bool SkProcCoeffXfermode::asCoeff(Coeff* sc, Coeff* dc) const {
return true;
}
+void SkProcCoeffXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
+ const SkPMColor* SK_RESTRICT src, int count,
+ const SkAlpha* SK_RESTRICT aa) const {
+ SkASSERT(dst && src && count >= 0);
+
+ SkXfermodeProc proc = fProc;
+
+ if (NULL != proc) {
+ if (NULL == aa) {
+ for (int i = count - 1; i >= 0; --i) {
+ dst[i] = proc(src[i], dst[i]);
+ }
+ } else {
+ for (int i = count - 1; i >= 0; --i) {
+ unsigned a = aa[i];
+ if (0 != a) {
+ SkPMColor dstC = dst[i];
+ SkPMColor C = proc(src[i], dstC);
+ if (a != 0xFF) {
+ C = SkFourByteInterp(C, dstC, a);
+ }
+ dst[i] = C;
+ }
+ }
+ }
+ }
+}
+
+void SkProcCoeffXfermode::xfer16(uint16_t* SK_RESTRICT dst,
+ const SkPMColor* SK_RESTRICT src, int count,
+ const SkAlpha* SK_RESTRICT aa) const {
+ SkASSERT(dst && src && count >= 0);
+
+ SkXfermodeProc proc = fProc;
+
+ if (NULL != proc) {
+ if (NULL == aa) {
+ for (int i = count - 1; i >= 0; --i) {
+ SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
+ dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
+ }
+ } else {
+ for (int i = count - 1; i >= 0; --i) {
+ unsigned a = aa[i];
+ if (0 != a) {
+ SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
+ SkPMColor C = proc(src[i], dstC);
+ if (0xFF != a) {
+ C = SkFourByteInterp(C, dstC, a);
+ }
+ dst[i] = SkPixel32ToPixel16_ToU16(C);
+ }
+ }
+ }
+ }
+}
+
+void SkProcCoeffXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
+ const SkPMColor* SK_RESTRICT src, int count,
+ const SkAlpha* SK_RESTRICT aa) const {
+ SkASSERT(dst && src && count >= 0);
+
+ SkXfermodeProc proc = fProc;
+
+ if (NULL != proc) {
+ if (NULL == aa) {
+ for (int i = count - 1; i >= 0; --i) {
+ SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
+ dst[i] = SkToU8(SkGetPackedA32(res));
+ }
+ } else {
+ for (int i = count - 1; i >= 0; --i) {
+ unsigned a = aa[i];
+ if (0 != a) {
+ SkAlpha dstA = dst[i];
+ SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
+ unsigned A = SkGetPackedA32(res);
+ if (0xFF != a) {
+ A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
+ }
+ dst[i] = SkToU8(A);
+ }
+ }
+ }
+ }
+}
+
#if SK_SUPPORT_GPU
bool SkProcCoeffXfermode::asNewEffect(GrEffectRef** effect,
GrTexture* background) const {
@@ -1394,7 +1376,7 @@ bool SkProcCoeffXfermode::asNewEffect(GrEffectRef** effect,
}
#endif
-void SkProcCoeffXfermode::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkProcCoeffXfermode::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.write32(fMode);
}
@@ -1412,7 +1394,7 @@ const char* SkXfermode::ModeName(Mode mode) {
SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count);
}
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkProcCoeffXfermode::toString(SkString* str) const {
str->append("SkProcCoeffXfermode: ");
@@ -1443,16 +1425,19 @@ void SkProcCoeffXfermode::toString(SkString* str) const {
class SkClearXfermode : public SkProcCoeffXfermode {
public:
- SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
+ static SkClearXfermode* Create(const ProcCoeff& rec) {
+ return SkNEW_ARGS(SkClearXfermode, (rec));
+ }
virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
- SK_DEVELOPER_TO_STRING()
+ SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkClearXfermode)
private:
- SkClearXfermode(SkFlattenableReadBuffer& buffer)
+ SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
+ SkClearXfermode(SkReadBuffer& buffer)
: SkProcCoeffXfermode(buffer) {}
typedef SkProcCoeffXfermode INHERITED;
@@ -1495,7 +1480,7 @@ void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
}
}
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkClearXfermode::toString(SkString* str) const {
this->INHERITED::toString(str);
}
@@ -1505,16 +1490,19 @@ void SkClearXfermode::toString(SkString* str) const {
class SkSrcXfermode : public SkProcCoeffXfermode {
public:
- SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
+ static SkSrcXfermode* Create(const ProcCoeff& rec) {
+ return SkNEW_ARGS(SkSrcXfermode, (rec));
+ }
virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
- SK_DEVELOPER_TO_STRING()
+ SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSrcXfermode)
private:
- SkSrcXfermode(SkFlattenableReadBuffer& buffer)
+ SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
+ SkSrcXfermode(SkReadBuffer& buffer)
: SkProcCoeffXfermode(buffer) {}
typedef SkProcCoeffXfermode INHERITED;
@@ -1562,7 +1550,7 @@ void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
}
}
}
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkSrcXfermode::toString(SkString* str) const {
this->INHERITED::toString(str);
}
@@ -1572,15 +1560,18 @@ void SkSrcXfermode::toString(SkString* str) const {
class SkDstInXfermode : public SkProcCoeffXfermode {
public:
- SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
+ static SkDstInXfermode* Create(const ProcCoeff& rec) {
+ return SkNEW_ARGS(SkDstInXfermode, (rec));
+ }
virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
- SK_DEVELOPER_TO_STRING()
+ SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstInXfermode)
private:
- SkDstInXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
+ SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
+ SkDstInXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {}
typedef SkProcCoeffXfermode INHERITED;
};
@@ -1605,7 +1596,7 @@ void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
} while (--count != 0);
}
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkDstInXfermode::toString(SkString* str) const {
this->INHERITED::toString(str);
}
@@ -1615,15 +1606,18 @@ void SkDstInXfermode::toString(SkString* str) const {
class SkDstOutXfermode : public SkProcCoeffXfermode {
public:
- SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
+ static SkDstOutXfermode* Create(const ProcCoeff& rec) {
+ return SkNEW_ARGS(SkDstOutXfermode, (rec));
+ }
virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
- SK_DEVELOPER_TO_STRING()
+ SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstOutXfermode)
private:
- SkDstOutXfermode(SkFlattenableReadBuffer& buffer)
+ SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
+ SkDstOutXfermode(SkReadBuffer& buffer)
: INHERITED(buffer) {}
typedef SkProcCoeffXfermode INHERITED;
@@ -1649,7 +1643,7 @@ void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
} while (--count != 0);
}
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkDstOutXfermode::toString(SkString* str) const {
this->INHERITED::toString(str);
}
@@ -1657,83 +1651,72 @@ void SkDstOutXfermode::toString(SkString* str) const {
///////////////////////////////////////////////////////////////////////////////
-SK_DECLARE_STATIC_MUTEX(gCachedXfermodesMutex);
-static SkXfermode* gCachedXfermodes[SkXfermode::kLastMode + 1];
+extern SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec, SkXfermode::Mode mode);
+extern SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode);
-void SkXfermode::Term() {
- SkAutoMutexAcquire ac(gCachedXfermodesMutex);
+// Technically, can't be static and passed as a template parameter. So we use anonymous namespace.
+namespace {
+SkXfermode* create_mode(int iMode) {
+ SkXfermode::Mode mode = (SkXfermode::Mode)iMode;
- for (size_t i = 0; i < SK_ARRAY_COUNT(gCachedXfermodes); ++i) {
- SkSafeUnref(gCachedXfermodes[i]);
- gCachedXfermodes[i] = NULL;
+ ProcCoeff rec = gProcCoeffs[mode];
+ SkXfermodeProc pp = SkPlatformXfermodeProcFactory(mode);
+ if (pp != NULL) {
+ rec.fProc = pp;
}
+
+ SkXfermode* xfer = NULL;
+ // check if we have a platform optim for that
+ SkProcCoeffXfermode* xfm = SkPlatformXfermodeFactory(rec, mode);
+ if (xfm != NULL) {
+ xfer = xfm;
+ } else {
+ // All modes can in theory be represented by the ProcCoeff rec, since
+ // it contains function ptrs. However, a few modes are both simple and
+ // commonly used, so we call those out for their own subclasses here.
+ switch (mode) {
+ case SkXfermode::kClear_Mode:
+ xfer = SkClearXfermode::Create(rec);
+ break;
+ case SkXfermode::kSrc_Mode:
+ xfer = SkSrcXfermode::Create(rec);
+ break;
+ case SkXfermode::kSrcOver_Mode:
+ SkASSERT(false); // should not land here
+ break;
+ case SkXfermode::kDstIn_Mode:
+ xfer = SkDstInXfermode::Create(rec);
+ break;
+ case SkXfermode::kDstOut_Mode:
+ xfer = SkDstOutXfermode::Create(rec);
+ break;
+ default:
+ // no special-case, just rely in the rec and its function-ptrs
+ xfer = SkProcCoeffXfermode::Create(rec, mode);
+ break;
+ }
+ }
+ return xfer;
}
+} // namespace
-extern SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec,
- SkXfermode::Mode mode);
-extern SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode);
SkXfermode* SkXfermode::Create(Mode mode) {
SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
- SkASSERT(SK_ARRAY_COUNT(gCachedXfermodes) == kModeCount);
if ((unsigned)mode >= kModeCount) {
// report error
return NULL;
}
- // Skia's "defaut" mode is srcover. NULL in SkPaint is interpreted as srcover
+ // Skia's "default" mode is srcover. NULL in SkPaint is interpreted as srcover
// so we can just return NULL from the factory.
if (kSrcOver_Mode == mode) {
return NULL;
}
- // guard our access to gCachedXfermodes, since we may write into it
- SkAutoMutexAcquire ac(gCachedXfermodesMutex);
-
- SkXfermode* xfer = gCachedXfermodes[mode];
- if (NULL == xfer) {
- ProcCoeff rec = gProcCoeffs[mode];
-
- SkXfermodeProc pp = SkPlatformXfermodeProcFactory(mode);
-
- if (pp != NULL) {
- rec.fProc = pp;
- }
-
- // check if we have a platform optim for that
- SkProcCoeffXfermode* xfm = SkPlatformXfermodeFactory(rec, mode);
- if (xfm != NULL) {
- xfer = xfm;
- } else {
- // All modes can in theory be represented by the ProcCoeff rec, since
- // it contains function ptrs. However, a few modes are both simple and
- // commonly used, so we call those out for their own subclasses here.
- switch (mode) {
- case kClear_Mode:
- xfer = SkNEW_ARGS(SkClearXfermode, (rec));
- break;
- case kSrc_Mode:
- xfer = SkNEW_ARGS(SkSrcXfermode, (rec));
- break;
- case kSrcOver_Mode:
- SkASSERT(false); // should not land here
- break;
- case kDstIn_Mode:
- xfer = SkNEW_ARGS(SkDstInXfermode, (rec));
- break;
- case kDstOut_Mode:
- xfer = SkNEW_ARGS(SkDstOutXfermode, (rec));
- break;
- default:
- // no special-case, just rely in the rec and its function-ptrs
- xfer = SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode));
- break;
- }
- }
- gCachedXfermodes[mode] = xfer;
- }
- return SkSafeRef(xfer);
+ SK_DECLARE_STATIC_LAZY_PTR_ARRAY(SkXfermode, cached, kModeCount, create_mode);
+ return SkSafeRef(cached[mode]);
}
SkXfermodeProc SkXfermode::GetProc(Mode mode) {
@@ -1976,4 +1959,7 @@ SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
#if !SK_ARM_NEON_IS_NONE
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkNEONProcCoeffXfermode)
#endif
+#if defined(SK_CPU_X86) && !defined(SK_BUILD_FOR_IOS)
+ SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSSE2ProcCoeffXfermode)
+#endif
SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
diff --git a/chromium/third_party/skia/src/core/SkXfermode_proccoeff.h b/chromium/third_party/skia/src/core/SkXfermode_proccoeff.h
index 205edf2fa0c..7edf6654a43 100644
--- a/chromium/third_party/skia/src/core/SkXfermode_proccoeff.h
+++ b/chromium/third_party/skia/src/core/SkXfermode_proccoeff.h
@@ -2,7 +2,8 @@
#define SkXfermode_proccoeff_DEFINED
#include "SkXfermode.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
struct ProcCoeff {
SkXfermodeProc fProc;
@@ -12,16 +13,19 @@ struct ProcCoeff {
#define CANNOT_USE_COEFF SkXfermode::Coeff(-1)
-class SkProcCoeffXfermode : public SkProcXfermode {
+class SK_API SkProcCoeffXfermode : public SkXfermode {
public:
- SkProcCoeffXfermode(const ProcCoeff& rec, Mode mode)
- : INHERITED(rec.fProc) {
- fMode = mode;
- // these may be valid, or may be CANNOT_USE_COEFF
- fSrcCoeff = rec.fSC;
- fDstCoeff = rec.fDC;
+ static SkProcCoeffXfermode* Create(const ProcCoeff& rec, Mode mode) {
+ return SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode));
}
+ virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
+ const SkAlpha aa[]) const SK_OVERRIDE;
+ virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count,
+ const SkAlpha aa[]) const SK_OVERRIDE;
+ virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
+ const SkAlpha aa[]) const SK_OVERRIDE;
+
virtual bool asMode(Mode* mode) const SK_OVERRIDE;
virtual bool asCoeff(Coeff* sc, Coeff* dc) const SK_OVERRIDE;
@@ -31,23 +35,32 @@ public:
GrTexture* background) const SK_OVERRIDE;
#endif
- SK_DEVELOPER_TO_STRING()
+ SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkProcCoeffXfermode)
protected:
- SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer);
+ SkProcCoeffXfermode(const ProcCoeff& rec, Mode mode) {
+ fMode = mode;
+ fProc = rec.fProc;
+ // these may be valid, or may be CANNOT_USE_COEFF
+ fSrcCoeff = rec.fSC;
+ fDstCoeff = rec.fDC;
+ }
- virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE;
+ SkProcCoeffXfermode(SkReadBuffer& buffer);
- Mode getMode() const {
- return fMode;
- }
+ virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE;
+
+ Mode getMode() const { return fMode; }
+
+ SkXfermodeProc getProc() const { return fProc; }
private:
- Mode fMode;
- Coeff fSrcCoeff, fDstCoeff;
+ SkXfermodeProc fProc;
+ Mode fMode;
+ Coeff fSrcCoeff, fDstCoeff;
- typedef SkProcXfermode INHERITED;
+ typedef SkXfermode INHERITED;
};
#endif // #ifndef SkXfermode_proccoeff_DEFINED
diff --git a/chromium/third_party/skia/src/device/xps/SkXPSDevice.cpp b/chromium/third_party/skia/src/device/xps/SkXPSDevice.cpp
index e7f5a8c760b..bdc612fae6d 100644
--- a/chromium/third_party/skia/src/device/xps/SkXPSDevice.cpp
+++ b/chromium/third_party/skia/src/device/xps/SkXPSDevice.cpp
@@ -106,10 +106,11 @@ static HRESULT create_id(wchar_t* buffer, size_t bufferSize,
static SkBitmap make_fake_bitmap(int width, int height) {
SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kNo_Config, width, height);
+ bitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
return bitmap;
}
+// TODO: should inherit from SkBaseDevice instead of SkBitmapDevice...
SkXPSDevice::SkXPSDevice()
: SkBitmapDevice(make_fake_bitmap(10000, 10000))
, fCurrentPage(0) {
@@ -1159,10 +1160,6 @@ HRESULT SkXPSDevice::createXpsQuad(const SkPoint (&points)[4],
return S_OK;
}
-uint32_t SkXPSDevice::getDeviceCapabilities() {
- return kVector_Capability;
-}
-
void SkXPSDevice::clear(SkColor color) {
//TODO: override this for XPS
SkDEBUGF(("XPS clear not yet implemented."));
@@ -1592,11 +1589,7 @@ HRESULT SkXPSDevice::applyMask(const SkDraw& d,
xy[1] = (SkShader::TileMode)3;
SkBitmap bm;
- bm.setConfig(SkBitmap::kA8_Config,
- mask.fBounds.width(),
- mask.fBounds.height(),
- mask.fRowBytes);
- bm.setPixels(mask.fImage);
+ bm.installMaskPixels(mask);
SkTScopedComPtr<IXpsOMTileBrush> maskBrush;
HR(this->createXpsImageBrush(bm, m, xy, 0xFF, &maskBrush));
@@ -1699,9 +1692,7 @@ void SkXPSDevice::drawPath(const SkDraw& d,
}
platonicPath.transform(*prePathMatrix, skeletalPath);
} else {
- if (!matrix.preConcat(*prePathMatrix)) {
- return;
- }
+ matrix.preConcat(*prePathMatrix);
}
}
@@ -2242,9 +2233,6 @@ static void text_draw_init(const SkPaint& paint,
SkBitSet& glyphsUsed,
SkDraw& myDraw, SkXPSDrawProcs& procs) {
procs.fD1GProc = xps_draw_1_glyph;
-#if SK_DISTANCEFIELD_FONTS
- procs.fFlags = 0;
-#endif
size_t numGlyphGuess;
switch (paint.getTextEncoding()) {
case SkPaint::kUTF8_TextEncoding:
@@ -2261,7 +2249,7 @@ static void text_draw_init(const SkPaint& paint,
numGlyphGuess = byteLength / 2;
break;
default:
- SK_DEBUGBREAK(true);
+ SK_ALWAYSBREAK(true);
}
procs.xpsGlyphs.setReserve(numGlyphGuess);
procs.glyphUse = &glyphsUsed;
@@ -2416,16 +2404,7 @@ void SkXPSDevice::drawDevice(const SkDraw& d, SkBaseDevice* dev,
"Could not add layer to current visuals.");
}
-bool SkXPSDevice::onReadPixels(const SkBitmap& bitmap, int x, int y,
- SkCanvas::Config8888) {
- return false;
-}
-
-SkBaseDevice* SkXPSDevice::onCreateCompatibleDevice(SkBitmap::Config config,
- int width, int height,
- bool isOpaque,
- Usage usage) {
-
+SkBaseDevice* SkXPSDevice::onCreateDevice(const SkImageInfo&, Usage) {
//Conditional for bug compatibility with PDF device.
#if 0
if (SkBaseDevice::kGeneral_Usage == usage) {
@@ -2456,6 +2435,6 @@ SkXPSDevice::SkXPSDevice(IXpsOMObjectFactory* xpsFactory)
"Could not create canvas for layer.");
}
-bool SkXPSDevice::allowImageFilter(SkImageFilter*) {
+bool SkXPSDevice::allowImageFilter(const SkImageFilter*) {
return false;
}
diff --git a/chromium/third_party/skia/src/effects/Sk1DPathEffect.cpp b/chromium/third_party/skia/src/effects/Sk1DPathEffect.cpp
index 10a68b9f840..7354cdacb45 100644
--- a/chromium/third_party/skia/src/effects/Sk1DPathEffect.cpp
+++ b/chromium/third_party/skia/src/effects/Sk1DPathEffect.cpp
@@ -8,7 +8,8 @@
#include "Sk1DPathEffect.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkPathMeasure.h"
bool Sk1DPathEffect::filterPath(SkPath* dst, const SkPath& src,
@@ -146,7 +147,7 @@ static void morphpath(SkPath* dst, const SkPath& src, SkPathMeasure& meas,
}
}
-SkPath1DPathEffect::SkPath1DPathEffect(SkFlattenableReadBuffer& buffer) {
+SkPath1DPathEffect::SkPath1DPathEffect(SkReadBuffer& buffer) {
fAdvance = buffer.readScalar();
if (fAdvance > 0) {
buffer.readPath(&fPath);
@@ -164,7 +165,7 @@ SkScalar SkPath1DPathEffect::begin(SkScalar contourLength) const {
return fInitialOffset;
}
-void SkPath1DPathEffect::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkPath1DPathEffect::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeScalar(fAdvance);
if (fAdvance > 0) {
diff --git a/chromium/third_party/skia/src/effects/Sk2DPathEffect.cpp b/chromium/third_party/skia/src/effects/Sk2DPathEffect.cpp
index dc15f076d6b..252866c0541 100644
--- a/chromium/third_party/skia/src/effects/Sk2DPathEffect.cpp
+++ b/chromium/third_party/skia/src/effects/Sk2DPathEffect.cpp
@@ -8,7 +8,8 @@
#include "Sk2DPathEffect.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkPath.h"
#include "SkRegion.h"
@@ -67,12 +68,12 @@ void Sk2DPathEffect::end(SkPath* dst) const {}
///////////////////////////////////////////////////////////////////////////////
-void Sk2DPathEffect::flatten(SkFlattenableWriteBuffer& buffer) const {
+void Sk2DPathEffect::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeMatrix(fMatrix);
}
-Sk2DPathEffect::Sk2DPathEffect(SkFlattenableReadBuffer& buffer) {
+Sk2DPathEffect::Sk2DPathEffect(SkReadBuffer& buffer) {
buffer.readMatrix(&fMatrix);
fMatrixIsInvertible = fMatrix.invert(&fInverse);
}
@@ -101,11 +102,11 @@ void SkLine2DPathEffect::nextSpan(int u, int v, int ucount, SkPath* dst) const {
}
}
-SkLine2DPathEffect::SkLine2DPathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
+SkLine2DPathEffect::SkLine2DPathEffect(SkReadBuffer& buffer) : INHERITED(buffer) {
fWidth = buffer.readScalar();
}
-void SkLine2DPathEffect::flatten(SkFlattenableWriteBuffer &buffer) const {
+void SkLine2DPathEffect::flatten(SkWriteBuffer &buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeScalar(fWidth);
}
@@ -116,12 +117,12 @@ SkPath2DPathEffect::SkPath2DPathEffect(const SkMatrix& m, const SkPath& p)
: INHERITED(m), fPath(p) {
}
-SkPath2DPathEffect::SkPath2DPathEffect(SkFlattenableReadBuffer& buffer)
+SkPath2DPathEffect::SkPath2DPathEffect(SkReadBuffer& buffer)
: INHERITED(buffer) {
buffer.readPath(&fPath);
}
-void SkPath2DPathEffect::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkPath2DPathEffect::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writePath(fPath);
}
diff --git a/chromium/third_party/skia/src/effects/SkAlphaThresholdFilter.cpp b/chromium/third_party/skia/src/effects/SkAlphaThresholdFilter.cpp
new file mode 100644
index 00000000000..6fcd2b4351e
--- /dev/null
+++ b/chromium/third_party/skia/src/effects/SkAlphaThresholdFilter.cpp
@@ -0,0 +1,366 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkAlphaThresholdFilter.h"
+#include "SkBitmap.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
+#include "SkRegion.h"
+
+class SK_API SkAlphaThresholdFilterImpl : public SkImageFilter {
+public:
+ SkAlphaThresholdFilterImpl(const SkRegion& region, SkScalar innerThreshold, SkScalar outerThreshold);
+
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkAlphaThresholdFilterImpl)
+
+protected:
+ explicit SkAlphaThresholdFilterImpl(SkReadBuffer& buffer);
+ virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
+
+ virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
+ SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE;
+#if SK_SUPPORT_GPU
+ virtual bool asNewEffect(GrEffectRef** effect, GrTexture* texture,
+ const SkMatrix& matrix, const SkIRect& bounds) const SK_OVERRIDE;
+#endif
+
+private:
+ SkRegion fRegion;
+ SkScalar fInnerThreshold;
+ SkScalar fOuterThreshold;
+ typedef SkImageFilter INHERITED;
+};
+
+SkImageFilter* SkAlphaThresholdFilter::Create(const SkRegion& region,
+ SkScalar innerThreshold,
+ SkScalar outerThreshold) {
+ return SkNEW_ARGS(SkAlphaThresholdFilterImpl, (region, innerThreshold, outerThreshold));
+}
+
+#if SK_SUPPORT_GPU
+#include "GrContext.h"
+#include "GrCoordTransform.h"
+#include "GrEffect.h"
+#include "gl/GrGLEffect.h"
+#include "GrTBackendEffectFactory.h"
+#include "GrTextureAccess.h"
+
+#include "SkGr.h"
+
+class GrGLAlphaThresholdEffect;
+
+class AlphaThresholdEffect : public GrEffect {
+
+public:
+ static GrEffectRef* Create(GrTexture* texture,
+ GrTexture* maskTexture,
+ float innerThreshold,
+ float outerThreshold) {
+ AutoEffectUnref effect(SkNEW_ARGS(AlphaThresholdEffect, (texture,
+ maskTexture,
+ innerThreshold,
+ outerThreshold)));
+ return CreateEffectRef(effect);
+ }
+
+ virtual ~AlphaThresholdEffect() {};
+
+ static const char* Name() { return "Alpha Threshold"; }
+
+ virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
+ virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
+
+ float innerThreshold() const { return fInnerThreshold; }
+ float outerThreshold() const { return fOuterThreshold; }
+
+ typedef GrGLAlphaThresholdEffect GLEffect;
+
+private:
+ AlphaThresholdEffect(GrTexture* texture,
+ GrTexture* maskTexture,
+ float innerThreshold,
+ float outerThreshold)
+ : fInnerThreshold(innerThreshold)
+ , fOuterThreshold(outerThreshold)
+ , fImageCoordTransform(kLocal_GrCoordSet, MakeDivByTextureWHMatrix(texture), texture)
+ , fImageTextureAccess(texture)
+ , fMaskCoordTransform(kLocal_GrCoordSet, MakeDivByTextureWHMatrix(maskTexture), maskTexture)
+ , fMaskTextureAccess(maskTexture) {
+ this->addCoordTransform(&fImageCoordTransform);
+ this->addTextureAccess(&fImageTextureAccess);
+ this->addCoordTransform(&fMaskCoordTransform);
+ this->addTextureAccess(&fMaskTextureAccess);
+ }
+
+ virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
+
+ GR_DECLARE_EFFECT_TEST;
+
+ float fInnerThreshold;
+ float fOuterThreshold;
+ GrCoordTransform fImageCoordTransform;
+ GrTextureAccess fImageTextureAccess;
+ GrCoordTransform fMaskCoordTransform;
+ GrTextureAccess fMaskTextureAccess;
+
+ typedef GrEffect INHERITED;
+};
+
+class GrGLAlphaThresholdEffect : public GrGLEffect {
+public:
+ GrGLAlphaThresholdEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
+
+ virtual void emitCode(GrGLShaderBuilder*,
+ const GrDrawEffect&,
+ EffectKey,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray&) SK_OVERRIDE;
+
+ virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
+
+private:
+
+ GrGLUniformManager::UniformHandle fInnerThresholdVar;
+ GrGLUniformManager::UniformHandle fOuterThresholdVar;
+
+ typedef GrGLEffect INHERITED;
+};
+
+GrGLAlphaThresholdEffect::GrGLAlphaThresholdEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
+ : INHERITED(factory) {
+}
+
+void GrGLAlphaThresholdEffect::emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect&,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray& coords,
+ const TextureSamplerArray& samplers) {
+ SkString coords2D = builder->ensureFSCoords2D(coords, 0);
+ SkString maskCoords2D = builder->ensureFSCoords2D(coords, 1);
+ fInnerThresholdVar = builder->addUniform(
+ GrGLShaderBuilder::kFragment_Visibility,
+ kFloat_GrSLType, "inner_threshold");
+ fOuterThresholdVar = builder->addUniform(
+ GrGLShaderBuilder::kFragment_Visibility,
+ kFloat_GrSLType, "outer_threshold");
+
+ builder->fsCodeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str());
+ builder->fsCodeAppendf("\t\tvec2 mask_coord = %s;\n", maskCoords2D.c_str());
+ builder->fsCodeAppend("\t\tvec4 input_color = ");
+ builder->fsAppendTextureLookup(samplers[0], "coord");
+ builder->fsCodeAppend(";\n");
+ builder->fsCodeAppend("\t\tvec4 mask_color = ");
+ builder->fsAppendTextureLookup(samplers[1], "mask_coord");
+ builder->fsCodeAppend(";\n");
+
+ builder->fsCodeAppendf("\t\tfloat inner_thresh = %s;\n",
+ builder->getUniformCStr(fInnerThresholdVar));
+ builder->fsCodeAppendf("\t\tfloat outer_thresh = %s;\n",
+ builder->getUniformCStr(fOuterThresholdVar));
+ builder->fsCodeAppend("\t\tfloat mask = mask_color.a;\n");
+
+ builder->fsCodeAppend("vec4 color = input_color;\n");
+ builder->fsCodeAppend("\t\tif (mask < 0.5) {\n"
+ "\t\t\tif (color.a > outer_thresh) {\n"
+ "\t\t\t\tfloat scale = outer_thresh / color.a;\n"
+ "\t\t\t\tcolor.rgb *= scale;\n"
+ "\t\t\t\tcolor.a = outer_thresh;\n"
+ "\t\t\t}\n"
+ "\t\t} else if (color.a < inner_thresh) {\n"
+ "\t\t\tfloat scale = inner_thresh / max(0.001, color.a);\n"
+ "\t\t\tcolor.rgb *= scale;\n"
+ "\t\t\tcolor.a = inner_thresh;\n"
+ "\t\t}\n");
+
+ builder->fsCodeAppendf("%s = %s;\n", outputColor,
+ (GrGLSLExpr4(inputColor) * GrGLSLExpr4("color")).c_str());
+}
+
+void GrGLAlphaThresholdEffect::setData(const GrGLUniformManager& uman,
+ const GrDrawEffect& drawEffect) {
+ const AlphaThresholdEffect& alpha_threshold =
+ drawEffect.castEffect<AlphaThresholdEffect>();
+ uman.set1f(fInnerThresholdVar, alpha_threshold.innerThreshold());
+ uman.set1f(fOuterThresholdVar, alpha_threshold.outerThreshold());
+}
+
+/////////////////////////////////////////////////////////////////////
+
+GR_DEFINE_EFFECT_TEST(AlphaThresholdEffect);
+
+GrEffectRef* AlphaThresholdEffect::TestCreate(SkRandom* random,
+ GrContext* context,
+ const GrDrawTargetCaps&,
+ GrTexture** textures) {
+ GrTexture* bmpTex = textures[GrEffectUnitTest::kSkiaPMTextureIdx];
+ GrTexture* maskTex = textures[GrEffectUnitTest::kAlphaTextureIdx];
+ float inner_thresh = random->nextUScalar1();
+ float outer_thresh = random->nextUScalar1();
+ return AlphaThresholdEffect::Create(bmpTex, maskTex, inner_thresh, outer_thresh);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+const GrBackendEffectFactory& AlphaThresholdEffect::getFactory() const {
+ return GrTBackendEffectFactory<AlphaThresholdEffect>::getInstance();
+}
+
+bool AlphaThresholdEffect::onIsEqual(const GrEffect& sBase) const {
+ const AlphaThresholdEffect& s = CastEffect<AlphaThresholdEffect>(sBase);
+ return (this->texture(0) == s.texture(0) &&
+ this->fInnerThreshold == s.fInnerThreshold &&
+ this->fOuterThreshold == s.fOuterThreshold);
+}
+
+void AlphaThresholdEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
+ if ((*validFlags & kA_GrColorComponentFlag) && 0xFF == GrColorUnpackA(*color) &&
+ GrPixelConfigIsOpaque(this->texture(0)->config())) {
+ *validFlags = kA_GrColorComponentFlag;
+ } else {
+ *validFlags = 0;
+ }
+}
+
+#endif
+
+SkAlphaThresholdFilterImpl::SkAlphaThresholdFilterImpl(SkReadBuffer& buffer)
+ : INHERITED(1, buffer) {
+ fInnerThreshold = buffer.readScalar();
+ fOuterThreshold = buffer.readScalar();
+ buffer.readRegion(&fRegion);
+}
+
+SkAlphaThresholdFilterImpl::SkAlphaThresholdFilterImpl(const SkRegion& region,
+ SkScalar innerThreshold,
+ SkScalar outerThreshold)
+ : INHERITED(0)
+ , fRegion(region)
+ , fInnerThreshold(innerThreshold)
+ , fOuterThreshold(outerThreshold) {
+}
+
+#if SK_SUPPORT_GPU
+bool SkAlphaThresholdFilterImpl::asNewEffect(GrEffectRef** effect, GrTexture* texture,
+ const SkMatrix& in_matrix, const SkIRect&) const {
+ if (effect) {
+ GrContext* context = texture->getContext();
+ GrTextureDesc maskDesc;
+ if (context->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
+ maskDesc.fConfig = kAlpha_8_GrPixelConfig;
+ } else {
+ maskDesc.fConfig = kRGBA_8888_GrPixelConfig;
+ }
+ maskDesc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
+ // Add one pixel of border to ensure that clamp mode will be all zeros
+ // the outside.
+ maskDesc.fWidth = texture->width();
+ maskDesc.fHeight = texture->height();
+ GrAutoScratchTexture ast(context, maskDesc, GrContext::kApprox_ScratchTexMatch);
+ GrTexture* maskTexture = ast.texture();
+ if (NULL == maskTexture) {
+ return false;
+ }
+
+ {
+ GrContext::AutoRenderTarget art(context, ast.texture()->asRenderTarget());
+ GrPaint grPaint;
+ grPaint.setBlendFunc(kOne_GrBlendCoeff, kZero_GrBlendCoeff);
+ SkRegion::Iterator iter(fRegion);
+ context->clear(NULL, 0x0, true);
+
+ SkMatrix old_matrix = context->getMatrix();
+ context->setMatrix(in_matrix);
+
+ while (!iter.done()) {
+ SkRect rect = SkRect::Make(iter.rect());
+ context->drawRect(grPaint, rect);
+ iter.next();
+ }
+ context->setMatrix(old_matrix);
+ }
+
+ *effect = AlphaThresholdEffect::Create(texture,
+ maskTexture,
+ fInnerThreshold,
+ fOuterThreshold);
+ }
+ return true;
+}
+#endif
+
+void SkAlphaThresholdFilterImpl::flatten(SkWriteBuffer& buffer) const {
+ this->INHERITED::flatten(buffer);
+ buffer.writeScalar(fInnerThreshold);
+ buffer.writeScalar(fOuterThreshold);
+ buffer.writeRegion(fRegion);
+}
+
+bool SkAlphaThresholdFilterImpl::onFilterImage(Proxy*, const SkBitmap& src,
+ const Context& ctx, SkBitmap* dst,
+ SkIPoint* offset) const {
+ SkASSERT(src.colorType() == kN32_SkColorType);
+
+ if (src.colorType() != kN32_SkColorType) {
+ return false;
+ }
+
+ SkMatrix localInverse;
+ if (!ctx.ctm().invert(&localInverse)) {
+ return false;
+ }
+
+ SkAutoLockPixels alp(src);
+ SkASSERT(src.getPixels());
+ if (!src.getPixels() || src.width() <= 0 || src.height() <= 0) {
+ return false;
+ }
+
+ if (!dst->allocPixels(src.info())) {
+ return false;
+ }
+
+ U8CPU innerThreshold = (U8CPU)(fInnerThreshold * 0xFF);
+ U8CPU outerThreshold = (U8CPU)(fOuterThreshold * 0xFF);
+ SkColor* sptr = src.getAddr32(0, 0);
+ SkColor* dptr = dst->getAddr32(0, 0);
+ int width = src.width(), height = src.height();
+ for (int y = 0; y < height; ++y) {
+ for (int x = 0; x < width; ++x) {
+ const SkColor& source = sptr[y * width + x];
+ SkColor output_color(source);
+ SkPoint position;
+ localInverse.mapXY((SkScalar)x, (SkScalar)y, &position);
+ if (fRegion.contains((int32_t)position.x(), (int32_t)position.y())) {
+ if (SkColorGetA(source) < innerThreshold) {
+ U8CPU alpha = SkColorGetA(source);
+ if (alpha == 0)
+ alpha = 1;
+ float scale = (float)innerThreshold / alpha;
+ output_color = SkColorSetARGB(innerThreshold,
+ (U8CPU)(SkColorGetR(source) * scale),
+ (U8CPU)(SkColorGetG(source) * scale),
+ (U8CPU)(SkColorGetB(source) * scale));
+ }
+ } else {
+ if (SkColorGetA(source) > outerThreshold) {
+ float scale = (float)outerThreshold / SkColorGetA(source);
+ output_color = SkColorSetARGB(outerThreshold,
+ (U8CPU)(SkColorGetR(source) * scale),
+ (U8CPU)(SkColorGetG(source) * scale),
+ (U8CPU)(SkColorGetB(source) * scale));
+ }
+ }
+ dptr[y * dst->width() + x] = output_color;
+ }
+ }
+
+ return true;
+}
diff --git a/chromium/third_party/skia/src/effects/SkArithmeticMode.cpp b/chromium/third_party/skia/src/effects/SkArithmeticMode.cpp
index 2cec1536fe5..41cc2667416 100644
--- a/chromium/third_party/skia/src/effects/SkArithmeticMode.cpp
+++ b/chromium/third_party/skia/src/effects/SkArithmeticMode.cpp
@@ -7,7 +7,8 @@
#include "SkArithmeticMode.h"
#include "SkColorPriv.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkString.h"
#include "SkUnPreMultiply.h"
#if SK_SUPPORT_GPU
@@ -15,24 +16,21 @@
#include "GrCoordTransform.h"
#include "gl/GrGLEffect.h"
#include "GrTBackendEffectFactory.h"
-#include "SkImageFilterUtils.h"
#endif
static const bool gUseUnpremul = false;
class SkArithmeticMode_scalar : public SkXfermode {
public:
- SkArithmeticMode_scalar(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4) {
- fK[0] = k1;
- fK[1] = k2;
- fK[2] = k3;
- fK[3] = k4;
+ static SkArithmeticMode_scalar* Create(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4,
+ bool enforcePMColor) {
+ return SkNEW_ARGS(SkArithmeticMode_scalar, (k1, k2, k3, k4, enforcePMColor));
}
virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
const SkAlpha aa[]) const SK_OVERRIDE;
- SK_DEVELOPER_TO_STRING()
+ SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkArithmeticMode_scalar)
#if SK_SUPPORT_GPU
@@ -40,21 +38,32 @@ public:
#endif
private:
- SkArithmeticMode_scalar(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
+ SkArithmeticMode_scalar(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4, bool enforcePMColor) {
+ fK[0] = k1;
+ fK[1] = k2;
+ fK[2] = k3;
+ fK[3] = k4;
+ fEnforcePMColor = enforcePMColor;
+ }
+
+ SkArithmeticMode_scalar(SkReadBuffer& buffer) : INHERITED(buffer) {
fK[0] = buffer.readScalar();
fK[1] = buffer.readScalar();
fK[2] = buffer.readScalar();
fK[3] = buffer.readScalar();
+ fEnforcePMColor = buffer.readBool();
}
- virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
+ virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE {
INHERITED::flatten(buffer);
buffer.writeScalar(fK[0]);
buffer.writeScalar(fK[1]);
buffer.writeScalar(fK[2]);
buffer.writeScalar(fK[3]);
+ buffer.writeBool(fEnforcePMColor);
}
SkScalar fK[4];
+ bool fEnforcePMColor;
typedef SkXfermode INHERITED;
};
@@ -141,11 +150,13 @@ void SkArithmeticMode_scalar::xfer32(SkPMColor dst[], const SkPMColor src[],
} else {
a = arith(k1, k2, k3, k4, SkGetPackedA32(sc), SkGetPackedA32(dc));
r = arith(k1, k2, k3, k4, SkGetPackedR32(sc), SkGetPackedR32(dc));
- r = SkMin32(r, a);
g = arith(k1, k2, k3, k4, SkGetPackedG32(sc), SkGetPackedG32(dc));
- g = SkMin32(g, a);
b = arith(k1, k2, k3, k4, SkGetPackedB32(sc), SkGetPackedB32(dc));
- b = SkMin32(b, a);
+ if (fEnforcePMColor) {
+ r = SkMin32(r, a);
+ g = SkMin32(g, a);
+ b = SkMin32(b, a);
+ }
}
// apply antialias coverage if necessary
@@ -164,50 +175,37 @@ void SkArithmeticMode_scalar::xfer32(SkPMColor dst[], const SkPMColor src[],
g = SkAlphaMul(g, scale);
b = SkAlphaMul(b, scale);
}
- dst[i] = SkPackARGB32(a, r, g, b);
+ dst[i] = fEnforcePMColor ? SkPackARGB32(a, r, g, b) : SkPackARGB32NoCheck(a, r, g, b);
}
}
}
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkArithmeticMode_scalar::toString(SkString* str) const {
str->append("SkArithmeticMode_scalar: ");
for (int i = 0; i < 4; ++i) {
str->appendScalar(fK[i]);
- if (i < 3) {
- str->append(" ");
- }
+ str->append(" ");
}
+ str->appendS32(fEnforcePMColor ? 1 : 0);
}
#endif
///////////////////////////////////////////////////////////////////////////////
static bool fitsInBits(SkScalar x, int bits) {
-#ifdef SK_SCALAR_IS_FIXED
- x = SkAbs32(x);
- x += 1 << 7;
- x >>= 8;
- return x < (1 << (bits - 1));
-#else
return SkScalarAbs(x) < (1 << (bits - 1));
-#endif
}
#if 0 // UNUSED
static int32_t toDot8(SkScalar x) {
-#ifdef SK_SCALAR_IS_FIXED
- x += 1 << 7;
- x >>= 8;
- return x;
-#else
return (int32_t)(x * 256);
-#endif
}
#endif
SkXfermode* SkArithmeticMode::Create(SkScalar k1, SkScalar k2,
- SkScalar k3, SkScalar k4) {
+ SkScalar k3, SkScalar k4,
+ bool enforcePMColor) {
if (fitsInBits(k1, 8) && fitsInBits(k2, 16) &&
fitsInBits(k2, 16) && fitsInBits(k2, 24)) {
@@ -228,7 +226,7 @@ SkXfermode* SkArithmeticMode::Create(SkScalar k1, SkScalar k2,
return SkNEW_ARGS(SkArithmeticMode_linear, (i2, i3, i4));
#endif
}
- return SkNEW_ARGS(SkArithmeticMode_scalar, (k1, k2, k3, k4));
+ return SkArithmeticMode_scalar::Create(k1, k2, k3, k4, enforcePMColor);
}
@@ -251,8 +249,11 @@ public:
virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
+ static EffectKey GenKey(const GrDrawEffect&, const GrGLCaps& caps);
+
private:
GrGLUniformManager::UniformHandle fKUni;
+ bool fEnforcePMColor;
typedef GrGLEffect INHERITED;
};
@@ -261,8 +262,10 @@ private:
class GrArithmeticEffect : public GrEffect {
public:
- static GrEffectRef* Create(float k1, float k2, float k3, float k4, GrTexture* background) {
- AutoEffectUnref effect(SkNEW_ARGS(GrArithmeticEffect, (k1, k2, k3, k4, background)));
+ static GrEffectRef* Create(float k1, float k2, float k3, float k4, bool enforcePMColor,
+ GrTexture* background) {
+ AutoEffectUnref effect(SkNEW_ARGS(GrArithmeticEffect, (k1, k2, k3, k4, enforcePMColor,
+ background)));
return CreateEffectRef(effect);
}
@@ -280,12 +283,15 @@ public:
float k2() const { return fK2; }
float k3() const { return fK3; }
float k4() const { return fK4; }
+ bool enforcePMColor() const { return fEnforcePMColor; }
private:
virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
- GrArithmeticEffect(float k1, float k2, float k3, float k4, GrTexture* background);
+ GrArithmeticEffect(float k1, float k2, float k3, float k4, bool enforcePMColor,
+ GrTexture* background);
float fK1, fK2, fK3, fK4;
+ bool fEnforcePMColor;
GrCoordTransform fBackgroundTransform;
GrTextureAccess fBackgroundAccess;
@@ -297,8 +303,8 @@ private:
///////////////////////////////////////////////////////////////////////////////
GrArithmeticEffect::GrArithmeticEffect(float k1, float k2, float k3, float k4,
- GrTexture* background)
- : fK1(k1), fK2(k2), fK3(k3), fK4(k4) {
+ bool enforcePMColor, GrTexture* background)
+ : fK1(k1), fK2(k2), fK3(k3), fK4(k4), fEnforcePMColor(enforcePMColor) {
if (background) {
fBackgroundTransform.reset(kLocal_GrCoordSet, background);
this->addCoordTransform(&fBackgroundTransform);
@@ -318,6 +324,7 @@ bool GrArithmeticEffect::onIsEqual(const GrEffect& sBase) const {
fK2 == s.fK2 &&
fK3 == s.fK3 &&
fK4 == s.fK4 &&
+ fEnforcePMColor == s.fEnforcePMColor &&
backgroundTexture() == s.backgroundTexture();
}
@@ -334,7 +341,8 @@ void GrArithmeticEffect::getConstantColorComponents(GrColor* color, uint32_t* va
GrGLArithmeticEffect::GrGLArithmeticEffect(const GrBackendEffectFactory& factory,
const GrDrawEffect& drawEffect)
- : INHERITED(factory) {
+ : INHERITED(factory),
+ fEnforcePMColor(true) {
}
GrGLArithmeticEffect::~GrGLArithmeticEffect() {
@@ -383,7 +391,7 @@ void GrGLArithmeticEffect::emitCode(GrGLShaderBuilder* builder,
builder->fsCodeAppendf("\t\t%s = clamp(%s, 0.0, 1.0);\n", outputColor, outputColor);
if (gUseUnpremul) {
builder->fsCodeAppendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor);
- } else {
+ } else if (fEnforcePMColor) {
builder->fsCodeAppendf("\t\t%s.rgb = min(%s.rgb, %s.a);\n", outputColor, outputColor, outputColor);
}
}
@@ -391,6 +399,17 @@ void GrGLArithmeticEffect::emitCode(GrGLShaderBuilder* builder,
void GrGLArithmeticEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) {
const GrArithmeticEffect& arith = drawEffect.castEffect<GrArithmeticEffect>();
uman.set4f(fKUni, arith.k1(), arith.k2(), arith.k3(), arith.k4());
+ fEnforcePMColor = arith.enforcePMColor();
+}
+
+GrGLEffect::EffectKey GrGLArithmeticEffect::GenKey(const GrDrawEffect& drawEffect,
+ const GrGLCaps&) {
+ const GrArithmeticEffect& arith = drawEffect.castEffect<GrArithmeticEffect>();
+ EffectKey key = arith.enforcePMColor() ? 1 : 0;
+ if (arith.backgroundTexture()) {
+ key |= 2;
+ }
+ return key;
}
GrEffectRef* GrArithmeticEffect::TestCreate(SkRandom* rand,
@@ -401,8 +420,10 @@ GrEffectRef* GrArithmeticEffect::TestCreate(SkRandom* rand,
float k2 = rand->nextF();
float k3 = rand->nextF();
float k4 = rand->nextF();
+ bool enforcePMColor = rand->nextBool();
- AutoEffectUnref gEffect(SkNEW_ARGS(GrArithmeticEffect, (k1, k2, k3, k4, NULL)));
+ AutoEffectUnref gEffect(SkNEW_ARGS(GrArithmeticEffect,
+ (k1, k2, k3, k4, enforcePMColor, NULL)));
return CreateEffectRef(gEffect);
}
@@ -414,6 +435,7 @@ bool SkArithmeticMode_scalar::asNewEffect(GrEffectRef** effect, GrTexture* backg
SkScalarToFloat(fK[1]),
SkScalarToFloat(fK[2]),
SkScalarToFloat(fK[3]),
+ fEnforcePMColor,
background);
}
return true;
diff --git a/chromium/third_party/skia/src/effects/SkAvoidXfermode.cpp b/chromium/third_party/skia/src/effects/SkAvoidXfermode.cpp
index d76efb839e4..ffe6a219ab8 100644
--- a/chromium/third_party/skia/src/effects/SkAvoidXfermode.cpp
+++ b/chromium/third_party/skia/src/effects/SkAvoidXfermode.cpp
@@ -7,7 +7,8 @@
#include "SkAvoidXfermode.h"
#include "SkColorPriv.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkString.h"
SkAvoidXfermode::SkAvoidXfermode(SkColor opColor, U8CPU tolerance, Mode mode) {
@@ -20,14 +21,14 @@ SkAvoidXfermode::SkAvoidXfermode(SkColor opColor, U8CPU tolerance, Mode mode) {
fMode = mode;
}
-SkAvoidXfermode::SkAvoidXfermode(SkFlattenableReadBuffer& buffer)
+SkAvoidXfermode::SkAvoidXfermode(SkReadBuffer& buffer)
: INHERITED(buffer) {
fOpColor = buffer.readColor();
fDistMul = buffer.readUInt();
fMode = (Mode)buffer.readUInt();
}
-void SkAvoidXfermode::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkAvoidXfermode::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeColor(fOpColor);
@@ -166,7 +167,7 @@ void SkAvoidXfermode::xferA8(SkAlpha dst[], const SkPMColor src[], int count,
// override in subclass
}
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkAvoidXfermode::toString(SkString* str) const {
str->append("SkAvoidXfermode: opColor: ");
str->appendHex(fOpColor);
diff --git a/chromium/third_party/skia/src/effects/SkBicubicImageFilter.cpp b/chromium/third_party/skia/src/effects/SkBicubicImageFilter.cpp
index 87ff046fc18..ea2d13e723e 100644
--- a/chromium/third_party/skia/src/effects/SkBicubicImageFilter.cpp
+++ b/chromium/third_party/skia/src/effects/SkBicubicImageFilter.cpp
@@ -8,7 +8,8 @@
#include "SkBicubicImageFilter.h"
#include "SkBitmap.h"
#include "SkColorPriv.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkMatrix.h"
#include "SkRect.h"
#include "SkUnPreMultiply.h"
@@ -17,7 +18,6 @@
#include "effects/GrBicubicEffect.h"
#include "GrContext.h"
#include "GrTexture.h"
-#include "SkImageFilterUtils.h"
#endif
#define DS(x) SkDoubleToScalar(x)
@@ -40,7 +40,7 @@ SkBicubicImageFilter* SkBicubicImageFilter::CreateMitchell(const SkSize& scale,
return SkNEW_ARGS(SkBicubicImageFilter, (scale, gMitchellCoefficients, input));
}
-SkBicubicImageFilter::SkBicubicImageFilter(SkFlattenableReadBuffer& buffer)
+SkBicubicImageFilter::SkBicubicImageFilter(SkReadBuffer& buffer)
: INHERITED(1, buffer) {
SkDEBUGCODE(bool success =) buffer.readScalarArray(fCoefficients, 16);
SkASSERT(success);
@@ -52,7 +52,7 @@ SkBicubicImageFilter::SkBicubicImageFilter(SkFlattenableReadBuffer& buffer)
(fScale.fHeight >= 0));
}
-void SkBicubicImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkBicubicImageFilter::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeScalarArray(fCoefficients, 16);
buffer.writeScalar(fScale.fWidth);
@@ -82,15 +82,16 @@ inline SkPMColor cubicBlend(const SkScalar c[16], SkScalar t, SkPMColor c0, SkPM
bool SkBicubicImageFilter::onFilterImage(Proxy* proxy,
const SkBitmap& source,
- const SkMatrix& matrix,
+ const Context& ctx,
SkBitmap* result,
- SkIPoint* loc) {
+ SkIPoint* offset) const {
SkBitmap src = source;
- if (getInput(0) && !getInput(0)->filterImage(proxy, source, matrix, &src, loc)) {
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
+ if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctx, &src, &srcOffset)) {
return false;
}
- if (src.config() != SkBitmap::kARGB_8888_Config) {
+ if (src.colorType() != kN32_SkColorType) {
return false;
}
@@ -106,14 +107,13 @@ bool SkBicubicImageFilter::onFilterImage(Proxy* proxy,
if (dstIRect.isEmpty()) {
return false;
}
- result->setConfig(src.config(), dstIRect.width(), dstIRect.height());
- result->allocPixels();
- if (!result->getPixels()) {
+ if (!result->allocPixels(src.info().makeWH(dstIRect.width(), dstIRect.height()))) {
return false;
}
SkRect srcRect;
src.getBounds(&srcRect);
+ srcRect.offset(SkPoint::Make(SkIntToScalar(srcOffset.fX), SkIntToScalar(srcOffset.fY)));
SkMatrix inverse;
inverse.setRectToRect(dstRect, srcRect, SkMatrix::kFill_ScaleToFit);
inverse.postTranslate(-0.5f, -0.5f);
@@ -158,6 +158,8 @@ bool SkBicubicImageFilter::onFilterImage(Proxy* proxy,
*dptr++ = cubicBlend(fCoefficients, fracty, s0, s1, s2, s3);
}
}
+ offset->fX = dstIRect.fLeft;
+ offset->fY = dstIRect.fTop;
return true;
}
@@ -165,10 +167,10 @@ bool SkBicubicImageFilter::onFilterImage(Proxy* proxy,
#if SK_SUPPORT_GPU
-bool SkBicubicImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
- SkBitmap* result, SkIPoint* offset) {
- SkBitmap srcBM;
- if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &srcBM, offset)) {
+bool SkBicubicImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx,
+ SkBitmap* result, SkIPoint* offset) const {
+ SkBitmap srcBM = src;
+ if (getInput(0) && !getInput(0)->getInputResultGPU(proxy, src, ctx, &srcBM, offset)) {
return false;
}
GrTexture* srcTexture = srcBM.getTexture();
@@ -194,7 +196,8 @@ bool SkBicubicImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, con
SkRect srcRect;
srcBM.getBounds(&srcRect);
context->drawRectToRect(paint, dstRect, srcRect);
- return SkImageFilterUtils::WrapTexture(dst, desc.fWidth, desc.fHeight, result);
+ WrapTexture(dst, desc.fWidth, desc.fHeight, result);
+ return true;
}
#endif
diff --git a/chromium/third_party/skia/src/effects/SkBitmapAlphaThresholdShader.cpp b/chromium/third_party/skia/src/effects/SkBitmapAlphaThresholdShader.cpp
deleted file mode 100644
index 44db167d4ec..00000000000
--- a/chromium/third_party/skia/src/effects/SkBitmapAlphaThresholdShader.cpp
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Copyright 2013 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkBitmapAlphaThresholdShader.h"
-
-class BATShader : public SkShader {
-public:
- SK_DECLARE_INST_COUNT(BATShader);
-
- BATShader(const SkBitmap& bitmap, SkRegion region, U8CPU);
- BATShader(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
- // We should probably do something here.
- }
-
-
- virtual void shadeSpan(int x, int y, SkPMColor[], int count) SK_OVERRIDE {};
-
-#if SK_SUPPORT_GPU
- virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint& paint) const SK_OVERRIDE;
-#endif
-
- SK_DEVELOPER_TO_STRING();
- SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(BATShader)
-
-private:
- SkBitmap fBitmap;
- SkRegion fRegion;
- U8CPU fThreshold;
-
- typedef SkShader INHERITED;
-};
-
-SkShader* SkBitmapAlphaThresholdShader::Create(const SkBitmap& bitmap,
- const SkRegion& region,
- U8CPU threshold) {
- SkASSERT(threshold < 256);
- return SkNEW_ARGS(BATShader, (bitmap, region, threshold));
-}
-
-BATShader::BATShader(const SkBitmap& bitmap, SkRegion region, U8CPU threshold)
-: fBitmap(bitmap)
-, fRegion(region)
-, fThreshold(threshold) {
-};
-
-
-#ifdef SK_DEVELOPER
-void BATShader::toString(SkString* str) const {
- str->append("BATShader: (");
-
- fBitmap.toString(str);
-
- this->INHERITED::toString(str);
-
- str->append(")");
-}
-#endif
-
-#if SK_SUPPORT_GPU
-#include "GrContext.h"
-#include "GrCoordTransform.h"
-#include "GrEffect.h"
-#include "gl/GrGLEffect.h"
-#include "GrTBackendEffectFactory.h"
-#include "GrTextureAccess.h"
-
-#include "SkGr.h"
-
-/**
- * Could create specializations for some simple cases:
- * - The region is empty.
- * - The region fully contains the bitmap.
- * - The regions is 1 rect (or maybe a small number of rects).
- */
-class ThresholdEffect : public GrEffect {
-public:
- virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
- return GrTBackendEffectFactory<ThresholdEffect>::getInstance();
- }
-
- static GrEffectRef* Create(GrTexture* bmpTexture, const SkMatrix& bmpMatrix,
- GrTexture* maskTexture, const SkMatrix& maskMatrix,
- U8CPU threshold) {
- SkScalar thresh = SkIntToScalar(threshold) / 255;
-
- AutoEffectUnref effect(SkNEW_ARGS(ThresholdEffect, (bmpTexture, bmpMatrix,
- maskTexture, maskMatrix,
- thresh)));
- return CreateEffectRef(effect);
- }
-
- virtual void getConstantColorComponents(GrColor* color,
- uint32_t* validFlags) const SK_OVERRIDE {
- if ((kA_GrColorComponentFlag & *validFlags) && 0 == GrColorUnpackA(*color)) {
- return;
- }
- *validFlags = 0;
- return;
- }
-
- static const char* Name() { return "Bitmap Alpha Threshold"; }
-
- class GLEffect : public GrGLEffect {
- public:
- GLEffect(const GrBackendEffectFactory& factory,
- const GrDrawEffect& e)
- : GrGLEffect(factory)
- , fPrevThreshold(-SK_Scalar1) {
- }
-
- virtual void emitCode(GrGLShaderBuilder* builder,
- const GrDrawEffect& drawEffect,
- EffectKey key,
- const char* outputColor,
- const char* inputColor,
- const TransformedCoordsArray& coords,
- const TextureSamplerArray& samplers) SK_OVERRIDE {
- // put bitmap color in "color"
- builder->fsCodeAppend("\t\tvec4 color = ");
- builder->fsAppendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type());
- builder->fsCodeAppend(";\n");
-
- // put alpha from mask texture in "mask"
- builder->fsCodeAppend("\t\tfloat mask = ");
- builder->fsAppendTextureLookup(samplers[1], coords[1].c_str(), coords[1].type());
- builder->fsCodeAppend(".a;\n");
-
- const char* threshold;
-
- fThresholdUniHandle = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
- kFloat_GrSLType,
- "threshold",
- &threshold);
- builder->fsCodeAppendf("\t\tfloat thresh = %s;\n", threshold);
-
- builder->fsCodeAppend("\t\tif (mask < 0.5) {\n"
- "\t\t\tif (color.a > thresh) {\n"
- "\t\t\t\tfloat scale = thresh / color.a;\n"
- "\t\t\t\tcolor.rgb *= scale;\n"
- "\t\t\t\tcolor.a = thresh;\n"
- "\t\t\t}\n"
- "\t\t} else if (color.a < thresh) {\n"
- "\t\t\tfloat scale = thresh / color.a;\n"
- "\t\t\tcolor.rgb *= scale;\n"
- "\t\t\tcolor.a = thresh;\n"
- "\t\t}\n");
-
- builder->fsCodeAppendf("color = %s = %s;\n", outputColor,
- (GrGLSLExpr4(inputColor) * GrGLSLExpr4("color")).c_str());
- }
-
- virtual void setData(const GrGLUniformManager& uman, const GrDrawEffect& e) SK_OVERRIDE {
- const ThresholdEffect& effect = e.castEffect<ThresholdEffect>();
- if (fPrevThreshold != effect.fThreshold) {
- uman.set1f(fThresholdUniHandle, effect.fThreshold);
- }
- }
-
- private:
- GrGLUniformManager::UniformHandle fThresholdUniHandle;
- SkScalar fPrevThreshold;
- };
-
- GR_DECLARE_EFFECT_TEST;
-
-private:
- ThresholdEffect(GrTexture* bmpTexture, const SkMatrix& bmpMatrix,
- GrTexture* maskTexture, const SkMatrix& maskMatrix,
- SkScalar threshold)
- : fBmpTransform(kLocal_GrCoordSet, bmpMatrix, bmpTexture)
- , fBmpAccess(bmpTexture, GrTextureParams())
- , fMaskTransform(kLocal_GrCoordSet, maskMatrix, maskTexture)
- , fMaskAccess(maskTexture, GrTextureParams())
- , fThreshold(threshold) {
- this->addCoordTransform(&fBmpTransform);
- this->addTextureAccess(&fBmpAccess);
- this->addCoordTransform(&fMaskTransform);
- this->addTextureAccess(&fMaskAccess);
- }
-
- virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
- const ThresholdEffect& e = CastEffect<ThresholdEffect>(other);
- return e.fBmpAccess.getTexture() == fBmpAccess.getTexture() &&
- e.fMaskAccess.getTexture() == fMaskAccess.getTexture() &&
- e.fBmpTransform.getMatrix() == fBmpTransform.getMatrix() &&
- e.fMaskTransform.getMatrix() == fMaskTransform.getMatrix() &&
- e.fThreshold == fThreshold;
- }
-
- GrCoordTransform fBmpTransform;
- GrTextureAccess fBmpAccess;
- GrCoordTransform fMaskTransform;
- GrTextureAccess fMaskAccess;
-
- SkScalar fThreshold;
-};
-
-GR_DEFINE_EFFECT_TEST(ThresholdEffect);
-
-GrEffectRef* ThresholdEffect::TestCreate(SkRandom* rand,
- GrContext*,
- const GrDrawTargetCaps&,
- GrTexture* textures[]) {
- GrTexture* bmpTex = textures[GrEffectUnitTest::kSkiaPMTextureIdx];
- GrTexture* maskTex = textures[GrEffectUnitTest::kAlphaTextureIdx];
- U8CPU thresh = rand->nextU() % 0xff;
- return ThresholdEffect::Create(bmpTex, SkMatrix::I(), maskTex, SkMatrix::I(), thresh);
-}
-
-GrEffectRef* BATShader::asNewEffect(GrContext* context, const SkPaint& paint) const {
- SkMatrix localInverse;
- if (!this->getLocalMatrix().invert(&localInverse)) {
- return NULL;
- }
-
- GrTextureDesc maskDesc;
- if (context->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
- maskDesc.fConfig = kAlpha_8_GrPixelConfig;
- } else {
- maskDesc.fConfig = kRGBA_8888_GrPixelConfig;
- }
- maskDesc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
- const SkIRect& bounds = fRegion.getBounds();
- // Add one pixel of border to ensure that clamp mode will be all zeros
- // the outside.
- maskDesc.fWidth = bounds.width() + 2;
- maskDesc.fHeight = bounds.height() + 2;
- GrAutoScratchTexture ast(context, maskDesc, GrContext::kApprox_ScratchTexMatch);
- GrTexture* maskTexture = ast.texture();
- if (NULL == maskTexture) {
- return NULL;
- }
-
- GrPaint grPaint;
- grPaint.setBlendFunc(kOne_GrBlendCoeff, kZero_GrBlendCoeff);
- SkRegion::Iterator iter(fRegion);
- context->setRenderTarget(maskTexture->asRenderTarget());
- context->clear(NULL, 0x0, true);
-
- // offset to ensure border is zero on top/left
- SkMatrix matrix;
- matrix.setTranslate(SK_Scalar1, SK_Scalar1);
- context->setMatrix(matrix);
-
- while (!iter.done()) {
- SkRect rect = SkRect::Make(iter.rect());
- context->drawRect(grPaint, rect);
- iter.next();
- }
-
- GrTexture* bmpTexture = GrLockAndRefCachedBitmapTexture(context, fBitmap, NULL);
- if (NULL == bmpTexture) {
- return NULL;
- }
-
- SkMatrix bmpMatrix = localInverse;
- bmpMatrix.postIDiv(bmpTexture->width(), bmpTexture->height());
-
- SkMatrix maskMatrix = localInverse;
- // compensate for the border
- maskMatrix.postTranslate(SK_Scalar1, SK_Scalar1);
- maskMatrix.postIDiv(maskTexture->width(), maskTexture->height());
-
- GrEffectRef* effect = ThresholdEffect::Create(bmpTexture, bmpMatrix,
- maskTexture, maskMatrix,
- fThreshold);
-
- GrUnlockAndUnrefCachedBitmapTexture(bmpTexture);
-
- return effect;
-}
-
-#endif
diff --git a/chromium/third_party/skia/src/effects/SkBitmapSource.cpp b/chromium/third_party/skia/src/effects/SkBitmapSource.cpp
index ef5ea869256..d8d4329e655 100644
--- a/chromium/third_party/skia/src/effects/SkBitmapSource.cpp
+++ b/chromium/third_party/skia/src/effects/SkBitmapSource.cpp
@@ -8,7 +8,8 @@
#include "SkBitmapSource.h"
#include "SkDevice.h"
#include "SkCanvas.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkValidationUtils.h"
SkBitmapSource::SkBitmapSource(const SkBitmap& bitmap)
@@ -20,35 +21,38 @@ SkBitmapSource::SkBitmapSource(const SkBitmap& bitmap)
}
SkBitmapSource::SkBitmapSource(const SkBitmap& bitmap, const SkRect& srcRect, const SkRect& dstRect)
- : INHERITED(0, 0),
- fBitmap(bitmap),
- fSrcRect(srcRect),
- fDstRect(dstRect) {
-}
+ : INHERITED(0, 0)
+ , fBitmap(bitmap)
+ , fSrcRect(srcRect)
+ , fDstRect(dstRect) {}
-SkBitmapSource::SkBitmapSource(SkFlattenableReadBuffer& buffer)
- : INHERITED(0, buffer) {
- fBitmap.unflatten(buffer);
+SkBitmapSource::SkBitmapSource(SkReadBuffer& buffer) : INHERITED(0, buffer) {
+ if (buffer.isVersionLT(SkReadBuffer::kNoMoreBitmapFlatten_Version)) {
+ fBitmap.legacyUnflatten(buffer);
+ } else {
+ buffer.readBitmap(&fBitmap);
+ }
buffer.readRect(&fSrcRect);
buffer.readRect(&fDstRect);
- buffer.validate(SkIsValidRect(fSrcRect) && SkIsValidRect(fDstRect));
+ buffer.validate(buffer.isValid() && SkIsValidRect(fSrcRect) && SkIsValidRect(fDstRect));
}
-void SkBitmapSource::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkBitmapSource::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
- fBitmap.flatten(buffer);
+ buffer.writeBitmap(fBitmap);
buffer.writeRect(fSrcRect);
buffer.writeRect(fDstRect);
}
-bool SkBitmapSource::onFilterImage(Proxy* proxy, const SkBitmap&, const SkMatrix& matrix,
- SkBitmap* result, SkIPoint* offset) {
+bool SkBitmapSource::onFilterImage(Proxy* proxy, const SkBitmap&, const Context& ctx,
+ SkBitmap* result, SkIPoint* offset) const {
SkRect bounds, dstRect;
fBitmap.getBounds(&bounds);
- matrix.mapRect(&dstRect, fDstRect);
+ ctx.ctm().mapRect(&dstRect, fDstRect);
if (fSrcRect == bounds && dstRect == bounds) {
// No regions cropped out or resized; return entire bitmap.
*result = fBitmap;
+ offset->fX = offset->fY = 0;
return true;
}
SkIRect dstIRect;
@@ -69,11 +73,21 @@ bool SkBitmapSource::onFilterImage(Proxy* proxy, const SkBitmap&, const SkMatrix
// None filtering when it's translate-only
paint.setFilterLevel(
fSrcRect.width() == dstRect.width() && fSrcRect.height() == dstRect.height() ?
- SkPaint::kNone_FilterLevel : SkPaint::kMedium_FilterLevel);
+ SkPaint::kNone_FilterLevel : SkPaint::kHigh_FilterLevel);
canvas.drawBitmapRectToRect(fBitmap, &fSrcRect, dstRect, &paint);
*result = device.get()->accessBitmap(false);
- offset->fX += dstIRect.fLeft;
- offset->fY += dstIRect.fTop;
+ offset->fX = dstIRect.fLeft;
+ offset->fY = dstIRect.fTop;
+ return true;
+}
+
+void SkBitmapSource::computeFastBounds(const SkRect&, SkRect* dst) const {
+ *dst = fDstRect;
+}
+
+bool SkBitmapSource::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
+ SkIRect* dst) const {
+ *dst = src;
return true;
}
diff --git a/chromium/third_party/skia/src/effects/SkBlurDrawLooper.cpp b/chromium/third_party/skia/src/effects/SkBlurDrawLooper.cpp
index 51e6ec98e0e..c3b843f1885 100644
--- a/chromium/third_party/skia/src/effects/SkBlurDrawLooper.cpp
+++ b/chromium/third_party/skia/src/effects/SkBlurDrawLooper.cpp
@@ -1,60 +1,48 @@
-
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
+
#include "SkBlurDrawLooper.h"
#include "SkBlurMask.h" // just for SkBlurMask::ConvertRadiusToSigma
#include "SkBlurMaskFilter.h"
#include "SkCanvas.h"
#include "SkColorFilter.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkMaskFilter.h"
#include "SkPaint.h"
#include "SkString.h"
#include "SkStringUtils.h"
-SkBlurDrawLooper::SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy,
- SkColor color, uint32_t flags) {
- this->init(SkBlurMask::ConvertRadiusToSigma(radius), dx, dy, color, flags);
-}
-
SkBlurDrawLooper::SkBlurDrawLooper(SkColor color, SkScalar sigma,
SkScalar dx, SkScalar dy, uint32_t flags) {
this->init(sigma, dx, dy, color, flags);
}
-void SkBlurDrawLooper::init(SkScalar sigma, SkScalar dx, SkScalar dy,
- SkColor color, uint32_t flags) {
- fDx = dx;
- fDy = dy;
- fBlurColor = color;
- fBlurFlags = flags;
- fState = kDone;
-
- SkASSERT(flags <= kAll_BlurFlag);
- if (sigma > 0) {
- uint32_t blurFlags = flags & kIgnoreTransform_BlurFlag ?
- SkBlurMaskFilter::kIgnoreTransform_BlurFlag :
- SkBlurMaskFilter::kNone_BlurFlag;
+// only call from constructor
+void SkBlurDrawLooper::initEffects() {
+ SkASSERT(fBlurFlags <= kAll_BlurFlag);
+ if (fSigma > 0) {
+ uint32_t flags = fBlurFlags & kIgnoreTransform_BlurFlag ?
+ SkBlurMaskFilter::kIgnoreTransform_BlurFlag :
+ SkBlurMaskFilter::kNone_BlurFlag;
- blurFlags |= flags & kHighQuality_BlurFlag ?
- SkBlurMaskFilter::kHighQuality_BlurFlag :
- SkBlurMaskFilter::kNone_BlurFlag;
+ flags |= fBlurFlags & kHighQuality_BlurFlag ?
+ SkBlurMaskFilter::kHighQuality_BlurFlag :
+ SkBlurMaskFilter::kNone_BlurFlag;
- fBlur = SkBlurMaskFilter::Create(SkBlurMaskFilter::kNormal_BlurStyle,
- sigma,
- blurFlags);
+ fBlur = SkBlurMaskFilter::Create(kNormal_SkBlurStyle, fSigma, flags);
} else {
fBlur = NULL;
}
- if (flags & kOverrideColor_BlurFlag) {
+ if (fBlurFlags & kOverrideColor_BlurFlag) {
// Set alpha to 1 for the override since transparency will already
// be baked into the blurred mask.
- SkColor opaqueColor = SkColorSetA(color, 255);
+ SkColor opaqueColor = SkColorSetA(fBlurColor, 255);
//The SrcIn xfer mode will multiply 'color' by the incoming alpha
fColorFilter = SkColorFilter::CreateModeFilter(opaqueColor,
SkXfermode::kSrcIn_Mode);
@@ -63,37 +51,70 @@ void SkBlurDrawLooper::init(SkScalar sigma, SkScalar dx, SkScalar dy,
}
}
-SkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer)
-: INHERITED(buffer) {
+void SkBlurDrawLooper::init(SkScalar sigma, SkScalar dx, SkScalar dy,
+ SkColor color, uint32_t flags) {
+ fSigma = sigma;
+ fDx = dx;
+ fDy = dy;
+ fBlurColor = color;
+ fBlurFlags = flags;
+
+ this->initEffects();
+}
+
+SkBlurDrawLooper::SkBlurDrawLooper(SkReadBuffer& buffer) : INHERITED(buffer) {
+ fSigma = buffer.readScalar();
fDx = buffer.readScalar();
fDy = buffer.readScalar();
fBlurColor = buffer.readColor();
- fBlur = buffer.readMaskFilter();
- fColorFilter = buffer.readColorFilter();
fBlurFlags = buffer.readUInt() & kAll_BlurFlag;
-}
-SkBlurDrawLooper::~SkBlurDrawLooper() {
- SkSafeUnref(fBlur);
- SkSafeUnref(fColorFilter);
+ this->initEffects();
}
-void SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkBlurDrawLooper::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
+ buffer.writeScalar(fSigma);
buffer.writeScalar(fDx);
buffer.writeScalar(fDy);
buffer.writeColor(fBlurColor);
- buffer.writeFlattenable(fBlur);
- buffer.writeFlattenable(fColorFilter);
- buffer.writeUInt(fBlurFlags);
+ buffer.write32(fBlurFlags);
+}
+
+SkBlurDrawLooper::~SkBlurDrawLooper() {
+ SkSafeUnref(fBlur);
+ SkSafeUnref(fColorFilter);
}
-void SkBlurDrawLooper::init(SkCanvas*) {
- fState = kBeforeEdge;
+bool SkBlurDrawLooper::asABlurShadow(BlurShadowRec* rec) const {
+ if (fSigma <= 0 || (fBlurFlags & fBlurFlags & kIgnoreTransform_BlurFlag)) {
+ return false;
+ }
+
+ if (rec) {
+ rec->fSigma = fSigma;
+ rec->fColor = fBlurColor;
+ rec->fOffset.set(fDx, fDy);
+ rec->fStyle = kNormal_SkBlurStyle;
+ rec->fQuality = (fBlurFlags & kHighQuality_BlurFlag) ?
+ kHigh_SkBlurQuality : kLow_SkBlurQuality;
+ }
+ return true;
}
-bool SkBlurDrawLooper::next(SkCanvas* canvas, SkPaint* paint) {
+////////////////////////////////////////////////////////////////////////////////////////
+
+SkDrawLooper::Context* SkBlurDrawLooper::createContext(SkCanvas*, void* storage) const {
+ return SkNEW_PLACEMENT_ARGS(storage, BlurDrawLooperContext, (this));
+}
+
+SkBlurDrawLooper::BlurDrawLooperContext::BlurDrawLooperContext(
+ const SkBlurDrawLooper* looper)
+ : fLooper(looper), fState(SkBlurDrawLooper::kBeforeEdge) {}
+
+bool SkBlurDrawLooper::BlurDrawLooperContext::next(SkCanvas* canvas,
+ SkPaint* paint) {
switch (fState) {
case kBeforeEdge:
// we do nothing if a maskfilter is already installed
@@ -103,23 +124,23 @@ bool SkBlurDrawLooper::next(SkCanvas* canvas, SkPaint* paint) {
}
#ifdef SK_BUILD_FOR_ANDROID
SkColor blurColor;
- blurColor = fBlurColor;
+ blurColor = fLooper->fBlurColor;
if (SkColorGetA(blurColor) == 255) {
blurColor = SkColorSetA(blurColor, paint->getAlpha());
}
paint->setColor(blurColor);
#else
- paint->setColor(fBlurColor);
+ paint->setColor(fLooper->fBlurColor);
#endif
- paint->setMaskFilter(fBlur);
- paint->setColorFilter(fColorFilter);
- canvas->save(SkCanvas::kMatrix_SaveFlag);
- if (fBlurFlags & kIgnoreTransform_BlurFlag) {
+ paint->setMaskFilter(fLooper->fBlur);
+ paint->setColorFilter(fLooper->fColorFilter);
+ canvas->save();
+ if (fLooper->fBlurFlags & kIgnoreTransform_BlurFlag) {
SkMatrix transform(canvas->getTotalMatrix());
- transform.postTranslate(fDx, fDy);
+ transform.postTranslate(fLooper->fDx, fLooper->fDy);
canvas->setMatrix(transform);
} else {
- canvas->translate(fDx, fDy);
+ canvas->translate(fLooper->fDx, fLooper->fDy);
}
fState = kAfterEdge;
return true;
@@ -133,7 +154,7 @@ bool SkBlurDrawLooper::next(SkCanvas* canvas, SkPaint* paint) {
}
}
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkBlurDrawLooper::toString(SkString* str) const {
str->append("SkBlurDrawLooper: ");
diff --git a/chromium/third_party/skia/src/effects/SkBlurImageFilter.cpp b/chromium/third_party/skia/src/effects/SkBlurImageFilter.cpp
index 2795f3a872a..470dcac3c85 100644
--- a/chromium/third_party/skia/src/effects/SkBlurImageFilter.cpp
+++ b/chromium/third_party/skia/src/effects/SkBlurImageFilter.cpp
@@ -8,15 +8,22 @@
#include "SkBitmap.h"
#include "SkBlurImageFilter.h"
#include "SkColorPriv.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkGpuBlurUtils.h"
#include "SkBlurImage_opts.h"
#if SK_SUPPORT_GPU
#include "GrContext.h"
-#include "SkImageFilterUtils.h"
#endif
-SkBlurImageFilter::SkBlurImageFilter(SkFlattenableReadBuffer& buffer)
+// This rather arbitrary-looking value results in a maximum box blur kernel size
+// of 1000 pixels on the raster path, which matches the WebKit and Firefox
+// implementations. Since the GPU path does not compute a box blur, putting
+// the limit on sigma ensures consistent behaviour between the GPU and
+// raster paths.
+#define MAX_SIGMA SkIntToScalar(532)
+
+SkBlurImageFilter::SkBlurImageFilter(SkReadBuffer& buffer)
: INHERITED(1, buffer) {
fSigma.fWidth = buffer.readScalar();
fSigma.fHeight = buffer.readScalar();
@@ -34,7 +41,7 @@ SkBlurImageFilter::SkBlurImageFilter(SkScalar sigmaX,
SkASSERT(sigmaX >= 0 && sigmaY >= 0);
}
-void SkBlurImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkBlurImageFilter::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeScalar(fSigma.fWidth);
buffer.writeScalar(fSigma.fHeight);
@@ -134,55 +141,62 @@ static void getBox3Params(SkScalar s, int *kernelSize, int* kernelSize3, int *lo
}
bool SkBlurImageFilter::onFilterImage(Proxy* proxy,
- const SkBitmap& source, const SkMatrix& ctm,
- SkBitmap* dst, SkIPoint* offset) {
+ const SkBitmap& source, const Context& ctx,
+ SkBitmap* dst, SkIPoint* offset) const {
SkBitmap src = source;
- if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctm, &src, offset)) {
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
+ if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctx, &src, &srcOffset)) {
return false;
}
- if (src.config() != SkBitmap::kARGB_8888_Config) {
+ if (src.colorType() != kN32_SkColorType) {
return false;
}
- SkAutoLockPixels alp(src);
- if (!src.getPixels()) {
+ SkIRect srcBounds, dstBounds;
+ if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &srcBounds, &src)) {
return false;
}
- SkIRect srcBounds, dstBounds;
- src.getBounds(&srcBounds);
- if (!this->applyCropRect(&srcBounds, ctm)) {
+ SkAutoLockPixels alp(src);
+ if (!src.getPixels()) {
return false;
}
- dst->setConfig(src.config(), srcBounds.width(), srcBounds.height());
- dst->getBounds(&dstBounds);
- dst->allocPixels();
- if (!dst->getPixels()) {
+ if (!dst->allocPixels(src.info().makeWH(srcBounds.width(), srcBounds.height()))) {
return false;
}
+ dst->getBounds(&dstBounds);
+
+ SkVector sigma = SkVector::Make(fSigma.width(), fSigma.height());
+ ctx.ctm().mapVectors(&sigma, 1);
+ sigma.fX = SkMinScalar(sigma.fX, MAX_SIGMA);
+ sigma.fY = SkMinScalar(sigma.fY, MAX_SIGMA);
int kernelSizeX, kernelSizeX3, lowOffsetX, highOffsetX;
int kernelSizeY, kernelSizeY3, lowOffsetY, highOffsetY;
- getBox3Params(fSigma.width(), &kernelSizeX, &kernelSizeX3, &lowOffsetX, &highOffsetX);
- getBox3Params(fSigma.height(), &kernelSizeY, &kernelSizeY3, &lowOffsetY, &highOffsetY);
+ getBox3Params(sigma.x(), &kernelSizeX, &kernelSizeX3, &lowOffsetX, &highOffsetX);
+ getBox3Params(sigma.y(), &kernelSizeY, &kernelSizeY3, &lowOffsetY, &highOffsetY);
if (kernelSizeX < 0 || kernelSizeY < 0) {
return false;
}
if (kernelSizeX == 0 && kernelSizeY == 0) {
- src.copyTo(dst, dst->config());
+ src.copyTo(dst, dst->colorType());
+ offset->fX = srcBounds.fLeft;
+ offset->fY = srcBounds.fTop;
return true;
}
SkBitmap temp;
- temp.setConfig(dst->config(), dst->width(), dst->height());
- if (!temp.allocPixels()) {
+ if (!temp.allocPixels(dst->info())) {
return false;
}
+ offset->fX = srcBounds.fLeft;
+ offset->fY = srcBounds.fTop;
+ srcBounds.offset(-srcOffset);
const SkPMColor* s = src.getAddr32(srcBounds.left(), srcBounds.top());
SkPMColor* t = temp.getAddr32(0, 0);
SkPMColor* d = dst->getAddr32(0, 0);
@@ -212,34 +226,64 @@ bool SkBlurImageFilter::onFilterImage(Proxy* proxy,
boxBlurX(d, h, t, kernelSizeY, highOffsetY, lowOffsetY, h, w);
boxBlurXY(t, h, d, kernelSizeY3, highOffsetY, highOffsetY, h, w);
}
- offset->fX += srcBounds.fLeft;
- offset->fY += srcBounds.fTop;
return true;
}
-bool SkBlurImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
- SkBitmap* result, SkIPoint* offset) {
+
+void SkBlurImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
+ if (getInput(0)) {
+ getInput(0)->computeFastBounds(src, dst);
+ } else {
+ *dst = src;
+ }
+
+ dst->outset(SkScalarMul(fSigma.width(), SkIntToScalar(3)),
+ SkScalarMul(fSigma.height(), SkIntToScalar(3)));
+}
+
+bool SkBlurImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
+ SkIRect* dst) const {
+ SkIRect bounds = src;
+ if (getInput(0) && !getInput(0)->filterBounds(src, ctm, &bounds)) {
+ return false;
+ }
+ SkVector sigma = SkVector::Make(fSigma.width(), fSigma.height());
+ ctm.mapVectors(&sigma, 1);
+ bounds.outset(SkScalarCeilToInt(SkScalarMul(sigma.x(), SkIntToScalar(3))),
+ SkScalarCeilToInt(SkScalarMul(sigma.y(), SkIntToScalar(3))));
+ *dst = bounds;
+ return true;
+}
+
+bool SkBlurImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx,
+ SkBitmap* result, SkIPoint* offset) const {
#if SK_SUPPORT_GPU
- SkBitmap input;
- if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &input, offset)) {
+ SkBitmap input = src;
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
+ if (getInput(0) && !getInput(0)->getInputResultGPU(proxy, src, ctx, &input, &srcOffset)) {
return false;
}
- GrTexture* source = input.getTexture();
SkIRect rect;
- src.getBounds(&rect);
- if (!this->applyCropRect(&rect, ctm)) {
+ if (!this->applyCropRect(ctx, proxy, input, &srcOffset, &rect, &input)) {
return false;
}
+ GrTexture* source = input.getTexture();
+ SkVector sigma = SkVector::Make(fSigma.width(), fSigma.height());
+ ctx.ctm().mapVectors(&sigma, 1);
+ sigma.fX = SkMinScalar(sigma.fX, MAX_SIGMA);
+ sigma.fY = SkMinScalar(sigma.fY, MAX_SIGMA);
+ offset->fX = rect.fLeft;
+ offset->fY = rect.fTop;
+ rect.offset(-srcOffset);
SkAutoTUnref<GrTexture> tex(SkGpuBlurUtils::GaussianBlur(source->getContext(),
source,
false,
SkRect::Make(rect),
true,
- fSigma.width(),
- fSigma.height()));
- offset->fX += rect.fLeft;
- offset->fY += rect.fTop;
- return SkImageFilterUtils::WrapTexture(tex, rect.width(), rect.height(), result);
+ sigma.x(),
+ sigma.y()));
+ WrapTexture(tex, rect.width(), rect.height(), result);
+ return true;
#else
SkDEBUGFAIL("Should not call in GPU-less build");
return false;
diff --git a/chromium/third_party/skia/src/effects/SkBlurMask.cpp b/chromium/third_party/skia/src/effects/SkBlurMask.cpp
index d2484c84b79..bf50845ab6c 100644
--- a/chromium/third_party/skia/src/effects/SkBlurMask.cpp
+++ b/chromium/third_party/skia/src/effects/SkBlurMask.cpp
@@ -13,17 +13,21 @@
#include "SkEndian.h"
+// This constant approximates the scaling done in the software path's
+// "high quality" mode, in SkBlurMask::Blur() (1 / sqrt(3)).
+// IMHO, it actually should be 1: we blur "less" than we should do
+// according to the CSS and canvas specs, simply because Safari does the same.
+// Firefox used to do the same too, until 4.0 where they fixed it. So at some
+// point we should probably get rid of these scaling constants and rebaseline
+// all the blur tests.
+static const SkScalar kBLUR_SIGMA_SCALE = 0.57735f;
+
SkScalar SkBlurMask::ConvertRadiusToSigma(SkScalar radius) {
- // This constant approximates the scaling done in the software path's
- // "high quality" mode, in SkBlurMask::Blur() (1 / sqrt(3)).
- // IMHO, it actually should be 1: we blur "less" than we should do
- // according to the CSS and canvas specs, simply because Safari does the same.
- // Firefox used to do the same too, until 4.0 where they fixed it. So at some
- // point we should probably get rid of these scaling constants and rebaseline
- // all the blur tests.
- static const SkScalar kBLUR_SIGMA_SCALE = 0.57735f;
-
- return radius ? kBLUR_SIGMA_SCALE * radius + 0.5f : 0.0f;
+ return radius > 0 ? kBLUR_SIGMA_SCALE * radius + 0.5f : 0.0f;
+}
+
+SkScalar SkBlurMask::ConvertSigmaToRadius(SkScalar sigma) {
+ return sigma > 0.5f ? (sigma - 0.5f) / kBLUR_SIGMA_SCALE : 0.0f;
}
#define UNROLL_SEPARABLE_LOOPS
@@ -404,7 +408,7 @@ static int boxBlurInterp(const uint8_t* src, int src_y_stride, uint8_t* dst,
static void get_adjusted_radii(SkScalar passRadius, int *loRadius, int *hiRadius)
{
- *loRadius = *hiRadius = SkScalarCeil(passRadius);
+ *loRadius = *hiRadius = SkScalarCeilToInt(passRadius);
if (SkIntToScalar(*hiRadius) - passRadius > 0.5f) {
*loRadius = *hiRadius - 1;
}
@@ -435,11 +439,11 @@ static void merge_src_with_blur(uint8_t dst[], int dstRB,
static void clamp_with_orig(uint8_t dst[], int dstRowBytes,
const uint8_t src[], int srcRowBytes,
int sw, int sh,
- SkBlurMask::Style style) {
+ SkBlurStyle style) {
int x;
while (--sh >= 0) {
switch (style) {
- case SkBlurMask::kSolid_Style:
+ case kSolid_SkBlurStyle:
for (x = sw - 1; x >= 0; --x) {
int s = *src;
int d = *dst;
@@ -448,7 +452,7 @@ static void clamp_with_orig(uint8_t dst[], int dstRowBytes,
src += 1;
}
break;
- case SkBlurMask::kOuter_Style:
+ case kOuter_SkBlurStyle:
for (x = sw - 1; x >= 0; --x) {
if (*src) {
*dst = SkToU8(SkAlphaMul(*dst, SkAlpha255To256(255 - *src)));
@@ -475,29 +479,21 @@ void SkMask_FreeImage(uint8_t* image) {
SkMask::FreeImage(image);
}
-bool SkBlurMask::Blur(SkMask* dst, const SkMask& src,
- SkScalar radius, Style style, Quality quality,
- SkIPoint* margin) {
- return SkBlurMask::BoxBlur(dst, src,
- SkBlurMask::ConvertRadiusToSigma(radius),
- style, quality, margin);
-}
-
bool SkBlurMask::BoxBlur(SkMask* dst, const SkMask& src,
- SkScalar sigma, Style style, Quality quality,
- SkIPoint* margin) {
+ SkScalar sigma, SkBlurStyle style, SkBlurQuality quality,
+ SkIPoint* margin, bool force_quality) {
if (src.fFormat != SkMask::kA8_Format) {
return false;
}
// Force high quality off for small radii (performance)
- if (sigma <= SkIntToScalar(2)) {
- quality = kLow_Quality;
+ if (!force_quality && sigma <= SkIntToScalar(2)) {
+ quality = kLow_SkBlurQuality;
}
SkScalar passRadius;
- if (kHigh_Quality == quality) {
+ if (kHigh_SkBlurQuality == quality) {
// For the high quality path the 3 pass box blur kernel width is
// 6*rad+1 while the full Gaussian width is 6*sigma.
passRadius = sigma - (1/6.0f);
@@ -510,10 +506,10 @@ bool SkBlurMask::BoxBlur(SkMask* dst, const SkMask& src,
// highQuality: use three box blur passes as a cheap way
// to approximate a Gaussian blur
- int passCount = (kHigh_Quality == quality) ? 3 : 1;
+ int passCount = (kHigh_SkBlurQuality == quality) ? 3 : 1;
- int rx = SkScalarCeil(passRadius);
- int outerWeight = 255 - SkScalarRound((SkIntToScalar(rx) - passRadius) * 255);
+ int rx = SkScalarCeilToInt(passRadius);
+ int outerWeight = 255 - SkScalarRoundToInt((SkIntToScalar(rx) - passRadius) * 255);
SkASSERT(rx >= 0);
SkASSERT((unsigned)outerWeight <= 255);
@@ -556,7 +552,7 @@ bool SkBlurMask::BoxBlur(SkMask* dst, const SkMask& src,
if (outerWeight == 255) {
int loRadius, hiRadius;
get_adjusted_radii(passRadius, &loRadius, &hiRadius);
- if (kHigh_Quality == quality) {
+ if (kHigh_SkBlurQuality == quality) {
// Do three X blurs, with a transpose on the final one.
w = boxBlur(sp, src.fRowBytes, tp, loRadius, hiRadius, w, h, false);
w = boxBlur(tp, w, dp, hiRadius, loRadius, w, h, false);
@@ -570,7 +566,7 @@ bool SkBlurMask::BoxBlur(SkMask* dst, const SkMask& src,
h = boxBlur(tp, h, dp, ry, ry, h, w, true);
}
} else {
- if (kHigh_Quality == quality) {
+ if (kHigh_SkBlurQuality == quality) {
// Do three X blurs, with a transpose on the final one.
w = boxBlurInterp(sp, src.fRowBytes, tp, rx, w, h, false, outerWeight);
w = boxBlurInterp(tp, w, dp, rx, w, h, false, outerWeight);
@@ -588,7 +584,7 @@ bool SkBlurMask::BoxBlur(SkMask* dst, const SkMask& src,
dst->fImage = dp;
// if need be, alloc the "real" dst (same size as src) and copy/merge
// the blur into it (applying the src)
- if (style == kInner_Style) {
+ if (style == kInner_SkBlurStyle) {
// now we allocate the "real" dst, mirror the size of src
size_t srcSize = src.computeImageSize();
if (0 == srcSize) {
@@ -600,14 +596,14 @@ bool SkBlurMask::BoxBlur(SkMask* dst, const SkMask& src,
dp + passCount * (rx + ry * dst->fRowBytes),
dst->fRowBytes, sw, sh);
SkMask::FreeImage(dp);
- } else if (style != kNormal_Style) {
+ } else if (style != kNormal_SkBlurStyle) {
clamp_with_orig(dp + passCount * (rx + ry * dst->fRowBytes),
dst->fRowBytes, sp, src.fRowBytes, sw, sh, style);
}
(void)autoCall.detach();
}
- if (style == kInner_Style) {
+ if (style == kInner_SkBlurStyle) {
dst->fBounds = src.fBounds; // restore trimmed bounds
dst->fRowBytes = src.fRowBytes;
}
@@ -671,7 +667,7 @@ static float gaussianIntegral(float x) {
return 0.4375f + (-x3 / 6.0f - 3.0f * x2 * 0.25f - 1.125f * x);
}
-/* compute_profile allocates and fills in an array of floating
+/* ComputeBlurProfile allocates and fills in an array of floating
point values between 0 and 255 for the profile signature of
a blurred half-plane with the given blur radius. Since we're
going to be doing screened multiplications (i.e., 1 - (1-x)(1-y))
@@ -682,11 +678,11 @@ static float gaussianIntegral(float x) {
memory returned in profile_out.
*/
-static void compute_profile(SkScalar sigma, unsigned int **profile_out) {
+void SkBlurMask::ComputeBlurProfile(SkScalar sigma, uint8_t **profile_out) {
int size = SkScalarCeilToInt(6*sigma);
int center = size >> 1;
- unsigned int *profile = SkNEW_ARRAY(unsigned int, size);
+ uint8_t *profile = SkNEW_ARRAY(uint8_t, size);
float invr = 1.f/(2*sigma);
@@ -707,7 +703,7 @@ static void compute_profile(SkScalar sigma, unsigned int **profile_out) {
// Implementation adapted from Michael Herf's approach:
// http://stereopsis.com/shadowrect/
-static inline unsigned int profile_lookup( unsigned int *profile, int loc, int blurred_width, int sharp_width ) {
+uint8_t SkBlurMask::ProfileLookup(const uint8_t *profile, int loc, int blurred_width, int sharp_width) {
int dx = SkAbs32(((loc << 1) + 1) - blurred_width) - sharp_width; // how far are we from the original edge?
int ox = dx >> 1;
if (ox < 0) {
@@ -717,16 +713,32 @@ static inline unsigned int profile_lookup( unsigned int *profile, int loc, int b
return profile[ox];
}
-bool SkBlurMask::BlurRect(SkMask *dst, const SkRect &src,
- SkScalar radius, Style style,
- SkIPoint *margin, SkMask::CreateMode createMode) {
- return SkBlurMask::BlurRect(SkBlurMask::ConvertRadiusToSigma(radius),
- dst, src,
- style, margin, createMode);
+void SkBlurMask::ComputeBlurredScanline(uint8_t *pixels, const uint8_t *profile,
+ unsigned int width, SkScalar sigma) {
+
+ unsigned int profile_size = SkScalarCeilToInt(6*sigma);
+ SkAutoTMalloc<uint8_t> horizontalScanline(width);
+
+ unsigned int sw = width - profile_size;
+ // nearest odd number less than the profile size represents the center
+ // of the (2x scaled) profile
+ int center = ( profile_size & ~1 ) - 1;
+
+ int w = sw - center;
+
+ for (unsigned int x = 0 ; x < width ; ++x) {
+ if (profile_size <= sw) {
+ pixels[x] = ProfileLookup(profile, x, width, w);
+ } else {
+ float span = float(sw)/(2*sigma);
+ float giX = 1.5f - (x+.5f)/(2*sigma);
+ pixels[x] = (uint8_t) (255 * (gaussianIntegral(giX) - gaussianIntegral(giX + span)));
+ }
+ }
}
bool SkBlurMask::BlurRect(SkScalar sigma, SkMask *dst,
- const SkRect &src, Style style,
+ const SkRect &src, SkBlurStyle style,
SkIPoint *margin, SkMask::CreateMode createMode) {
int profile_size = SkScalarCeilToInt(6*sigma);
@@ -748,7 +760,7 @@ bool SkBlurMask::BlurRect(SkScalar sigma, SkMask *dst,
int sh = SkScalarFloorToInt(src.height());
if (createMode == SkMask::kJustComputeBounds_CreateMode) {
- if (style == kInner_Style) {
+ if (style == kInner_SkBlurStyle) {
dst->fBounds.set(SkScalarRoundToInt(src.fLeft),
SkScalarRoundToInt(src.fTop),
SkScalarRoundToInt(src.fRight),
@@ -757,10 +769,10 @@ bool SkBlurMask::BlurRect(SkScalar sigma, SkMask *dst,
}
return true;
}
- unsigned int *profile = NULL;
+ uint8_t *profile = NULL;
- compute_profile(sigma, &profile);
- SkAutoTDeleteArray<unsigned int> ada(profile);
+ ComputeBlurProfile(sigma, &profile);
+ SkAutoTDeleteArray<uint8_t> ada(profile);
size_t dstSize = dst->computeImageSize();
if (0 == dstSize) {
@@ -774,44 +786,22 @@ bool SkBlurMask::BlurRect(SkScalar sigma, SkMask *dst,
int dstHeight = dst->fBounds.height();
int dstWidth = dst->fBounds.width();
- // nearest odd number less than the profile size represents the center
- // of the (2x scaled) profile
- int center = ( profile_size & ~1 ) - 1;
-
- int w = sw - center;
- int h = sh - center;
-
uint8_t *outptr = dp;
SkAutoTMalloc<uint8_t> horizontalScanline(dstWidth);
+ SkAutoTMalloc<uint8_t> verticalScanline(dstHeight);
- for (int x = 0 ; x < dstWidth ; ++x) {
- if (profile_size <= sw) {
- horizontalScanline[x] = profile_lookup(profile, x, dstWidth, w);
- } else {
- float span = float(sw)/(2*sigma);
- float giX = 1.5f - (x+.5f)/(2*sigma);
- horizontalScanline[x] = (uint8_t) (255 * (gaussianIntegral(giX) - gaussianIntegral(giX + span)));
- }
- }
+ ComputeBlurredScanline(horizontalScanline, profile, dstWidth, sigma);
+ ComputeBlurredScanline(verticalScanline, profile, dstHeight, sigma);
for (int y = 0 ; y < dstHeight ; ++y) {
- unsigned int profile_y;
- if (profile_size <= sh) {
- profile_y = profile_lookup(profile, y, dstHeight, h);
- } else {
- float span = float(sh)/(2*sigma);
- float giY = 1.5f - (y+.5f)/(2*sigma);
- profile_y = (uint8_t) (255 * (gaussianIntegral(giY) - gaussianIntegral(giY + span)));
- }
-
for (int x = 0 ; x < dstWidth ; x++) {
- unsigned int maskval = SkMulDiv255Round(horizontalScanline[x], profile_y);
+ unsigned int maskval = SkMulDiv255Round(horizontalScanline[x], verticalScanline[y]);
*(outptr++) = maskval;
}
}
- if (style == kInner_Style) {
+ if (style == kInner_SkBlurStyle) {
// now we allocate the "real" dst, mirror the size of src
size_t srcSize = (size_t)(src.width() * src.height());
if (0 == srcSize) {
@@ -831,12 +821,12 @@ bool SkBlurMask::BlurRect(SkScalar sigma, SkMask *dst,
SkScalarRoundToInt(src.fBottom)); // restore trimmed bounds
dst->fRowBytes = sw;
- } else if (style == kOuter_Style) {
+ } else if (style == kOuter_SkBlurStyle) {
for (int y = pad ; y < dstHeight-pad ; y++) {
uint8_t *dst_scanline = dp + y*dstWidth + pad;
memset(dst_scanline, 0, sw);
}
- } else if (style == kSolid_Style) {
+ } else if (style == kSolid_SkBlurStyle) {
for (int y = pad ; y < dstHeight-pad ; y++) {
uint8_t *dst_scanline = dp + y*dstWidth + pad;
memset(dst_scanline, 0xff, sw);
@@ -848,16 +838,21 @@ bool SkBlurMask::BlurRect(SkScalar sigma, SkMask *dst,
return true;
}
-bool SkBlurMask::BlurGroundTruth(SkMask* dst, const SkMask& src, SkScalar radius,
- Style style, SkIPoint* margin) {
- return BlurGroundTruth(ConvertRadiusToSigma(radius), dst, src, style, margin);
+bool SkBlurMask::BlurRRect(SkScalar sigma, SkMask *dst,
+ const SkRRect &src, SkBlurStyle style,
+ SkIPoint *margin, SkMask::CreateMode createMode) {
+ // Temporary for now -- always fail, should cause caller to fall back
+ // to old path. Plumbing just to land API and parallelize effort.
+
+ return false;
}
+
// The "simple" blur is a direct implementation of separable convolution with a discrete
// gaussian kernel. It's "ground truth" in a sense; too slow to be used, but very
// useful for correctness comparisons.
bool SkBlurMask::BlurGroundTruth(SkScalar sigma, SkMask* dst, const SkMask& src,
- Style style, SkIPoint* margin) {
+ SkBlurStyle style, SkIPoint* margin) {
if (src.fFormat != SkMask::kA8_Format) {
return false;
@@ -865,7 +860,7 @@ bool SkBlurMask::BlurGroundTruth(SkScalar sigma, SkMask* dst, const SkMask& src,
float variance = sigma * sigma;
- int windowSize = SkScalarCeil(sigma*6);
+ int windowSize = SkScalarCeilToInt(sigma*6);
// round window size up to nearest odd number
windowSize |= 1;
@@ -973,7 +968,7 @@ bool SkBlurMask::BlurGroundTruth(SkScalar sigma, SkMask* dst, const SkMask& src,
dst->fImage = dstPixels;
// if need be, alloc the "real" dst (same size as src) and copy/merge
// the blur into it (applying the src)
- if (style == kInner_Style) {
+ if (style == kInner_SkBlurStyle) {
// now we allocate the "real" dst, mirror the size of src
size_t srcSize = src.computeImageSize();
if (0 == srcSize) {
@@ -985,14 +980,14 @@ bool SkBlurMask::BlurGroundTruth(SkScalar sigma, SkMask* dst, const SkMask& src,
dstPixels + pad*dst->fRowBytes + pad,
dst->fRowBytes, srcWidth, srcHeight);
SkMask::FreeImage(dstPixels);
- } else if (style != kNormal_Style) {
+ } else if (style != kNormal_SkBlurStyle) {
clamp_with_orig(dstPixels + pad*dst->fRowBytes + pad,
dst->fRowBytes, srcPixels, src.fRowBytes, srcWidth, srcHeight, style);
}
(void)autoCall.detach();
}
- if (style == kInner_Style) {
+ if (style == kInner_SkBlurStyle) {
dst->fBounds = src.fBounds; // restore trimmed bounds
dst->fRowBytes = src.fRowBytes;
}
diff --git a/chromium/third_party/skia/src/effects/SkBlurMask.h b/chromium/third_party/skia/src/effects/SkBlurMask.h
index e0b8d54ce1e..71f60d91faa 100644
--- a/chromium/third_party/skia/src/effects/SkBlurMask.h
+++ b/chromium/third_party/skia/src/effects/SkBlurMask.h
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -6,62 +5,79 @@
* found in the LICENSE file.
*/
-
#ifndef SkBlurMask_DEFINED
#define SkBlurMask_DEFINED
+#include "SkBlurTypes.h"
#include "SkShader.h"
#include "SkMask.h"
+#include "SkRRect.h"
class SkBlurMask {
public:
- enum Style {
- kNormal_Style, //!< fuzzy inside and outside
- kSolid_Style, //!< solid inside, fuzzy outside
- kOuter_Style, //!< nothing inside, fuzzy outside
- kInner_Style, //!< fuzzy inside, nothing outside
-
- kStyleCount
- };
-
- enum Quality {
- kLow_Quality, //!< box blur
- kHigh_Quality //!< three pass box blur (similar to gaussian)
- };
-
- static bool BlurRect(SkScalar sigma, SkMask *dst, const SkRect &src,
- Style style,
+ static bool BlurRect(SkScalar sigma, SkMask *dst, const SkRect &src, SkBlurStyle,
+ SkIPoint *margin = NULL,
+ SkMask::CreateMode createMode =
+ SkMask::kComputeBoundsAndRenderImage_CreateMode);
+ static bool BlurRRect(SkScalar sigma, SkMask *dst, const SkRRect &src, SkBlurStyle,
SkIPoint *margin = NULL,
SkMask::CreateMode createMode =
SkMask::kComputeBoundsAndRenderImage_CreateMode);
+
+ // forceQuality will prevent BoxBlur from falling back to the low quality approach when sigma
+ // is very small -- this can be used predict the margin bump ahead of time without completely
+ // replicating the internal logic. This permits not only simpler caching of blurred results,
+ // but also being able to predict precisely at what pixels the blurred profile of e.g. a
+ // rectangle will lie.
+
static bool BoxBlur(SkMask* dst, const SkMask& src,
- SkScalar sigma, Style style, Quality quality,
- SkIPoint* margin = NULL);
+ SkScalar sigma, SkBlurStyle style, SkBlurQuality quality,
+ SkIPoint* margin = NULL, bool force_quality=false);
// the "ground truth" blur does a gaussian convolution; it's slow
// but useful for comparison purposes.
- static bool BlurGroundTruth(SkScalar sigma, SkMask* dst, const SkMask& src,
- Style style,
+ static bool BlurGroundTruth(SkScalar sigma, SkMask* dst, const SkMask& src, SkBlurStyle,
SkIPoint* margin = NULL);
- SK_ATTR_DEPRECATED("use sigma version")
- static bool BlurRect(SkMask *dst, const SkRect &src,
- SkScalar radius, Style style,
- SkIPoint *margin = NULL,
- SkMask::CreateMode createMode =
- SkMask::kComputeBoundsAndRenderImage_CreateMode);
+ // If radius > 0, return the corresponding sigma, else return 0
+ static SkScalar ConvertRadiusToSigma(SkScalar radius);
+ // If sigma > 0.5, return the corresponding radius, else return 0
+ static SkScalar ConvertSigmaToRadius(SkScalar sigma);
+
+ /* Helper functions for analytic rectangle blurs */
+
+ /** Look up the intensity of the (one dimnensional) blurred half-plane.
+ @param profile The precomputed 1D blur profile; memory allocated by and managed by
+ ComputeBlurProfile below.
+ @param loc the location to look up; The lookup will clamp invalid inputs, but
+ meaningful data are available between 0 and blurred_width
+ @param blurred_width The width of the final, blurred rectangle
+ @param sharp_width The width of the original, unblurred rectangle.
+ */
+ static uint8_t ProfileLookup(const uint8_t* profile, int loc, int blurred_width, int sharp_width);
+
+ /** Allocate memory for and populate the profile of a 1D blurred halfplane. The caller
+ must free the memory. The amount of memory allocated will be exactly 6*sigma bytes.
+ @param sigma The standard deviation of the gaussian blur kernel
+ @param profile_out The location to store the allocated profile curve
+ */
+
+ static void ComputeBlurProfile(SkScalar sigma, uint8_t** profile_out);
+
+ /** Compute an entire scanline of a blurred step function. This is a 1D helper that
+ will produce both the horizontal and vertical profiles of the blurry rectangle.
+ @param pixels Location to store the resulting pixel data; allocated and managed by caller
+ @param profile Precomputed blur profile computed by ComputeBlurProfile above.
+ @param width Size of the pixels array.
+ @param sigma Standard deviation of the gaussian blur kernel used to compute the profile;
+ this implicitly gives the size of the pixels array.
+ */
+
+ static void ComputeBlurredScanline(uint8_t* pixels, const uint8_t* profile,
+ unsigned int width, SkScalar sigma);
- SK_ATTR_DEPRECATED("use sigma version")
- static bool Blur(SkMask* dst, const SkMask& src,
- SkScalar radius, Style style, Quality quality,
- SkIPoint* margin = NULL);
- SK_ATTR_DEPRECATED("use sigma version")
- static bool BlurGroundTruth(SkMask* dst, const SkMask& src,
- SkScalar radius, Style style,
- SkIPoint* margin = NULL);
- static SkScalar ConvertRadiusToSigma(SkScalar radius);
};
#endif
diff --git a/chromium/third_party/skia/src/effects/SkBlurMaskFilter.cpp b/chromium/third_party/skia/src/effects/SkBlurMaskFilter.cpp
index d2c43d719bc..fca38a1eaac 100644
--- a/chromium/third_party/skia/src/effects/SkBlurMaskFilter.cpp
+++ b/chromium/third_party/skia/src/effects/SkBlurMaskFilter.cpp
@@ -9,7 +9,8 @@
#include "SkBlurMaskFilter.h"
#include "SkBlurMask.h"
#include "SkGpuBlurUtils.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkMaskFilter.h"
#include "SkRRect.h"
#include "SkRTConf.h"
@@ -19,13 +20,21 @@
#if SK_SUPPORT_GPU
#include "GrContext.h"
#include "GrTexture.h"
+#include "GrEffect.h"
+#include "gl/GrGLEffect.h"
#include "effects/GrSimpleTextureEffect.h"
+#include "GrTBackendEffectFactory.h"
#include "SkGrPixelRef.h"
+#include "SkDraw.h"
#endif
+SkScalar SkBlurMaskFilter::ConvertRadiusToSigma(SkScalar radius) {
+ return SkBlurMask::ConvertRadiusToSigma(radius);
+}
+
class SkBlurMaskFilterImpl : public SkMaskFilter {
public:
- SkBlurMaskFilterImpl(SkScalar sigma, SkBlurMaskFilter::BlurStyle, uint32_t flags);
+ SkBlurMaskFilterImpl(SkScalar sigma, SkBlurStyle, uint32_t flags);
// overrides from SkMaskFilter
virtual SkMask::Format getFormat() const SK_OVERRIDE;
@@ -37,15 +46,26 @@ public:
const SkIRect& clipBounds,
const SkMatrix& ctm,
SkRect* maskRect) const SK_OVERRIDE;
+ virtual bool directFilterMaskGPU(GrContext* context,
+ GrPaint* grp,
+ const SkStrokeRec& strokeRec,
+ const SkPath& path) const SK_OVERRIDE;
+ virtual bool directFilterRRectMaskGPU(GrContext* context,
+ GrPaint* grp,
+ const SkStrokeRec& strokeRec,
+ const SkRRect& rrect) const SK_OVERRIDE;
+
virtual bool filterMaskGPU(GrTexture* src,
+ const SkMatrix& ctm,
const SkRect& maskRect,
GrTexture** result,
- bool canOverwriteSrc) const;
+ bool canOverwriteSrc) const SK_OVERRIDE;
#endif
virtual void computeFastBounds(const SkRect&, SkRect*) const SK_OVERRIDE;
+ virtual bool asABlur(BlurRec*) const SK_OVERRIDE;
- SkDEVCODE(virtual void toString(SkString* str) const SK_OVERRIDE;)
+ SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurMaskFilterImpl)
protected:
@@ -59,6 +79,8 @@ protected:
bool filterRectMask(SkMask* dstM, const SkRect& r, const SkMatrix& matrix,
SkIPoint* margin, SkMask::CreateMode createMode) const;
+ bool filterRRectMask(SkMask* dstM, const SkRRect& r, const SkMatrix& matrix,
+ SkIPoint* margin, SkMask::CreateMode createMode) const;
private:
// To avoid unseemly allocation requests (esp. for finite platforms like
@@ -66,12 +88,17 @@ private:
// a request like 10,000)
static const SkScalar kMAX_BLUR_SIGMA;
- SkScalar fSigma;
- SkBlurMaskFilter::BlurStyle fBlurStyle;
- uint32_t fBlurFlags;
+ SkScalar fSigma;
+ SkBlurStyle fBlurStyle;
+ uint32_t fBlurFlags;
- SkBlurMaskFilterImpl(SkFlattenableReadBuffer&);
- virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+ SkBlurQuality getQuality() const {
+ return (fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ?
+ kHigh_SkBlurQuality : kLow_SkBlurQuality;
+ }
+
+ SkBlurMaskFilterImpl(SkReadBuffer&);
+ virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
SkScalar computeXformedSigma(const SkMatrix& ctm) const {
bool ignoreTransform = SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag);
@@ -85,50 +112,27 @@ private:
const SkScalar SkBlurMaskFilterImpl::kMAX_BLUR_SIGMA = SkIntToScalar(128);
-SkMaskFilter* SkBlurMaskFilter::Create(SkScalar radius,
- SkBlurMaskFilter::BlurStyle style,
- uint32_t flags) {
- // use !(radius > 0) instead of radius <= 0 to reject NaN values
- if (!(radius > 0) || (unsigned)style >= SkBlurMaskFilter::kBlurStyleCount
- || flags > SkBlurMaskFilter::kAll_BlurFlag) {
+SkMaskFilter* SkBlurMaskFilter::Create(SkBlurStyle style, SkScalar sigma, uint32_t flags) {
+ if (!SkScalarIsFinite(sigma) || sigma <= 0) {
return NULL;
}
-
- SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(radius);
-
- return SkNEW_ARGS(SkBlurMaskFilterImpl, (sigma, style, flags));
-}
-
-SkMaskFilter* SkBlurMaskFilter::Create(SkBlurMaskFilter::BlurStyle style,
- SkScalar sigma,
- uint32_t flags) {
- // use !(sigma > 0) instead of sigma <= 0 to reject NaN values
- if (!(sigma > 0) || (unsigned)style >= SkBlurMaskFilter::kBlurStyleCount
- || flags > SkBlurMaskFilter::kAll_BlurFlag) {
+ if ((unsigned)style > (unsigned)kLastEnum_SkBlurStyle) {
+ return NULL;
+ }
+ if (flags > SkBlurMaskFilter::kAll_BlurFlag) {
return NULL;
}
-
return SkNEW_ARGS(SkBlurMaskFilterImpl, (sigma, style, flags));
}
///////////////////////////////////////////////////////////////////////////////
-SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar sigma,
- SkBlurMaskFilter::BlurStyle style,
- uint32_t flags)
- : fSigma(sigma), fBlurStyle(style), fBlurFlags(flags) {
-#if 0
- fGamma = NULL;
- if (gammaScale) {
- fGamma = new U8[256];
- if (gammaScale > 0)
- SkBlurMask::BuildSqrGamma(fGamma, gammaScale);
- else
- SkBlurMask::BuildSqrtGamma(fGamma, -gammaScale);
- }
-#endif
- SkASSERT(fSigma >= 0);
- SkASSERT((unsigned)style < SkBlurMaskFilter::kBlurStyleCount);
+SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar sigma, SkBlurStyle style, uint32_t flags)
+ : fSigma(sigma)
+ , fBlurStyle(style)
+ , fBlurFlags(flags) {
+ SkASSERT(fSigma > 0);
+ SkASSERT((unsigned)style <= kLastEnum_SkBlurStyle);
SkASSERT(flags <= SkBlurMaskFilter::kAll_BlurFlag);
}
@@ -136,25 +140,41 @@ SkMask::Format SkBlurMaskFilterImpl::getFormat() const {
return SkMask::kA8_Format;
}
+bool SkBlurMaskFilterImpl::asABlur(BlurRec* rec) const {
+ if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) {
+ return false;
+ }
+
+ if (rec) {
+ rec->fSigma = fSigma;
+ rec->fStyle = fBlurStyle;
+ rec->fQuality = this->getQuality();
+ }
+ return true;
+}
+
bool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src,
const SkMatrix& matrix,
SkIPoint* margin) const{
SkScalar sigma = this->computeXformedSigma(matrix);
+ return SkBlurMask::BoxBlur(dst, src, sigma, fBlurStyle, this->getQuality(), margin);
+}
- SkBlurMask::Quality blurQuality =
- (fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ?
- SkBlurMask::kHigh_Quality : SkBlurMask::kLow_Quality;
+bool SkBlurMaskFilterImpl::filterRectMask(SkMask* dst, const SkRect& r,
+ const SkMatrix& matrix,
+ SkIPoint* margin, SkMask::CreateMode createMode) const{
+ SkScalar sigma = computeXformedSigma(matrix);
- return SkBlurMask::BoxBlur(dst, src, sigma, (SkBlurMask::Style)fBlurStyle,
- blurQuality, margin);
+ return SkBlurMask::BlurRect(sigma, dst, r, fBlurStyle,
+ margin, createMode);
}
-bool SkBlurMaskFilterImpl::filterRectMask(SkMask* dst, const SkRect& r,
+bool SkBlurMaskFilterImpl::filterRRectMask(SkMask* dst, const SkRRect& r,
const SkMatrix& matrix,
SkIPoint* margin, SkMask::CreateMode createMode) const{
SkScalar sigma = computeXformedSigma(matrix);
- return SkBlurMask::BlurRect(sigma, dst, r, (SkBlurMask::Style)fBlurStyle,
+ return SkBlurMask::BlurRRect(sigma, dst, r, fBlurStyle,
margin, createMode);
}
@@ -185,10 +205,7 @@ static bool draw_rrect_into_mask(const SkRRect rrect, SkMask* mask) {
// FIXME: This code duplicates code in draw_rects_into_mask, below. Is there a
// clean way to share more code?
SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kA8_Config,
- mask->fBounds.width(), mask->fBounds.height(),
- mask->fRowBytes);
- bitmap.setPixels(mask->fImage);
+ bitmap.installMaskPixels(*mask);
SkCanvas canvas(bitmap);
canvas.translate(-SkIntToScalar(mask->fBounds.left()),
@@ -206,10 +223,11 @@ static bool draw_rects_into_mask(const SkRect rects[], int count, SkMask* mask)
}
SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kA8_Config,
- mask->fBounds.width(), mask->fBounds.height(),
- mask->fRowBytes);
- bitmap.setPixels(mask->fImage);
+ bitmap.installPixels(SkImageInfo::Make(mask->fBounds.width(),
+ mask->fBounds.height(),
+ kAlpha_8_SkColorType,
+ kPremul_SkAlphaType),
+ mask->fImage, mask->fRowBytes);
SkCanvas canvas(bitmap);
canvas.translate(-SkIntToScalar(mask->fBounds.left()),
@@ -236,6 +254,12 @@ static bool rect_exceeds(const SkRect& r, SkScalar v) {
r.width() > v || r.height() > v;
}
+#ifdef SK_IGNORE_FAST_RRECT_BLUR
+SK_CONF_DECLARE( bool, c_analyticBlurRRect, "mask.filter.blur.analyticblurrrect", false, "Use the faster analytic blur approach for ninepatch rects" );
+#else
+SK_CONF_DECLARE( bool, c_analyticBlurRRect, "mask.filter.blur.analyticblurrrect", true, "Use the faster analytic blur approach for ninepatch round rects" );
+#endif
+
SkMaskFilter::FilterReturn
SkBlurMaskFilterImpl::filterRRectToNine(const SkRRect& rrect, const SkMatrix& matrix,
const SkIRect& clipBounds,
@@ -259,16 +283,16 @@ SkBlurMaskFilterImpl::filterRRectToNine(const SkRRect& rrect, const SkMatrix& ma
// already have code for rectangles.
return kUnimplemented_FilterReturn;
+ // These three can take advantage of this fast path.
case SkRRect::kSimple_Type:
- // Fall through.
+ case SkRRect::kNinePatch_Type:
case SkRRect::kComplex_Type:
- // These can take advantage of this fast path.
break;
}
// TODO: report correct metrics for innerstyle, where we do not grow the
// total bounds, but we do need an inset the size of our blur-radius
- if (SkBlurMaskFilter::kInner_BlurStyle == fBlurStyle) {
+ if (kInner_SkBlurStyle == fBlurStyle) {
return kUnimplemented_FilterReturn;
}
@@ -285,7 +309,19 @@ SkBlurMaskFilterImpl::filterRRectToNine(const SkRRect& rrect, const SkMatrix& ma
srcM.fFormat = SkMask::kA8_Format;
srcM.fRowBytes = 0;
- if (!this->filterMask(&dstM, srcM, matrix, &margin)) {
+ bool filterResult = false;
+ if (c_analyticBlurRRect) {
+ // special case for fast round rect blur
+ // don't actually do the blur the first time, just compute the correct size
+ filterResult = this->filterRRectMask(&dstM, rrect, matrix, &margin,
+ SkMask::kJustComputeBounds_CreateMode);
+ }
+
+ if (!filterResult) {
+ filterResult = this->filterMask(&dstM, srcM, matrix, &margin);
+ }
+
+ if (!filterResult) {
return kFalse_FilterReturn;
}
@@ -329,14 +365,23 @@ SkBlurMaskFilterImpl::filterRRectToNine(const SkRRect& rrect, const SkMatrix& ma
radii[SkRRect::kLowerLeft_Corner] = LL;
smallRR.setRectRadii(smallR, radii);
- if (!draw_rrect_into_mask(smallRR, &srcM)) {
- return kFalse_FilterReturn;
+ bool analyticBlurWorked = false;
+ if (c_analyticBlurRRect) {
+ analyticBlurWorked =
+ this->filterRRectMask(&patch->fMask, smallRR, matrix, &margin,
+ SkMask::kComputeBoundsAndRenderImage_CreateMode);
}
- SkAutoMaskFreeImage amf(srcM.fImage);
+ if (!analyticBlurWorked) {
+ if (!draw_rrect_into_mask(smallRR, &srcM)) {
+ return kFalse_FilterReturn;
+ }
+
+ SkAutoMaskFreeImage amf(srcM.fImage);
- if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) {
- return kFalse_FilterReturn;
+ if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) {
+ return kFalse_FilterReturn;
+ }
}
patch->fMask.fBounds.offsetTo(0, 0);
@@ -346,11 +391,7 @@ SkBlurMaskFilterImpl::filterRRectToNine(const SkRRect& rrect, const SkMatrix& ma
return kTrue_FilterReturn;
}
-#ifdef SK_IGNORE_FAST_RECT_BLUR
-SK_CONF_DECLARE( bool, c_analyticBlurNinepatch, "mask.filter.analyticNinePatch", false, "Use the faster analytic blur approach for ninepatch rects" );
-#else
SK_CONF_DECLARE( bool, c_analyticBlurNinepatch, "mask.filter.analyticNinePatch", true, "Use the faster analytic blur approach for ninepatch rects" );
-#endif
SkMaskFilter::FilterReturn
SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count,
@@ -363,8 +404,7 @@ SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count,
// TODO: report correct metrics for innerstyle, where we do not grow the
// total bounds, but we do need an inset the size of our blur-radius
- if (SkBlurMaskFilter::kInner_BlurStyle == fBlurStyle ||
- SkBlurMaskFilter::kOuter_BlurStyle == fBlurStyle) {
+ if (kInner_SkBlurStyle == fBlurStyle || kOuter_SkBlurStyle == fBlurStyle) {
return kUnimplemented_FilterReturn;
}
@@ -481,19 +521,16 @@ void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src,
src.fRight + pad, src.fBottom + pad);
}
-SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkFlattenableReadBuffer& buffer)
+SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkReadBuffer& buffer)
: SkMaskFilter(buffer) {
-#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
- // TODO: when the skps are recaptured at > v15 the SkScalarAbs can be removed
-#endif
- fSigma = SkScalarAbs(buffer.readScalar());
- fBlurStyle = (SkBlurMaskFilter::BlurStyle)buffer.readInt();
+ fSigma = buffer.readScalar();
+ fBlurStyle = (SkBlurStyle)buffer.readInt();
fBlurFlags = buffer.readUInt() & SkBlurMaskFilter::kAll_BlurFlag;
- SkASSERT(fSigma >= 0);
- SkASSERT((unsigned)fBlurStyle < SkBlurMaskFilter::kBlurStyleCount);
+ SkASSERT(fSigma > 0);
+ SkASSERT((unsigned)fBlurStyle <= kLastEnum_SkBlurStyle);
}
-void SkBlurMaskFilterImpl::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkBlurMaskFilterImpl::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeScalar(fSigma);
buffer.writeInt(fBlurStyle);
@@ -502,6 +539,560 @@ void SkBlurMaskFilterImpl::flatten(SkFlattenableWriteBuffer& buffer) const {
#if SK_SUPPORT_GPU
+class GrGLRectBlurEffect;
+
+class GrRectBlurEffect : public GrEffect {
+public:
+ virtual ~GrRectBlurEffect();
+
+ static const char* Name() { return "RectBlur"; }
+
+ typedef GrGLRectBlurEffect GLEffect;
+
+ virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
+ virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
+
+ /**
+ * Create a simple filter effect with custom bicubic coefficients.
+ */
+ static GrEffectRef* Create(GrContext *context, const SkRect& rect,
+ float sigma) {
+ GrTexture *blurProfileTexture = NULL;
+ int doubleProfileSize = SkScalarCeilToInt(12*sigma);
+
+ if (doubleProfileSize >= rect.width() || doubleProfileSize >= rect.height()) {
+ // if the blur sigma is too large so the gaussian overlaps the whole
+ // rect in either direction, fall back to CPU path for now.
+
+ return NULL;
+ }
+
+ bool createdBlurProfileTexture = CreateBlurProfileTexture(context, sigma, &blurProfileTexture);
+ SkAutoTUnref<GrTexture> hunref(blurProfileTexture);
+ if (!createdBlurProfileTexture) {
+ return NULL;
+ }
+ AutoEffectUnref effect(SkNEW_ARGS(GrRectBlurEffect, (rect, sigma, blurProfileTexture)));
+ return CreateEffectRef(effect);
+ }
+
+ const SkRect& getRect() const { return fRect; }
+ float getSigma() const { return fSigma; }
+
+private:
+ GrRectBlurEffect(const SkRect& rect, float sigma, GrTexture *blur_profile);
+ virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
+
+ static bool CreateBlurProfileTexture(GrContext *context, float sigma,
+ GrTexture **blurProfileTexture);
+
+ SkRect fRect;
+ float fSigma;
+ GrTextureAccess fBlurProfileAccess;
+
+ GR_DECLARE_EFFECT_TEST;
+
+ typedef GrEffect INHERITED;
+};
+
+class GrGLRectBlurEffect : public GrGLEffect {
+public:
+ GrGLRectBlurEffect(const GrBackendEffectFactory& factory,
+ const GrDrawEffect&);
+ virtual void emitCode(GrGLShaderBuilder*,
+ const GrDrawEffect&,
+ EffectKey,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray&) SK_OVERRIDE;
+
+ virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
+
+private:
+ typedef GrGLUniformManager::UniformHandle UniformHandle;
+
+ UniformHandle fProxyRectUniform;
+ UniformHandle fProfileSizeUniform;
+
+ typedef GrGLEffect INHERITED;
+};
+
+
+
+GrGLRectBlurEffect::GrGLRectBlurEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
+ : INHERITED(factory) {
+}
+
+void OutputRectBlurProfileLookup(GrGLShaderBuilder* builder,
+ const GrGLShaderBuilder::TextureSampler& sampler,
+ const char *output,
+ const char *profileSize, const char *loc,
+ const char *blurred_width,
+ const char *sharp_width) {
+ builder->fsCodeAppendf("\tfloat %s;\n", output);
+ builder->fsCodeAppendf("\t\t{\n");
+ builder->fsCodeAppendf("\t\t\tfloat coord = (0.5 * (abs(2.0*%s - %s) - %s))/%s;\n",
+ loc, blurred_width, sharp_width, profileSize);
+ builder->fsCodeAppendf("\t\t\t%s = ", output);
+ builder->fsAppendTextureLookup(sampler, "vec2(coord,0.5)");
+ builder->fsCodeAppend(".a;\n");
+ builder->fsCodeAppendf("\t\t}\n");
+}
+
+void GrGLRectBlurEffect::emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect&,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray& coords,
+ const TextureSamplerArray& samplers) {
+
+ const char *rectName;
+ const char *profileSizeName;
+
+ fProxyRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kVec4f_GrSLType,
+ "proxyRect",
+ &rectName);
+ fProfileSizeUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kFloat_GrSLType,
+ "profileSize",
+ &profileSizeName);
+
+ const char *fragmentPos = builder->fragmentPosition();
+
+ if (inputColor) {
+ builder->fsCodeAppendf("\tvec4 src=%s;\n", inputColor);
+ } else {
+ builder->fsCodeAppendf("\tvec4 src=vec4(1)\n;");
+ }
+
+ builder->fsCodeAppendf("\tvec2 translatedPos = %s.xy - %s.xy;\n", fragmentPos, rectName );
+ builder->fsCodeAppendf("\tfloat width = %s.z - %s.x;\n", rectName, rectName);
+ builder->fsCodeAppendf("\tfloat height = %s.w - %s.y;\n", rectName, rectName);
+
+ builder->fsCodeAppendf("\tvec2 smallDims = vec2(width - %s, height-%s);\n", profileSizeName, profileSizeName);
+ builder->fsCodeAppendf("\tfloat center = 2.0 * floor(%s/2.0 + .25) - 1.0;\n", profileSizeName);
+ builder->fsCodeAppendf("\tvec2 wh = smallDims - vec2(center,center);\n");
+
+ OutputRectBlurProfileLookup(builder, samplers[0], "horiz_lookup", profileSizeName, "translatedPos.x", "width", "wh.x");
+ OutputRectBlurProfileLookup(builder, samplers[0], "vert_lookup", profileSizeName, "translatedPos.y", "height", "wh.y");
+
+ builder->fsCodeAppendf("\tfloat final = horiz_lookup * vert_lookup;\n");
+ builder->fsCodeAppendf("\t%s = src * vec4(final);\n", outputColor );
+}
+
+void GrGLRectBlurEffect::setData(const GrGLUniformManager& uman,
+ const GrDrawEffect& drawEffect) {
+ const GrRectBlurEffect& rbe = drawEffect.castEffect<GrRectBlurEffect>();
+ SkRect rect = rbe.getRect();
+
+ uman.set4f(fProxyRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
+ uman.set1f(fProfileSizeUniform, SkScalarCeilToScalar(6*rbe.getSigma()));
+}
+
+bool GrRectBlurEffect::CreateBlurProfileTexture(GrContext *context, float sigma,
+ GrTexture **blurProfileTexture) {
+ GrTextureParams params;
+ GrTextureDesc texDesc;
+
+ unsigned int profile_size = SkScalarCeilToInt(6*sigma);
+
+ texDesc.fWidth = profile_size;
+ texDesc.fHeight = 1;
+ texDesc.fConfig = kAlpha_8_GrPixelConfig;
+
+ static const GrCacheID::Domain gBlurProfileDomain = GrCacheID::GenerateDomain();
+ GrCacheID::Key key;
+ memset(&key, 0, sizeof(key));
+ key.fData32[0] = profile_size;
+ key.fData32[1] = 1;
+ GrCacheID blurProfileKey(gBlurProfileDomain, key);
+
+ uint8_t *profile = NULL;
+ SkAutoTDeleteArray<uint8_t> ada(NULL);
+
+ *blurProfileTexture = context->findAndRefTexture(texDesc, blurProfileKey, &params);
+
+ if (NULL == *blurProfileTexture) {
+
+ SkBlurMask::ComputeBlurProfile(sigma, &profile);
+ ada.reset(profile);
+
+ *blurProfileTexture = context->createTexture(&params, texDesc, blurProfileKey,
+ profile, 0);
+
+ if (NULL == *blurProfileTexture) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+GrRectBlurEffect::GrRectBlurEffect(const SkRect& rect, float sigma,
+ GrTexture *blur_profile)
+ : INHERITED(),
+ fRect(rect),
+ fSigma(sigma),
+ fBlurProfileAccess(blur_profile) {
+ this->addTextureAccess(&fBlurProfileAccess);
+ this->setWillReadFragmentPosition();
+}
+
+GrRectBlurEffect::~GrRectBlurEffect() {
+}
+
+const GrBackendEffectFactory& GrRectBlurEffect::getFactory() const {
+ return GrTBackendEffectFactory<GrRectBlurEffect>::getInstance();
+}
+
+bool GrRectBlurEffect::onIsEqual(const GrEffect& sBase) const {
+ const GrRectBlurEffect& s = CastEffect<GrRectBlurEffect>(sBase);
+ return this->getSigma() == s.getSigma() && this->getRect() == s.getRect();
+}
+
+void GrRectBlurEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
+ *validFlags = 0;
+ return;
+}
+
+GR_DEFINE_EFFECT_TEST(GrRectBlurEffect);
+
+GrEffectRef* GrRectBlurEffect::TestCreate(SkRandom* random,
+ GrContext* context,
+ const GrDrawTargetCaps&,
+ GrTexture**) {
+ float sigma = random->nextRangeF(3,8);
+ float width = random->nextRangeF(200,300);
+ float height = random->nextRangeF(200,300);
+ return GrRectBlurEffect::Create(context, SkRect::MakeWH(width, height), sigma);
+}
+
+
+bool SkBlurMaskFilterImpl::directFilterMaskGPU(GrContext* context,
+ GrPaint* grp,
+ const SkStrokeRec& strokeRec,
+ const SkPath& path) const {
+ if (fBlurStyle != kNormal_SkBlurStyle) {
+ return false;
+ }
+
+ SkRect rect;
+ if (!path.isRect(&rect)) {
+ return false;
+ }
+
+ if (!strokeRec.isFillStyle()) {
+ return false;
+ }
+
+ SkMatrix ctm = context->getMatrix();
+ SkScalar xformedSigma = this->computeXformedSigma(ctm);
+
+ int pad=SkScalarCeilToInt(6*xformedSigma)/2;
+ rect.outset(SkIntToScalar(pad), SkIntToScalar(pad));
+
+ SkAutoTUnref<GrEffectRef> effect(GrRectBlurEffect::Create(
+ context, rect, xformedSigma));
+ if (!effect) {
+ return false;
+ }
+
+ GrContext::AutoMatrix am;
+ if (!am.setIdentity(context, grp)) {
+ return false;
+ }
+
+ grp->addCoverageEffect(effect);
+
+ context->drawRect(*grp, rect);
+ return true;
+}
+
+class GrGLRRectBlurEffect;
+
+class GrRRectBlurEffect : public GrEffect {
+public:
+
+ static GrEffectRef* Create(GrContext* context, float sigma, const SkRRect&);
+
+ virtual ~GrRRectBlurEffect() {};
+ static const char* Name() { return "GrRRectBlur"; }
+
+ const SkRRect& getRRect() const { return fRRect; }
+ float getSigma() const { return fSigma; }
+
+ typedef GrGLRRectBlurEffect GLEffect;
+
+ virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
+
+ virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
+
+private:
+ GrRRectBlurEffect(float sigma, const SkRRect&, GrTexture* profileTexture);
+
+ virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE;
+
+ SkRRect fRRect;
+ float fSigma;
+ GrTextureAccess fNinePatchAccess;
+
+ GR_DECLARE_EFFECT_TEST;
+
+ typedef GrEffect INHERITED;
+};
+
+
+GrEffectRef* GrRRectBlurEffect::Create(GrContext* context, float sigma, const SkRRect& rrect) {
+ if (!rrect.isSimpleCircular()) {
+ return NULL;
+ }
+
+ // Make sure we can successfully ninepatch this rrect -- the blur sigma has to be
+ // sufficiently small relative to both the size of the corner radius and the
+ // width (and height) of the rrect.
+
+ unsigned int blurRadius = 3*SkScalarCeilToInt(sigma-1/6.0f);
+ unsigned int cornerRadius = SkScalarCeilToInt(rrect.getSimpleRadii().x());
+ if (cornerRadius + blurRadius > rrect.width()/2 ||
+ cornerRadius + blurRadius > rrect.height()/2) {
+ return NULL;
+ }
+
+ static const GrCacheID::Domain gRRectBlurDomain = GrCacheID::GenerateDomain();
+ GrCacheID::Key key;
+ memset(&key, 0, sizeof(key));
+ key.fData32[0] = blurRadius;
+ key.fData32[1] = cornerRadius;
+ GrCacheID blurRRectNinePatchID(gRRectBlurDomain, key);
+
+ GrTextureParams params;
+ params.setFilterMode(GrTextureParams::kBilerp_FilterMode);
+
+ unsigned int smallRectSide = 2*(blurRadius + cornerRadius) + 1;
+ unsigned int texSide = smallRectSide + 2*blurRadius;
+ GrTextureDesc texDesc;
+ texDesc.fWidth = texSide;
+ texDesc.fHeight = texSide;
+ texDesc.fConfig = kAlpha_8_GrPixelConfig;
+
+ GrTexture *blurNinePatchTexture = context->findAndRefTexture(texDesc, blurRRectNinePatchID, &params);
+
+ if (NULL == blurNinePatchTexture) {
+ SkMask mask;
+
+ mask.fBounds = SkIRect::MakeWH(smallRectSide, smallRectSide);
+ mask.fFormat = SkMask::kA8_Format;
+ mask.fRowBytes = mask.fBounds.width();
+ mask.fImage = SkMask::AllocImage(mask.computeTotalImageSize());
+ SkAutoMaskFreeImage amfi(mask.fImage);
+
+ memset(mask.fImage, 0, mask.computeTotalImageSize());
+
+ SkRect smallRect;
+ smallRect.setWH(SkIntToScalar(smallRectSide), SkIntToScalar(smallRectSide));
+
+ SkRRect smallRRect;
+ smallRRect.setRectXY(smallRect, SkIntToScalar(cornerRadius), SkIntToScalar(cornerRadius));
+
+ SkPath path;
+ path.addRRect( smallRRect );
+
+ SkDraw::DrawToMask(path, &mask.fBounds, NULL, NULL, &mask, SkMask::kJustRenderImage_CreateMode, SkPaint::kFill_Style);
+
+ SkMask blurred_mask;
+ SkBlurMask::BoxBlur(&blurred_mask, mask, sigma, kNormal_SkBlurStyle, kHigh_SkBlurQuality, NULL, true );
+
+ blurNinePatchTexture = context->createTexture(&params, texDesc, blurRRectNinePatchID, blurred_mask.fImage, 0);
+ SkMask::FreeImage(blurred_mask.fImage);
+ }
+
+ SkAutoTUnref<GrTexture> blurunref(blurNinePatchTexture);
+ if (NULL == blurNinePatchTexture) {
+ return NULL;
+ }
+
+ return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(GrRRectBlurEffect,
+ (sigma, rrect, blurNinePatchTexture))));
+}
+
+void GrRRectBlurEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
+ *validFlags = 0;
+}
+
+const GrBackendEffectFactory& GrRRectBlurEffect::getFactory() const {
+ return GrTBackendEffectFactory<GrRRectBlurEffect>::getInstance();
+}
+
+GrRRectBlurEffect::GrRRectBlurEffect(float sigma, const SkRRect& rrect, GrTexture *ninePatchTexture)
+ : fRRect(rrect),
+ fSigma(sigma),
+ fNinePatchAccess(ninePatchTexture) {
+ this->addTextureAccess(&fNinePatchAccess);
+ this->setWillReadFragmentPosition();
+}
+
+bool GrRRectBlurEffect::onIsEqual(const GrEffect& other) const {
+ const GrRRectBlurEffect& rrbe = CastEffect<GrRRectBlurEffect>(other);
+ return fRRect.getSimpleRadii().fX == rrbe.fRRect.getSimpleRadii().fX && fSigma == rrbe.fSigma;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+GR_DEFINE_EFFECT_TEST(GrRRectBlurEffect);
+
+GrEffectRef* GrRRectBlurEffect::TestCreate(SkRandom* random,
+ GrContext* context,
+ const GrDrawTargetCaps& caps,
+ GrTexture*[]) {
+ SkScalar w = random->nextRangeScalar(100.f, 1000.f);
+ SkScalar h = random->nextRangeScalar(100.f, 1000.f);
+ SkScalar r = random->nextRangeF(1.f, 9.f);
+ SkScalar sigma = random->nextRangeF(1.f,10.f);
+ SkRRect rrect;
+ rrect.setRectXY(SkRect::MakeWH(w, h), r, r);
+ return GrRRectBlurEffect::Create(context, sigma, rrect);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+class GrGLRRectBlurEffect : public GrGLEffect {
+public:
+ GrGLRRectBlurEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
+
+ virtual void emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect& drawEffect,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray&) SK_OVERRIDE;
+
+ virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
+
+private:
+ GrGLUniformManager::UniformHandle fProxyRectUniform;
+ GrGLUniformManager::UniformHandle fCornerRadiusUniform;
+ GrGLUniformManager::UniformHandle fBlurRadiusUniform;
+ typedef GrGLEffect INHERITED;
+};
+
+GrGLRRectBlurEffect::GrGLRRectBlurEffect(const GrBackendEffectFactory& factory,
+ const GrDrawEffect& drawEffect)
+ : INHERITED (factory) {
+}
+
+void GrGLRRectBlurEffect::emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect& drawEffect,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray& samplers) {
+ const char *rectName;
+ const char *cornerRadiusName;
+ const char *blurRadiusName;
+
+ // The proxy rect has left, top, right, and bottom edges correspond to
+ // components x, y, z, and w, respectively.
+
+ fProxyRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kVec4f_GrSLType,
+ "proxyRect",
+ &rectName);
+ fCornerRadiusUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kFloat_GrSLType,
+ "cornerRadius",
+ &cornerRadiusName);
+ fBlurRadiusUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kFloat_GrSLType,
+ "blurRadius",
+ &blurRadiusName);
+ const char* fragmentPos = builder->fragmentPosition();
+
+ // warp the fragment position to the appropriate part of the 9patch blur texture
+
+ builder->fsCodeAppendf("\t\tvec2 rectCenter = (%s.xy + %s.zw)/2.0;\n", rectName, rectName);
+ builder->fsCodeAppendf("\t\tvec2 translatedFragPos = %s.xy - %s.xy;\n", fragmentPos, rectName);
+ builder->fsCodeAppendf("\t\tfloat threshold = %s + 2.0*%s;\n", cornerRadiusName, blurRadiusName );
+ builder->fsCodeAppendf("\t\tvec2 middle = %s.zw - %s.xy - 2.0*threshold;\n", rectName, rectName );
+
+ builder->fsCodeAppendf("\t\tif (translatedFragPos.x >= threshold && translatedFragPos.x < (middle.x+threshold)) {\n" );
+ builder->fsCodeAppendf("\t\t\ttranslatedFragPos.x = threshold;\n");
+ builder->fsCodeAppendf("\t\t} else if (translatedFragPos.x >= (middle.x + threshold)) {\n");
+ builder->fsCodeAppendf("\t\t\ttranslatedFragPos.x -= middle.x - 1.0;\n");
+ builder->fsCodeAppendf("\t\t}\n");
+
+ builder->fsCodeAppendf("\t\tif (translatedFragPos.y > threshold && translatedFragPos.y < (middle.y+threshold)) {\n" );
+ builder->fsCodeAppendf("\t\t\ttranslatedFragPos.y = threshold;\n");
+ builder->fsCodeAppendf("\t\t} else if (translatedFragPos.y >= (middle.y + threshold)) {\n");
+ builder->fsCodeAppendf("\t\t\ttranslatedFragPos.y -= middle.y - 1.0;\n");
+ builder->fsCodeAppendf("\t\t}\n");
+
+ builder->fsCodeAppendf("\t\tvec2 proxyDims = vec2(2.0*threshold+1.0);\n");
+ builder->fsCodeAppendf("\t\tvec2 texCoord = translatedFragPos / proxyDims;\n");
+
+ builder->fsCodeAppendf("\t%s = ", outputColor);
+ builder->fsAppendTextureLookupAndModulate(inputColor, samplers[0], "texCoord");
+ builder->fsCodeAppend(";\n");
+}
+
+void GrGLRRectBlurEffect::setData(const GrGLUniformManager& uman,
+ const GrDrawEffect& drawEffect) {
+ const GrRRectBlurEffect& brre = drawEffect.castEffect<GrRRectBlurEffect>();
+ SkRRect rrect = brre.getRRect();
+
+ float blurRadius = 3.f*SkScalarCeilToScalar(brre.getSigma()-1/6.0f);
+ uman.set1f(fBlurRadiusUniform, blurRadius);
+
+ SkRect rect = rrect.getBounds();
+ rect.outset(blurRadius, blurRadius);
+ uman.set4f(fProxyRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
+
+ SkScalar radius = 0;
+ SkASSERT(rrect.isSimpleCircular() || rrect.isRect());
+ radius = rrect.getSimpleRadii().fX;
+ uman.set1f(fCornerRadiusUniform, radius);
+}
+
+
+bool SkBlurMaskFilterImpl::directFilterRRectMaskGPU(GrContext* context,
+ GrPaint* grp,
+ const SkStrokeRec& strokeRec,
+ const SkRRect& rrect) const {
+ if (fBlurStyle != kNormal_SkBlurStyle) {
+ return false;
+ }
+
+ if (!strokeRec.isFillStyle()) {
+ return false;
+ }
+
+ SkRect proxy_rect = rrect.rect();
+ SkMatrix ctm = context->getMatrix();
+ SkScalar xformedSigma = this->computeXformedSigma(ctm);
+ float extra=3.f*SkScalarCeilToScalar(xformedSigma-1/6.0f);
+ proxy_rect.outset(extra, extra);
+
+ SkAutoTUnref<GrEffectRef> effect(GrRRectBlurEffect::Create(
+ context, xformedSigma, rrect));
+ if (!effect) {
+ return false;
+ }
+
+ GrContext::AutoMatrix am;
+ if (!am.setIdentity(context, grp)) {
+ return false;
+ }
+
+ grp->addCoverageEffect(effect);
+
+ context->drawRect(*grp, proxy_rect);
+ return true;
+}
+
bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRect& srcBounds,
const SkIRect& clipBounds,
const SkMatrix& ctm,
@@ -540,6 +1131,7 @@ bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRect& srcBounds,
}
bool SkBlurMaskFilterImpl::filterMaskGPU(GrTexture* src,
+ const SkMatrix& ctm,
const SkRect& maskRect,
GrTexture** result,
bool canOverwriteSrc) const {
@@ -549,12 +1141,12 @@ bool SkBlurMaskFilterImpl::filterMaskGPU(GrTexture* src,
GrContext::AutoWideOpenIdentityDraw awo(context, NULL);
- SkScalar xformedSigma = this->computeXformedSigma(context->getMatrix());
+ SkScalar xformedSigma = this->computeXformedSigma(ctm);
SkASSERT(xformedSigma > 0);
// If we're doing a normal blur, we can clobber the pathTexture in the
// gaussianBlur. Otherwise, we need to save it for later compositing.
- bool isNormalBlur = (SkBlurMaskFilter::kNormal_BlurStyle == fBlurStyle);
+ bool isNormalBlur = (kNormal_SkBlurStyle == fBlurStyle);
*result = SkGpuBlurUtils::GaussianBlur(context, src, isNormalBlur && canOverwriteSrc,
clipRect, false, xformedSigma, xformedSigma);
if (NULL == *result) {
@@ -569,14 +1161,14 @@ bool SkBlurMaskFilterImpl::filterMaskGPU(GrTexture* src,
// Blend pathTexture over blurTexture.
GrContext::AutoRenderTarget art(context, (*result)->asRenderTarget());
paint.addColorEffect(GrSimpleTextureEffect::Create(src, matrix))->unref();
- if (SkBlurMaskFilter::kInner_BlurStyle == fBlurStyle) {
+ if (kInner_SkBlurStyle == fBlurStyle) {
// inner: dst = dst * src
paint.setBlendFunc(kDC_GrBlendCoeff, kZero_GrBlendCoeff);
- } else if (SkBlurMaskFilter::kSolid_BlurStyle == fBlurStyle) {
+ } else if (kSolid_SkBlurStyle == fBlurStyle) {
// solid: dst = src + dst - src * dst
// = (1 - dst) * src + 1 * dst
paint.setBlendFunc(kIDC_GrBlendCoeff, kOne_GrBlendCoeff);
- } else if (SkBlurMaskFilter::kOuter_BlurStyle == fBlurStyle) {
+ } else if (kOuter_SkBlurStyle == fBlurStyle) {
// outer: dst = dst * (1 - src)
// = 0 * src + (1 - src) * dst
paint.setBlendFunc(kZero_GrBlendCoeff, kISC_GrBlendCoeff);
@@ -590,7 +1182,7 @@ bool SkBlurMaskFilterImpl::filterMaskGPU(GrTexture* src,
#endif // SK_SUPPORT_GPU
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkBlurMaskFilterImpl::toString(SkString* str) const {
str->append("SkBlurMaskFilterImpl: (");
@@ -598,7 +1190,7 @@ void SkBlurMaskFilterImpl::toString(SkString* str) const {
str->appendScalar(fSigma);
str->append(" ");
- static const char* gStyleName[SkBlurMaskFilter::kBlurStyleCount] = {
+ static const char* gStyleName[kLastEnum_SkBlurStyle + 1] = {
"normal", "solid", "outer", "inner"
};
diff --git a/chromium/third_party/skia/src/effects/SkColorFilterImageFilter.cpp b/chromium/third_party/skia/src/effects/SkColorFilterImageFilter.cpp
index 8b7b390ea8f..f2490e32735 100755
--- a/chromium/third_party/skia/src/effects/SkColorFilterImageFilter.cpp
+++ b/chromium/third_party/skia/src/effects/SkColorFilterImageFilter.cpp
@@ -11,7 +11,8 @@
#include "SkColorMatrixFilter.h"
#include "SkDevice.h"
#include "SkColorFilter.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
namespace {
@@ -67,8 +68,8 @@ SkColorFilterImageFilter* SkColorFilterImageFilter::Create(SkColorFilter* cf,
SkAutoUnref autoUnref(inputColorFilter);
if (inputColorFilter->asColorMatrix(inputMatrix) && !matrix_needs_clamping(inputMatrix)) {
SkScalar combinedMatrix[20];
- mult_color_matrix(inputMatrix, colorMatrix, combinedMatrix);
- SkAutoTUnref<SkColorFilter> newCF(SkNEW_ARGS(SkColorMatrixFilter, (combinedMatrix)));
+ mult_color_matrix(colorMatrix, inputMatrix, combinedMatrix);
+ SkAutoTUnref<SkColorFilter> newCF(SkColorMatrixFilter::Create(combinedMatrix));
return SkNEW_ARGS(SkColorFilterImageFilter, (newCF, input->getInput(0), cropRect));
}
}
@@ -82,12 +83,12 @@ SkColorFilterImageFilter::SkColorFilterImageFilter(SkColorFilter* cf,
SkSafeRef(cf);
}
-SkColorFilterImageFilter::SkColorFilterImageFilter(SkFlattenableReadBuffer& buffer)
+SkColorFilterImageFilter::SkColorFilterImageFilter(SkReadBuffer& buffer)
: INHERITED(1, buffer) {
fColorFilter = buffer.readColorFilter();
}
-void SkColorFilterImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkColorFilterImageFilter::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeFlattenable(fColorFilter);
@@ -98,17 +99,17 @@ SkColorFilterImageFilter::~SkColorFilterImageFilter() {
}
bool SkColorFilterImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source,
- const SkMatrix& matrix,
+ const Context& ctx,
SkBitmap* result,
- SkIPoint* loc) {
+ SkIPoint* offset) const {
SkBitmap src = source;
- if (getInput(0) && !getInput(0)->filterImage(proxy, source, matrix, &src, loc)) {
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
+ if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctx, &src, &srcOffset)) {
return false;
}
SkIRect bounds;
- src.getBounds(&bounds);
- if (!this->applyCropRect(&bounds, matrix)) {
+ if (!this->applyCropRect(ctx, src, srcOffset, &bounds)) {
return false;
}
@@ -121,11 +122,11 @@ bool SkColorFilterImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& sourc
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
paint.setColorFilter(fColorFilter);
- canvas.drawSprite(src, -bounds.fLeft, -bounds.fTop, &paint);
+ canvas.drawSprite(src, srcOffset.fX - bounds.fLeft, srcOffset.fY - bounds.fTop, &paint);
*result = device.get()->accessBitmap(false);
- loc->fX += bounds.fLeft;
- loc->fY += bounds.fTop;
+ offset->fX = bounds.fLeft;
+ offset->fY = bounds.fTop;
return true;
}
diff --git a/chromium/third_party/skia/src/effects/SkColorFilters.cpp b/chromium/third_party/skia/src/effects/SkColorFilters.cpp
index d482a09d1f8..81d70a7ff9f 100644
--- a/chromium/third_party/skia/src/effects/SkColorFilters.cpp
+++ b/chromium/third_party/skia/src/effects/SkColorFilters.cpp
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -6,14 +5,15 @@
* found in the LICENSE file.
*/
-
#include "SkBlitRow.h"
#include "SkColorFilter.h"
#include "SkColorPriv.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkUtils.h"
#include "SkString.h"
#include "SkValidationUtils.h"
+#include "SkColorMatrixFilter.h"
#define ILLEGAL_XFERMODE_MODE ((SkXfermode::Mode)-1)
@@ -77,7 +77,7 @@ public:
}
}
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
virtual void toString(SkString* str) const SK_OVERRIDE {
str->append("SkModeColorFilter: color: 0x");
str->appendHex(fColor);
@@ -92,13 +92,13 @@ public:
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkModeColorFilter)
protected:
- virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
+ virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE {
this->INHERITED::flatten(buffer);
buffer.writeColor(fColor);
buffer.writeUInt(fMode);
}
- SkModeColorFilter(SkFlattenableReadBuffer& buffer) {
+ SkModeColorFilter(SkReadBuffer& buffer) {
fColor = buffer.readColor();
fMode = (SkXfermode::Mode)buffer.readUInt();
if (buffer.isValid()) {
@@ -145,7 +145,7 @@ static inline ColorExpr blend_term(SkXfermode::Coeff coeff,
const ColorExpr& value) {
switch (coeff) {
default:
- GrCrash("Unexpected xfer coeff.");
+ SkFAIL("Unexpected xfer coeff.");
case SkXfermode::kZero_Coeff: /** 0 */
return ColorExpr(0);
case SkXfermode::kOne_Coeff: /** 1 */
@@ -305,7 +305,7 @@ namespace {
* to which direction the 0.5 goes.
*/
static inline int color_component_to_int(float value) {
- return sk_float_round2int(GrMax(0.f, GrMin(1.f, value)) * 255.f);
+ return sk_float_round2int(SkTMax(0.f, SkTMin(1.f, value)) * 255.f);
}
/** MaskedColorExpr is used to evaluate the color and valid color component flags through the
@@ -446,7 +446,7 @@ public:
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Src_SkModeColorFilter)
protected:
- Src_SkModeColorFilter(SkFlattenableReadBuffer& buffer)
+ Src_SkModeColorFilter(SkReadBuffer& buffer)
: INHERITED(buffer) {}
private:
@@ -482,7 +482,7 @@ public:
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SrcOver_SkModeColorFilter)
protected:
- SrcOver_SkModeColorFilter(SkFlattenableReadBuffer& buffer)
+ SrcOver_SkModeColorFilter(SkReadBuffer& buffer)
: INHERITED(buffer) {
fColor32Proc = SkBlitRow::ColorProcFactory();
}
@@ -538,313 +538,30 @@ SkColorFilter* SkColorFilter::CreateModeFilter(SkColor color,
///////////////////////////////////////////////////////////////////////////////
-static inline unsigned pin(unsigned value, unsigned max) {
- if (value > max) {
- value = max;
+static SkScalar byte_to_scale(U8CPU byte) {
+ if (0xFF == byte) {
+ // want to get this exact
+ return 1;
+ } else {
+ return byte * 0.00392156862745f;
}
- return value;
}
-class SkLightingColorFilter : public SkColorFilter {
-public:
- SkLightingColorFilter(SkColor mul, SkColor add) : fMul(mul), fAdd(add) {}
-
- virtual void filterSpan(const SkPMColor shader[], int count,
- SkPMColor result[]) const SK_OVERRIDE {
- unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul));
- unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul));
- unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul));
-
- unsigned addR = SkColorGetR(fAdd);
- unsigned addG = SkColorGetG(fAdd);
- unsigned addB = SkColorGetB(fAdd);
-
- for (int i = 0; i < count; i++) {
- SkPMColor c = shader[i];
- if (c) {
- unsigned a = SkGetPackedA32(c);
- unsigned scaleA = SkAlpha255To256(a);
- unsigned r = pin(SkAlphaMul(SkGetPackedR32(c), scaleR) + SkAlphaMul(addR, scaleA), a);
- unsigned g = pin(SkAlphaMul(SkGetPackedG32(c), scaleG) + SkAlphaMul(addG, scaleA), a);
- unsigned b = pin(SkAlphaMul(SkGetPackedB32(c), scaleB) + SkAlphaMul(addB, scaleA), a);
- c = SkPackARGB32(a, r, g, b);
- }
- result[i] = c;
- }
- }
-
-#ifdef SK_DEVELOPER
- virtual void toString(SkString* str) const SK_OVERRIDE {
- str->append("SkLightingColorFilter: mul: 0x");
- str->appendHex(fMul);
- str->append(" add: 0x");
- str->appendHex(fAdd);
- }
-#endif
-
- SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingColorFilter)
-
-protected:
- virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
- this->INHERITED::flatten(buffer);
- buffer.writeColor(fMul);
- buffer.writeColor(fAdd);
- }
-
- SkLightingColorFilter(SkFlattenableReadBuffer& buffer) {
- fMul = buffer.readColor();
- fAdd = buffer.readColor();
- }
-
- SkColor fMul, fAdd;
-
-private:
- typedef SkColorFilter INHERITED;
-};
-
-class SkLightingColorFilter_JustAdd : public SkLightingColorFilter {
-public:
- SkLightingColorFilter_JustAdd(SkColor mul, SkColor add)
- : INHERITED(mul, add) {}
-
- virtual void filterSpan(const SkPMColor shader[], int count,
- SkPMColor result[]) const SK_OVERRIDE {
- unsigned addR = SkColorGetR(fAdd);
- unsigned addG = SkColorGetG(fAdd);
- unsigned addB = SkColorGetB(fAdd);
-
- for (int i = 0; i < count; i++) {
- SkPMColor c = shader[i];
- if (c) {
- unsigned a = SkGetPackedA32(c);
- unsigned scaleA = SkAlpha255To256(a);
- unsigned r = pin(SkGetPackedR32(c) + SkAlphaMul(addR, scaleA), a);
- unsigned g = pin(SkGetPackedG32(c) + SkAlphaMul(addG, scaleA), a);
- unsigned b = pin(SkGetPackedB32(c) + SkAlphaMul(addB, scaleA), a);
- c = SkPackARGB32(a, r, g, b);
- }
- result[i] = c;
- }
- }
-
-#ifdef SK_DEVELOPER
- virtual void toString(SkString* str) const SK_OVERRIDE {
- str->append("SkLightingColorFilter_JustAdd: add: 0x");
- str->appendHex(fAdd);
- }
-#endif
-
- SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingColorFilter_JustAdd)
-
-protected:
- SkLightingColorFilter_JustAdd(SkFlattenableReadBuffer& buffer)
- : INHERITED(buffer) {}
-
-private:
- typedef SkLightingColorFilter INHERITED;
-};
-
-class SkLightingColorFilter_JustMul : public SkLightingColorFilter {
-public:
- SkLightingColorFilter_JustMul(SkColor mul, SkColor add)
- : INHERITED(mul, add) {}
-
- virtual void filterSpan(const SkPMColor shader[], int count,
- SkPMColor result[]) const SK_OVERRIDE {
- unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul));
- unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul));
- unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul));
-
- for (int i = 0; i < count; i++) {
- SkPMColor c = shader[i];
- if (c) {
- unsigned a = SkGetPackedA32(c);
- unsigned r = SkAlphaMul(SkGetPackedR32(c), scaleR);
- unsigned g = SkAlphaMul(SkGetPackedG32(c), scaleG);
- unsigned b = SkAlphaMul(SkGetPackedB32(c), scaleB);
- c = SkPackARGB32(a, r, g, b);
- }
- result[i] = c;
- }
- }
-
-#ifdef SK_DEVELOPER
- virtual void toString(SkString* str) const SK_OVERRIDE {
- str->append("SkLightingColorFilter_JustMul: mul: 0x");
- str->appendHex(fMul);
- }
-#endif
-
- SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingColorFilter_JustMul)
-
-protected:
- SkLightingColorFilter_JustMul(SkFlattenableReadBuffer& buffer)
- : INHERITED(buffer) {}
-
-private:
- typedef SkLightingColorFilter INHERITED;
-};
-
-class SkLightingColorFilter_SingleMul : public SkLightingColorFilter {
-public:
- SkLightingColorFilter_SingleMul(SkColor mul, SkColor add)
- : INHERITED(mul, add) {
- SkASSERT(SkColorGetR(add) == 0);
- SkASSERT(SkColorGetG(add) == 0);
- SkASSERT(SkColorGetB(add) == 0);
- SkASSERT(SkColorGetR(mul) == SkColorGetG(mul));
- SkASSERT(SkColorGetR(mul) == SkColorGetB(mul));
- }
-
- virtual uint32_t getFlags() const SK_OVERRIDE {
- return this->INHERITED::getFlags() | (kAlphaUnchanged_Flag | kHasFilter16_Flag);
- }
-
- virtual void filterSpan16(const uint16_t shader[], int count,
- uint16_t result[]) const SK_OVERRIDE {
- // all mul components are the same
- unsigned scale = SkAlpha255To256(SkColorGetR(fMul));
-
- if (count > 0) {
- do {
- *result++ = SkAlphaMulRGB16(*shader++, scale);
- } while (--count > 0);
- }
- }
-
-#ifdef SK_DEVELOPER
- virtual void toString(SkString* str) const SK_OVERRIDE {
- str->append("SkLightingColorFilter_SingleMul: mul: 0x");
- str->appendHex(fMul);
- }
-#endif
-
- SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingColorFilter_SingleMul)
-
-protected:
- SkLightingColorFilter_SingleMul(SkFlattenableReadBuffer& buffer)
- : INHERITED(buffer) {}
-
-private:
- typedef SkLightingColorFilter INHERITED;
-};
-
-class SkLightingColorFilter_NoPin : public SkLightingColorFilter {
-public:
- SkLightingColorFilter_NoPin(SkColor mul, SkColor add)
- : INHERITED(mul, add) {}
-
- virtual void filterSpan(const SkPMColor shader[], int count,
- SkPMColor result[]) const SK_OVERRIDE {
- unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul));
- unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul));
- unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul));
-
- unsigned addR = SkColorGetR(fAdd);
- unsigned addG = SkColorGetG(fAdd);
- unsigned addB = SkColorGetB(fAdd);
-
- for (int i = 0; i < count; i++) {
- SkPMColor c = shader[i];
- if (c) {
- unsigned a = SkGetPackedA32(c);
- unsigned scaleA = SkAlpha255To256(a);
- unsigned r = SkAlphaMul(SkGetPackedR32(c), scaleR) + SkAlphaMul(addR, scaleA);
- unsigned g = SkAlphaMul(SkGetPackedG32(c), scaleG) + SkAlphaMul(addG, scaleA);
- unsigned b = SkAlphaMul(SkGetPackedB32(c), scaleB) + SkAlphaMul(addB, scaleA);
- c = SkPackARGB32(a, r, g, b);
- }
- result[i] = c;
- }
- }
-
-#ifdef SK_DEVELOPER
- virtual void toString(SkString* str) const SK_OVERRIDE {
- str->append("SkLightingColorFilter_NoPin: mul: 0x");
- str->appendHex(fMul);
- str->append(" add: 0x");
- str->appendHex(fAdd);
- }
-#endif
-
- SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingColorFilter_NoPin)
-
-protected:
- SkLightingColorFilter_NoPin(SkFlattenableReadBuffer& buffer)
- : INHERITED(buffer) {}
-
-private:
- typedef SkLightingColorFilter INHERITED;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-class SkSimpleColorFilter : public SkColorFilter {
-public:
- static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
- return SkNEW(SkSimpleColorFilter);
- }
-
-#ifdef SK_DEVELOPER
- virtual void toString(SkString* str) const SK_OVERRIDE {
- str->append("SkSimpleColorFilter");
- }
-#endif
-
-protected:
- void filterSpan(const SkPMColor src[], int count, SkPMColor
- result[]) const SK_OVERRIDE {
- if (result != src) {
- memcpy(result, src, count * sizeof(SkPMColor));
- }
- }
-
- virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {}
-
- virtual Factory getFactory() const {
- return CreateProc;
- }
-
-};
-
SkColorFilter* SkColorFilter::CreateLightingFilter(SkColor mul, SkColor add) {
- mul &= 0x00FFFFFF;
- add &= 0x00FFFFFF;
-
- if (0xFFFFFF == mul) {
- if (0 == add) {
- return SkNEW(SkSimpleColorFilter); // no change to the colors
- } else {
- return SkNEW_ARGS(SkLightingColorFilter_JustAdd, (mul, add));
- }
- }
-
- if (0 == add) {
- if (SkColorGetR(mul) == SkColorGetG(mul) &&
- SkColorGetR(mul) == SkColorGetB(mul)) {
- return SkNEW_ARGS(SkLightingColorFilter_SingleMul, (mul, add));
- } else {
- return SkNEW_ARGS(SkLightingColorFilter_JustMul, (mul, add));
- }
- }
-
- if (SkColorGetR(mul) + SkColorGetR(add) <= 255 &&
- SkColorGetG(mul) + SkColorGetG(add) <= 255 &&
- SkColorGetB(mul) + SkColorGetB(add) <= 255) {
- return SkNEW_ARGS(SkLightingColorFilter_NoPin, (mul, add));
- }
-
- return SkNEW_ARGS(SkLightingColorFilter, (mul, add));
+ SkColorMatrix matrix;
+ matrix.setScale(byte_to_scale(SkColorGetR(mul)),
+ byte_to_scale(SkColorGetG(mul)),
+ byte_to_scale(SkColorGetB(mul)),
+ 1);
+ matrix.postTranslate(SkIntToScalar(SkColorGetR(add)),
+ SkIntToScalar(SkColorGetG(add)),
+ SkIntToScalar(SkColorGetB(add)),
+ 0);
+ return SkColorMatrixFilter::Create(matrix);
}
SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(Src_SkModeColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SrcOver_SkModeColorFilter)
- SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingColorFilter)
- SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingColorFilter_JustAdd)
- SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingColorFilter_JustMul)
- SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingColorFilter_SingleMul)
- SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingColorFilter_NoPin)
- SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSimpleColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
diff --git a/chromium/third_party/skia/src/effects/SkColorMatrix.cpp b/chromium/third_party/skia/src/effects/SkColorMatrix.cpp
index 535d6cc2471..3842285bf40 100644
--- a/chromium/third_party/skia/src/effects/SkColorMatrix.cpp
+++ b/chromium/third_party/skia/src/effects/SkColorMatrix.cpp
@@ -1,4 +1,3 @@
-
/*
* Copyright 2011 Google Inc.
*
@@ -6,25 +5,27 @@
* found in the LICENSE file.
*/
#include "SkColorMatrix.h"
-#include "SkFlattenableBuffers.h"
-
-#define kRScale 0
-#define kGScale 6
-#define kBScale 12
-#define kAScale 18
void SkColorMatrix::setIdentity() {
memset(fMat, 0, sizeof(fMat));
- fMat[kRScale] = fMat[kGScale] = fMat[kBScale] = fMat[kAScale] = SK_Scalar1;
+ fMat[kR_Scale] = fMat[kG_Scale] = fMat[kB_Scale] = fMat[kA_Scale] = 1;
}
void SkColorMatrix::setScale(SkScalar rScale, SkScalar gScale, SkScalar bScale,
SkScalar aScale) {
memset(fMat, 0, sizeof(fMat));
- fMat[kRScale] = rScale;
- fMat[kGScale] = gScale;
- fMat[kBScale] = bScale;
- fMat[kAScale] = aScale;
+ fMat[kR_Scale] = rScale;
+ fMat[kG_Scale] = gScale;
+ fMat[kB_Scale] = bScale;
+ fMat[kA_Scale] = aScale;
+}
+
+void SkColorMatrix::postTranslate(SkScalar dr, SkScalar dg, SkScalar db,
+ SkScalar da) {
+ fMat[kR_Trans] += dr;
+ fMat[kG_Trans] += dg;
+ fMat[kB_Trans] += db;
+ fMat[kA_Trans] += da;
}
///////////////////////////////////////////////////////////////////////////////
@@ -115,14 +116,14 @@ static const SkScalar kHueB = 0.072f;
void SkColorMatrix::setSaturation(SkScalar sat) {
memset(fMat, 0, sizeof(fMat));
- const SkScalar R = SkScalarMul(kHueR, SK_Scalar1 - sat);
- const SkScalar G = SkScalarMul(kHueG, SK_Scalar1 - sat);
- const SkScalar B = SkScalarMul(kHueB, SK_Scalar1 - sat);
+ const SkScalar R = kHueR * (1 - sat);
+ const SkScalar G = kHueG * (1 - sat);
+ const SkScalar B = kHueB * (1 - sat);
setrow(fMat + 0, R + sat, G, B);
setrow(fMat + 5, R, G + sat, B);
setrow(fMat + 10, R, G, B + sat);
- fMat[18] = SK_Scalar1;
+ fMat[kA_Scale] = 1;
}
static const SkScalar kR2Y = 0.299f;
@@ -143,7 +144,7 @@ void SkColorMatrix::setRGB2YUV() {
setrow(fMat + 0, kR2Y, kG2Y, kB2Y);
setrow(fMat + 5, kR2U, kG2U, kB2U);
setrow(fMat + 10, kR2V, kG2V, kB2V);
- fMat[18] = SK_Scalar1;
+ fMat[kA_Scale] = 1;
}
static const SkScalar kV2R = 1.402f;
@@ -154,8 +155,8 @@ static const SkScalar kU2B = 1.772f;
void SkColorMatrix::setYUV2RGB() {
memset(fMat, 0, sizeof(fMat));
- setrow(fMat + 0, SK_Scalar1, 0, kV2R);
- setrow(fMat + 5, SK_Scalar1, kU2G, kV2G);
- setrow(fMat + 10, SK_Scalar1, kU2B, 0);
- fMat[18] = SK_Scalar1;
+ setrow(fMat + 0, 1, 0, kV2R);
+ setrow(fMat + 5, 1, kU2G, kV2G);
+ setrow(fMat + 10, 1, kU2B, 0);
+ fMat[kA_Scale] = 1;
}
diff --git a/chromium/third_party/skia/src/effects/SkColorMatrixFilter.cpp b/chromium/third_party/skia/src/effects/SkColorMatrixFilter.cpp
index fc1b77b7d5e..bd1df79d14f 100644
--- a/chromium/third_party/skia/src/effects/SkColorMatrixFilter.cpp
+++ b/chromium/third_party/skia/src/effects/SkColorMatrixFilter.cpp
@@ -8,7 +8,8 @@
#include "SkColorMatrixFilter.h"
#include "SkColorMatrix.h"
#include "SkColorPriv.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkUnPreMultiply.h"
#include "SkString.h"
@@ -75,9 +76,9 @@ static void ScaleAdd(const SkColorMatrixFilter::State& state,
const int shift = state.fShift;
// cast to (int) to keep the expression signed for the shift
- result[0] = (array[0] * (int)r + array[4]) >> shift;
- result[1] = (array[6] * (int)g + array[9]) >> shift;
- result[2] = (array[12] * (int)b + array[14]) >> shift;
+ result[0] = (array[SkColorMatrix::kR_Scale] * (int)r + array[4]) >> shift;
+ result[1] = (array[SkColorMatrix::kG_Scale] * (int)g + array[9]) >> shift;
+ result[2] = (array[SkColorMatrix::kB_Scale] * (int)b + array[14]) >> shift;
result[3] = a;
}
@@ -87,9 +88,9 @@ static void ScaleAdd16(const SkColorMatrixFilter::State& state,
const int32_t* SK_RESTRICT array = state.fArray;
// cast to (int) to keep the expression signed for the shift
- result[0] = (array[0] * (int)r + array[4]) >> 16;
- result[1] = (array[6] * (int)g + array[9]) >> 16;
- result[2] = (array[12] * (int)b + array[14]) >> 16;
+ result[0] = (array[SkColorMatrix::kR_Scale] * (int)r + array[4]) >> 16;
+ result[1] = (array[SkColorMatrix::kG_Scale] * (int)g + array[9]) >> 16;
+ result[2] = (array[SkColorMatrix::kB_Scale] * (int)b + array[14]) >> 16;
result[3] = a;
}
@@ -99,9 +100,9 @@ static void Add(const SkColorMatrixFilter::State& state,
const int32_t* SK_RESTRICT array = state.fArray;
const int shift = state.fShift;
- result[0] = r + (array[4] >> shift);
- result[1] = g + (array[9] >> shift);
- result[2] = b + (array[14] >> shift);
+ result[0] = r + (array[SkColorMatrix::kR_Trans] >> shift);
+ result[1] = g + (array[SkColorMatrix::kG_Trans] >> shift);
+ result[2] = b + (array[SkColorMatrix::kB_Trans] >> shift);
result[3] = a;
}
@@ -110,9 +111,9 @@ static void Add16(const SkColorMatrixFilter::State& state,
int32_t* SK_RESTRICT result) {
const int32_t* SK_RESTRICT array = state.fArray;
- result[0] = r + (array[4] >> 16);
- result[1] = g + (array[9] >> 16);
- result[2] = b + (array[14] >> 16);
+ result[0] = r + (array[SkColorMatrix::kR_Trans] >> 16);
+ result[1] = g + (array[SkColorMatrix::kG_Trans] >> 16);
+ result[2] = b + (array[SkColorMatrix::kB_Trans] >> 16);
result[3] = a;
}
@@ -160,9 +161,9 @@ void SkColorMatrixFilter::initState(const SkScalar* SK_RESTRICT src) {
} else {
fFlags = kNO_ALPHA_FLAGS;
- int32_t needsScale = (array[0] - one) | // red axis
- (array[6] - one) | // green axis
- (array[12] - one); // blue axis
+ int32_t needsScale = (array[SkColorMatrix::kR_Scale] - one) |
+ (array[SkColorMatrix::kG_Scale] - one) |
+ (array[SkColorMatrix::kB_Scale] - one);
int32_t needs3x3 = array[1] | array[2] | // red off-axis
array[5] | array[7] | // green off-axis
@@ -172,7 +173,9 @@ void SkColorMatrixFilter::initState(const SkScalar* SK_RESTRICT src) {
fProc = shiftIs16 ? AffineAdd16 : AffineAdd;
} else if (needsScale) {
fProc = shiftIs16 ? ScaleAdd16 : ScaleAdd;
- } else if (array[4] | array[9] | array[14]) { // needs add
+ } else if (array[SkColorMatrix::kR_Trans] |
+ array[SkColorMatrix::kG_Trans] |
+ array[SkColorMatrix::kB_Trans]) {
fProc = shiftIs16 ? Add16 : Add;
} else {
fProc = NULL; // identity
@@ -299,13 +302,13 @@ void SkColorMatrixFilter::filterSpan16(const uint16_t src[], int count,
///////////////////////////////////////////////////////////////////////////////
-void SkColorMatrixFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkColorMatrixFilter::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
SkASSERT(sizeof(fMatrix.fMat)/sizeof(SkScalar) == 20);
buffer.writeScalarArray(fMatrix.fMat, 20);
}
-SkColorMatrixFilter::SkColorMatrixFilter(SkFlattenableReadBuffer& buffer)
+SkColorMatrixFilter::SkColorMatrixFilter(SkReadBuffer& buffer)
: INHERITED(buffer) {
SkASSERT(buffer.getArrayCount() == 20);
if (buffer.readScalarArray(fMatrix.fMat, 20)) {
@@ -421,6 +424,7 @@ public:
builder->getUniformCStr(fMatrixHandle),
inputColor,
builder->getUniformCStr(fVectorHandle));
+ builder->fsCodeAppendf("\t%s = clamp(%s, 0.0, 1.0);\n", outputColor, outputColor);
builder->fsCodeAppendf("\t%s.rgb *= %s.a;\n", outputColor, outputColor);
}
@@ -446,6 +450,8 @@ public:
private:
GrGLUniformManager::UniformHandle fMatrixHandle;
GrGLUniformManager::UniformHandle fVectorHandle;
+
+ typedef GrGLEffect INHERITED;
};
private:
@@ -458,7 +464,7 @@ private:
SkColorMatrix fMatrix;
- typedef GrGLEffect INHERITED;
+ typedef GrEffect INHERITED;
};
GR_DEFINE_EFFECT_TEST(ColorMatrixEffect);
@@ -480,7 +486,7 @@ GrEffectRef* SkColorMatrixFilter::asNewEffect(GrContext*) const {
#endif
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkColorMatrixFilter::toString(SkString* str) const {
str->append("SkColorMatrixFilter: ");
diff --git a/chromium/third_party/skia/src/effects/SkComposeImageFilter.cpp b/chromium/third_party/skia/src/effects/SkComposeImageFilter.cpp
index 2412d9fe871..645d63372a0 100644
--- a/chromium/third_party/skia/src/effects/SkComposeImageFilter.cpp
+++ b/chromium/third_party/skia/src/effects/SkComposeImageFilter.cpp
@@ -7,16 +7,17 @@
#include "SkBitmap.h"
#include "SkComposeImageFilter.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
SkComposeImageFilter::~SkComposeImageFilter() {
}
bool SkComposeImageFilter::onFilterImage(Proxy* proxy,
const SkBitmap& src,
- const SkMatrix& ctm,
+ const Context& ctx,
SkBitmap* result,
- SkIPoint* loc) {
+ SkIPoint* offset) const {
SkImageFilter* outer = getInput(0);
SkImageFilter* inner = getInput(1);
@@ -25,17 +26,17 @@ bool SkComposeImageFilter::onFilterImage(Proxy* proxy,
}
if (!outer || !inner) {
- return (outer ? outer : inner)->filterImage(proxy, src, ctm, result, loc);
+ return (outer ? outer : inner)->filterImage(proxy, src, ctx, result, offset);
}
SkBitmap tmp;
- return inner->filterImage(proxy, src, ctm, &tmp, loc) &&
- outer->filterImage(proxy, tmp, ctm, result, loc);
+ return inner->filterImage(proxy, src, ctx, &tmp, offset) &&
+ outer->filterImage(proxy, tmp, ctx, result, offset);
}
bool SkComposeImageFilter::onFilterBounds(const SkIRect& src,
const SkMatrix& ctm,
- SkIRect* dst) {
+ SkIRect* dst) const {
SkImageFilter* outer = getInput(0);
SkImageFilter* inner = getInput(1);
@@ -52,6 +53,6 @@ bool SkComposeImageFilter::onFilterBounds(const SkIRect& src,
outer->filterBounds(tmp, ctm, dst);
}
-SkComposeImageFilter::SkComposeImageFilter(SkFlattenableReadBuffer& buffer)
+SkComposeImageFilter::SkComposeImageFilter(SkReadBuffer& buffer)
: INHERITED(2, buffer) {
}
diff --git a/chromium/third_party/skia/src/effects/SkCornerPathEffect.cpp b/chromium/third_party/skia/src/effects/SkCornerPathEffect.cpp
index f4c31473018..5b61e06df80 100644
--- a/chromium/third_party/skia/src/effects/SkCornerPathEffect.cpp
+++ b/chromium/third_party/skia/src/effects/SkCornerPathEffect.cpp
@@ -10,7 +10,8 @@
#include "SkCornerPathEffect.h"
#include "SkPath.h"
#include "SkPoint.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
SkCornerPathEffect::SkCornerPathEffect(SkScalar radius) : fRadius(radius) {}
SkCornerPathEffect::~SkCornerPathEffect() {}
@@ -127,11 +128,11 @@ DONE:
return true;
}
-void SkCornerPathEffect::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkCornerPathEffect::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeScalar(fRadius);
}
-SkCornerPathEffect::SkCornerPathEffect(SkFlattenableReadBuffer& buffer) {
+SkCornerPathEffect::SkCornerPathEffect(SkReadBuffer& buffer) {
fRadius = buffer.readScalar();
}
diff --git a/chromium/third_party/skia/src/effects/SkDashPathEffect.cpp b/chromium/third_party/skia/src/effects/SkDashPathEffect.cpp
index 40990585024..2838b1ff3e2 100644
--- a/chromium/third_party/skia/src/effects/SkDashPathEffect.cpp
+++ b/chromium/third_party/skia/src/effects/SkDashPathEffect.cpp
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -6,333 +5,37 @@
* found in the LICENSE file.
*/
-
#include "SkDashPathEffect.h"
-#include "SkFlattenableBuffers.h"
-#include "SkPathMeasure.h"
-
-static inline int is_even(int x) {
- return (~x) << 31;
-}
-static SkScalar FindFirstInterval(const SkScalar intervals[], SkScalar phase,
- int32_t* index, int count) {
- for (int i = 0; i < count; ++i) {
- if (phase > intervals[i]) {
- phase -= intervals[i];
- } else {
- *index = i;
- return intervals[i] - phase;
- }
- }
- // If we get here, phase "appears" to be larger than our length. This
- // shouldn't happen with perfect precision, but we can accumulate errors
- // during the initial length computation (rounding can make our sum be too
- // big or too small. In that event, we just have to eat the error here.
- *index = 0;
- return intervals[0];
-}
+#include "SkDashPathPriv.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
SkDashPathEffect::SkDashPathEffect(const SkScalar intervals[], int count,
- SkScalar phase, bool scaleToFit)
- : fScaleToFit(scaleToFit) {
+ SkScalar phase) {
SkASSERT(intervals);
SkASSERT(count > 1 && SkAlign2(count) == count);
fIntervals = (SkScalar*)sk_malloc_throw(sizeof(SkScalar) * count);
fCount = count;
-
- SkScalar len = 0;
for (int i = 0; i < count; i++) {
SkASSERT(intervals[i] >= 0);
fIntervals[i] = intervals[i];
- len += intervals[i];
}
- fIntervalLength = len;
-
- // watch out for values that might make us go out of bounds
- if ((len > 0) && SkScalarIsFinite(phase) && SkScalarIsFinite(len)) {
-
- // Adjust phase to be between 0 and len, "flipping" phase if negative.
- // e.g., if len is 100, then phase of -20 (or -120) is equivalent to 80
- if (phase < 0) {
- phase = -phase;
- if (phase > len) {
- phase = SkScalarMod(phase, len);
- }
- phase = len - phase;
-
- // Due to finite precision, it's possible that phase == len,
- // even after the subtract (if len >>> phase), so fix that here.
- // This fixes http://crbug.com/124652 .
- SkASSERT(phase <= len);
- if (phase == len) {
- phase = 0;
- }
- } else if (phase >= len) {
- phase = SkScalarMod(phase, len);
- }
- SkASSERT(phase >= 0 && phase < len);
-
- fInitialDashLength = FindFirstInterval(intervals, phase,
- &fInitialDashIndex, count);
- SkASSERT(fInitialDashLength >= 0);
- SkASSERT(fInitialDashIndex >= 0 && fInitialDashIndex < fCount);
- } else {
- fInitialDashLength = -1; // signal bad dash intervals
- }
+ // set the internal data members
+ SkDashPath::CalcDashParameters(phase, fIntervals, fCount, &fInitialDashLength,
+ &fInitialDashIndex, &fIntervalLength, &fPhase);
}
SkDashPathEffect::~SkDashPathEffect() {
sk_free(fIntervals);
}
-static void outset_for_stroke(SkRect* rect, const SkStrokeRec& rec) {
- SkScalar radius = SkScalarHalf(rec.getWidth());
- if (0 == radius) {
- radius = SK_Scalar1; // hairlines
- }
- if (SkPaint::kMiter_Join == rec.getJoin()) {
- radius = SkScalarMul(radius, rec.getMiter());
- }
- rect->outset(radius, radius);
-}
-
-// Only handles lines for now. If returns true, dstPath is the new (smaller)
-// path. If returns false, then dstPath parameter is ignored.
-static bool cull_path(const SkPath& srcPath, const SkStrokeRec& rec,
- const SkRect* cullRect, SkScalar intervalLength,
- SkPath* dstPath) {
- if (NULL == cullRect) {
- return false;
- }
-
- SkPoint pts[2];
- if (!srcPath.isLine(pts)) {
- return false;
- }
-
- SkRect bounds = *cullRect;
- outset_for_stroke(&bounds, rec);
-
- SkScalar dx = pts[1].x() - pts[0].x();
- SkScalar dy = pts[1].y() - pts[0].y();
-
- // just do horizontal lines for now (lazy)
- if (dy) {
- return false;
- }
-
- SkScalar minX = pts[0].fX;
- SkScalar maxX = pts[1].fX;
-
- if (maxX < bounds.fLeft || minX > bounds.fRight) {
- return false;
- }
-
- if (dx < 0) {
- SkTSwap(minX, maxX);
- }
-
- // Now we actually perform the chop, removing the excess to the left and
- // right of the bounds (keeping our new line "in phase" with the dash,
- // hence the (mod intervalLength).
-
- if (minX < bounds.fLeft) {
- minX = bounds.fLeft - SkScalarMod(bounds.fLeft - minX,
- intervalLength);
- }
- if (maxX > bounds.fRight) {
- maxX = bounds.fRight + SkScalarMod(maxX - bounds.fRight,
- intervalLength);
- }
-
- SkASSERT(maxX >= minX);
- if (dx < 0) {
- SkTSwap(minX, maxX);
- }
- pts[0].fX = minX;
- pts[1].fX = maxX;
-
- dstPath->moveTo(pts[0]);
- dstPath->lineTo(pts[1]);
- return true;
-}
-
-class SpecialLineRec {
-public:
- bool init(const SkPath& src, SkPath* dst, SkStrokeRec* rec,
- int intervalCount, SkScalar intervalLength) {
- if (rec->isHairlineStyle() || !src.isLine(fPts)) {
- return false;
- }
-
- // can relax this in the future, if we handle square and round caps
- if (SkPaint::kButt_Cap != rec->getCap()) {
- return false;
- }
-
- SkScalar pathLength = SkPoint::Distance(fPts[0], fPts[1]);
-
- fTangent = fPts[1] - fPts[0];
- if (fTangent.isZero()) {
- return false;
- }
-
- fPathLength = pathLength;
- fTangent.scale(SkScalarInvert(pathLength));
- fTangent.rotateCCW(&fNormal);
- fNormal.scale(SkScalarHalf(rec->getWidth()));
-
- // now estimate how many quads will be added to the path
- // resulting segments = pathLen * intervalCount / intervalLen
- // resulting points = 4 * segments
-
- SkScalar ptCount = SkScalarMulDiv(pathLength,
- SkIntToScalar(intervalCount),
- intervalLength);
- int n = SkScalarCeilToInt(ptCount) << 2;
- dst->incReserve(n);
-
- // we will take care of the stroking
- rec->setFillStyle();
- return true;
- }
-
- void addSegment(SkScalar d0, SkScalar d1, SkPath* path) const {
- SkASSERT(d0 < fPathLength);
- // clamp the segment to our length
- if (d1 > fPathLength) {
- d1 = fPathLength;
- }
-
- SkScalar x0 = fPts[0].fX + SkScalarMul(fTangent.fX, d0);
- SkScalar x1 = fPts[0].fX + SkScalarMul(fTangent.fX, d1);
- SkScalar y0 = fPts[0].fY + SkScalarMul(fTangent.fY, d0);
- SkScalar y1 = fPts[0].fY + SkScalarMul(fTangent.fY, d1);
-
- SkPoint pts[4];
- pts[0].set(x0 + fNormal.fX, y0 + fNormal.fY); // moveTo
- pts[1].set(x1 + fNormal.fX, y1 + fNormal.fY); // lineTo
- pts[2].set(x1 - fNormal.fX, y1 - fNormal.fY); // lineTo
- pts[3].set(x0 - fNormal.fX, y0 - fNormal.fY); // lineTo
-
- path->addPoly(pts, SK_ARRAY_COUNT(pts), false);
- }
-
-private:
- SkPoint fPts[2];
- SkVector fTangent;
- SkVector fNormal;
- SkScalar fPathLength;
-};
-
bool SkDashPathEffect::filterPath(SkPath* dst, const SkPath& src,
SkStrokeRec* rec, const SkRect* cullRect) const {
- // we do nothing if the src wants to be filled, or if our dashlength is 0
- if (rec->isFillStyle() || fInitialDashLength < 0) {
- return false;
- }
-
- const SkScalar* intervals = fIntervals;
- SkScalar dashCount = 0;
- int segCount = 0;
-
- SkPath cullPathStorage;
- const SkPath* srcPtr = &src;
- if (cull_path(src, *rec, cullRect, fIntervalLength, &cullPathStorage)) {
- srcPtr = &cullPathStorage;
- }
-
- SpecialLineRec lineRec;
- bool specialLine = lineRec.init(*srcPtr, dst, rec, fCount >> 1, fIntervalLength);
-
- SkPathMeasure meas(*srcPtr, false);
-
- do {
- bool skipFirstSegment = meas.isClosed();
- bool addedSegment = false;
- SkScalar length = meas.getLength();
- int index = fInitialDashIndex;
- SkScalar scale = SK_Scalar1;
-
- // Since the path length / dash length ratio may be arbitrarily large, we can exert
- // significant memory pressure while attempting to build the filtered path. To avoid this,
- // we simply give up dashing beyond a certain threshold.
- //
- // The original bug report (http://crbug.com/165432) is based on a path yielding more than
- // 90 million dash segments and crashing the memory allocator. A limit of 1 million
- // segments seems reasonable: at 2 verbs per segment * 9 bytes per verb, this caps the
- // maximum dash memory overhead at roughly 17MB per path.
- static const SkScalar kMaxDashCount = 1000000;
- dashCount += length * (fCount >> 1) / fIntervalLength;
- if (dashCount > kMaxDashCount) {
- dst->reset();
- return false;
- }
-
- if (fScaleToFit) {
- if (fIntervalLength >= length) {
- scale = SkScalarDiv(length, fIntervalLength);
- } else {
- SkScalar div = SkScalarDiv(length, fIntervalLength);
- int n = SkScalarFloor(div);
- scale = SkScalarDiv(length, n * fIntervalLength);
- }
- }
-
- // Using double precision to avoid looping indefinitely due to single precision rounding
- // (for extreme path_length/dash_length ratios). See test_infinite_dash() unittest.
- double distance = 0;
- double dlen = SkScalarMul(fInitialDashLength, scale);
-
- while (distance < length) {
- SkASSERT(dlen >= 0);
- addedSegment = false;
- if (is_even(index) && dlen > 0 && !skipFirstSegment) {
- addedSegment = true;
- ++segCount;
-
- if (specialLine) {
- lineRec.addSegment(SkDoubleToScalar(distance),
- SkDoubleToScalar(distance + dlen),
- dst);
- } else {
- meas.getSegment(SkDoubleToScalar(distance),
- SkDoubleToScalar(distance + dlen),
- dst, true);
- }
- }
- distance += dlen;
-
- // clear this so we only respect it the first time around
- skipFirstSegment = false;
-
- // wrap around our intervals array if necessary
- index += 1;
- SkASSERT(index <= fCount);
- if (index == fCount) {
- index = 0;
- }
-
- // fetch our next dlen
- dlen = SkScalarMul(intervals[index], scale);
- }
-
- // extend if we ended on a segment and we need to join up with the (skipped) initial segment
- if (meas.isClosed() && is_even(fInitialDashIndex) &&
- fInitialDashLength > 0) {
- meas.getSegment(0, SkScalarMul(fInitialDashLength, scale), dst, !addedSegment);
- ++segCount;
- }
- } while (meas.nextContour());
-
- if (segCount > 1) {
- dst->setConvexity(SkPath::kConcave_Convexity);
- }
-
- return true;
+ return SkDashPath::FilterDashPath(dst, src, rec, cullRect, fIntervals, fCount,
+ fInitialDashLength, fInitialDashIndex, fIntervalLength);
}
// Currently asPoints is more restrictive then it needs to be. In the future
@@ -361,13 +64,6 @@ bool SkDashPathEffect::asPoints(PointData* results,
return false;
}
- // TODO: this next test could be eased up. The rescaling should not impact
- // the equality of the ons & offs. However, we would need to remove the
- // integer intervals restriction first
- if (fScaleToFit) {
- return false;
- }
-
SkPoint pts[2];
if (!src.isLine(pts)) {
@@ -528,32 +224,63 @@ bool SkDashPathEffect::asPoints(PointData* results,
return true;
}
-SkFlattenable::Factory SkDashPathEffect::getFactory() const {
- return fInitialDashLength < 0 ? NULL : CreateProc;
+SkPathEffect::DashType SkDashPathEffect::asADash(DashInfo* info) const {
+ if (info) {
+ if (info->fCount >= fCount && NULL != info->fIntervals) {
+ memcpy(info->fIntervals, fIntervals, fCount * sizeof(SkScalar));
+ }
+ info->fCount = fCount;
+ info->fPhase = fPhase;
+ }
+ return kDash_DashType;
}
-void SkDashPathEffect::flatten(SkFlattenableWriteBuffer& buffer) const {
- SkASSERT(fInitialDashLength >= 0);
+SkFlattenable::Factory SkDashPathEffect::getFactory() const {
+ return CreateProc;
+}
+void SkDashPathEffect::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
- buffer.writeInt(fInitialDashIndex);
- buffer.writeScalar(fInitialDashLength);
- buffer.writeScalar(fIntervalLength);
- buffer.writeBool(fScaleToFit);
+ buffer.writeScalar(fPhase);
buffer.writeScalarArray(fIntervals, fCount);
}
-SkFlattenable* SkDashPathEffect::CreateProc(SkFlattenableReadBuffer& buffer) {
+SkFlattenable* SkDashPathEffect::CreateProc(SkReadBuffer& buffer) {
return SkNEW_ARGS(SkDashPathEffect, (buffer));
}
-SkDashPathEffect::SkDashPathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
- fInitialDashIndex = buffer.readInt();
- fInitialDashLength = buffer.readScalar();
- fIntervalLength = buffer.readScalar();
- fScaleToFit = buffer.readBool();
+SkDashPathEffect::SkDashPathEffect(SkReadBuffer& buffer) : INHERITED(buffer) {
+ bool useOldPic = buffer.isVersionLT(SkReadBuffer::kDashWritesPhaseIntervals_Version);
+ if (useOldPic) {
+ fInitialDashIndex = buffer.readInt();
+ fInitialDashLength = buffer.readScalar();
+ fIntervalLength = buffer.readScalar();
+ buffer.readBool(); // Dummy for old ScalarToFit field
+ } else {
+ fPhase = buffer.readScalar();
+ }
fCount = buffer.getArrayCount();
- fIntervals = (SkScalar*)sk_malloc_throw(sizeof(SkScalar) * fCount);
- buffer.readScalarArray(fIntervals, fCount);
+ size_t allocSize = sizeof(SkScalar) * fCount;
+ if (buffer.validateAvailable(allocSize)) {
+ fIntervals = (SkScalar*)sk_malloc_throw(allocSize);
+ buffer.readScalarArray(fIntervals, fCount);
+ } else {
+ fIntervals = NULL;
+ }
+
+ if (useOldPic) {
+ fPhase = 0;
+ if (fInitialDashLength != -1) { // Signal for bad dash interval
+ for (int i = 0; i < fInitialDashIndex; ++i) {
+ fPhase += fIntervals[i];
+ }
+ fPhase += fIntervals[fInitialDashIndex] - fInitialDashLength;
+ }
+ } else {
+ // set the internal data members, fPhase should have been between 0 and intervalLength
+ // when written to buffer so no need to adjust it
+ SkDashPath::CalcDashParameters(fPhase, fIntervals, fCount, &fInitialDashLength,
+ &fInitialDashIndex, &fIntervalLength);
+ }
}
diff --git a/chromium/third_party/skia/src/effects/SkDiscretePathEffect.cpp b/chromium/third_party/skia/src/effects/SkDiscretePathEffect.cpp
index eece2eff861..f6f91124479 100644
--- a/chromium/third_party/skia/src/effects/SkDiscretePathEffect.cpp
+++ b/chromium/third_party/skia/src/effects/SkDiscretePathEffect.cpp
@@ -8,7 +8,8 @@
#include "SkDiscretePathEffect.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkPathMeasure.h"
#include "SkRandom.h"
@@ -19,9 +20,10 @@ static void Perterb(SkPoint* p, const SkVector& tangent, SkScalar scale) {
*p += normal;
}
-
-SkDiscretePathEffect::SkDiscretePathEffect(SkScalar segLength, SkScalar deviation)
- : fSegLength(segLength), fPerterb(deviation)
+SkDiscretePathEffect::SkDiscretePathEffect(SkScalar segLength,
+ SkScalar deviation,
+ uint32_t seedAssist)
+ : fSegLength(segLength), fPerterb(deviation), fSeedAssist(seedAssist)
{
}
@@ -30,7 +32,10 @@ bool SkDiscretePathEffect::filterPath(SkPath* dst, const SkPath& src,
bool doFill = rec->isFillStyle();
SkPathMeasure meas(src, doFill);
- uint32_t seed = SkScalarRound(meas.getLength());
+
+ /* Caller may supply their own seed assist, which by default is 0 */
+ uint32_t seed = fSeedAssist ^ SkScalarRoundToInt(meas.getLength());
+
SkLCGRandom rand(seed ^ ((seed << 16) | (seed >> 16)));
SkScalar scale = fPerterb;
SkPoint p;
@@ -42,7 +47,7 @@ bool SkDiscretePathEffect::filterPath(SkPath* dst, const SkPath& src,
if (fSegLength * (2 + doFill) > length) {
meas.getSegment(0, length, dst, true); // to short for us to mangle
} else {
- int n = SkScalarRound(SkScalarDiv(length, fSegLength));
+ int n = SkScalarRoundToInt(length / fSegLength);
SkScalar delta = length / n;
SkScalar distance = 0;
@@ -70,13 +75,15 @@ bool SkDiscretePathEffect::filterPath(SkPath* dst, const SkPath& src,
return true;
}
-void SkDiscretePathEffect::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkDiscretePathEffect::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeScalar(fSegLength);
buffer.writeScalar(fPerterb);
+ buffer.writeUInt(fSeedAssist);
}
-SkDiscretePathEffect::SkDiscretePathEffect(SkFlattenableReadBuffer& buffer) {
+SkDiscretePathEffect::SkDiscretePathEffect(SkReadBuffer& buffer) {
fSegLength = buffer.readScalar();
fPerterb = buffer.readScalar();
+ fSeedAssist = buffer.readUInt();
}
diff --git a/chromium/third_party/skia/src/effects/SkDisplacementMapEffect.cpp b/chromium/third_party/skia/src/effects/SkDisplacementMapEffect.cpp
index f43287c4d7f..a5519d1e9aa 100644
--- a/chromium/third_party/skia/src/effects/SkDisplacementMapEffect.cpp
+++ b/chromium/third_party/skia/src/effects/SkDisplacementMapEffect.cpp
@@ -6,7 +6,8 @@
*/
#include "SkDisplacementMapEffect.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkUnPreMultiply.h"
#include "SkColorPriv.h"
#if SK_SUPPORT_GPU
@@ -14,11 +15,12 @@
#include "GrCoordTransform.h"
#include "gl/GrGLEffect.h"
#include "GrTBackendEffectFactory.h"
-#include "SkImageFilterUtils.h"
#endif
namespace {
+#define kChannelSelectorKeyBits 3; // Max value is 4, so 3 bits are required at most
+
template<SkDisplacementMapEffect::ChannelSelectorType type>
uint32_t getValue(SkColor, const SkUnPreMultiply::Scale*) {
SkDEBUGFAIL("Unknown channel selector");
@@ -47,22 +49,28 @@ template<> uint32_t getValue<SkDisplacementMapEffect::kA_ChannelSelectorType>(
template<SkDisplacementMapEffect::ChannelSelectorType typeX,
SkDisplacementMapEffect::ChannelSelectorType typeY>
-void computeDisplacement(SkScalar scale, SkBitmap* dst, SkBitmap* displ, SkBitmap* src, const SkIRect& bounds)
+void computeDisplacement(const SkVector& scale, SkBitmap* dst,
+ SkBitmap* displ, const SkIPoint& offset,
+ SkBitmap* src,
+ const SkIRect& bounds)
{
static const SkScalar Inv8bit = SkScalarDiv(SK_Scalar1, 255.0f);
const int srcW = src->width();
const int srcH = src->height();
- const SkScalar scaleForColor = SkScalarMul(scale, Inv8bit);
- const SkScalar scaleAdj = SK_ScalarHalf - SkScalarMul(scale, SK_ScalarHalf);
+ const SkVector scaleForColor = SkVector::Make(SkScalarMul(scale.fX, Inv8bit),
+ SkScalarMul(scale.fY, Inv8bit));
+ const SkVector scaleAdj = SkVector::Make(SK_ScalarHalf - SkScalarMul(scale.fX, SK_ScalarHalf),
+ SK_ScalarHalf - SkScalarMul(scale.fY, SK_ScalarHalf));
const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable();
SkPMColor* dstPtr = dst->getAddr32(0, 0);
for (int y = bounds.top(); y < bounds.bottom(); ++y) {
- const SkPMColor* displPtr = displ->getAddr32(bounds.left(), y);
+ const SkPMColor* displPtr = displ->getAddr32(bounds.left() + offset.fX,
+ y + offset.fY);
for (int x = bounds.left(); x < bounds.right(); ++x, ++displPtr) {
- const SkScalar displX = SkScalarMul(scaleForColor,
- SkIntToScalar(getValue<typeX>(*displPtr, table))) + scaleAdj;
- const SkScalar displY = SkScalarMul(scaleForColor,
- SkIntToScalar(getValue<typeY>(*displPtr, table))) + scaleAdj;
+ const SkScalar displX = SkScalarMul(scaleForColor.fX,
+ SkIntToScalar(getValue<typeX>(*displPtr, table))) + scaleAdj.fX;
+ const SkScalar displY = SkScalarMul(scaleForColor.fY,
+ SkIntToScalar(getValue<typeY>(*displPtr, table))) + scaleAdj.fY;
// Truncate the displacement values
const int srcX = x + SkScalarTruncToInt(displX);
const int srcY = y + SkScalarTruncToInt(displY);
@@ -74,24 +82,27 @@ void computeDisplacement(SkScalar scale, SkBitmap* dst, SkBitmap* displ, SkBitma
template<SkDisplacementMapEffect::ChannelSelectorType typeX>
void computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
- SkScalar scale, SkBitmap* dst, SkBitmap* displ, SkBitmap* src, const SkIRect& bounds)
+ const SkVector& scale, SkBitmap* dst,
+ SkBitmap* displ, const SkIPoint& offset,
+ SkBitmap* src,
+ const SkIRect& bounds)
{
switch (yChannelSelector) {
case SkDisplacementMapEffect::kR_ChannelSelectorType:
computeDisplacement<typeX, SkDisplacementMapEffect::kR_ChannelSelectorType>(
- scale, dst, displ, src, bounds);
+ scale, dst, displ, offset, src, bounds);
break;
case SkDisplacementMapEffect::kG_ChannelSelectorType:
computeDisplacement<typeX, SkDisplacementMapEffect::kG_ChannelSelectorType>(
- scale, dst, displ, src, bounds);
+ scale, dst, displ, offset, src, bounds);
break;
case SkDisplacementMapEffect::kB_ChannelSelectorType:
computeDisplacement<typeX, SkDisplacementMapEffect::kB_ChannelSelectorType>(
- scale, dst, displ, src, bounds);
+ scale, dst, displ, offset, src, bounds);
break;
case SkDisplacementMapEffect::kA_ChannelSelectorType:
computeDisplacement<typeX, SkDisplacementMapEffect::kA_ChannelSelectorType>(
- scale, dst, displ, src, bounds);
+ scale, dst, displ, offset, src, bounds);
break;
case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
default:
@@ -101,24 +112,27 @@ void computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType yChannelSe
void computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
- SkScalar scale, SkBitmap* dst, SkBitmap* displ, SkBitmap* src, const SkIRect& bounds)
+ const SkVector& scale, SkBitmap* dst,
+ SkBitmap* displ, const SkIPoint& offset,
+ SkBitmap* src,
+ const SkIRect& bounds)
{
switch (xChannelSelector) {
case SkDisplacementMapEffect::kR_ChannelSelectorType:
computeDisplacement<SkDisplacementMapEffect::kR_ChannelSelectorType>(
- yChannelSelector, scale, dst, displ, src, bounds);
+ yChannelSelector, scale, dst, displ, offset, src, bounds);
break;
case SkDisplacementMapEffect::kG_ChannelSelectorType:
computeDisplacement<SkDisplacementMapEffect::kG_ChannelSelectorType>(
- yChannelSelector, scale, dst, displ, src, bounds);
+ yChannelSelector, scale, dst, displ, offset, src, bounds);
break;
case SkDisplacementMapEffect::kB_ChannelSelectorType:
computeDisplacement<SkDisplacementMapEffect::kB_ChannelSelectorType>(
- yChannelSelector, scale, dst, displ, src, bounds);
+ yChannelSelector, scale, dst, displ, offset, src, bounds);
break;
case SkDisplacementMapEffect::kA_ChannelSelectorType:
computeDisplacement<SkDisplacementMapEffect::kA_ChannelSelectorType>(
- yChannelSelector, scale, dst, displ, src, bounds);
+ yChannelSelector, scale, dst, displ, offset, src, bounds);
break;
case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
default:
@@ -160,7 +174,7 @@ SkDisplacementMapEffect::SkDisplacementMapEffect(ChannelSelectorType xChannelSel
SkDisplacementMapEffect::~SkDisplacementMapEffect() {
}
-SkDisplacementMapEffect::SkDisplacementMapEffect(SkFlattenableReadBuffer& buffer)
+SkDisplacementMapEffect::SkDisplacementMapEffect(SkReadBuffer& buffer)
: INHERITED(2, buffer)
{
fXChannelSelector = (SkDisplacementMapEffect::ChannelSelectorType) buffer.readInt();
@@ -171,7 +185,7 @@ SkDisplacementMapEffect::SkDisplacementMapEffect(SkFlattenableReadBuffer& buffer
SkScalarIsFinite(fScale));
}
-void SkDisplacementMapEffect::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkDisplacementMapEffect::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeInt((int) fXChannelSelector);
buffer.writeInt((int) fYChannelSelector);
@@ -180,50 +194,76 @@ void SkDisplacementMapEffect::flatten(SkFlattenableWriteBuffer& buffer) const {
bool SkDisplacementMapEffect::onFilterImage(Proxy* proxy,
const SkBitmap& src,
- const SkMatrix& ctm,
+ const Context& ctx,
SkBitmap* dst,
- SkIPoint* offset) {
- SkBitmap displ, color = src;
- SkImageFilter* colorInput = getColorInput();
- SkImageFilter* displacementInput = getDisplacementInput();
- SkASSERT(NULL != displacementInput);
- if ((colorInput && !colorInput->filterImage(proxy, src, ctm, &color, offset)) ||
- !displacementInput->filterImage(proxy, src, ctm, &displ, offset)) {
- return false;
- }
- if ((displ.config() != SkBitmap::kARGB_8888_Config) ||
- (color.config() != SkBitmap::kARGB_8888_Config)) {
+ SkIPoint* offset) const {
+ SkBitmap displ = src, color = src;
+ const SkImageFilter* colorInput = getColorInput();
+ const SkImageFilter* displInput = getDisplacementInput();
+ SkIPoint colorOffset = SkIPoint::Make(0, 0), displOffset = SkIPoint::Make(0, 0);
+ if ((colorInput && !colorInput->filterImage(proxy, src, ctx, &color, &colorOffset)) ||
+ (displInput && !displInput->filterImage(proxy, src, ctx, &displ, &displOffset))) {
return false;
}
-
- SkAutoLockPixels alp_displacement(displ), alp_color(color);
- if (!displ.getPixels() || !color.getPixels()) {
+ if ((displ.colorType() != kN32_SkColorType) ||
+ (color.colorType() != kN32_SkColorType)) {
return false;
}
SkIRect bounds;
- color.getBounds(&bounds);
- if (!this->applyCropRect(&bounds, ctm)) {
+ // Since computeDisplacement does bounds checking on color pixel access, we don't need to pad
+ // the color bitmap to bounds here.
+ if (!this->applyCropRect(ctx, color, colorOffset, &bounds)) {
return false;
}
SkIRect displBounds;
- displ.getBounds(&displBounds);
- if (!this->applyCropRect(&displBounds, ctm)) {
+ if (!this->applyCropRect(ctx, proxy, displ, &displOffset, &displBounds, &displ)) {
return false;
}
if (!bounds.intersect(displBounds)) {
return false;
}
+ SkAutoLockPixels alp_displacement(displ), alp_color(color);
+ if (!displ.getPixels() || !color.getPixels()) {
+ return false;
+ }
- dst->setConfig(color.config(), bounds.width(), bounds.height());
- dst->allocPixels();
- if (!dst->getPixels()) {
+ if (!dst->allocPixels(color.info().makeWH(bounds.width(), bounds.height()))) {
return false;
}
- computeDisplacement(fXChannelSelector, fYChannelSelector, fScale, dst, &displ, &color, bounds);
+ SkVector scale = SkVector::Make(fScale, fScale);
+ ctx.ctm().mapVectors(&scale, 1);
+ SkIRect colorBounds = bounds;
+ colorBounds.offset(-colorOffset);
+
+ computeDisplacement(fXChannelSelector, fYChannelSelector, scale, dst,
+ &displ, colorOffset - displOffset, &color, colorBounds);
- offset->fX += bounds.left();
- offset->fY += bounds.top();
+ offset->fX = bounds.left();
+ offset->fY = bounds.top();
+ return true;
+}
+
+void SkDisplacementMapEffect::computeFastBounds(const SkRect& src, SkRect* dst) const {
+ if (getColorInput()) {
+ getColorInput()->computeFastBounds(src, dst);
+ } else {
+ *dst = src;
+ }
+ dst->outset(fScale * SK_ScalarHalf, fScale * SK_ScalarHalf);
+}
+
+bool SkDisplacementMapEffect::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
+ SkIRect* dst) const {
+ SkIRect bounds = src;
+ SkVector scale = SkVector::Make(fScale, fScale);
+ ctm.mapVectors(&scale, 1);
+ bounds.outset(SkScalarCeilToInt(scale.fX * SK_ScalarHalf),
+ SkScalarCeilToInt(scale.fY * SK_ScalarHalf));
+ if (getColorInput()) {
+ return getColorInput()->filterBounds(bounds, ctm, dst);
+ }
+ *dst = bounds;
return true;
}
@@ -262,11 +302,14 @@ class GrDisplacementMapEffect : public GrEffect {
public:
static GrEffectRef* Create(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
- SkScalar scale, GrTexture* displacement, GrTexture* color) {
+ SkVector scale,
+ GrTexture* displacement, const SkMatrix& offsetMatrix,
+ GrTexture* color) {
AutoEffectUnref effect(SkNEW_ARGS(GrDisplacementMapEffect, (xChannelSelector,
yChannelSelector,
scale,
displacement,
+ offsetMatrix,
color)));
return CreateEffectRef(effect);
}
@@ -278,7 +321,7 @@ public:
{ return fXChannelSelector; }
SkDisplacementMapEffect::ChannelSelectorType yChannelSelector() const
{ return fYChannelSelector; }
- SkScalar scale() const { return fScale; }
+ const SkVector& scale() const { return fScale; }
typedef GrGLDisplacementMapEffect GLEffect;
static const char* Name() { return "DisplacementMap"; }
@@ -290,7 +333,9 @@ private:
GrDisplacementMapEffect(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
- SkScalar scale, GrTexture* displacement, GrTexture* color);
+ const SkVector& scale,
+ GrTexture* displacement, const SkMatrix& offsetMatrix,
+ GrTexture* color);
GR_DECLARE_EFFECT_TEST;
@@ -300,33 +345,48 @@ private:
GrTextureAccess fColorAccess;
SkDisplacementMapEffect::ChannelSelectorType fXChannelSelector;
SkDisplacementMapEffect::ChannelSelectorType fYChannelSelector;
- SkScalar fScale;
+ SkVector fScale;
typedef GrEffect INHERITED;
};
-bool SkDisplacementMapEffect::filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
- SkBitmap* result, SkIPoint* offset) {
- SkBitmap colorBM;
+bool SkDisplacementMapEffect::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx,
+ SkBitmap* result, SkIPoint* offset) const {
+ SkBitmap colorBM = src;
SkIPoint colorOffset = SkIPoint::Make(0, 0);
- if (!SkImageFilterUtils::GetInputResultGPU(getColorInput(), proxy, src, ctm, &colorBM,
- &colorOffset)) {
+ if (getColorInput() && !getColorInput()->getInputResultGPU(proxy, src, ctx, &colorBM,
+ &colorOffset)) {
return false;
}
- GrTexture* color = colorBM.getTexture();
- SkBitmap displacementBM;
+ SkBitmap displacementBM = src;
SkIPoint displacementOffset = SkIPoint::Make(0, 0);
- if (!SkImageFilterUtils::GetInputResultGPU(getDisplacementInput(), proxy, src, ctm,
- &displacementBM, &displacementOffset)) {
+ if (getDisplacementInput() &&
+ !getDisplacementInput()->getInputResultGPU(proxy, src, ctx, &displacementBM,
+ &displacementOffset)) {
return false;
}
+ SkIRect bounds;
+ // Since GrDisplacementMapEffect does bounds checking on color pixel access, we don't need to
+ // pad the color bitmap to bounds here.
+ if (!this->applyCropRect(ctx, colorBM, colorOffset, &bounds)) {
+ return false;
+ }
+ SkIRect displBounds;
+ if (!this->applyCropRect(ctx, proxy, displacementBM,
+ &displacementOffset, &displBounds, &displacementBM)) {
+ return false;
+ }
+ if (!bounds.intersect(displBounds)) {
+ return false;
+ }
+ GrTexture* color = colorBM.getTexture();
GrTexture* displacement = displacementBM.getTexture();
GrContext* context = color->getContext();
GrTextureDesc desc;
desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
- desc.fWidth = src.width();
- desc.fHeight = src.height();
+ desc.fWidth = bounds.width();
+ desc.fHeight = bounds.height();
desc.fConfig = kSkia8888_GrPixelConfig;
GrAutoScratchTexture ast(context, desc);
@@ -334,32 +394,34 @@ bool SkDisplacementMapEffect::filterImageGPU(Proxy* proxy, const SkBitmap& src,
GrContext::AutoRenderTarget art(context, dst->asRenderTarget());
+ SkVector scale = SkVector::Make(fScale, fScale);
+ ctx.ctm().mapVectors(&scale, 1);
+
GrPaint paint;
+ SkMatrix offsetMatrix = GrEffect::MakeDivByTextureWHMatrix(displacement);
+ offsetMatrix.preTranslate(SkIntToScalar(colorOffset.fX - displacementOffset.fX),
+ SkIntToScalar(colorOffset.fY - displacementOffset.fY));
+
paint.addColorEffect(
GrDisplacementMapEffect::Create(fXChannelSelector,
fYChannelSelector,
- fScale,
+ scale,
displacement,
+ offsetMatrix,
color))->unref();
- SkIRect bounds;
- src.getBounds(&bounds);
- if (!this->applyCropRect(&bounds, ctm)) {
- return false;
- }
- SkIRect displBounds;
- displacementBM.getBounds(&displBounds);
- if (!this->applyCropRect(&displBounds, ctm)) {
- return false;
- }
- if (!bounds.intersect(displBounds)) {
- return false;
- }
- SkRect srcRect = SkRect::Make(bounds);
- SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
- context->drawRectToRect(paint, dstRect, srcRect);
- offset->fX += bounds.left();
- offset->fY += bounds.top();
- return SkImageFilterUtils::WrapTexture(dst, bounds.width(), bounds.height(), result);
+ SkIRect colorBounds = bounds;
+ colorBounds.offset(-colorOffset);
+ GrContext::AutoMatrix am;
+ am.setIdentity(context);
+ SkMatrix matrix;
+ matrix.setTranslate(-SkIntToScalar(colorBounds.x()),
+ -SkIntToScalar(colorBounds.y()));
+ context->concatMatrix(matrix);
+ context->drawRect(paint, SkRect::Make(colorBounds));
+ offset->fX = bounds.left();
+ offset->fY = bounds.top();
+ WrapTexture(dst, bounds.width(), bounds.height(), result);
+ return true;
}
///////////////////////////////////////////////////////////////////////////////
@@ -367,10 +429,11 @@ bool SkDisplacementMapEffect::filterImageGPU(Proxy* proxy, const SkBitmap& src,
GrDisplacementMapEffect::GrDisplacementMapEffect(
SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
- SkScalar scale,
+ const SkVector& scale,
GrTexture* displacement,
+ const SkMatrix& offsetMatrix,
GrTexture* color)
- : fDisplacementTransform(kLocal_GrCoordSet, displacement)
+ : fDisplacementTransform(kLocal_GrCoordSet, offsetMatrix, displacement)
, fDisplacementAccess(displacement)
, fColorTransform(kLocal_GrCoordSet, color)
, fColorAccess(color)
@@ -429,10 +492,12 @@ GrEffectRef* GrDisplacementMapEffect::TestCreate(SkRandom* random,
SkDisplacementMapEffect::ChannelSelectorType yChannelSelector =
static_cast<SkDisplacementMapEffect::ChannelSelectorType>(
random->nextRangeU(1, kMaxComponent));
- SkScalar scale = random->nextRangeScalar(0, 100.0f);
+ SkVector scale = SkVector::Make(random->nextRangeScalar(0, 100.0f),
+ random->nextRangeScalar(0, 100.0f));
return GrDisplacementMapEffect::Create(xChannelSelector, yChannelSelector, scale,
- textures[texIdxDispl], textures[texIdxColor]);
+ textures[texIdxDispl], SkMatrix::I(),
+ textures[texIdxColor]);
}
///////////////////////////////////////////////////////////////////////////////
@@ -529,8 +594,8 @@ void GrGLDisplacementMapEffect::setData(const GrGLUniformManager& uman,
const GrDisplacementMapEffect& displacementMap =
drawEffect.castEffect<GrDisplacementMapEffect>();
GrTexture* colorTex = displacementMap.texture(1);
- SkScalar scaleX = SkScalarDiv(displacementMap.scale(), SkIntToScalar(colorTex->width()));
- SkScalar scaleY = SkScalarDiv(displacementMap.scale(), SkIntToScalar(colorTex->height()));
+ SkScalar scaleX = SkScalarDiv(displacementMap.scale().fX, SkIntToScalar(colorTex->width()));
+ SkScalar scaleY = SkScalarDiv(displacementMap.scale().fY, SkIntToScalar(colorTex->height()));
uman.set2f(fScaleUni, SkScalarToFloat(scaleX),
colorTex->origin() == kTopLeft_GrSurfaceOrigin ?
SkScalarToFloat(scaleY) : SkScalarToFloat(-scaleY));
@@ -542,7 +607,7 @@ GrGLEffect::EffectKey GrGLDisplacementMapEffect::GenKey(const GrDrawEffect& draw
drawEffect.castEffect<GrDisplacementMapEffect>();
EffectKey xKey = displacementMap.xChannelSelector();
- EffectKey yKey = displacementMap.yChannelSelector() << SkDisplacementMapEffect::kKeyBits;
+ EffectKey yKey = displacementMap.yChannelSelector() << kChannelSelectorKeyBits;
return xKey | yKey;
}
diff --git a/chromium/third_party/skia/src/effects/SkDropShadowImageFilter.cpp b/chromium/third_party/skia/src/effects/SkDropShadowImageFilter.cpp
index 24a910d0b67..032acec8c6c 100644
--- a/chromium/third_party/skia/src/effects/SkDropShadowImageFilter.cpp
+++ b/chromium/third_party/skia/src/effects/SkDropShadowImageFilter.cpp
@@ -12,9 +12,11 @@
#include "SkCanvas.h"
#include "SkColorMatrixFilter.h"
#include "SkDevice.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
-SkDropShadowImageFilter::SkDropShadowImageFilter(SkScalar dx, SkScalar dy, SkScalar sigma, SkColor color, SkImageFilter* input)
+SkDropShadowImageFilter::SkDropShadowImageFilter(SkScalar dx, SkScalar dy, SkScalar sigma,
+ SkColor color, SkImageFilter* input)
: INHERITED(input)
, fDx(dx)
, fDy(dy)
@@ -24,7 +26,9 @@ SkDropShadowImageFilter::SkDropShadowImageFilter(SkScalar dx, SkScalar dy, SkSca
{
}
-SkDropShadowImageFilter::SkDropShadowImageFilter(SkScalar dx, SkScalar dy, SkScalar sigmaX, SkScalar sigmaY, SkColor color, SkImageFilter* input, const CropRect* cropRect)
+SkDropShadowImageFilter::SkDropShadowImageFilter(SkScalar dx, SkScalar dy,
+ SkScalar sigmaX, SkScalar sigmaY, SkColor color,
+ SkImageFilter* input, const CropRect* cropRect)
: INHERITED(input, cropRect)
, fDx(dx)
, fDy(dy)
@@ -34,7 +38,7 @@ SkDropShadowImageFilter::SkDropShadowImageFilter(SkScalar dx, SkScalar dy, SkSca
{
}
-SkDropShadowImageFilter::SkDropShadowImageFilter(SkFlattenableReadBuffer& buffer)
+SkDropShadowImageFilter::SkDropShadowImageFilter(SkReadBuffer& buffer)
: INHERITED(1, buffer) {
fDx = buffer.readScalar();
fDy = buffer.readScalar();
@@ -47,7 +51,7 @@ SkDropShadowImageFilter::SkDropShadowImageFilter(SkFlattenableReadBuffer& buffer
SkScalarIsFinite(fSigmaY));
}
-void SkDropShadowImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const
+void SkDropShadowImageFilter::flatten(SkWriteBuffer& buffer) const
{
this->INHERITED::flatten(buffer);
buffer.writeScalar(fDx);
@@ -57,15 +61,17 @@ void SkDropShadowImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const
buffer.writeColor(fColor);
}
-bool SkDropShadowImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source, const SkMatrix& matrix, SkBitmap* result, SkIPoint* loc)
+bool SkDropShadowImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source,
+ const Context& ctx,
+ SkBitmap* result, SkIPoint* offset) const
{
SkBitmap src = source;
- if (getInput(0) && !getInput(0)->filterImage(proxy, source, matrix, &src, loc))
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
+ if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctx, &src, &srcOffset))
return false;
SkIRect bounds;
- src.getBounds(&bounds);
- if (!this->applyCropRect(&bounds, matrix)) {
+ if (!this->applyCropRect(ctx, src, srcOffset, &bounds)) {
return false;
}
@@ -75,17 +81,58 @@ bool SkDropShadowImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source
}
SkCanvas canvas(device.get());
- SkAutoTUnref<SkImageFilter> blurFilter(new SkBlurImageFilter(fSigmaX, fSigmaY));
- SkAutoTUnref<SkColorFilter> colorFilter(SkColorFilter::CreateModeFilter(fColor, SkXfermode::kSrcIn_Mode));
+ SkVector sigma = SkVector::Make(fSigmaX, fSigmaY);
+ ctx.ctm().mapVectors(&sigma, 1);
+ sigma.fX = SkMaxScalar(0, sigma.fX);
+ sigma.fY = SkMaxScalar(0, sigma.fY);
+ SkAutoTUnref<SkImageFilter> blurFilter(SkBlurImageFilter::Create(sigma.fX, sigma.fY));
+ SkAutoTUnref<SkColorFilter> colorFilter(
+ SkColorFilter::CreateModeFilter(fColor, SkXfermode::kSrcIn_Mode));
SkPaint paint;
paint.setImageFilter(blurFilter.get());
paint.setColorFilter(colorFilter.get());
paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
- canvas.translate(-SkIntToScalar(bounds.fLeft), -SkIntToScalar(bounds.fTop));
- canvas.drawBitmap(src, fDx, fDy, &paint);
+ SkVector offsetVec = SkVector::Make(fDx, fDy);
+ ctx.ctm().mapVectors(&offsetVec, 1);
+ canvas.translate(SkIntToScalar(srcOffset.fX - bounds.fLeft),
+ SkIntToScalar(srcOffset.fY - bounds.fTop));
+ canvas.drawBitmap(src, offsetVec.fX, offsetVec.fY, &paint);
canvas.drawBitmap(src, 0, 0);
*result = device->accessBitmap(false);
- loc->fX += bounds.fLeft;
- loc->fY += bounds.fTop;
+ offset->fX = bounds.fLeft;
+ offset->fY = bounds.fTop;
+ return true;
+}
+
+void SkDropShadowImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
+ if (getInput(0)) {
+ getInput(0)->computeFastBounds(src, dst);
+ } else {
+ *dst = src;
+ }
+
+ SkRect shadowBounds = *dst;
+ shadowBounds.offset(fDx, fDy);
+ shadowBounds.outset(SkScalarMul(fSigmaX, SkIntToScalar(3)),
+ SkScalarMul(fSigmaY, SkIntToScalar(3)));
+ dst->join(shadowBounds);
+}
+
+bool SkDropShadowImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
+ SkIRect* dst) const {
+ SkIRect bounds = src;
+ if (getInput(0) && !getInput(0)->filterBounds(src, ctm, &bounds)) {
+ return false;
+ }
+ SkVector offsetVec = SkVector::Make(fDx, fDy);
+ ctm.mapVectors(&offsetVec, 1);
+ bounds.offset(-SkScalarCeilToInt(offsetVec.x()),
+ -SkScalarCeilToInt(offsetVec.y()));
+ SkVector sigma = SkVector::Make(fSigmaX, fSigmaY);
+ ctm.mapVectors(&sigma, 1);
+ bounds.outset(SkScalarCeilToInt(SkScalarMul(sigma.x(), SkIntToScalar(3))),
+ SkScalarCeilToInt(SkScalarMul(sigma.y(), SkIntToScalar(3))));
+ bounds.join(src);
+ *dst = bounds;
return true;
}
diff --git a/chromium/third_party/skia/src/effects/SkEmbossMaskFilter.cpp b/chromium/third_party/skia/src/effects/SkEmbossMaskFilter.cpp
index 905cfab941b..cdd55fcc5b8 100644
--- a/chromium/third_party/skia/src/effects/SkEmbossMaskFilter.cpp
+++ b/chromium/third_party/skia/src/effects/SkEmbossMaskFilter.cpp
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -6,14 +5,18 @@
* found in the LICENSE file.
*/
-
#include "SkEmbossMaskFilter.h"
#include "SkBlurMaskFilter.h"
#include "SkBlurMask.h"
#include "SkEmbossMask.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkString.h"
+SkEmbossMaskFilter* SkEmbossMaskFilter::Create(SkScalar blurSigma, const Light& light) {
+ return SkNEW_ARGS(SkEmbossMaskFilter, (blurSigma, light));
+}
+
static inline int pin2byte(int n) {
if (n < 0) {
n = 0;
@@ -48,7 +51,7 @@ SkMaskFilter* SkBlurMaskFilter::CreateEmboss(SkScalar blurSigma, const SkScalar
light.fAmbient = SkToU8(am);
light.fSpecular = SkToU8(sp);
- return SkNEW_ARGS(SkEmbossMaskFilter, (blurSigma, light));
+ return SkEmbossMaskFilter::Create(blurSigma, light);
}
///////////////////////////////////////////////////////////////////////////////
@@ -67,13 +70,6 @@ SkEmbossMaskFilter::SkEmbossMaskFilter(SkScalar blurSigma, const Light& light)
normalize(fLight.fDirection);
}
-SkEmbossMaskFilter::SkEmbossMaskFilter(const Light& light, SkScalar blurRadius)
- : fLight(light) {
- normalize(fLight.fDirection);
-
- fBlurSigma = SkBlurMask::ConvertRadiusToSigma(blurRadius);
-}
-
SkMask::Format SkEmbossMaskFilter::getFormat() const {
return SkMask::k3D_Format;
}
@@ -82,14 +78,13 @@ bool SkEmbossMaskFilter::filterMask(SkMask* dst, const SkMask& src,
const SkMatrix& matrix, SkIPoint* margin) const {
SkScalar sigma = matrix.mapRadius(fBlurSigma);
- if (!SkBlurMask::BoxBlur(dst, src, sigma, SkBlurMask::kInner_Style,
- SkBlurMask::kLow_Quality)) {
+ if (!SkBlurMask::BoxBlur(dst, src, sigma, kInner_SkBlurStyle, kLow_SkBlurQuality)) {
return false;
}
dst->fFormat = SkMask::k3D_Format;
if (margin) {
- margin->set(SkScalarCeil(3*sigma), SkScalarCeil(3*sigma));
+ margin->set(SkScalarCeilToInt(3*sigma), SkScalarCeilToInt(3*sigma));
}
if (src.fImage == NULL) {
@@ -129,18 +124,15 @@ bool SkEmbossMaskFilter::filterMask(SkMask* dst, const SkMask& src,
return true;
}
-SkEmbossMaskFilter::SkEmbossMaskFilter(SkFlattenableReadBuffer& buffer)
+SkEmbossMaskFilter::SkEmbossMaskFilter(SkReadBuffer& buffer)
: SkMaskFilter(buffer) {
SkASSERT(buffer.getArrayCount() == sizeof(Light));
buffer.readByteArray(&fLight, sizeof(Light));
SkASSERT(fLight.fPad == 0); // for the font-cache lookup to be clean
-#ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TOO
- // TODO: Once skps are recaptured in > v15 this SkScalarAbs can be removed
-#endif
- fBlurSigma = SkScalarAbs(buffer.readScalar());
+ fBlurSigma = buffer.readScalar();
}
-void SkEmbossMaskFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkEmbossMaskFilter::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
Light tmpLight = fLight;
@@ -149,7 +141,7 @@ void SkEmbossMaskFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
buffer.writeScalar(fBlurSigma);
}
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkEmbossMaskFilter::toString(SkString* str) const {
str->append("SkEmbossMaskFilter: (");
diff --git a/chromium/third_party/skia/src/effects/SkGpuBlurUtils.cpp b/chromium/third_party/skia/src/effects/SkGpuBlurUtils.cpp
index 6133db11d20..9da08e6f71f 100644
--- a/chromium/third_party/skia/src/effects/SkGpuBlurUtils.cpp
+++ b/chromium/third_party/skia/src/effects/SkGpuBlurUtils.cpp
@@ -28,11 +28,15 @@ static void scale_rect(SkRect* rect, float xScale, float yScale) {
rect->fBottom = SkScalarMul(rect->fBottom, yScale);
}
-static float adjust_sigma(float sigma, int *scaleFactor, int *radius) {
+static float adjust_sigma(float sigma, int maxTextureSize, int *scaleFactor, int *radius) {
*scaleFactor = 1;
while (sigma > MAX_BLUR_SIGMA) {
*scaleFactor *= 2;
sigma *= 0.5f;
+ if (*scaleFactor > maxTextureSize) {
+ *scaleFactor = maxTextureSize;
+ sigma = MAX_BLUR_SIGMA;
+ }
}
*radius = static_cast<int>(ceilf(sigma * 3.0f));
SkASSERT(*radius <= GrConvolutionEffect::kMaxKernelRadius);
@@ -129,8 +133,9 @@ GrTexture* GaussianBlur(GrContext* context,
SkIRect clearRect;
int scaleFactorX, radiusX;
int scaleFactorY, radiusY;
- sigmaX = adjust_sigma(sigmaX, &scaleFactorX, &radiusX);
- sigmaY = adjust_sigma(sigmaY, &scaleFactorY, &radiusY);
+ int maxTextureSize = context->getMaxTextureSize();
+ sigmaX = adjust_sigma(sigmaX, maxTextureSize, &scaleFactorX, &radiusX);
+ sigmaY = adjust_sigma(sigmaY, maxTextureSize, &scaleFactorY, &radiusY);
SkRect srcRect(rect);
scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
diff --git a/chromium/third_party/skia/src/effects/SkKernel33MaskFilter.cpp b/chromium/third_party/skia/src/effects/SkKernel33MaskFilter.cpp
deleted file mode 100644
index 821eebd7853..00000000000
--- a/chromium/third_party/skia/src/effects/SkKernel33MaskFilter.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "SkKernel33MaskFilter.h"
-#include "SkColorPriv.h"
-#include "SkFlattenableBuffers.h"
-#include "SkString.h"
-
-SkMask::Format SkKernel33ProcMaskFilter::getFormat() const {
- return SkMask::kA8_Format;
-}
-
-bool SkKernel33ProcMaskFilter::filterMask(SkMask* dst, const SkMask& src,
- const SkMatrix&, SkIPoint* margin) const {
- // margin???
- dst->fImage = NULL;
- dst->fBounds = src.fBounds;
- dst->fBounds.inset(-1, -1);
- dst->fFormat = SkMask::kA8_Format;
-
- if (NULL == src.fImage) {
- return true;
- }
-
- dst->fRowBytes = dst->fBounds.width();
- size_t size = dst->computeImageSize();
- if (0 == size) {
- return false; // too big to allocate, abort
- }
- dst->fImage = SkMask::AllocImage(size);
-
- const int h = src.fBounds.height();
- const int w = src.fBounds.width();
- const int srcRB = src.fRowBytes;
- const uint8_t* srcImage = src.fImage;
- uint8_t* dstImage = dst->fImage;
-
- uint8_t* srcRows[3];
- uint8_t storage[3][3];
-
- srcRows[0] = storage[0];
- srcRows[1] = storage[1];
- srcRows[2] = storage[2];
-
- unsigned scale = fPercent256;
-
- for (int y = -1; y <= h; y++) {
- uint8_t* dstRow = dstImage;
- for (int x = -1; x <= w; x++) {
- memset(storage, 0, sizeof(storage));
- uint8_t* storagePtr = &storage[0][0];
-
- for (int ky = y - 1; ky <= y + 1; ky++) {
- const uint8_t* srcRow = srcImage + ky * srcRB; // may be out-of-range
- for (int kx = x - 1; kx <= x + 1; kx++) {
- if ((unsigned)ky < (unsigned)h && (unsigned)kx < (unsigned)w) {
- *storagePtr = srcRow[kx];
- }
- storagePtr++;
- }
- }
- int value = this->computeValue(srcRows);
-
- if (scale < 256) {
- value = SkAlphaBlend(value, srcRows[1][1], scale);
- }
- *dstRow++ = SkToU8(value);
- }
- dstImage += dst->fRowBytes;
- }
- return true;
-}
-
-void SkKernel33ProcMaskFilter::flatten(SkFlattenableWriteBuffer& wb) const {
- this->INHERITED::flatten(wb);
- wb.writeInt(fPercent256);
-}
-
-SkKernel33ProcMaskFilter::SkKernel33ProcMaskFilter(SkFlattenableReadBuffer& rb)
- : SkMaskFilter(rb) {
- fPercent256 = rb.readInt();
-}
-
-#ifdef SK_DEVELOPER
-void SkKernel33ProcMaskFilter::toString(SkString* str) const {
- str->appendf("percent256: %d, ", fPercent256);
-}
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-
-uint8_t SkKernel33MaskFilter::computeValue(uint8_t* const* srcRows) const {
- int value = 0;
-
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++) {
- value += fKernel[i][j] * srcRows[i][j];
- }
- }
-
- value >>= fShift;
-
- if (value < 0) {
- value = 0;
- } else if (value > 255) {
- value = 255;
- }
- return (uint8_t)value;
-}
-
-void SkKernel33MaskFilter::flatten(SkFlattenableWriteBuffer& wb) const {
- this->INHERITED::flatten(wb);
- wb.writeIntArray(&fKernel[0][0], 9);
- wb.writeInt(fShift);
-}
-
-SkKernel33MaskFilter::SkKernel33MaskFilter(SkFlattenableReadBuffer& rb)
- : SkKernel33ProcMaskFilter(rb) {
- SkDEBUGCODE(bool success = )rb.readIntArray(&fKernel[0][0], 9);
- SkASSERT(success);
- fShift = rb.readInt();
-}
-
-#ifdef SK_DEVELOPER
-void SkKernel33MaskFilter::toString(SkString* str) const {
- str->append("SkKernel33MaskFilter: (");
-
- str->appendf("kernel: (%d, %d, %d, %d, %d, %d, %d, %d, %d), ",
- fKernel[0][0], fKernel[0][1], fKernel[0][2],
- fKernel[1][0], fKernel[1][1], fKernel[1][2],
- fKernel[2][0], fKernel[2][1], fKernel[2][2]);
- str->appendf("shift: %d, ", fShift);
-
- this->INHERITED::toString(str);
-
- str->append(")");
-}
-#endif
diff --git a/chromium/third_party/skia/src/effects/SkLayerDrawLooper.cpp b/chromium/third_party/skia/src/effects/SkLayerDrawLooper.cpp
index 65f058b9d44..aed2c9bbd4e 100644
--- a/chromium/third_party/skia/src/effects/SkLayerDrawLooper.cpp
+++ b/chromium/third_party/skia/src/effects/SkLayerDrawLooper.cpp
@@ -7,14 +7,14 @@
*/
#include "SkCanvas.h"
#include "SkColor.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkLayerDrawLooper.h"
#include "SkString.h"
#include "SkStringUtils.h"
#include "SkUnPreMultiply.h"
SkLayerDrawLooper::LayerInfo::LayerInfo() {
- fFlagsMask = 0; // ignore our paint flags
fPaintBits = 0; // ignore our paint fields
fColorMode = SkXfermode::kDst_Mode; // ignore our color
fOffset.set(0, 0);
@@ -24,8 +24,7 @@ SkLayerDrawLooper::LayerInfo::LayerInfo() {
SkLayerDrawLooper::SkLayerDrawLooper()
: fRecs(NULL),
fTopRec(NULL),
- fCount(0),
- fCurrRec(NULL) {
+ fCount(0) {
}
SkLayerDrawLooper::~SkLayerDrawLooper() {
@@ -37,47 +36,9 @@ SkLayerDrawLooper::~SkLayerDrawLooper() {
}
}
-SkPaint* SkLayerDrawLooper::addLayer(const LayerInfo& info) {
- fCount += 1;
-
- Rec* rec = SkNEW(Rec);
- rec->fNext = fRecs;
- rec->fInfo = info;
- fRecs = rec;
- if (NULL == fTopRec) {
- fTopRec = rec;
- }
-
- return &rec->fPaint;
-}
-
-void SkLayerDrawLooper::addLayer(SkScalar dx, SkScalar dy) {
- LayerInfo info;
-
- info.fOffset.set(dx, dy);
- (void)this->addLayer(info);
-}
-
-SkPaint* SkLayerDrawLooper::addLayerOnTop(const LayerInfo& info) {
- fCount += 1;
-
- Rec* rec = SkNEW(Rec);
- rec->fNext = NULL;
- rec->fInfo = info;
- if (NULL == fRecs) {
- fRecs = rec;
- } else {
- SkASSERT(NULL != fTopRec);
- fTopRec->fNext = rec;
- }
- fTopRec = rec;
-
- return &rec->fPaint;
-}
-
-void SkLayerDrawLooper::init(SkCanvas* canvas) {
- fCurrRec = fRecs;
- canvas->save(SkCanvas::kMatrix_SaveFlag);
+SkLayerDrawLooper::Context* SkLayerDrawLooper::createContext(SkCanvas* canvas, void* storage) const {
+ canvas->save();
+ return SkNEW_PLACEMENT_ARGS(storage, LayerDrawLooperContext, (this));
}
static SkColor xferColor(SkColor src, SkColor dst, SkXfermode::Mode mode) {
@@ -98,11 +59,9 @@ static SkColor xferColor(SkColor src, SkColor dst, SkXfermode::Mode mode) {
// Even with kEntirePaint_Bits, we always ensure that the master paint's
// text-encoding is respected, since that controls how we interpret the
// text/length parameters of a draw[Pos]Text call.
-void SkLayerDrawLooper::ApplyInfo(SkPaint* dst, const SkPaint& src,
- const LayerInfo& info) {
+void SkLayerDrawLooper::LayerDrawLooperContext::ApplyInfo(
+ SkPaint* dst, const SkPaint& src, const LayerInfo& info) {
- uint32_t mask = info.fFlagsMask;
- dst->setFlags((dst->getFlags() & ~mask) | (src.getFlags() & mask));
dst->setColor(xferColor(src.getColor(), dst->getColor(), info.fColorMode));
BitFlags bits = info.fPaintBits;
@@ -169,7 +128,11 @@ static void postTranslate(SkCanvas* canvas, SkScalar dx, SkScalar dy) {
canvas->setMatrix(m);
}
-bool SkLayerDrawLooper::next(SkCanvas* canvas, SkPaint* paint) {
+SkLayerDrawLooper::LayerDrawLooperContext::LayerDrawLooperContext(
+ const SkLayerDrawLooper* looper) : fCurrRec(looper->fRecs) {}
+
+bool SkLayerDrawLooper::LayerDrawLooperContext::next(SkCanvas* canvas,
+ SkPaint* paint) {
canvas->restore();
if (NULL == fCurrRec) {
return false;
@@ -177,21 +140,66 @@ bool SkLayerDrawLooper::next(SkCanvas* canvas, SkPaint* paint) {
ApplyInfo(paint, fCurrRec->fPaint, fCurrRec->fInfo);
- canvas->save(SkCanvas::kMatrix_SaveFlag);
+ canvas->save();
if (fCurrRec->fInfo.fPostTranslate) {
postTranslate(canvas, fCurrRec->fInfo.fOffset.fX,
fCurrRec->fInfo.fOffset.fY);
} else {
- canvas->translate(fCurrRec->fInfo.fOffset.fX, fCurrRec->fInfo.fOffset.fY);
+ canvas->translate(fCurrRec->fInfo.fOffset.fX,
+ fCurrRec->fInfo.fOffset.fY);
}
fCurrRec = fCurrRec->fNext;
return true;
}
+bool SkLayerDrawLooper::asABlurShadow(BlurShadowRec* bsRec) const {
+ if (fCount != 2) {
+ return false;
+ }
+ const Rec* rec = fRecs;
+
+ // bottom layer needs to be just blur(maskfilter)
+ if ((rec->fInfo.fPaintBits & ~kMaskFilter_Bit)) {
+ return false;
+ }
+ if (SkXfermode::kSrc_Mode != rec->fInfo.fColorMode) {
+ return false;
+ }
+ const SkMaskFilter* mf = rec->fPaint.getMaskFilter();
+ if (NULL == mf) {
+ return false;
+ }
+ SkMaskFilter::BlurRec maskBlur;
+ if (!mf->asABlur(&maskBlur)) {
+ return false;
+ }
+
+ rec = rec->fNext;
+ // top layer needs to be "plain"
+ if (rec->fInfo.fPaintBits) {
+ return false;
+ }
+ if (SkXfermode::kDst_Mode != rec->fInfo.fColorMode) {
+ return false;
+ }
+ if (!rec->fInfo.fOffset.equals(0, 0)) {
+ return false;
+ }
+
+ if (bsRec) {
+ bsRec->fSigma = maskBlur.fSigma;
+ bsRec->fOffset = fRecs->fInfo.fOffset;
+ bsRec->fColor = fRecs->fPaint.getColor();
+ bsRec->fStyle = maskBlur.fStyle;
+ bsRec->fQuality = maskBlur.fQuality;
+ }
+ return true;
+}
+
///////////////////////////////////////////////////////////////////////////////
-void SkLayerDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkLayerDrawLooper::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
#ifdef SK_DEBUG
@@ -210,7 +218,9 @@ void SkLayerDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) const {
Rec* rec = fRecs;
for (int i = 0; i < fCount; i++) {
- buffer.writeInt(rec->fInfo.fFlagsMask);
+ // Legacy "flagsmask" field -- now ignored, remove when we bump version
+ buffer.writeInt(0);
+
buffer.writeInt(rec->fInfo.fPaintBits);
buffer.writeInt(rec->fInfo.fColorMode);
buffer.writePoint(rec->fInfo.fOffset);
@@ -220,28 +230,27 @@ void SkLayerDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) const {
}
}
-SkLayerDrawLooper::SkLayerDrawLooper(SkFlattenableReadBuffer& buffer)
- : INHERITED(buffer),
- fRecs(NULL),
- fTopRec(NULL),
- fCount(0),
- fCurrRec(NULL) {
+SkFlattenable* SkLayerDrawLooper::CreateProc(SkReadBuffer& buffer) {
int count = buffer.readInt();
+ Builder builder;
for (int i = 0; i < count; i++) {
LayerInfo info;
- info.fFlagsMask = buffer.readInt();
+ // Legacy "flagsmask" field -- now ignored, remove when we bump version
+ (void)buffer.readInt();
+
info.fPaintBits = buffer.readInt();
info.fColorMode = (SkXfermode::Mode)buffer.readInt();
buffer.readPoint(&info.fOffset);
info.fPostTranslate = buffer.readBool();
- buffer.readPaint(this->addLayerOnTop(info));
+ buffer.readPaint(builder.addLayerOnTop(info));
}
- SkASSERT(count == fCount);
+ SkLayerDrawLooper* looper = builder.detachLooper();
+ SkASSERT(count == looper->fCount);
#ifdef SK_DEBUG
{
- Rec* rec = fRecs;
+ Rec* rec = looper->fRecs;
int n = 0;
while (rec) {
rec = rec->fNext;
@@ -250,52 +259,17 @@ SkLayerDrawLooper::SkLayerDrawLooper(SkFlattenableReadBuffer& buffer)
SkASSERT(count == n);
}
#endif
+
+ return looper;
}
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkLayerDrawLooper::toString(SkString* str) const {
str->appendf("SkLayerDrawLooper (%d): ", fCount);
Rec* rec = fRecs;
for (int i = 0; i < fCount; i++) {
- str->appendf("%d: ", i);
-
- str->append("flagsMask: (");
- if (0 == rec->fInfo.fFlagsMask) {
- str->append("None");
- } else {
- bool needSeparator = false;
- SkAddFlagToString(str, SkToBool(SkPaint::kAntiAlias_Flag & rec->fInfo.fFlagsMask),
- "AntiAlias", &needSeparator);
-// SkAddFlagToString(str, SkToBool(SkPaint::kFilterBitmap_Flag & rec->fInfo.fFlagsMask), "FilterBitmap", &needSeparator);
- SkAddFlagToString(str, SkToBool(SkPaint::kDither_Flag & rec->fInfo.fFlagsMask),
- "Dither", &needSeparator);
- SkAddFlagToString(str, SkToBool(SkPaint::kUnderlineText_Flag & rec->fInfo.fFlagsMask),
- "UnderlineText", &needSeparator);
- SkAddFlagToString(str, SkToBool(SkPaint::kStrikeThruText_Flag & rec->fInfo.fFlagsMask),
- "StrikeThruText", &needSeparator);
- SkAddFlagToString(str, SkToBool(SkPaint::kFakeBoldText_Flag & rec->fInfo.fFlagsMask),
- "FakeBoldText", &needSeparator);
- SkAddFlagToString(str, SkToBool(SkPaint::kLinearText_Flag & rec->fInfo.fFlagsMask),
- "LinearText", &needSeparator);
- SkAddFlagToString(str, SkToBool(SkPaint::kSubpixelText_Flag & rec->fInfo.fFlagsMask),
- "SubpixelText", &needSeparator);
- SkAddFlagToString(str, SkToBool(SkPaint::kDevKernText_Flag & rec->fInfo.fFlagsMask),
- "DevKernText", &needSeparator);
- SkAddFlagToString(str, SkToBool(SkPaint::kLCDRenderText_Flag & rec->fInfo.fFlagsMask),
- "LCDRenderText", &needSeparator);
- SkAddFlagToString(str, SkToBool(SkPaint::kEmbeddedBitmapText_Flag & rec->fInfo.fFlagsMask),
- "EmbeddedBitmapText", &needSeparator);
- SkAddFlagToString(str, SkToBool(SkPaint::kAutoHinting_Flag & rec->fInfo.fFlagsMask),
- "Autohinted", &needSeparator);
- SkAddFlagToString(str, SkToBool(SkPaint::kVerticalText_Flag & rec->fInfo.fFlagsMask),
- "VerticalText", &needSeparator);
- SkAddFlagToString(str, SkToBool(SkPaint::kGenA8FromLCD_Flag & rec->fInfo.fFlagsMask),
- "GenA8FromLCD", &needSeparator);
- }
- str->append(") ");
-
- str->append("paintBits: (");
+ str->appendf("%d: paintBits: (", i);
if (0 == rec->fInfo.fPaintBits) {
str->append("None");
} else if (kEntirePaint_Bits == rec->fInfo.fPaintBits) {
@@ -346,3 +320,68 @@ void SkLayerDrawLooper::toString(SkString* str) const {
}
}
#endif
+
+SkLayerDrawLooper::Builder::Builder()
+ : fRecs(NULL),
+ fTopRec(NULL),
+ fCount(0) {
+}
+
+SkLayerDrawLooper::Builder::~Builder() {
+ Rec* rec = fRecs;
+ while (rec) {
+ Rec* next = rec->fNext;
+ SkDELETE(rec);
+ rec = next;
+ }
+}
+
+SkPaint* SkLayerDrawLooper::Builder::addLayer(const LayerInfo& info) {
+ fCount += 1;
+
+ Rec* rec = SkNEW(Rec);
+ rec->fNext = fRecs;
+ rec->fInfo = info;
+ fRecs = rec;
+ if (NULL == fTopRec) {
+ fTopRec = rec;
+ }
+
+ return &rec->fPaint;
+}
+
+void SkLayerDrawLooper::Builder::addLayer(SkScalar dx, SkScalar dy) {
+ LayerInfo info;
+
+ info.fOffset.set(dx, dy);
+ (void)this->addLayer(info);
+}
+
+SkPaint* SkLayerDrawLooper::Builder::addLayerOnTop(const LayerInfo& info) {
+ fCount += 1;
+
+ Rec* rec = SkNEW(Rec);
+ rec->fNext = NULL;
+ rec->fInfo = info;
+ if (NULL == fRecs) {
+ fRecs = rec;
+ } else {
+ SkASSERT(NULL != fTopRec);
+ fTopRec->fNext = rec;
+ }
+ fTopRec = rec;
+
+ return &rec->fPaint;
+}
+
+SkLayerDrawLooper* SkLayerDrawLooper::Builder::detachLooper() {
+ SkLayerDrawLooper* looper = SkNEW(SkLayerDrawLooper);
+ looper->fCount = fCount;
+ looper->fRecs = fRecs;
+
+ fCount = 0;
+ fRecs = NULL;
+ fTopRec = NULL;
+
+ return looper;
+}
diff --git a/chromium/third_party/skia/src/effects/SkLayerRasterizer.cpp b/chromium/third_party/skia/src/effects/SkLayerRasterizer.cpp
index ea5808c2b4e..90fd59b585b 100644
--- a/chromium/third_party/skia/src/effects/SkLayerRasterizer.cpp
+++ b/chromium/third_party/skia/src/effects/SkLayerRasterizer.cpp
@@ -9,7 +9,8 @@
#include "SkLayerRasterizer.h"
#include "SkDraw.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkMask.h"
#include "SkMaskFilter.h"
#include "SkPaint.h"
@@ -24,25 +25,41 @@ struct SkLayerRasterizer_Rec {
SkVector fOffset;
};
-SkLayerRasterizer::SkLayerRasterizer() : fLayers(sizeof(SkLayerRasterizer_Rec))
+SkLayerRasterizer::SkLayerRasterizer()
+ : fLayers(SkNEW_ARGS(SkDeque, (sizeof(SkLayerRasterizer_Rec))))
{
}
-SkLayerRasterizer::~SkLayerRasterizer() {
- SkDeque::F2BIter iter(fLayers);
+SkLayerRasterizer::SkLayerRasterizer(SkDeque* layers) : fLayers(layers)
+{
+}
+
+// Helper function to call destructors on SkPaints held by layers and delete layers.
+static void clean_up_layers(SkDeque* layers) {
+ SkDeque::F2BIter iter(*layers);
SkLayerRasterizer_Rec* rec;
while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != NULL)
rec->fPaint.~SkPaint();
+
+ SkDELETE(layers);
+}
+
+SkLayerRasterizer::~SkLayerRasterizer() {
+ SkASSERT(fLayers);
+ clean_up_layers(const_cast<SkDeque*>(fLayers));
}
+#ifdef SK_SUPPORT_LEGACY_LAYERRASTERIZER_API
void SkLayerRasterizer::addLayer(const SkPaint& paint, SkScalar dx,
SkScalar dy) {
- SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)fLayers.push_back();
+ SkASSERT(fLayers);
+ SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)fLayers->push_back();
SkNEW_PLACEMENT_ARGS(&rec->fPaint, SkPaint, (paint));
rec->fOffset.set(dx, dy);
}
+#endif
static bool compute_bounds(const SkDeque& layers, const SkPath& path,
const SkMatrix& matrix,
@@ -88,12 +105,13 @@ static bool compute_bounds(const SkDeque& layers, const SkPath& path,
bool SkLayerRasterizer::onRasterize(const SkPath& path, const SkMatrix& matrix,
const SkIRect* clipBounds,
SkMask* mask, SkMask::CreateMode mode) const {
- if (fLayers.empty()) {
+ SkASSERT(fLayers);
+ if (fLayers->empty()) {
return false;
}
if (SkMask::kJustRenderImage_CreateMode != mode) {
- if (!compute_bounds(fLayers, path, matrix, clipBounds, &mask->fBounds))
+ if (!compute_bounds(*fLayers, path, matrix, clipBounds, &mask->fBounds))
return false;
}
@@ -121,17 +139,15 @@ bool SkLayerRasterizer::onRasterize(const SkPath& path, const SkMatrix& matrix,
translatedMatrix.postTranslate(-SkIntToScalar(mask->fBounds.fLeft),
-SkIntToScalar(mask->fBounds.fTop));
- device.setConfig(SkBitmap::kA8_Config, mask->fBounds.width(), mask->fBounds.height(), mask->fRowBytes);
- device.setPixels(mask->fImage);
+ device.installMaskPixels(*mask);
draw.fBitmap = &device;
draw.fMatrix = &drawMatrix;
draw.fRC = &rectClip;
draw.fClip = &rectClip.bwRgn();
// we set the matrixproc in the loop, as the matrix changes each time (potentially)
- draw.fBounder = NULL;
- SkDeque::F2BIter iter(fLayers);
+ SkDeque::F2BIter iter(*fLayers);
SkLayerRasterizer_Rec* rec;
while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != NULL) {
@@ -143,25 +159,30 @@ bool SkLayerRasterizer::onRasterize(const SkPath& path, const SkMatrix& matrix,
return true;
}
-SkLayerRasterizer::SkLayerRasterizer(SkFlattenableReadBuffer& buffer)
- : SkRasterizer(buffer), fLayers(sizeof(SkLayerRasterizer_Rec)) {
+SkLayerRasterizer::SkLayerRasterizer(SkReadBuffer& buffer)
+ : SkRasterizer(buffer), fLayers(ReadLayers(buffer)) {}
+
+SkDeque* SkLayerRasterizer::ReadLayers(SkReadBuffer& buffer) {
int count = buffer.readInt();
+ SkDeque* layers = SkNEW_ARGS(SkDeque, (sizeof(SkLayerRasterizer_Rec)));
for (int i = 0; i < count; i++) {
- SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)fLayers.push_back();
+ SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)layers->push_back();
SkNEW_PLACEMENT(&rec->fPaint, SkPaint);
buffer.readPaint(&rec->fPaint);
buffer.readPoint(&rec->fOffset);
}
+ return layers;
}
-void SkLayerRasterizer::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkLayerRasterizer::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
- buffer.writeInt(fLayers.count());
+ SkASSERT(fLayers);
+ buffer.writeInt(fLayers->count());
- SkDeque::F2BIter iter(fLayers);
+ SkDeque::F2BIter iter(*fLayers);
const SkLayerRasterizer_Rec* rec;
while ((rec = (const SkLayerRasterizer_Rec*)iter.next()) != NULL) {
@@ -169,3 +190,56 @@ void SkLayerRasterizer::flatten(SkFlattenableWriteBuffer& buffer) const {
buffer.writePoint(rec->fOffset);
}
}
+
+SkLayerRasterizer::Builder::Builder()
+ : fLayers(SkNEW_ARGS(SkDeque, (sizeof(SkLayerRasterizer_Rec))))
+{
+}
+
+SkLayerRasterizer::Builder::~Builder()
+{
+ if (fLayers != NULL) {
+ clean_up_layers(fLayers);
+ }
+}
+
+void SkLayerRasterizer::Builder::addLayer(const SkPaint& paint, SkScalar dx,
+ SkScalar dy) {
+ SkASSERT(fLayers);
+ SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)fLayers->push_back();
+
+ SkNEW_PLACEMENT_ARGS(&rec->fPaint, SkPaint, (paint));
+ rec->fOffset.set(dx, dy);
+}
+
+SkLayerRasterizer* SkLayerRasterizer::Builder::detachRasterizer() {
+ SkLayerRasterizer* rasterizer;
+ if (0 == fLayers->count()) {
+ rasterizer = NULL;
+ SkDELETE(fLayers);
+ } else {
+ rasterizer = SkNEW_ARGS(SkLayerRasterizer, (fLayers));
+ }
+ fLayers = NULL;
+ return rasterizer;
+}
+
+SkLayerRasterizer* SkLayerRasterizer::Builder::snapshotRasterizer() const {
+ if (0 == fLayers->count()) {
+ return NULL;
+ }
+ SkDeque* layers = SkNEW_ARGS(SkDeque, (sizeof(SkLayerRasterizer_Rec), fLayers->count()));
+ SkDeque::F2BIter iter(*fLayers);
+ const SkLayerRasterizer_Rec* recOrig;
+ SkDEBUGCODE(int count = 0;)
+ while ((recOrig = static_cast<SkLayerRasterizer_Rec*>(iter.next())) != NULL) {
+ SkDEBUGCODE(count++);
+ SkLayerRasterizer_Rec* recCopy = static_cast<SkLayerRasterizer_Rec*>(layers->push_back());
+ SkNEW_PLACEMENT_ARGS(&recCopy->fPaint, SkPaint, (recOrig->fPaint));
+ recCopy->fOffset = recOrig->fOffset;
+ }
+ SkASSERT(fLayers->count() == count);
+ SkASSERT(layers->count() == count);
+ SkLayerRasterizer* rasterizer = SkNEW_ARGS(SkLayerRasterizer, (layers));
+ return rasterizer;
+}
diff --git a/chromium/third_party/skia/src/effects/SkLerpXfermode.cpp b/chromium/third_party/skia/src/effects/SkLerpXfermode.cpp
index d73ecf4c577..c8389fea799 100644
--- a/chromium/third_party/skia/src/effects/SkLerpXfermode.cpp
+++ b/chromium/third_party/skia/src/effects/SkLerpXfermode.cpp
@@ -7,7 +7,8 @@
#include "SkLerpXfermode.h"
#include "SkColorPriv.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkString.h"
SkXfermode* SkLerpXfermode::Create(SkScalar scale) {
@@ -22,12 +23,12 @@ SkXfermode* SkLerpXfermode::Create(SkScalar scale) {
SkLerpXfermode::SkLerpXfermode(unsigned scale256) : fScale256(scale256) {}
-SkLerpXfermode::SkLerpXfermode(SkFlattenableReadBuffer& buffer)
+SkLerpXfermode::SkLerpXfermode(SkReadBuffer& buffer)
: INHERITED(buffer) {
fScale256 = buffer.readUInt();
}
-void SkLerpXfermode::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkLerpXfermode::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeUInt(fScale256);
}
@@ -103,7 +104,7 @@ void SkLerpXfermode::xferA8(SkAlpha dst[], const SkPMColor src[], int count,
}
}
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkLerpXfermode::toString(SkString* str) const {
str->printf("SkLerpXfermode: scale: %g", fScale256 / 256.0);
}
diff --git a/chromium/third_party/skia/src/effects/SkLightingImageFilter.cpp b/chromium/third_party/skia/src/effects/SkLightingImageFilter.cpp
index 50cca07dfdb..c0c605ca040 100644
--- a/chromium/third_party/skia/src/effects/SkLightingImageFilter.cpp
+++ b/chromium/third_party/skia/src/effects/SkLightingImageFilter.cpp
@@ -8,9 +8,10 @@
#include "SkLightingImageFilter.h"
#include "SkBitmap.h"
#include "SkColorPriv.h"
-#include "SkFlattenableBuffers.h"
-#include "SkOrderedReadBuffer.h"
-#include "SkOrderedWriteBuffer.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkTypes.h"
#if SK_SUPPORT_GPU
@@ -63,9 +64,9 @@ public:
colorScale = SkScalarClampMax(colorScale, SK_Scalar1);
SkPoint3 color(lightColor * colorScale);
return SkPackARGB32(255,
- SkClampMax(SkScalarFloorToInt(color.fX), 255),
- SkClampMax(SkScalarFloorToInt(color.fY), 255),
- SkClampMax(SkScalarFloorToInt(color.fZ), 255));
+ SkClampMax(SkScalarRoundToInt(color.fX), 255),
+ SkClampMax(SkScalarRoundToInt(color.fY), 255),
+ SkClampMax(SkScalarRoundToInt(color.fZ), 255));
}
private:
SkScalar fKD;
@@ -83,10 +84,10 @@ public:
SkScalarPow(normal.dot(halfDir), fShininess));
colorScale = SkScalarClampMax(colorScale, SK_Scalar1);
SkPoint3 color(lightColor * colorScale);
- return SkPackARGB32(SkClampMax(SkScalarFloorToInt(color.maxComponent()), 255),
- SkClampMax(SkScalarFloorToInt(color.fX), 255),
- SkClampMax(SkScalarFloorToInt(color.fY), 255),
- SkClampMax(SkScalarFloorToInt(color.fZ), 255));
+ return SkPackARGB32(SkClampMax(SkScalarRoundToInt(color.maxComponent()), 255),
+ SkClampMax(SkScalarRoundToInt(color.fX), 255),
+ SkClampMax(SkScalarRoundToInt(color.fY), 255),
+ SkClampMax(SkScalarRoundToInt(color.fZ), 255));
}
private:
SkScalar fKS;
@@ -243,7 +244,7 @@ template <class LightingType, class LightType> void lightBitmap(const LightingTy
}
}
-SkPoint3 readPoint3(SkFlattenableReadBuffer& buffer) {
+SkPoint3 readPoint3(SkReadBuffer& buffer) {
SkPoint3 point;
point.fX = buffer.readScalar();
point.fY = buffer.readScalar();
@@ -254,7 +255,7 @@ SkPoint3 readPoint3(SkFlattenableReadBuffer& buffer) {
return point;
};
-void writePoint3(const SkPoint3& point, SkFlattenableWriteBuffer& buffer) {
+void writePoint3(const SkPoint3& point, SkWriteBuffer& buffer) {
buffer.writeScalar(point.fX);
buffer.writeScalar(point.fY);
buffer.writeScalar(point.fZ);
@@ -268,10 +269,10 @@ public:
SkScalar kd() const { return fKD; }
protected:
- explicit SkDiffuseLightingImageFilter(SkFlattenableReadBuffer& buffer);
- virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE;
- virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
- SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
+ explicit SkDiffuseLightingImageFilter(SkReadBuffer& buffer);
+ virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE;
+ virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
+ SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE;
#if SK_SUPPORT_GPU
virtual bool asNewEffect(GrEffectRef** effect, GrTexture*, const SkMatrix& matrix, const SkIRect& bounds) const SK_OVERRIDE;
#endif
@@ -290,10 +291,10 @@ public:
SkScalar shininess() const { return fShininess; }
protected:
- explicit SkSpecularLightingImageFilter(SkFlattenableReadBuffer& buffer);
- virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE;
- virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
- SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
+ explicit SkSpecularLightingImageFilter(SkReadBuffer& buffer);
+ virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE;
+ virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
+ SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE;
#if SK_SUPPORT_GPU
virtual bool asNewEffect(GrEffectRef** effect, GrTexture*, const SkMatrix& matrix, const SkIRect& bounds) const SK_OVERRIDE;
#endif
@@ -527,8 +528,8 @@ public:
virtual SkLight* transform(const SkMatrix& matrix) const = 0;
// Defined below SkLight's subclasses.
- void flattenLight(SkFlattenableWriteBuffer& buffer) const;
- static SkLight* UnflattenLight(SkFlattenableReadBuffer& buffer);
+ void flattenLight(SkWriteBuffer& buffer) const;
+ static SkLight* UnflattenLight(SkReadBuffer& buffer);
protected:
SkLight(SkColor color)
@@ -537,11 +538,11 @@ protected:
SkIntToScalar(SkColorGetB(color))) {}
SkLight(const SkPoint3& color)
: fColor(color) {}
- SkLight(SkFlattenableReadBuffer& buffer) {
+ SkLight(SkReadBuffer& buffer) {
fColor = readPoint3(buffer);
}
- virtual void onFlattenLight(SkFlattenableWriteBuffer& buffer) const = 0;
+ virtual void onFlattenLight(SkWriteBuffer& buffer) const = 0;
private:
@@ -583,7 +584,7 @@ public:
fDirection == o.fDirection;
}
- SkDistantLight(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
+ SkDistantLight(SkReadBuffer& buffer) : INHERITED(buffer) {
fDirection = readPoint3(buffer);
}
@@ -594,7 +595,7 @@ protected:
virtual SkLight* transform(const SkMatrix& matrix) const {
return new SkDistantLight(direction(), color());
}
- virtual void onFlattenLight(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
+ virtual void onFlattenLight(SkWriteBuffer& buffer) const SK_OVERRIDE {
writePoint3(fDirection, buffer);
}
@@ -640,18 +641,21 @@ public:
virtual SkLight* transform(const SkMatrix& matrix) const {
SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY);
matrix.mapPoints(&location2, 1);
- SkPoint3 location(location2.fX, location2.fY, fLocation.fZ);
+ // Use X scale and Y scale on Z and average the result
+ SkPoint locationZ = SkPoint::Make(fLocation.fZ, fLocation.fZ);
+ matrix.mapVectors(&locationZ, 1);
+ SkPoint3 location(location2.fX, location2.fY, SkScalarAve(locationZ.fX, locationZ.fY));
return new SkPointLight(location, color());
}
- SkPointLight(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
+ SkPointLight(SkReadBuffer& buffer) : INHERITED(buffer) {
fLocation = readPoint3(buffer);
}
protected:
SkPointLight(const SkPoint3& location, const SkPoint3& color)
: INHERITED(color), fLocation(location) {}
- virtual void onFlattenLight(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
+ virtual void onFlattenLight(SkWriteBuffer& buffer) const SK_OVERRIDE {
writePoint3(fLocation, buffer);
}
@@ -681,11 +685,18 @@ public:
virtual SkLight* transform(const SkMatrix& matrix) const {
SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY);
matrix.mapPoints(&location2, 1);
- SkPoint3 location(location2.fX, location2.fY, fLocation.fZ);
+ // Use X scale and Y scale on Z and average the result
+ SkPoint locationZ = SkPoint::Make(fLocation.fZ, fLocation.fZ);
+ matrix.mapVectors(&locationZ, 1);
+ SkPoint3 location(location2.fX, location2.fY, SkScalarAve(locationZ.fX, locationZ.fY));
SkPoint target2 = SkPoint::Make(fTarget.fX, fTarget.fY);
matrix.mapPoints(&target2, 1);
- SkPoint3 target(target2.fX, target2.fY, fTarget.fZ);
- return new SkSpotLight(location, target, fSpecularExponent, fCosOuterConeAngle, fCosInnerConeAngle, fConeScale, fS, color());
+ SkPoint targetZ = SkPoint::Make(fTarget.fZ, fTarget.fZ);
+ matrix.mapVectors(&targetZ, 1);
+ SkPoint3 target(target2.fX, target2.fY, SkScalarAve(targetZ.fX, targetZ.fY));
+ SkPoint3 s = target - location;
+ s.normalize();
+ return new SkSpotLight(location, target, fSpecularExponent, fCosOuterConeAngle, fCosInnerConeAngle, fConeScale, s, color());
}
SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
@@ -725,7 +736,7 @@ public:
SkScalar coneScale() const { return fConeScale; }
const SkPoint3& s() const { return fS; }
- SkSpotLight(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
+ SkSpotLight(SkReadBuffer& buffer) : INHERITED(buffer) {
fLocation = readPoint3(buffer);
fTarget = readPoint3(buffer);
fSpecularExponent = buffer.readScalar();
@@ -750,7 +761,7 @@ protected:
fS(s)
{
}
- virtual void onFlattenLight(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
+ virtual void onFlattenLight(SkWriteBuffer& buffer) const SK_OVERRIDE {
writePoint3(fLocation, buffer);
writePoint3(fTarget, buffer);
buffer.writeScalar(fSpecularExponent);
@@ -794,14 +805,14 @@ const SkScalar SkSpotLight::kSpecularExponentMax = 128.0f;
///////////////////////////////////////////////////////////////////////////////
-void SkLight::flattenLight(SkFlattenableWriteBuffer& buffer) const {
+void SkLight::flattenLight(SkWriteBuffer& buffer) const {
// Write type first, then baseclass, then subclass.
buffer.writeInt(this->type());
writePoint3(fColor, buffer);
this->onFlattenLight(buffer);
}
-/*static*/ SkLight* SkLight::UnflattenLight(SkFlattenableReadBuffer& buffer) {
+/*static*/ SkLight* SkLight::UnflattenLight(SkReadBuffer& buffer) {
// Read type first.
const SkLight::LightType type = (SkLight::LightType)buffer.readInt();
switch (type) {
@@ -885,14 +896,14 @@ SkLightingImageFilter::~SkLightingImageFilter() {
SkSafeUnref(fLight);
}
-SkLightingImageFilter::SkLightingImageFilter(SkFlattenableReadBuffer& buffer)
+SkLightingImageFilter::SkLightingImageFilter(SkReadBuffer& buffer)
: INHERITED(1, buffer) {
fLight = SkLight::UnflattenLight(buffer);
fSurfaceScale = buffer.readScalar();
buffer.validate(SkScalarIsFinite(fSurfaceScale));
}
-void SkLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
fLight->flattenLight(buffer);
buffer.writeScalar(fSurfaceScale);
@@ -908,56 +919,57 @@ SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkLight* light, SkSca
{
}
-SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkFlattenableReadBuffer& buffer)
+SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkReadBuffer& buffer)
: INHERITED(buffer)
{
fKD = buffer.readScalar();
buffer.validate(SkScalarIsFinite(fKD) && (fKD >= 0));
}
-void SkDiffuseLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkDiffuseLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeScalar(fKD);
}
bool SkDiffuseLightingImageFilter::onFilterImage(Proxy* proxy,
const SkBitmap& source,
- const SkMatrix& ctm,
+ const Context& ctx,
SkBitmap* dst,
- SkIPoint* offset) {
+ SkIPoint* offset) const {
SkImageFilter* input = getInput(0);
SkBitmap src = source;
- if (input && !input->filterImage(proxy, source, ctm, &src, offset)) {
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
+ if (input && !input->filterImage(proxy, source, ctx, &src, &srcOffset)) {
return false;
}
- if (src.config() != SkBitmap::kARGB_8888_Config) {
+ if (src.colorType() != kN32_SkColorType) {
return false;
}
- SkAutoLockPixels alp(src);
- if (!src.getPixels()) {
+ SkIRect bounds;
+ if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) {
return false;
}
- SkIRect bounds;
- src.getBounds(&bounds);
- if (!this->applyCropRect(&bounds, ctm)) {
+ if (bounds.width() < 2 || bounds.height() < 2) {
return false;
}
- if (bounds.width() < 2 || bounds.height() < 2) {
+ SkAutoLockPixels alp(src);
+ if (!src.getPixels()) {
return false;
}
- dst->setConfig(src.config(), bounds.width(), bounds.height());
- dst->allocPixels();
- if (!dst->getPixels()) {
+ if (!dst->allocPixels(src.info().makeWH(bounds.width(), bounds.height()))) {
return false;
}
- SkAutoTUnref<SkLight> transformedLight(light()->transform(ctm));
+ SkAutoTUnref<SkLight> transformedLight(light()->transform(ctx.ctm()));
DiffuseLightingType lightingType(fKD);
+ offset->fX = bounds.left();
+ offset->fY = bounds.top();
+ bounds.offset(-srcOffset);
switch (transformedLight->type()) {
case SkLight::kDistant_LightType:
lightBitmap<DiffuseLightingType, SkDistantLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
@@ -970,8 +982,6 @@ bool SkDiffuseLightingImageFilter::onFilterImage(Proxy* proxy,
break;
}
- offset->fX += bounds.left();
- offset->fY += bounds.top();
return true;
}
@@ -996,7 +1006,7 @@ SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkLight* light, SkS
{
}
-SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkFlattenableReadBuffer& buffer)
+SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkReadBuffer& buffer)
: INHERITED(buffer)
{
fKS = buffer.readScalar();
@@ -1005,7 +1015,7 @@ SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkFlattenableReadBu
SkScalarIsFinite(fShininess));
}
-void SkSpecularLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkSpecularLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeScalar(fKS);
buffer.writeScalar(fShininess);
@@ -1013,26 +1023,22 @@ void SkSpecularLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) co
bool SkSpecularLightingImageFilter::onFilterImage(Proxy* proxy,
const SkBitmap& source,
- const SkMatrix& ctm,
+ const Context& ctx,
SkBitmap* dst,
- SkIPoint* offset) {
+ SkIPoint* offset) const {
SkImageFilter* input = getInput(0);
SkBitmap src = source;
- if (input && !input->filterImage(proxy, source, ctm, &src, offset)) {
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
+ if (input && !input->filterImage(proxy, source, ctx, &src, &srcOffset)) {
return false;
}
- if (src.config() != SkBitmap::kARGB_8888_Config) {
- return false;
- }
- SkAutoLockPixels alp(src);
- if (!src.getPixels()) {
+ if (src.colorType() != kN32_SkColorType) {
return false;
}
SkIRect bounds;
- src.getBounds(&bounds);
- if (!this->applyCropRect(&bounds, ctm)) {
+ if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) {
return false;
}
@@ -1040,14 +1046,20 @@ bool SkSpecularLightingImageFilter::onFilterImage(Proxy* proxy,
return false;
}
- dst->setConfig(src.config(), bounds.width(), bounds.height());
- dst->allocPixels();
- if (!dst->getPixels()) {
+ SkAutoLockPixels alp(src);
+ if (!src.getPixels()) {
+ return false;
+ }
+
+ if (!dst->allocPixels(src.info().makeWH(bounds.width(), bounds.height()))) {
return false;
}
SpecularLightingType lightingType(fKS, fShininess);
- SkAutoTUnref<SkLight> transformedLight(light()->transform(ctm));
+ offset->fX = bounds.left();
+ offset->fY = bounds.top();
+ bounds.offset(-srcOffset);
+ SkAutoTUnref<SkLight> transformedLight(light()->transform(ctx.ctm()));
switch (transformedLight->type()) {
case SkLight::kDistant_LightType:
lightBitmap<SpecularLightingType, SkDistantLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
@@ -1059,8 +1071,6 @@ bool SkSpecularLightingImageFilter::onFilterImage(Proxy* proxy,
lightBitmap<SpecularLightingType, SkSpotLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
break;
}
- offset->fX += bounds.left();
- offset->fY += bounds.top();
return true;
}
@@ -1102,7 +1112,7 @@ SkLight* create_random_light(SkRandom* random) {
random->nextU()));
}
default:
- GrCrash();
+ SkFAIL("Unexpected value.");
return NULL;
}
}
diff --git a/chromium/third_party/skia/src/effects/SkLumaColorFilter.cpp b/chromium/third_party/skia/src/effects/SkLumaColorFilter.cpp
index fd4826b5a9b..ae8b9056451 100644
--- a/chromium/third_party/skia/src/effects/SkLumaColorFilter.cpp
+++ b/chromium/third_party/skia/src/effects/SkLumaColorFilter.cpp
@@ -44,14 +44,14 @@ SkLumaColorFilter::SkLumaColorFilter()
: INHERITED() {
}
-SkLumaColorFilter::SkLumaColorFilter(SkFlattenableReadBuffer& buffer)
+SkLumaColorFilter::SkLumaColorFilter(SkReadBuffer& buffer)
: INHERITED(buffer) {
}
-void SkLumaColorFilter::flatten(SkFlattenableWriteBuffer&) const {
+void SkLumaColorFilter::flatten(SkWriteBuffer&) const {
}
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkLumaColorFilter::toString(SkString* str) const {
str->append("SkLumaColorFilter ");
}
diff --git a/chromium/third_party/skia/src/effects/SkMagnifierImageFilter.cpp b/chromium/third_party/skia/src/effects/SkMagnifierImageFilter.cpp
index e6f3984bddd..99c0176a113 100644
--- a/chromium/third_party/skia/src/effects/SkMagnifierImageFilter.cpp
+++ b/chromium/third_party/skia/src/effects/SkMagnifierImageFilter.cpp
@@ -8,7 +8,8 @@
#include "SkBitmap.h"
#include "SkMagnifierImageFilter.h"
#include "SkColorPriv.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkValidationUtils.h"
////////////////////////////////////////////////////////////////////////////////
@@ -231,7 +232,7 @@ void GrMagnifierEffect::getConstantColorComponents(GrColor* color, uint32_t* val
#endif
////////////////////////////////////////////////////////////////////////////////
-SkMagnifierImageFilter::SkMagnifierImageFilter(SkFlattenableReadBuffer& buffer)
+SkMagnifierImageFilter::SkMagnifierImageFilter(SkReadBuffer& buffer)
: INHERITED(1, buffer) {
float x = buffer.readScalar();
float y = buffer.readScalar();
@@ -246,7 +247,7 @@ SkMagnifierImageFilter::SkMagnifierImageFilter(SkFlattenableReadBuffer& buffer)
}
// FIXME: implement single-input semantics
-SkMagnifierImageFilter::SkMagnifierImageFilter(SkRect srcRect, SkScalar inset)
+SkMagnifierImageFilter::SkMagnifierImageFilter(const SkRect& srcRect, SkScalar inset)
: INHERITED(0), fSrcRect(srcRect), fInset(inset) {
SkASSERT(srcRect.x() >= 0 && srcRect.y() >= 0 && inset >= 0);
}
@@ -269,7 +270,7 @@ bool SkMagnifierImageFilter::asNewEffect(GrEffectRef** effect, GrTexture* textur
}
#endif
-void SkMagnifierImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkMagnifierImageFilter::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeScalar(fSrcRect.x());
buffer.writeScalar(fSrcRect.y());
@@ -279,13 +280,13 @@ void SkMagnifierImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
}
bool SkMagnifierImageFilter::onFilterImage(Proxy*, const SkBitmap& src,
- const SkMatrix&, SkBitmap* dst,
- SkIPoint* offset) {
- SkASSERT(src.config() == SkBitmap::kARGB_8888_Config);
+ const Context&, SkBitmap* dst,
+ SkIPoint* offset) const {
+ SkASSERT(src.colorType() == kN32_SkColorType);
SkASSERT(fSrcRect.width() < src.width());
SkASSERT(fSrcRect.height() < src.height());
- if ((src.config() != SkBitmap::kARGB_8888_Config) ||
+ if ((src.colorType() != kN32_SkColorType) ||
(fSrcRect.width() >= src.width()) ||
(fSrcRect.height() >= src.height())) {
return false;
@@ -297,9 +298,7 @@ bool SkMagnifierImageFilter::onFilterImage(Proxy*, const SkBitmap& src,
return false;
}
- dst->setConfig(src.config(), src.width(), src.height());
- dst->allocPixels();
- if (!dst->getPixels()) {
+ if (!dst->allocPixels(src.info())) {
return false;
}
diff --git a/chromium/third_party/skia/src/effects/SkMatrixConvolutionImageFilter.cpp b/chromium/third_party/skia/src/effects/SkMatrixConvolutionImageFilter.cpp
index 3da27cef26e..ca2cfcaab78 100644
--- a/chromium/third_party/skia/src/effects/SkMatrixConvolutionImageFilter.cpp
+++ b/chromium/third_party/skia/src/effects/SkMatrixConvolutionImageFilter.cpp
@@ -8,7 +8,8 @@
#include "SkMatrixConvolutionImageFilter.h"
#include "SkBitmap.h"
#include "SkColorPriv.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkRect.h"
#include "SkUnPreMultiply.h"
@@ -37,7 +38,7 @@ SkMatrixConvolutionImageFilter::SkMatrixConvolutionImageFilter(
const SkScalar* kernel,
SkScalar gain,
SkScalar bias,
- const SkIPoint& target,
+ const SkIPoint& kernelOffset,
TileMode tileMode,
bool convolveAlpha,
SkImageFilter* input,
@@ -46,18 +47,18 @@ SkMatrixConvolutionImageFilter::SkMatrixConvolutionImageFilter(
fKernelSize(kernelSize),
fGain(gain),
fBias(bias),
- fTarget(target),
+ fKernelOffset(kernelOffset),
fTileMode(tileMode),
fConvolveAlpha(convolveAlpha) {
uint32_t size = fKernelSize.fWidth * fKernelSize.fHeight;
fKernel = SkNEW_ARRAY(SkScalar, size);
memcpy(fKernel, kernel, size * sizeof(SkScalar));
SkASSERT(kernelSize.fWidth >= 1 && kernelSize.fHeight >= 1);
- SkASSERT(target.fX >= 0 && target.fX < kernelSize.fWidth);
- SkASSERT(target.fY >= 0 && target.fY < kernelSize.fHeight);
+ SkASSERT(kernelOffset.fX >= 0 && kernelOffset.fX < kernelSize.fWidth);
+ SkASSERT(kernelOffset.fY >= 0 && kernelOffset.fY < kernelSize.fHeight);
}
-SkMatrixConvolutionImageFilter::SkMatrixConvolutionImageFilter(SkFlattenableReadBuffer& buffer)
+SkMatrixConvolutionImageFilter::SkMatrixConvolutionImageFilter(SkReadBuffer& buffer)
: INHERITED(1, buffer) {
// We need to be able to read at most SK_MaxS32 bytes, so divide that
// by the size of a scalar to know how many scalars we can read.
@@ -78,25 +79,27 @@ SkMatrixConvolutionImageFilter::SkMatrixConvolutionImageFilter(SkFlattenableRead
}
fGain = buffer.readScalar();
fBias = buffer.readScalar();
- fTarget.fX = buffer.readInt();
- fTarget.fY = buffer.readInt();
+ fKernelOffset.fX = buffer.readInt();
+ fKernelOffset.fY = buffer.readInt();
fTileMode = (TileMode) buffer.readInt();
fConvolveAlpha = buffer.readBool();
buffer.validate((fKernel != 0) &&
SkScalarIsFinite(fGain) &&
SkScalarIsFinite(fBias) &&
- tile_mode_is_valid(fTileMode));
+ tile_mode_is_valid(fTileMode) &&
+ (fKernelOffset.fX >= 0) && (fKernelOffset.fX < fKernelSize.fWidth) &&
+ (fKernelOffset.fY >= 0) && (fKernelOffset.fY < fKernelSize.fHeight));
}
-void SkMatrixConvolutionImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkMatrixConvolutionImageFilter::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeInt(fKernelSize.fWidth);
buffer.writeInt(fKernelSize.fHeight);
buffer.writeScalarArray(fKernel, fKernelSize.fWidth * fKernelSize.fHeight);
buffer.writeScalar(fGain);
buffer.writeScalar(fBias);
- buffer.writeInt(fTarget.fX);
- buffer.writeInt(fTarget.fY);
+ buffer.writeInt(fKernelOffset.fX);
+ buffer.writeInt(fKernelOffset.fY);
buffer.writeInt((int) fTileMode);
buffer.writeBool(fConvolveAlpha);
}
@@ -150,8 +153,12 @@ public:
template<class PixelFetcher, bool convolveAlpha>
void SkMatrixConvolutionImageFilter::filterPixels(const SkBitmap& src,
SkBitmap* result,
- const SkIRect& rect,
- const SkIRect& bounds) {
+ const SkIRect& r,
+ const SkIRect& bounds) const {
+ SkIRect rect(r);
+ if (!rect.intersect(bounds)) {
+ return;
+ }
for (int y = rect.fTop; y < rect.fBottom; ++y) {
SkPMColor* dptr = result->getAddr32(rect.fLeft - bounds.fLeft, y - bounds.fTop);
for (int x = rect.fLeft; x < rect.fRight; ++x) {
@@ -159,8 +166,8 @@ void SkMatrixConvolutionImageFilter::filterPixels(const SkBitmap& src,
for (int cy = 0; cy < fKernelSize.fHeight; cy++) {
for (int cx = 0; cx < fKernelSize.fWidth; cx++) {
SkPMColor s = PixelFetcher::fetch(src,
- x + cx - fTarget.fX,
- y + cy - fTarget.fY,
+ x + cx - fKernelOffset.fX,
+ y + cy - fKernelOffset.fY,
bounds);
SkScalar k = fKernel[cy * fKernelSize.fWidth + cx];
if (convolveAlpha) {
@@ -191,7 +198,7 @@ template<class PixelFetcher>
void SkMatrixConvolutionImageFilter::filterPixels(const SkBitmap& src,
SkBitmap* result,
const SkIRect& rect,
- const SkIRect& bounds) {
+ const SkIRect& bounds) const {
if (fConvolveAlpha) {
filterPixels<PixelFetcher, true>(src, result, rect, bounds);
} else {
@@ -202,14 +209,14 @@ void SkMatrixConvolutionImageFilter::filterPixels(const SkBitmap& src,
void SkMatrixConvolutionImageFilter::filterInteriorPixels(const SkBitmap& src,
SkBitmap* result,
const SkIRect& rect,
- const SkIRect& bounds) {
+ const SkIRect& bounds) const {
filterPixels<UncheckedPixelFetcher>(src, result, rect, bounds);
}
void SkMatrixConvolutionImageFilter::filterBorderPixels(const SkBitmap& src,
SkBitmap* result,
const SkIRect& rect,
- const SkIRect& bounds) {
+ const SkIRect& bounds) const {
switch (fTileMode) {
case kClamp_TileMode:
filterPixels<ClampPixelFetcher>(src, result, rect, bounds);
@@ -233,9 +240,7 @@ static SkBitmap unpremultiplyBitmap(const SkBitmap& src)
return SkBitmap();
}
SkBitmap result;
- result.setConfig(src.config(), src.width(), src.height());
- result.allocPixels();
- if (!result.getPixels()) {
+ if (!result.allocPixels(src.info())) {
return SkBitmap();
}
for (int y = 0; y < src.height(); ++y) {
@@ -250,21 +255,21 @@ static SkBitmap unpremultiplyBitmap(const SkBitmap& src)
bool SkMatrixConvolutionImageFilter::onFilterImage(Proxy* proxy,
const SkBitmap& source,
- const SkMatrix& matrix,
+ const Context& ctx,
SkBitmap* result,
- SkIPoint* loc) {
+ SkIPoint* offset) const {
SkBitmap src = source;
- if (getInput(0) && !getInput(0)->filterImage(proxy, source, matrix, &src, loc)) {
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
+ if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctx, &src, &srcOffset)) {
return false;
}
- if (src.config() != SkBitmap::kARGB_8888_Config) {
+ if (src.colorType() != kN32_SkColorType) {
return false;
}
SkIRect bounds;
- src.getBounds(&bounds);
- if (!this->applyCropRect(&bounds, matrix)) {
+ if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) {
return false;
}
@@ -277,14 +282,15 @@ bool SkMatrixConvolutionImageFilter::onFilterImage(Proxy* proxy,
return false;
}
- result->setConfig(src.config(), bounds.width(), bounds.height());
- result->allocPixels();
- if (!result->getPixels()) {
+ if (!result->allocPixels(src.info().makeWH(bounds.width(), bounds.height()))) {
return false;
}
- SkIRect interior = SkIRect::MakeXYWH(bounds.left() + fTarget.fX,
- bounds.top() + fTarget.fY,
+ offset->fX = bounds.fLeft;
+ offset->fY = bounds.fTop;
+ bounds.offset(-srcOffset);
+ SkIRect interior = SkIRect::MakeXYWH(bounds.left() + fKernelOffset.fX,
+ bounds.top() + fKernelOffset.fY,
bounds.width() - fKernelSize.fWidth + 1,
bounds.height() - fKernelSize.fHeight + 1);
SkIRect top = SkIRect::MakeLTRB(bounds.left(), bounds.top(), bounds.right(), interior.top());
@@ -299,8 +305,19 @@ bool SkMatrixConvolutionImageFilter::onFilterImage(Proxy* proxy,
filterInteriorPixels(src, result, interior, bounds);
filterBorderPixels(src, result, right, bounds);
filterBorderPixels(src, result, bottom, bounds);
- loc->fX += bounds.fLeft;
- loc->fY += bounds.fTop;
+ return true;
+}
+
+bool SkMatrixConvolutionImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
+ SkIRect* dst) const {
+ SkIRect bounds = src;
+ bounds.fRight += fKernelSize.width() - 1;
+ bounds.fBottom += fKernelSize.height() - 1;
+ bounds.offset(-fKernelOffset);
+ if (getInput(0) && !getInput(0)->filterBounds(bounds, ctm, &bounds)) {
+ return false;
+ }
+ *dst = bounds;
return true;
}
@@ -319,7 +336,7 @@ public:
const SkScalar* kernel,
SkScalar gain,
SkScalar bias,
- const SkIPoint& target,
+ const SkIPoint& kernelOffset,
TileMode tileMode,
bool convolveAlpha) {
AutoEffectUnref effect(SkNEW_ARGS(GrMatrixConvolutionEffect, (texture,
@@ -328,7 +345,7 @@ public:
kernel,
gain,
bias,
- target,
+ kernelOffset,
tileMode,
convolveAlpha)));
return CreateEffectRef(effect);
@@ -344,7 +361,7 @@ public:
static const char* Name() { return "MatrixConvolution"; }
const SkIRect& bounds() const { return fBounds; }
const SkISize& kernelSize() const { return fKernelSize; }
- const float* target() const { return fTarget; }
+ const float* kernelOffset() const { return fKernelOffset; }
const float* kernel() const { return fKernel; }
float gain() const { return fGain; }
float bias() const { return fBias; }
@@ -362,7 +379,7 @@ private:
const SkScalar* kernel,
SkScalar gain,
SkScalar bias,
- const SkIPoint& target,
+ const SkIPoint& kernelOffset,
TileMode tileMode,
bool convolveAlpha);
@@ -373,7 +390,7 @@ private:
float *fKernel;
float fGain;
float fBias;
- float fTarget[2];
+ float fKernelOffset[2];
TileMode fTileMode;
bool fConvolveAlpha;
@@ -408,7 +425,7 @@ private:
UniformHandle fBoundsUni;
UniformHandle fKernelUni;
UniformHandle fImageIncrementUni;
- UniformHandle fTargetUni;
+ UniformHandle fKernelOffsetUni;
UniformHandle fGainUni;
UniformHandle fBiasUni;
@@ -463,15 +480,15 @@ void GrGLMatrixConvolutionEffect::emitCode(GrGLShaderBuilder* builder,
kFloat_GrSLType,
"Kernel",
fKernelSize.width() * fKernelSize.height());
- fTargetUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
- kVec2f_GrSLType, "Target");
+ fKernelOffsetUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kVec2f_GrSLType, "KernelOffset");
fGainUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
kFloat_GrSLType, "Gain");
fBiasUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
kFloat_GrSLType, "Bias");
const char* bounds = builder->getUniformCStr(fBoundsUni);
- const char* target = builder->getUniformCStr(fTargetUni);
+ const char* kernelOffset = builder->getUniformCStr(fKernelOffsetUni);
const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
const char* kernel = builder->getUniformCStr(fKernelUni);
const char* gain = builder->getUniformCStr(fGainUni);
@@ -480,7 +497,7 @@ void GrGLMatrixConvolutionEffect::emitCode(GrGLShaderBuilder* builder,
int kHeight = fKernelSize.height();
builder->fsCodeAppend("\t\tvec4 sum = vec4(0, 0, 0, 0);\n");
- builder->fsCodeAppendf("\t\tvec2 coord = %s - %s * %s;\n", coords2D.c_str(), target, imgInc);
+ builder->fsCodeAppendf("\t\tvec2 coord = %s - %s * %s;\n", coords2D.c_str(), kernelOffset, imgInc);
builder->fsCodeAppendf("\t\tfor (int y = 0; y < %d; y++) {\n", kHeight);
builder->fsCodeAppendf("\t\t\tfor (int x = 0; x < %d; x++) {\n", kWidth);
builder->fsCodeAppendf("\t\t\t\tfloat k = %s[y * %d + x];\n", kernel, kWidth);
@@ -541,7 +558,7 @@ void GrGLMatrixConvolutionEffect::setData(const GrGLUniformManager& uman,
imageIncrement[0] = 1.0f / texture.width();
imageIncrement[1] = ySign / texture.height();
uman.set2fv(fImageIncrementUni, 1, imageIncrement);
- uman.set2fv(fTargetUni, 1, conv.target());
+ uman.set2fv(fKernelOffsetUni, 1, conv.kernelOffset());
uman.set1fv(fKernelUni, fKernelSize.width() * fKernelSize.height(), conv.kernel());
uman.set1f(fGainUni, conv.gain());
uman.set1f(fBiasUni, conv.bias());
@@ -563,7 +580,7 @@ GrMatrixConvolutionEffect::GrMatrixConvolutionEffect(GrTexture* texture,
const SkScalar* kernel,
SkScalar gain,
SkScalar bias,
- const SkIPoint& target,
+ const SkIPoint& kernelOffset,
TileMode tileMode,
bool convolveAlpha)
: INHERITED(texture, MakeDivByTextureWHMatrix(texture)),
@@ -577,8 +594,8 @@ GrMatrixConvolutionEffect::GrMatrixConvolutionEffect(GrTexture* texture,
for (int i = 0; i < kernelSize.width() * kernelSize.height(); i++) {
fKernel[i] = SkScalarToFloat(kernel[i]);
}
- fTarget[0] = static_cast<float>(target.x());
- fTarget[1] = static_cast<float>(target.y());
+ fKernelOffset[0] = static_cast<float>(kernelOffset.x());
+ fKernelOffset[1] = static_cast<float>(kernelOffset.y());
this->setWillNotUseInputColor();
}
@@ -598,7 +615,7 @@ bool GrMatrixConvolutionEffect::onIsEqual(const GrEffect& sBase) const {
fKernelSize.width() * fKernelSize.height() * sizeof(float)) &&
fGain == s.gain() &&
fBias == s.bias() &&
- fTarget == s.target() &&
+ fKernelOffset == s.kernelOffset() &&
fTileMode == s.tileMode() &&
fConvolveAlpha == s.convolveAlpha();
}
@@ -624,8 +641,8 @@ GrEffectRef* GrMatrixConvolutionEffect::TestCreate(SkRandom* random,
}
SkScalar gain = random->nextSScalar1();
SkScalar bias = random->nextSScalar1();
- SkIPoint target = SkIPoint::Make(random->nextRangeU(0, kernelSize.width()),
- random->nextRangeU(0, kernelSize.height()));
+ SkIPoint kernelOffset = SkIPoint::Make(random->nextRangeU(0, kernelSize.width()),
+ random->nextRangeU(0, kernelSize.height()));
SkIRect bounds = SkIRect::MakeXYWH(random->nextRangeU(0, textures[texIdx]->width()),
random->nextRangeU(0, textures[texIdx]->height()),
random->nextRangeU(0, textures[texIdx]->width()),
@@ -638,7 +655,7 @@ GrEffectRef* GrMatrixConvolutionEffect::TestCreate(SkRandom* random,
kernel.get(),
gain,
bias,
- target,
+ kernelOffset,
tileMode,
convolveAlpha);
}
@@ -658,7 +675,7 @@ bool SkMatrixConvolutionImageFilter::asNewEffect(GrEffectRef** effect,
fKernel,
fGain,
fBias,
- fTarget,
+ fKernelOffset,
fTileMode,
fConvolveAlpha);
return true;
diff --git a/chromium/third_party/skia/src/effects/SkMatrixImageFilter.cpp b/chromium/third_party/skia/src/effects/SkMatrixImageFilter.cpp
new file mode 100644
index 00000000000..55179d3565c
--- /dev/null
+++ b/chromium/third_party/skia/src/effects/SkMatrixImageFilter.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkMatrixImageFilter.h"
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkDevice.h"
+#include "SkColorPriv.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
+#include "SkMatrix.h"
+#include "SkRect.h"
+
+SkMatrixImageFilter::SkMatrixImageFilter(const SkMatrix& transform,
+ SkPaint::FilterLevel filterLevel,
+ SkImageFilter* input)
+ : INHERITED(input),
+ fTransform(transform),
+ fFilterLevel(filterLevel) {
+}
+
+SkMatrixImageFilter* SkMatrixImageFilter::Create(const SkMatrix& transform,
+ SkPaint::FilterLevel filterLevel,
+ SkImageFilter* input) {
+ return SkNEW_ARGS(SkMatrixImageFilter, (transform, filterLevel, input));
+}
+
+SkMatrixImageFilter::SkMatrixImageFilter(SkReadBuffer& buffer)
+ : INHERITED(1, buffer) {
+ buffer.readMatrix(&fTransform);
+ fFilterLevel = static_cast<SkPaint::FilterLevel>(buffer.readInt());
+}
+
+void SkMatrixImageFilter::flatten(SkWriteBuffer& buffer) const {
+ this->INHERITED::flatten(buffer);
+ buffer.writeMatrix(fTransform);
+ buffer.writeInt(fFilterLevel);
+}
+
+SkMatrixImageFilter::~SkMatrixImageFilter() {
+}
+
+bool SkMatrixImageFilter::onFilterImage(Proxy* proxy,
+ const SkBitmap& source,
+ const Context& ctx,
+ SkBitmap* result,
+ SkIPoint* offset) const {
+ SkBitmap src = source;
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
+ if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctx, &src, &srcOffset)) {
+ return false;
+ }
+
+ SkRect dstRect;
+ SkIRect srcBounds, dstBounds;
+ src.getBounds(&srcBounds);
+ srcBounds.offset(srcOffset);
+ SkRect srcRect = SkRect::Make(srcBounds);
+ SkMatrix matrix;
+ if (!ctx.ctm().invert(&matrix)) {
+ return false;
+ }
+ matrix.postConcat(fTransform);
+ matrix.postConcat(ctx.ctm());
+ matrix.mapRect(&dstRect, srcRect);
+ dstRect.roundOut(&dstBounds);
+
+ SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(dstBounds.width(), dstBounds.height()));
+ if (NULL == device.get()) {
+ return false;
+ }
+
+ SkCanvas canvas(device.get());
+ canvas.translate(-SkIntToScalar(dstBounds.x()), -SkIntToScalar(dstBounds.y()));
+ canvas.concat(matrix);
+ SkPaint paint;
+
+ paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+ paint.setFilterLevel(fFilterLevel);
+ canvas.drawBitmap(src, srcRect.x(), srcRect.y(), &paint);
+
+ *result = device.get()->accessBitmap(false);
+ offset->fX = dstBounds.fLeft;
+ offset->fY = dstBounds.fTop;
+ return true;
+}
+
+void SkMatrixImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
+ SkRect bounds = src;
+ if (getInput(0)) {
+ getInput(0)->computeFastBounds(src, &bounds);
+ }
+ SkMatrix matrix;
+ matrix.setTranslate(-bounds.x(), -bounds.y());
+ matrix.postConcat(fTransform);
+ matrix.postTranslate(bounds.x(), bounds.y());
+ matrix.mapRect(dst, bounds);
+}
+
+bool SkMatrixImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
+ SkIRect* dst) const {
+ SkMatrix transformInverse;
+ if (!fTransform.invert(&transformInverse)) {
+ return false;
+ }
+ SkMatrix matrix;
+ if (!ctm.invert(&matrix)) {
+ return false;
+ }
+ matrix.postConcat(transformInverse);
+ matrix.postConcat(ctm);
+ SkRect floatBounds;
+ matrix.mapRect(&floatBounds, SkRect::Make(src));
+ SkIRect bounds;
+ floatBounds.roundOut(&bounds);
+ if (getInput(0) && !getInput(0)->filterBounds(bounds, ctm, &bounds)) {
+ return false;
+ }
+
+ *dst = bounds;
+ return true;
+}
diff --git a/chromium/third_party/skia/src/effects/SkMergeImageFilter.cpp b/chromium/third_party/skia/src/effects/SkMergeImageFilter.cpp
index 33673b06392..adf9afe9b3d 100755
--- a/chromium/third_party/skia/src/effects/SkMergeImageFilter.cpp
+++ b/chromium/third_party/skia/src/effects/SkMergeImageFilter.cpp
@@ -8,7 +8,8 @@
#include "SkMergeImageFilter.h"
#include "SkCanvas.h"
#include "SkDevice.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkValidationUtils.h"
///////////////////////////////////////////////////////////////////////////////
@@ -64,48 +65,15 @@ SkMergeImageFilter::~SkMergeImageFilter() {
}
}
-bool SkMergeImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
- SkIRect* dst) {
- if (countInputs() < 1) {
- return false;
- }
-
- SkIRect totalBounds;
-
- int inputCount = countInputs();
- for (int i = 0; i < inputCount; ++i) {
- SkImageFilter* filter = getInput(i);
- SkIRect r;
- if (filter) {
- if (!filter->filterBounds(src, ctm, &r)) {
- return false;
- }
- } else {
- r = src;
- }
- if (0 == i) {
- totalBounds = r;
- } else {
- totalBounds.join(r);
- }
- }
-
- // don't modify dst until now, so we don't accidentally change it in the
- // loop, but then return false on the next filter.
- *dst = totalBounds;
- return true;
-}
-
bool SkMergeImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
- const SkMatrix& ctm,
- SkBitmap* result, SkIPoint* loc) {
+ const Context& ctx,
+ SkBitmap* result, SkIPoint* offset) const {
if (countInputs() < 1) {
return false;
}
SkIRect bounds;
- src.getBounds(&bounds);
- if (!this->applyCropRect(&bounds, ctm)) {
+ if (!this->applyCropRect(ctx, src, SkIPoint::Make(0, 0), &bounds)) {
return false;
}
@@ -126,7 +94,7 @@ bool SkMergeImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
SkIPoint pos = SkIPoint::Make(0, 0);
SkImageFilter* filter = getInput(i);
if (filter) {
- if (!filter->filterImage(proxy, src, ctm, &tmp, &pos)) {
+ if (!filter->filterImage(proxy, src, ctx, &tmp, &pos)) {
return false;
}
srcPtr = &tmp;
@@ -142,13 +110,13 @@ bool SkMergeImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
canvas.drawSprite(*srcPtr, pos.x() - x0, pos.y() - y0, &paint);
}
- loc->fX += bounds.left();
- loc->fY += bounds.top();
+ offset->fX = bounds.left();
+ offset->fY = bounds.top();
*result = dst->accessBitmap(false);
return true;
}
-void SkMergeImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkMergeImageFilter::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeBool(fModes != NULL);
@@ -157,7 +125,7 @@ void SkMergeImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
}
}
-SkMergeImageFilter::SkMergeImageFilter(SkFlattenableReadBuffer& buffer)
+SkMergeImageFilter::SkMergeImageFilter(SkReadBuffer& buffer)
: INHERITED(-1, buffer) {
bool hasModes = buffer.readBool();
if (hasModes) {
@@ -165,7 +133,8 @@ SkMergeImageFilter::SkMergeImageFilter(SkFlattenableReadBuffer& buffer)
int nbInputs = countInputs();
size_t size = nbInputs * sizeof(fModes[0]);
SkASSERT(buffer.getArrayCount() == size);
- if (buffer.readByteArray(fModes, size)) {
+ if (buffer.validate(buffer.getArrayCount() == size) &&
+ buffer.readByteArray(fModes, size)) {
for (int i = 0; i < nbInputs; ++i) {
buffer.validate(SkIsValidMode((SkXfermode::Mode)fModes[i]));
}
diff --git a/chromium/third_party/skia/src/effects/SkMorphologyImageFilter.cpp b/chromium/third_party/skia/src/effects/SkMorphologyImageFilter.cpp
index 0d00c359d85..19a9b68aa8d 100644
--- a/chromium/third_party/skia/src/effects/SkMorphologyImageFilter.cpp
+++ b/chromium/third_party/skia/src/effects/SkMorphologyImageFilter.cpp
@@ -8,7 +8,8 @@
#include "SkMorphologyImageFilter.h"
#include "SkBitmap.h"
#include "SkColorPriv.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkRect.h"
#include "SkMorphology_opts.h"
#if SK_SUPPORT_GPU
@@ -17,10 +18,9 @@
#include "GrTBackendEffectFactory.h"
#include "gl/GrGLEffect.h"
#include "effects/Gr1DKernelEffect.h"
-#include "SkImageFilterUtils.h"
#endif
-SkMorphologyImageFilter::SkMorphologyImageFilter(SkFlattenableReadBuffer& buffer)
+SkMorphologyImageFilter::SkMorphologyImageFilter(SkReadBuffer& buffer)
: INHERITED(1, buffer) {
fRadius.fWidth = buffer.readInt();
fRadius.fHeight = buffer.readInt();
@@ -28,12 +28,15 @@ SkMorphologyImageFilter::SkMorphologyImageFilter(SkFlattenableReadBuffer& buffer
(fRadius.fHeight >= 0));
}
-SkMorphologyImageFilter::SkMorphologyImageFilter(int radiusX, int radiusY, SkImageFilter* input, const CropRect* cropRect)
+SkMorphologyImageFilter::SkMorphologyImageFilter(int radiusX,
+ int radiusY,
+ SkImageFilter* input,
+ const CropRect* cropRect)
: INHERITED(input, cropRect), fRadius(SkISize::Make(radiusX, radiusY)) {
}
-void SkMorphologyImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkMorphologyImageFilter::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeInt(fRadius.fWidth);
buffer.writeInt(fRadius.fHeight);
@@ -81,28 +84,6 @@ static void erode(const SkPMColor* src, SkPMColor* dst,
}
}
-static void erodeX(const SkBitmap& src, SkBitmap* dst, int radiusX, const SkIRect& bounds)
-{
- SkMorphologyProc erodeXProc = SkMorphologyGetPlatformProc(kErodeX_SkMorphologyProcType);
- if (!erodeXProc) {
- erodeXProc = erode<kX>;
- }
- erodeXProc(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0),
- radiusX, bounds.width(), bounds.height(),
- src.rowBytesAsPixels(), dst->rowBytesAsPixels());
-}
-
-static void erodeY(const SkBitmap& src, SkBitmap* dst, int radiusY, const SkIRect& bounds)
-{
- SkMorphologyProc erodeYProc = SkMorphologyGetPlatformProc(kErodeY_SkMorphologyProcType);
- if (!erodeYProc) {
- erodeYProc = erode<kY>;
- }
- erodeYProc(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0),
- radiusY, bounds.height(), bounds.width(),
- src.rowBytesAsPixels(), dst->rowBytesAsPixels());
-}
-
template<MorphDirection direction>
static void dilate(const SkPMColor* src, SkPMColor* dst,
int radius, int width, int height,
@@ -141,43 +122,39 @@ static void dilate(const SkPMColor* src, SkPMColor* dst,
}
}
-static void dilateX(const SkBitmap& src, SkBitmap* dst, int radiusX, const SkIRect& bounds)
+static void callProcX(SkMorphologyImageFilter::Proc procX, const SkBitmap& src, SkBitmap* dst, int radiusX, const SkIRect& bounds)
{
- SkMorphologyProc dilateXProc = SkMorphologyGetPlatformProc(kDilateX_SkMorphologyProcType);
- if (!dilateXProc) {
- dilateXProc = dilate<kX>;
- }
- dilateXProc(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0),
- radiusX, bounds.width(), bounds.height(),
- src.rowBytesAsPixels(), dst->rowBytesAsPixels());
+ procX(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0),
+ radiusX, bounds.width(), bounds.height(),
+ src.rowBytesAsPixels(), dst->rowBytesAsPixels());
}
-static void dilateY(const SkBitmap& src, SkBitmap* dst, int radiusY, const SkIRect& bounds)
+static void callProcY(SkMorphologyImageFilter::Proc procY, const SkBitmap& src, SkBitmap* dst, int radiusY, const SkIRect& bounds)
{
- SkMorphologyProc dilateYProc = SkMorphologyGetPlatformProc(kDilateY_SkMorphologyProcType);
- if (!dilateYProc) {
- dilateYProc = dilate<kY>;
- }
- dilateYProc(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0),
- radiusY, bounds.height(), bounds.width(),
- src.rowBytesAsPixels(), dst->rowBytesAsPixels());
+ procY(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0),
+ radiusY, bounds.height(), bounds.width(),
+ src.rowBytesAsPixels(), dst->rowBytesAsPixels());
}
-bool SkErodeImageFilter::onFilterImage(Proxy* proxy,
- const SkBitmap& source, const SkMatrix& ctm,
- SkBitmap* dst, SkIPoint* offset) {
+bool SkMorphologyImageFilter::filterImageGeneric(SkMorphologyImageFilter::Proc procX,
+ SkMorphologyImageFilter::Proc procY,
+ Proxy* proxy,
+ const SkBitmap& source,
+ const Context& ctx,
+ SkBitmap* dst,
+ SkIPoint* offset) const {
SkBitmap src = source;
- if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctm, &src, offset)) {
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
+ if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctx, &src, &srcOffset)) {
return false;
}
- if (src.config() != SkBitmap::kARGB_8888_Config) {
+ if (src.colorType() != kN32_SkColorType) {
return false;
}
SkIRect bounds;
- src.getBounds(&bounds);
- if (!this->applyCropRect(&bounds, ctm)) {
+ if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) {
return false;
}
@@ -186,105 +163,97 @@ bool SkErodeImageFilter::onFilterImage(Proxy* proxy,
return false;
}
- dst->setConfig(src.config(), bounds.width(), bounds.height());
- dst->allocPixels();
- if (!dst->getPixels()) {
+ if (!dst->allocPixels(src.info().makeWH(bounds.width(), bounds.height()))) {
return false;
}
- int width = radius().width();
- int height = radius().height();
+ SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()),
+ SkIntToScalar(this->radius().height()));
+ ctx.ctm().mapVectors(&radius, 1);
+ int width = SkScalarFloorToInt(radius.fX);
+ int height = SkScalarFloorToInt(radius.fY);
if (width < 0 || height < 0) {
return false;
}
+ SkIRect srcBounds = bounds;
+ srcBounds.offset(-srcOffset);
+
if (width == 0 && height == 0) {
- src.extractSubset(dst, bounds);
- offset->fX += bounds.left();
- offset->fY += bounds.top();
+ src.extractSubset(dst, srcBounds);
+ offset->fX = bounds.left();
+ offset->fY = bounds.top();
return true;
}
SkBitmap temp;
- temp.setConfig(dst->config(), dst->width(), dst->height());
- if (!temp.allocPixels()) {
+ if (!temp.allocPixels(dst->info())) {
return false;
}
if (width > 0 && height > 0) {
- erodeX(src, &temp, width, bounds);
- SkIRect tmpBounds = SkIRect::MakeWH(bounds.width(), bounds.height());
- erodeY(temp, dst, height, tmpBounds);
+ callProcX(procX, src, &temp, width, srcBounds);
+ SkIRect tmpBounds = SkIRect::MakeWH(srcBounds.width(), srcBounds.height());
+ callProcY(procY, temp, dst, height, tmpBounds);
} else if (width > 0) {
- erodeX(src, dst, width, bounds);
+ callProcX(procX, src, dst, width, srcBounds);
} else if (height > 0) {
- erodeY(src, dst, height, bounds);
+ callProcY(procY, src, dst, height, srcBounds);
}
- offset->fX += bounds.left();
- offset->fY += bounds.top();
+ offset->fX = bounds.left();
+ offset->fY = bounds.top();
return true;
}
-bool SkDilateImageFilter::onFilterImage(Proxy* proxy,
- const SkBitmap& source, const SkMatrix& ctm,
- SkBitmap* dst, SkIPoint* offset) {
- SkBitmap src = source;
- if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctm, &src, offset)) {
- return false;
- }
- if (src.config() != SkBitmap::kARGB_8888_Config) {
- return false;
- }
-
- SkIRect bounds;
- src.getBounds(&bounds);
- if (!this->applyCropRect(&bounds, ctm)) {
- return false;
+bool SkErodeImageFilter::onFilterImage(Proxy* proxy,
+ const SkBitmap& source, const Context& ctx,
+ SkBitmap* dst, SkIPoint* offset) const {
+ Proc erodeXProc = SkMorphologyGetPlatformProc(kErodeX_SkMorphologyProcType);
+ if (!erodeXProc) {
+ erodeXProc = erode<kX>;
}
-
- SkAutoLockPixels alp(src);
- if (!src.getPixels()) {
- return false;
+ Proc erodeYProc = SkMorphologyGetPlatformProc(kErodeY_SkMorphologyProcType);
+ if (!erodeYProc) {
+ erodeYProc = erode<kY>;
}
+ return this->filterImageGeneric(erodeXProc, erodeYProc, proxy, source, ctx, dst, offset);
+}
- dst->setConfig(src.config(), bounds.width(), bounds.height());
- dst->allocPixels();
- if (!dst->getPixels()) {
- return false;
+bool SkDilateImageFilter::onFilterImage(Proxy* proxy,
+ const SkBitmap& source, const Context& ctx,
+ SkBitmap* dst, SkIPoint* offset) const {
+ Proc dilateXProc = SkMorphologyGetPlatformProc(kDilateX_SkMorphologyProcType);
+ if (!dilateXProc) {
+ dilateXProc = dilate<kX>;
}
-
- int width = radius().width();
- int height = radius().height();
-
- if (width < 0 || height < 0) {
- return false;
+ Proc dilateYProc = SkMorphologyGetPlatformProc(kDilateY_SkMorphologyProcType);
+ if (!dilateYProc) {
+ dilateYProc = dilate<kY>;
}
+ return this->filterImageGeneric(dilateXProc, dilateYProc, proxy, source, ctx, dst, offset);
+}
- if (width == 0 && height == 0) {
- src.extractSubset(dst, bounds);
- offset->fX += bounds.left();
- offset->fY += bounds.top();
- return true;
+void SkMorphologyImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
+ if (getInput(0)) {
+ getInput(0)->computeFastBounds(src, dst);
+ } else {
+ *dst = src;
}
+ dst->outset(SkIntToScalar(fRadius.width()), SkIntToScalar(fRadius.height()));
+}
- SkBitmap temp;
- temp.setConfig(dst->config(), dst->width(), dst->height());
- if (!temp.allocPixels()) {
+bool SkMorphologyImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
+ SkIRect* dst) const {
+ SkIRect bounds = src;
+ if (getInput(0) && !getInput(0)->filterBounds(src, ctm, &bounds)) {
return false;
}
-
- if (width > 0 && height > 0) {
- dilateX(src, &temp, width, bounds);
- SkIRect tmpBounds = SkIRect::MakeWH(bounds.width(), bounds.height());
- dilateY(temp, dst, height, tmpBounds);
- } else if (width > 0) {
- dilateX(src, dst, width, bounds);
- } else if (height > 0) {
- dilateY(src, dst, height, bounds);
- }
- offset->fX += bounds.left();
- offset->fY += bounds.top();
+ SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()),
+ SkIntToScalar(this->radius().height()));
+ ctm.mapVectors(&radius, 1);
+ bounds.outset(SkScalarCeilToInt(radius.x()), SkScalarCeilToInt(radius.y()));
+ *dst = bounds;
return true;
}
@@ -397,7 +366,7 @@ void GrGLMorphologyEffect::emitCode(GrGLShaderBuilder* builder,
func = "max";
break;
default:
- GrCrash("Unexpected type");
+ SkFAIL("Unexpected type");
func = ""; // suppress warning
break;
}
@@ -438,7 +407,7 @@ void GrGLMorphologyEffect::setData(const GrGLUniformManager& uman,
imageIncrement[1] = 1.0f / texture.height();
break;
default:
- GrCrash("Unknown filter direction.");
+ SkFAIL("Unknown filter direction.");
}
uman.set2fv(fImageIncrementUni, 1, imageIncrement);
}
@@ -555,75 +524,64 @@ bool apply_morphology(const SkBitmap& input,
morphType, Gr1DKernelEffect::kY_Direction);
src.reset(ast.detach());
}
- return SkImageFilterUtils::WrapTexture(src, rect.width(), rect.height(), dst);
+ SkImageFilter::WrapTexture(src, rect.width(), rect.height(), dst);
+ return true;
}
};
-bool SkDilateImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
- SkBitmap* result, SkIPoint* offset) {
- SkBitmap input;
- if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &input, offset)) {
+bool SkMorphologyImageFilter::filterImageGPUGeneric(bool dilate,
+ Proxy* proxy,
+ const SkBitmap& src,
+ const Context& ctx,
+ SkBitmap* result,
+ SkIPoint* offset) const {
+ SkBitmap input = src;
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
+ if (getInput(0) && !getInput(0)->getInputResultGPU(proxy, src, ctx, &input, &srcOffset)) {
return false;
}
SkIRect bounds;
- src.getBounds(&bounds);
- if (!this->applyCropRect(&bounds, ctm)) {
+ if (!this->applyCropRect(ctx, proxy, input, &srcOffset, &bounds, &input)) {
return false;
}
- int width = radius().width();
- int height = radius().height();
+ SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()),
+ SkIntToScalar(this->radius().height()));
+ ctx.ctm().mapVectors(&radius, 1);
+ int width = SkScalarFloorToInt(radius.fX);
+ int height = SkScalarFloorToInt(radius.fY);
if (width < 0 || height < 0) {
return false;
}
+ SkIRect srcBounds = bounds;
+ srcBounds.offset(-srcOffset);
if (width == 0 && height == 0) {
- src.extractSubset(result, bounds);
- offset->fX += bounds.left();
- offset->fY += bounds.top();
+ input.extractSubset(result, srcBounds);
+ offset->fX = bounds.left();
+ offset->fY = bounds.top();
return true;
}
- if (!apply_morphology(input, bounds, GrMorphologyEffect::kDilate_MorphologyType, radius(), result)) {
+ GrMorphologyEffect::MorphologyType type = dilate ? GrMorphologyEffect::kDilate_MorphologyType : GrMorphologyEffect::kErode_MorphologyType;
+ if (!apply_morphology(input, srcBounds, type,
+ SkISize::Make(width, height), result)) {
return false;
}
- offset->fX += bounds.left();
- offset->fY += bounds.top();
+ offset->fX = bounds.left();
+ offset->fY = bounds.top();
return true;
}
-bool SkErodeImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
- SkBitmap* result, SkIPoint* offset) {
- SkBitmap input;
- if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &input, offset)) {
- return false;
- }
- SkIRect bounds;
- src.getBounds(&bounds);
- if (!this->applyCropRect(&bounds, ctm)) {
- return false;
- }
- int width = radius().width();
- int height = radius().height();
-
- if (width < 0 || height < 0) {
- return false;
- }
-
- if (width == 0 && height == 0) {
- src.extractSubset(result, bounds);
- offset->fX += bounds.left();
- offset->fY += bounds.top();
- return true;
- }
+bool SkDilateImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx,
+ SkBitmap* result, SkIPoint* offset) const {
+ return this->filterImageGPUGeneric(true, proxy, src, ctx, result, offset);
+}
- if (!apply_morphology(input, bounds, GrMorphologyEffect::kErode_MorphologyType, radius(), result)) {
- return false;
- }
- offset->fX += bounds.left();
- offset->fY += bounds.top();
- return true;
+bool SkErodeImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx,
+ SkBitmap* result, SkIPoint* offset) const {
+ return this->filterImageGPUGeneric(false, proxy, src, ctx, result, offset);
}
#endif
diff --git a/chromium/third_party/skia/src/effects/SkOffsetImageFilter.cpp b/chromium/third_party/skia/src/effects/SkOffsetImageFilter.cpp
index 59318e3915c..7680c62cfc9 100644
--- a/chromium/third_party/skia/src/effects/SkOffsetImageFilter.cpp
+++ b/chromium/third_party/skia/src/effects/SkOffsetImageFilter.cpp
@@ -9,41 +9,40 @@
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkDevice.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkMatrix.h"
#include "SkPaint.h"
bool SkOffsetImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source,
- const SkMatrix& matrix,
+ const Context& ctx,
SkBitmap* result,
- SkIPoint* loc) {
+ SkIPoint* offset) const {
SkImageFilter* input = getInput(0);
SkBitmap src = source;
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
#ifdef SK_DISABLE_OFFSETIMAGEFILTER_OPTIMIZATION
if (false) {
#else
if (!cropRectIsSet()) {
#endif
- if (input && !input->filterImage(proxy, source, matrix, &src, loc)) {
+ if (input && !input->filterImage(proxy, source, ctx, &src, &srcOffset)) {
return false;
}
SkVector vec;
- matrix.mapVectors(&vec, &fOffset, 1);
+ ctx.ctm().mapVectors(&vec, &fOffset, 1);
- loc->fX += SkScalarRoundToInt(vec.fX);
- loc->fY += SkScalarRoundToInt(vec.fY);
+ offset->fX = srcOffset.fX + SkScalarRoundToInt(vec.fX);
+ offset->fY = srcOffset.fY + SkScalarRoundToInt(vec.fY);
*result = src;
} else {
- SkIPoint srcOffset = SkIPoint::Make(0, 0);
- if (input && !input->filterImage(proxy, source, matrix, &src, &srcOffset)) {
+ if (input && !input->filterImage(proxy, source, ctx, &src, &srcOffset)) {
return false;
}
SkIRect bounds;
- src.getBounds(&bounds);
-
- if (!applyCropRect(&bounds, matrix)) {
+ if (!this->applyCropRect(ctx, src, srcOffset, &bounds)) {
return false;
}
@@ -54,25 +53,45 @@ bool SkOffsetImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source,
SkCanvas canvas(device);
SkPaint paint;
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
- canvas.drawBitmap(src, fOffset.fX - bounds.left(), fOffset.fY - bounds.top(), &paint);
+ canvas.translate(SkIntToScalar(srcOffset.fX - bounds.fLeft),
+ SkIntToScalar(srcOffset.fY - bounds.fTop));
+ SkVector vec;
+ ctx.ctm().mapVectors(&vec, &fOffset, 1);
+ canvas.drawBitmap(src, vec.x(), vec.y(), &paint);
*result = device->accessBitmap(false);
- loc->fX += bounds.left();
- loc->fY += bounds.top();
+ offset->fX = bounds.fLeft;
+ offset->fY = bounds.fTop;
}
return true;
}
+void SkOffsetImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
+ if (getInput(0)) {
+ getInput(0)->computeFastBounds(src, dst);
+ } else {
+ *dst = src;
+ }
+ SkRect copy = *dst;
+ dst->offset(fOffset.fX, fOffset.fY);
+ dst->join(copy);
+}
+
bool SkOffsetImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
- SkIRect* dst) {
+ SkIRect* dst) const {
SkVector vec;
ctm.mapVectors(&vec, &fOffset, 1);
- *dst = src;
- dst->offset(SkScalarRoundToInt(vec.fX), SkScalarRoundToInt(vec.fY));
+ SkIRect bounds = src;
+ bounds.offset(-SkScalarCeilToInt(vec.fX), -SkScalarCeilToInt(vec.fY));
+ bounds.join(src);
+ if (getInput(0)) {
+ return getInput(0)->filterBounds(bounds, ctm, dst);
+ }
+ *dst = bounds;
return true;
}
-void SkOffsetImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkOffsetImageFilter::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writePoint(fOffset);
}
@@ -82,7 +101,7 @@ SkOffsetImageFilter::SkOffsetImageFilter(SkScalar dx, SkScalar dy, SkImageFilter
fOffset.set(dx, dy);
}
-SkOffsetImageFilter::SkOffsetImageFilter(SkFlattenableReadBuffer& buffer)
+SkOffsetImageFilter::SkOffsetImageFilter(SkReadBuffer& buffer)
: INHERITED(1, buffer) {
buffer.readPoint(&fOffset);
buffer.validate(SkScalarIsFinite(fOffset.fX) &&
diff --git a/chromium/third_party/skia/src/effects/SkPerlinNoiseShader.cpp b/chromium/third_party/skia/src/effects/SkPerlinNoiseShader.cpp
index 26771c5db7d..84026b60464 100644
--- a/chromium/third_party/skia/src/effects/SkPerlinNoiseShader.cpp
+++ b/chromium/third_party/skia/src/effects/SkPerlinNoiseShader.cpp
@@ -8,7 +8,8 @@
#include "SkDither.h"
#include "SkPerlinNoiseShader.h"
#include "SkColorFilter.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkShader.h"
#include "SkUnPreMultiply.h"
#include "SkString.h"
@@ -38,9 +39,6 @@ inline int checkNoise(int noiseValue, int limitValue, int newValue) {
if (noiseValue >= limitValue) {
noiseValue -= newValue;
}
- if (noiseValue >= limitValue - 1) {
- noiseValue -= newValue - 1;
- }
return noiseValue;
}
@@ -80,17 +78,23 @@ struct SkPerlinNoiseShader::StitchData {
};
struct SkPerlinNoiseShader::PaintingData {
- PaintingData(const SkISize& tileSize)
- : fSeed(0)
- , fTileSize(tileSize)
- , fPermutationsBitmap(NULL)
- , fNoiseBitmap(NULL)
- {}
-
- ~PaintingData()
+ PaintingData(const SkISize& tileSize, SkScalar seed,
+ SkScalar baseFrequencyX, SkScalar baseFrequencyY)
+ : fTileSize(tileSize)
+ , fBaseFrequency(SkPoint::Make(baseFrequencyX, baseFrequencyY))
{
- SkDELETE(fPermutationsBitmap);
- SkDELETE(fNoiseBitmap);
+ this->init(seed);
+ if (!fTileSize.isEmpty()) {
+ this->stitch();
+ }
+
+#if SK_SUPPORT_GPU
+ fPermutationsBitmap.setInfo(SkImageInfo::MakeA8(kBlockSize, 1));
+ fPermutationsBitmap.setPixels(fLatticeSelector);
+
+ fNoiseBitmap.setInfo(SkImageInfo::MakeN32Premul(kBlockSize, 4));
+ fNoiseBitmap.setPixels(fNoise[0][0]);
+#endif
}
int fSeed;
@@ -103,10 +107,10 @@ struct SkPerlinNoiseShader::PaintingData {
private:
- SkBitmap* fPermutationsBitmap;
- SkBitmap* fNoiseBitmap;
-
-public:
+#if SK_SUPPORT_GPU
+ SkBitmap fPermutationsBitmap;
+ SkBitmap fNoiseBitmap;
+#endif
inline int random() {
static const int gRandAmplitude = 16807; // 7**5; primitive root of m
@@ -120,12 +124,14 @@ public:
return result;
}
+ // Only called once. Could be part of the constructor.
void init(SkScalar seed)
{
static const SkScalar gInvBlockSizef = SkScalarInvert(SkIntToScalar(kBlockSize));
+ // According to the SVG spec, we must truncate (not round) the seed value.
+ fSeed = SkScalarTruncToInt(seed);
// The seed value clamp to the range [1, kRandMaximum - 1].
- fSeed = SkScalarRoundToInt(seed);
if (fSeed <= 0) {
fSeed = -(fSeed % (kRandMaximum - 1)) + 1;
}
@@ -188,14 +194,9 @@ public:
fGradient[channel][i].fY + SK_Scalar1, gHalfMax16bits));
}
}
-
- // Invalidate bitmaps
- SkDELETE(fPermutationsBitmap);
- fPermutationsBitmap = NULL;
- SkDELETE(fNoiseBitmap);
- fNoiseBitmap = NULL;
}
+ // Only called once. Could be part of the constructor.
void stitch() {
SkScalar tileWidth = SkIntToScalar(fTileSize.width());
SkScalar tileHeight = SkIntToScalar(fTileSize.height());
@@ -203,10 +204,10 @@ public:
// When stitching tiled turbulence, the frequencies must be adjusted
// so that the tile borders will be continuous.
if (fBaseFrequency.fX) {
- SkScalar lowFrequencx = SkScalarDiv(
- SkScalarMulFloor(tileWidth, fBaseFrequency.fX), tileWidth);
- SkScalar highFrequencx = SkScalarDiv(
- SkScalarMulCeil(tileWidth, fBaseFrequency.fX), tileWidth);
+ SkScalar lowFrequencx =
+ SkScalarFloorToScalar(tileWidth * fBaseFrequency.fX) / tileWidth;
+ SkScalar highFrequencx =
+ SkScalarCeilToScalar(tileWidth * fBaseFrequency.fX) / tileWidth;
// BaseFrequency should be non-negative according to the standard.
if (SkScalarDiv(fBaseFrequency.fX, lowFrequencx) <
SkScalarDiv(highFrequencx, fBaseFrequency.fX)) {
@@ -216,10 +217,10 @@ public:
}
}
if (fBaseFrequency.fY) {
- SkScalar lowFrequency = SkScalarDiv(
- SkScalarMulFloor(tileHeight, fBaseFrequency.fY), tileHeight);
- SkScalar highFrequency = SkScalarDiv(
- SkScalarMulCeil(tileHeight, fBaseFrequency.fY), tileHeight);
+ SkScalar lowFrequency =
+ SkScalarFloorToScalar(tileHeight * fBaseFrequency.fY) / tileHeight;
+ SkScalar highFrequency =
+ SkScalarCeilToScalar(tileHeight * fBaseFrequency.fY) / tileHeight;
if (SkScalarDiv(fBaseFrequency.fY, lowFrequency) <
SkScalarDiv(highFrequency, fBaseFrequency.fY)) {
fBaseFrequency.fY = lowFrequency;
@@ -229,36 +230,20 @@ public:
}
// Set up TurbulenceInitial stitch values.
fStitchDataInit.fWidth =
- SkScalarMulRound(tileWidth, fBaseFrequency.fX);
+ SkScalarRoundToInt(tileWidth * fBaseFrequency.fX);
fStitchDataInit.fWrapX = kPerlinNoise + fStitchDataInit.fWidth;
fStitchDataInit.fHeight =
- SkScalarMulRound(tileHeight, fBaseFrequency.fY);
+ SkScalarRoundToInt(tileHeight * fBaseFrequency.fY);
fStitchDataInit.fWrapY = kPerlinNoise + fStitchDataInit.fHeight;
}
- SkBitmap* getPermutationsBitmap()
- {
- if (!fPermutationsBitmap) {
- fPermutationsBitmap = SkNEW(SkBitmap);
- fPermutationsBitmap->setConfig(SkBitmap::kA8_Config, kBlockSize, 1);
- fPermutationsBitmap->allocPixels();
- uint8_t* bitmapPixels = fPermutationsBitmap->getAddr8(0, 0);
- memcpy(bitmapPixels, fLatticeSelector, sizeof(uint8_t) * kBlockSize);
- }
- return fPermutationsBitmap;
- }
+public:
- SkBitmap* getNoiseBitmap()
- {
- if (!fNoiseBitmap) {
- fNoiseBitmap = SkNEW(SkBitmap);
- fNoiseBitmap->setConfig(SkBitmap::kARGB_8888_Config, kBlockSize, 4);
- fNoiseBitmap->allocPixels();
- uint32_t* bitmapPixels = fNoiseBitmap->getAddr32(0, 0);
- memcpy(bitmapPixels, fNoise[0][0], sizeof(uint16_t) * kBlockSize * 4 * 2);
- }
- return fNoiseBitmap;
- }
+#if SK_SUPPORT_GPU
+ const SkBitmap& getPermutationsBitmap() const { return fPermutationsBitmap; }
+
+ const SkBitmap& getNoiseBitmap() const { return fNoiseBitmap; }
+#endif
};
SkShader* SkPerlinNoiseShader::CreateFractalNoise(SkScalar baseFrequencyX, SkScalar baseFrequencyY,
@@ -268,7 +253,7 @@ SkShader* SkPerlinNoiseShader::CreateFractalNoise(SkScalar baseFrequencyX, SkSca
numOctaves, seed, tileSize));
}
-SkShader* SkPerlinNoiseShader::CreateTubulence(SkScalar baseFrequencyX, SkScalar baseFrequencyY,
+SkShader* SkPerlinNoiseShader::CreateTurbulence(SkScalar baseFrequencyX, SkScalar baseFrequencyY,
int numOctaves, SkScalar seed,
const SkISize* tileSize) {
return SkNEW_ARGS(SkPerlinNoiseShader, (kTurbulence_Type, baseFrequencyX, baseFrequencyY,
@@ -286,16 +271,16 @@ SkPerlinNoiseShader::SkPerlinNoiseShader(SkPerlinNoiseShader::Type type,
, fBaseFrequencyY(baseFrequencyY)
, fNumOctaves(numOctaves > 255 ? 255 : numOctaves/*[0,255] octaves allowed*/)
, fSeed(seed)
- , fStitchTiles((tileSize != NULL) && !tileSize->isEmpty())
- , fPaintingData(NULL)
+ , fTileSize(NULL == tileSize ? SkISize::Make(0, 0) : *tileSize)
+ , fStitchTiles(!fTileSize.isEmpty())
{
SkASSERT(numOctaves >= 0 && numOctaves < 256);
- setTileSize(fStitchTiles ? *tileSize : SkISize::Make(0,0));
- fMatrix.reset();
+ fPaintingData = SkNEW_ARGS(PaintingData, (fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY));
}
-SkPerlinNoiseShader::SkPerlinNoiseShader(SkFlattenableReadBuffer& buffer) :
- INHERITED(buffer), fPaintingData(NULL) {
+SkPerlinNoiseShader::SkPerlinNoiseShader(SkReadBuffer& buffer)
+ : INHERITED(buffer)
+{
fType = (SkPerlinNoiseShader::Type) buffer.readInt();
fBaseFrequencyX = buffer.readScalar();
fBaseFrequencyY = buffer.readScalar();
@@ -304,10 +289,10 @@ SkPerlinNoiseShader::SkPerlinNoiseShader(SkFlattenableReadBuffer& buffer) :
fStitchTiles = buffer.readBool();
fTileSize.fWidth = buffer.readInt();
fTileSize.fHeight = buffer.readInt();
- setTileSize(fTileSize);
- fMatrix.reset();
+ fPaintingData = SkNEW_ARGS(PaintingData, (fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY));
buffer.validate(perlin_noise_type_is_valid(fType) &&
- (fNumOctaves >= 0) && (fNumOctaves <= 255));
+ (fNumOctaves >= 0) && (fNumOctaves <= 255) &&
+ (fStitchTiles != fTileSize.isEmpty()));
}
SkPerlinNoiseShader::~SkPerlinNoiseShader() {
@@ -315,7 +300,7 @@ SkPerlinNoiseShader::~SkPerlinNoiseShader() {
SkDELETE(fPaintingData);
}
-void SkPerlinNoiseShader::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkPerlinNoiseShader::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeInt((int) fType);
buffer.writeScalar(fBaseFrequencyX);
@@ -327,88 +312,70 @@ void SkPerlinNoiseShader::flatten(SkFlattenableWriteBuffer& buffer) const {
buffer.writeInt(fTileSize.fHeight);
}
-void SkPerlinNoiseShader::initPaint(PaintingData& paintingData)
-{
- paintingData.init(fSeed);
-
- // Set frequencies to original values
- paintingData.fBaseFrequency.set(fBaseFrequencyX, fBaseFrequencyY);
- // Adjust frequecies based on size if stitching is enabled
- if (fStitchTiles) {
- paintingData.stitch();
- }
-}
-
-void SkPerlinNoiseShader::setTileSize(const SkISize& tileSize) {
- fTileSize = tileSize;
-
- if (NULL == fPaintingData) {
- fPaintingData = SkNEW_ARGS(PaintingData, (fTileSize));
- initPaint(*fPaintingData);
- } else {
- // Set Size
- fPaintingData->fTileSize = fTileSize;
- // Set frequencies to original values
- fPaintingData->fBaseFrequency.set(fBaseFrequencyX, fBaseFrequencyY);
- // Adjust frequecies based on size if stitching is enabled
- if (fStitchTiles) {
- fPaintingData->stitch();
- }
- }
-}
-
-SkScalar SkPerlinNoiseShader::noise2D(int channel, const PaintingData& paintingData,
- const StitchData& stitchData, const SkPoint& noiseVector)
-{
+SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::noise2D(
+ int channel, const PaintingData& paintingData,
+ const StitchData& stitchData, const SkPoint& noiseVector) const {
struct Noise {
int noisePositionIntegerValue;
+ int nextNoisePositionIntegerValue;
SkScalar noisePositionFractionValue;
Noise(SkScalar component)
{
SkScalar position = component + kPerlinNoise;
noisePositionIntegerValue = SkScalarFloorToInt(position);
noisePositionFractionValue = position - SkIntToScalar(noisePositionIntegerValue);
+ nextNoisePositionIntegerValue = noisePositionIntegerValue + 1;
}
};
Noise noiseX(noiseVector.x());
Noise noiseY(noiseVector.y());
SkScalar u, v;
+ const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader);
// If stitching, adjust lattice points accordingly.
- if (fStitchTiles) {
+ if (perlinNoiseShader.fStitchTiles) {
noiseX.noisePositionIntegerValue =
checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth);
noiseY.noisePositionIntegerValue =
checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight);
+ noiseX.nextNoisePositionIntegerValue =
+ checkNoise(noiseX.nextNoisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth);
+ noiseY.nextNoisePositionIntegerValue =
+ checkNoise(noiseY.nextNoisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight);
}
noiseX.noisePositionIntegerValue &= kBlockMask;
noiseY.noisePositionIntegerValue &= kBlockMask;
- int latticeIndex =
- paintingData.fLatticeSelector[noiseX.noisePositionIntegerValue] +
- noiseY.noisePositionIntegerValue;
- int nextLatticeIndex =
- paintingData.fLatticeSelector[(noiseX.noisePositionIntegerValue + 1) & kBlockMask] +
- noiseY.noisePositionIntegerValue;
+ noiseX.nextNoisePositionIntegerValue &= kBlockMask;
+ noiseY.nextNoisePositionIntegerValue &= kBlockMask;
+ int i =
+ paintingData.fLatticeSelector[noiseX.noisePositionIntegerValue];
+ int j =
+ paintingData.fLatticeSelector[noiseX.nextNoisePositionIntegerValue];
+ int b00 = (i + noiseY.noisePositionIntegerValue) & kBlockMask;
+ int b10 = (j + noiseY.noisePositionIntegerValue) & kBlockMask;
+ int b01 = (i + noiseY.nextNoisePositionIntegerValue) & kBlockMask;
+ int b11 = (j + noiseY.nextNoisePositionIntegerValue) & kBlockMask;
SkScalar sx = smoothCurve(noiseX.noisePositionFractionValue);
SkScalar sy = smoothCurve(noiseY.noisePositionFractionValue);
// This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement
SkPoint fractionValue = SkPoint::Make(noiseX.noisePositionFractionValue,
noiseY.noisePositionFractionValue); // Offset (0,0)
- u = paintingData.fGradient[channel][latticeIndex & kBlockMask].dot(fractionValue);
+ u = paintingData.fGradient[channel][b00].dot(fractionValue);
fractionValue.fX -= SK_Scalar1; // Offset (-1,0)
- v = paintingData.fGradient[channel][nextLatticeIndex & kBlockMask].dot(fractionValue);
+ v = paintingData.fGradient[channel][b10].dot(fractionValue);
SkScalar a = SkScalarInterp(u, v, sx);
fractionValue.fY -= SK_Scalar1; // Offset (-1,-1)
- v = paintingData.fGradient[channel][(nextLatticeIndex + 1) & kBlockMask].dot(fractionValue);
+ v = paintingData.fGradient[channel][b11].dot(fractionValue);
fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1)
- u = paintingData.fGradient[channel][(latticeIndex + 1) & kBlockMask].dot(fractionValue);
+ u = paintingData.fGradient[channel][b01].dot(fractionValue);
SkScalar b = SkScalarInterp(u, v, sx);
return SkScalarInterp(a, b, sy);
}
-SkScalar SkPerlinNoiseShader::calculateTurbulenceValueForPoint(
- int channel, const PaintingData& paintingData, StitchData& stitchData, const SkPoint& point)
-{
- if (fStitchTiles) {
+SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::calculateTurbulenceValueForPoint(
+ int channel, const PaintingData& paintingData,
+ StitchData& stitchData, const SkPoint& point) const {
+ const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader);
+ if (perlinNoiseShader.fStitchTiles) {
// Set up TurbulenceInitial stitch values.
stitchData = paintingData.fStitchDataInit;
}
@@ -416,14 +383,14 @@ SkScalar SkPerlinNoiseShader::calculateTurbulenceValueForPoint(
SkPoint noiseVector(SkPoint::Make(SkScalarMul(point.x(), paintingData.fBaseFrequency.fX),
SkScalarMul(point.y(), paintingData.fBaseFrequency.fY)));
SkScalar ratio = SK_Scalar1;
- for (int octave = 0; octave < fNumOctaves; ++octave) {
+ for (int octave = 0; octave < perlinNoiseShader.fNumOctaves; ++octave) {
SkScalar noise = noise2D(channel, paintingData, stitchData, noiseVector);
turbulenceFunctionResult += SkScalarDiv(
- (fType == kFractalNoise_Type) ? noise : SkScalarAbs(noise), ratio);
+ (perlinNoiseShader.fType == kFractalNoise_Type) ? noise : SkScalarAbs(noise), ratio);
noiseVector.fX *= 2;
noiseVector.fY *= 2;
ratio *= 2;
- if (fStitchTiles) {
+ if (perlinNoiseShader.fStitchTiles) {
// Update stitch values
stitchData.fWidth *= 2;
stitchData.fWrapX = stitchData.fWidth + kPerlinNoise;
@@ -434,7 +401,7 @@ SkScalar SkPerlinNoiseShader::calculateTurbulenceValueForPoint(
// The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
// by fractalNoise and (turbulenceFunctionResult) by turbulence.
- if (fType == kFractalNoise_Type) {
+ if (perlinNoiseShader.fType == kFractalNoise_Type) {
turbulenceFunctionResult =
SkScalarMul(turbulenceFunctionResult, SK_ScalarHalf) + SK_ScalarHalf;
}
@@ -448,38 +415,55 @@ SkScalar SkPerlinNoiseShader::calculateTurbulenceValueForPoint(
return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1);
}
-SkPMColor SkPerlinNoiseShader::shade(const SkPoint& point, StitchData& stitchData) {
- SkMatrix matrix = fMatrix;
- SkMatrix invMatrix;
- if (!matrix.invert(&invMatrix)) {
- invMatrix.reset();
- } else {
- invMatrix.postConcat(invMatrix); // Square the matrix
- }
- // This (1,1) translation is due to WebKit's 1 based coordinates for the noise
- // (as opposed to 0 based, usually). The same adjustment is in the setData() function.
- matrix.postTranslate(SK_Scalar1, SK_Scalar1);
+SkPMColor SkPerlinNoiseShader::PerlinNoiseShaderContext::shade(
+ const SkPoint& point, StitchData& stitchData) const {
+ const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader);
SkPoint newPoint;
- matrix.mapPoints(&newPoint, &point, 1);
- invMatrix.mapPoints(&newPoint, &newPoint, 1);
+ fMatrix.mapPoints(&newPoint, &point, 1);
newPoint.fX = SkScalarRoundToScalar(newPoint.fX);
newPoint.fY = SkScalarRoundToScalar(newPoint.fY);
U8CPU rgba[4];
for (int channel = 3; channel >= 0; --channel) {
rgba[channel] = SkScalarFloorToInt(255 *
- calculateTurbulenceValueForPoint(channel, *fPaintingData, stitchData, newPoint));
+ calculateTurbulenceValueForPoint(channel, *perlinNoiseShader.fPaintingData,
+ stitchData, newPoint));
}
return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]);
}
-bool SkPerlinNoiseShader::setContext(const SkBitmap& device, const SkPaint& paint,
- const SkMatrix& matrix) {
- fMatrix = matrix;
- return INHERITED::setContext(device, paint, matrix);
+SkShader::Context* SkPerlinNoiseShader::onCreateContext(const ContextRec& rec,
+ void* storage) const {
+ return SkNEW_PLACEMENT_ARGS(storage, PerlinNoiseShaderContext, (*this, rec));
+}
+
+size_t SkPerlinNoiseShader::contextSize() const {
+ return sizeof(PerlinNoiseShaderContext);
}
-void SkPerlinNoiseShader::shadeSpan(int x, int y, SkPMColor result[], int count) {
+SkPerlinNoiseShader::PerlinNoiseShaderContext::PerlinNoiseShaderContext(
+ const SkPerlinNoiseShader& shader, const ContextRec& rec)
+ : INHERITED(shader, rec)
+{
+ SkMatrix newMatrix = *rec.fMatrix;
+ newMatrix.preConcat(shader.getLocalMatrix());
+ if (rec.fLocalMatrix) {
+ newMatrix.preConcat(*rec.fLocalMatrix);
+ }
+ SkMatrix invMatrix;
+ if (!newMatrix.invert(&invMatrix)) {
+ invMatrix.reset();
+ }
+ // This (1,1) translation is due to WebKit's 1 based coordinates for the noise
+ // (as opposed to 0 based, usually). The same adjustment is in the setData() function.
+ newMatrix.postTranslate(SK_Scalar1, SK_Scalar1);
+ newMatrix.postConcat(invMatrix);
+ newMatrix.postConcat(invMatrix);
+ fMatrix = newMatrix;
+}
+
+void SkPerlinNoiseShader::PerlinNoiseShaderContext::shadeSpan(
+ int x, int y, SkPMColor result[], int count) {
SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y));
StitchData stitchData;
for (int i = 0; i < count; ++i) {
@@ -488,7 +472,8 @@ void SkPerlinNoiseShader::shadeSpan(int x, int y, SkPMColor result[], int count)
}
}
-void SkPerlinNoiseShader::shadeSpan16(int x, int y, uint16_t result[], int count) {
+void SkPerlinNoiseShader::PerlinNoiseShaderContext::shadeSpan16(
+ int x, int y, uint16_t result[], int count) {
SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y));
StitchData stitchData;
DITHER_565_SCAN(y);
@@ -506,33 +491,10 @@ void SkPerlinNoiseShader::shadeSpan16(int x, int y, uint16_t result[], int count
#include "GrTBackendEffectFactory.h"
-class GrGLNoise : public GrGLEffect {
-public:
- GrGLNoise(const GrBackendEffectFactory& factory,
- const GrDrawEffect& drawEffect);
- virtual ~GrGLNoise() {}
-
- static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
-
- virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
-
-protected:
- SkPerlinNoiseShader::Type fType;
- bool fStitchTiles;
- int fNumOctaves;
- GrGLUniformManager::UniformHandle fBaseFrequencyUni;
- GrGLUniformManager::UniformHandle fAlphaUni;
- GrGLUniformManager::UniformHandle fInvMatrixUni;
-
-private:
- typedef GrGLEffect INHERITED;
-};
-
-class GrGLPerlinNoise : public GrGLNoise {
+class GrGLPerlinNoise : public GrGLEffect {
public:
GrGLPerlinNoise(const GrBackendEffectFactory& factory,
- const GrDrawEffect& drawEffect)
- : GrGLNoise(factory, drawEffect) {}
+ const GrDrawEffect& drawEffect);
virtual ~GrGLPerlinNoise() {}
virtual void emitCode(GrGLShaderBuilder*,
@@ -545,95 +507,25 @@ public:
virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
-private:
- GrGLUniformManager::UniformHandle fStitchDataUni;
-
- typedef GrGLNoise INHERITED;
-};
-
-class GrGLSimplexNoise : public GrGLNoise {
- // Note : This is for reference only. GrGLPerlinNoise is used for processing.
-public:
- GrGLSimplexNoise(const GrBackendEffectFactory& factory,
- const GrDrawEffect& drawEffect)
- : GrGLNoise(factory, drawEffect) {}
-
- virtual ~GrGLSimplexNoise() {}
+ static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
- virtual void emitCode(GrGLShaderBuilder*,
- const GrDrawEffect&,
- EffectKey,
- const char* outputColor,
- const char* inputColor,
- const TransformedCoordsArray&,
- const TextureSamplerArray&) SK_OVERRIDE;
+private:
- virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
+ GrGLUniformManager::UniformHandle fStitchDataUni;
+ SkPerlinNoiseShader::Type fType;
+ bool fStitchTiles;
+ int fNumOctaves;
+ GrGLUniformManager::UniformHandle fBaseFrequencyUni;
+ GrGLUniformManager::UniformHandle fAlphaUni;
+ GrGLUniformManager::UniformHandle fInvMatrixUni;
private:
- GrGLUniformManager::UniformHandle fSeedUni;
-
- typedef GrGLNoise INHERITED;
+ typedef GrGLEffect INHERITED;
};
/////////////////////////////////////////////////////////////////////
-class GrNoiseEffect : public GrEffect {
-public:
- virtual ~GrNoiseEffect() { }
-
- SkPerlinNoiseShader::Type type() const { return fType; }
- bool stitchTiles() const { return fStitchTiles; }
- const SkVector& baseFrequency() const { return fBaseFrequency; }
- int numOctaves() const { return fNumOctaves; }
- const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
- uint8_t alpha() const { return fAlpha; }
-
- void getConstantColorComponents(GrColor*, uint32_t* validFlags) const SK_OVERRIDE {
- *validFlags = 0; // This is noise. Nothing is constant.
- }
-
-protected:
- virtual bool onIsEqual(const GrEffect& sBase) const SK_OVERRIDE {
- const GrNoiseEffect& s = CastEffect<GrNoiseEffect>(sBase);
- return fType == s.fType &&
- fBaseFrequency == s.fBaseFrequency &&
- fNumOctaves == s.fNumOctaves &&
- fStitchTiles == s.fStitchTiles &&
- fCoordTransform.getMatrix() == s.fCoordTransform.getMatrix() &&
- fAlpha == s.fAlpha;
- }
-
- GrNoiseEffect(SkPerlinNoiseShader::Type type, const SkVector& baseFrequency, int numOctaves,
- bool stitchTiles, const SkMatrix& matrix, uint8_t alpha)
- : fType(type)
- , fBaseFrequency(baseFrequency)
- , fNumOctaves(numOctaves)
- , fStitchTiles(stitchTiles)
- , fMatrix(matrix)
- , fAlpha(alpha) {
- // This (1,1) translation is due to WebKit's 1 based coordinates for the noise
- // (as opposed to 0 based, usually). The same adjustment is in the shadeSpan() functions.
- SkMatrix m = matrix;
- m.postTranslate(SK_Scalar1, SK_Scalar1);
- fCoordTransform.reset(kLocal_GrCoordSet, m);
- this->addCoordTransform(&fCoordTransform);
- this->setWillNotUseInputColor();
- }
-
- SkPerlinNoiseShader::Type fType;
- GrCoordTransform fCoordTransform;
- SkVector fBaseFrequency;
- int fNumOctaves;
- bool fStitchTiles;
- SkMatrix fMatrix;
- uint8_t fAlpha;
-
-private:
- typedef GrEffect INHERITED;
-};
-
-class GrPerlinNoiseEffect : public GrNoiseEffect {
+class GrPerlinNoiseEffect : public GrEffect {
public:
static GrEffectRef* Create(SkPerlinNoiseShader::Type type, const SkVector& baseFrequency,
int numOctaves, bool stitchTiles,
@@ -653,12 +545,24 @@ public:
}
const SkPerlinNoiseShader::StitchData& stitchData() const { return fStitchData; }
+ SkPerlinNoiseShader::Type type() const { return fType; }
+ bool stitchTiles() const { return fStitchTiles; }
+ const SkVector& baseFrequency() const { return fBaseFrequency; }
+ int numOctaves() const { return fNumOctaves; }
+ const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
+ uint8_t alpha() const { return fAlpha; }
+
typedef GrGLPerlinNoise GLEffect;
private:
virtual bool onIsEqual(const GrEffect& sBase) const SK_OVERRIDE {
const GrPerlinNoiseEffect& s = CastEffect<GrPerlinNoiseEffect>(sBase);
- return INHERITED::onIsEqual(sBase) &&
+ return fType == s.fType &&
+ fBaseFrequency == s.fBaseFrequency &&
+ fNumOctaves == s.fNumOctaves &&
+ fStitchTiles == s.fStitchTiles &&
+ fCoordTransform.getMatrix() == s.fCoordTransform.getMatrix() &&
+ fAlpha == s.fAlpha &&
fPermutationsAccess.getTexture() == s.fPermutationsAccess.getTexture() &&
fNoiseAccess.getTexture() == s.fNoiseAccess.getTexture() &&
fStitchData == s.fStitchData;
@@ -669,60 +573,41 @@ private:
const SkPerlinNoiseShader::StitchData& stitchData,
GrTexture* permutationsTexture, GrTexture* noiseTexture,
const SkMatrix& matrix, uint8_t alpha)
- : GrNoiseEffect(type, baseFrequency, numOctaves, stitchTiles, matrix, alpha)
+ : fType(type)
+ , fBaseFrequency(baseFrequency)
+ , fNumOctaves(numOctaves)
+ , fStitchTiles(stitchTiles)
+ , fAlpha(alpha)
, fPermutationsAccess(permutationsTexture)
, fNoiseAccess(noiseTexture)
, fStitchData(stitchData) {
this->addTextureAccess(&fPermutationsAccess);
this->addTextureAccess(&fNoiseAccess);
+ SkMatrix m = matrix;
+ m.postTranslate(SK_Scalar1, SK_Scalar1);
+ fCoordTransform.reset(kLocal_GrCoordSet, m);
+ this->addCoordTransform(&fCoordTransform);
+ this->setWillNotUseInputColor();
}
GR_DECLARE_EFFECT_TEST;
+ SkPerlinNoiseShader::Type fType;
+ GrCoordTransform fCoordTransform;
+ SkVector fBaseFrequency;
+ int fNumOctaves;
+ bool fStitchTiles;
+ uint8_t fAlpha;
GrTextureAccess fPermutationsAccess;
GrTextureAccess fNoiseAccess;
SkPerlinNoiseShader::StitchData fStitchData;
- typedef GrNoiseEffect INHERITED;
-};
-
-class GrSimplexNoiseEffect : public GrNoiseEffect {
- // Note : This is for reference only. GrPerlinNoiseEffect is used for processing.
-public:
- static GrEffectRef* Create(SkPerlinNoiseShader::Type type, const SkVector& baseFrequency,
- int numOctaves, bool stitchTiles, const SkScalar seed,
- const SkMatrix& matrix, uint8_t alpha) {
- AutoEffectUnref effect(SkNEW_ARGS(GrSimplexNoiseEffect, (type, baseFrequency, numOctaves,
- stitchTiles, seed, matrix, alpha)));
- return CreateEffectRef(effect);
- }
-
- virtual ~GrSimplexNoiseEffect() { }
-
- static const char* Name() { return "SimplexNoise"; }
- virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
- return GrTBackendEffectFactory<GrSimplexNoiseEffect>::getInstance();
+ void getConstantColorComponents(GrColor*, uint32_t* validFlags) const SK_OVERRIDE {
+ *validFlags = 0; // This is noise. Nothing is constant.
}
- const SkScalar& seed() const { return fSeed; }
-
- typedef GrGLSimplexNoise GLEffect;
private:
- virtual bool onIsEqual(const GrEffect& sBase) const SK_OVERRIDE {
- const GrSimplexNoiseEffect& s = CastEffect<GrSimplexNoiseEffect>(sBase);
- return INHERITED::onIsEqual(sBase) && fSeed == s.fSeed;
- }
-
- GrSimplexNoiseEffect(SkPerlinNoiseShader::Type type, const SkVector& baseFrequency,
- int numOctaves, bool stitchTiles, const SkScalar seed,
- const SkMatrix& matrix, uint8_t alpha)
- : GrNoiseEffect(type, baseFrequency, numOctaves, stitchTiles, matrix, alpha)
- , fSeed(seed) {
- }
-
- SkScalar fSeed;
-
- typedef GrNoiseEffect INHERITED;
+ typedef GrEffect INHERITED;
};
/////////////////////////////////////////////////////////////////////
@@ -744,233 +629,24 @@ GrEffectRef* GrPerlinNoiseEffect::TestCreate(SkRandom* random,
SkShader* shader = random->nextBool() ?
SkPerlinNoiseShader::CreateFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves, seed,
stitchTiles ? &tileSize : NULL) :
- SkPerlinNoiseShader::CreateTubulence(baseFrequencyX, baseFrequencyY, numOctaves, seed,
+ SkPerlinNoiseShader::CreateTurbulence(baseFrequencyX, baseFrequencyY, numOctaves, seed,
stitchTiles ? &tileSize : NULL);
SkPaint paint;
- GrEffectRef* effect = shader->asNewEffect(context, paint);
+ GrColor grColor;
+ GrEffectRef* effect;
+ shader->asNewEffect(context, paint, NULL, &grColor, &effect);
SkDELETE(shader);
return effect;
}
-/////////////////////////////////////////////////////////////////////
-
-void GrGLSimplexNoise::emitCode(GrGLShaderBuilder* builder,
- const GrDrawEffect&,
- EffectKey key,
- const char* outputColor,
- const char* inputColor,
- const TransformedCoordsArray& coords,
- const TextureSamplerArray&) {
- sk_ignore_unused_variable(inputColor);
-
- SkString vCoords = builder->ensureFSCoords2D(coords, 0);
-
- fSeedUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
- kFloat_GrSLType, "seed");
- const char* seedUni = builder->getUniformCStr(fSeedUni);
- fInvMatrixUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
- kMat33f_GrSLType, "invMatrix");
- const char* invMatrixUni = builder->getUniformCStr(fInvMatrixUni);
- fBaseFrequencyUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
- kVec2f_GrSLType, "baseFrequency");
- const char* baseFrequencyUni = builder->getUniformCStr(fBaseFrequencyUni);
- fAlphaUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
- kFloat_GrSLType, "alpha");
- const char* alphaUni = builder->getUniformCStr(fAlphaUni);
-
- // Add vec3 modulo 289 function
- static const GrGLShaderVar gVec3Args[] = {
- GrGLShaderVar("x", kVec3f_GrSLType)
- };
-
- SkString mod289_3_funcName;
- builder->fsEmitFunction(kVec3f_GrSLType,
- "mod289", SK_ARRAY_COUNT(gVec3Args), gVec3Args,
- "const vec2 C = vec2(1.0 / 289.0, 289.0);\n"
- "return x - floor(x * C.xxx) * C.yyy;", &mod289_3_funcName);
-
- // Add vec4 modulo 289 function
- static const GrGLShaderVar gVec4Args[] = {
- GrGLShaderVar("x", kVec4f_GrSLType)
- };
-
- SkString mod289_4_funcName;
- builder->fsEmitFunction(kVec4f_GrSLType,
- "mod289", SK_ARRAY_COUNT(gVec4Args), gVec4Args,
- "const vec2 C = vec2(1.0 / 289.0, 289.0);\n"
- "return x - floor(x * C.xxxx) * C.yyyy;", &mod289_4_funcName);
-
- // Add vec4 permute function
- SkString permuteCode;
- permuteCode.appendf("const vec2 C = vec2(34.0, 1.0);\n"
- "return %s(((x * C.xxxx) + C.yyyy) * x);", mod289_4_funcName.c_str());
- SkString permuteFuncName;
- builder->fsEmitFunction(kVec4f_GrSLType,
- "permute", SK_ARRAY_COUNT(gVec4Args), gVec4Args,
- permuteCode.c_str(), &permuteFuncName);
-
- // Add vec4 taylorInvSqrt function
- SkString taylorInvSqrtFuncName;
- builder->fsEmitFunction(kVec4f_GrSLType,
- "taylorInvSqrt", SK_ARRAY_COUNT(gVec4Args), gVec4Args,
- "const vec2 C = vec2(-0.85373472095314, 1.79284291400159);\n"
- "return x * C.xxxx + C.yyyy;", &taylorInvSqrtFuncName);
-
- // Add vec3 noise function
- static const GrGLShaderVar gNoiseVec3Args[] = {
- GrGLShaderVar("v", kVec3f_GrSLType)
- };
-
- SkString noiseCode;
- noiseCode.append(
- "const vec2 C = vec2(1.0/6.0, 1.0/3.0);\n"
- "const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);\n"
-
- // First corner
- "vec3 i = floor(v + dot(v, C.yyy));\n"
- "vec3 x0 = v - i + dot(i, C.xxx);\n"
-
- // Other corners
- "vec3 g = step(x0.yzx, x0.xyz);\n"
- "vec3 l = 1.0 - g;\n"
- "vec3 i1 = min(g.xyz, l.zxy);\n"
- "vec3 i2 = max(g.xyz, l.zxy);\n"
-
- "vec3 x1 = x0 - i1 + C.xxx;\n"
- "vec3 x2 = x0 - i2 + C.yyy;\n" // 2.0*C.x = 1/3 = C.y
- "vec3 x3 = x0 - D.yyy;\n" // -1.0+3.0*C.x = -0.5 = -D.y
- );
-
- noiseCode.appendf(
- // Permutations
- "i = %s(i);\n"
- "vec4 p = %s(%s(%s(\n"
- " i.z + vec4(0.0, i1.z, i2.z, 1.0)) +\n"
- " i.y + vec4(0.0, i1.y, i2.y, 1.0)) +\n"
- " i.x + vec4(0.0, i1.x, i2.x, 1.0));\n",
- mod289_3_funcName.c_str(), permuteFuncName.c_str(), permuteFuncName.c_str(),
- permuteFuncName.c_str());
-
- noiseCode.append(
- // Gradients: 7x7 points over a square, mapped onto an octahedron.
- // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
- "float n_ = 0.142857142857;\n" // 1.0/7.0
- "vec3 ns = n_ * D.wyz - D.xzx;\n"
-
- "vec4 j = p - 49.0 * floor(p * ns.z * ns.z);\n" // mod(p,7*7)
-
- "vec4 x_ = floor(j * ns.z);\n"
- "vec4 y_ = floor(j - 7.0 * x_);" // mod(j,N)
-
- "vec4 x = x_ *ns.x + ns.yyyy;\n"
- "vec4 y = y_ *ns.x + ns.yyyy;\n"
- "vec4 h = 1.0 - abs(x) - abs(y);\n"
-
- "vec4 b0 = vec4(x.xy, y.xy);\n"
- "vec4 b1 = vec4(x.zw, y.zw);\n"
- );
-
- noiseCode.append(
- "vec4 s0 = floor(b0) * 2.0 + 1.0;\n"
- "vec4 s1 = floor(b1) * 2.0 + 1.0;\n"
- "vec4 sh = -step(h, vec4(0.0));\n"
-
- "vec4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;\n"
- "vec4 a1 = b1.xzyw + s1.xzyw * sh.zzww;\n"
-
- "vec3 p0 = vec3(a0.xy, h.x);\n"
- "vec3 p1 = vec3(a0.zw, h.y);\n"
- "vec3 p2 = vec3(a1.xy, h.z);\n"
- "vec3 p3 = vec3(a1.zw, h.w);\n"
- );
-
- noiseCode.appendf(
- // Normalise gradients
- "vec4 norm = %s(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));\n"
- "p0 *= norm.x;\n"
- "p1 *= norm.y;\n"
- "p2 *= norm.z;\n"
- "p3 *= norm.w;\n"
-
- // Mix final noise value
- "vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);\n"
- "m = m * m;\n"
- "return 42.0 * dot(m*m, vec4(dot(p0,x0), dot(p1,x1), dot(p2,x2), dot(p3,x3)));",
- taylorInvSqrtFuncName.c_str());
-
- SkString noiseFuncName;
- builder->fsEmitFunction(kFloat_GrSLType,
- "snoise", SK_ARRAY_COUNT(gNoiseVec3Args), gNoiseVec3Args,
- noiseCode.c_str(), &noiseFuncName);
-
- const char* noiseVecIni = "noiseVecIni";
- const char* factors = "factors";
- const char* sum = "sum";
- const char* xOffsets = "xOffsets";
- const char* yOffsets = "yOffsets";
- const char* channel = "channel";
-
- // Fill with some prime numbers
- builder->fsCodeAppendf("\t\tconst vec4 %s = vec4(13.0, 53.0, 101.0, 151.0);\n", xOffsets);
- builder->fsCodeAppendf("\t\tconst vec4 %s = vec4(109.0, 167.0, 23.0, 67.0);\n", yOffsets);
-
- // There are rounding errors if the floor operation is not performed here
- builder->fsCodeAppendf(
- "\t\tvec3 %s = vec3(floor((%s*vec3(%s, 1.0)).xy) * vec2(0.66) * %s, 0.0);\n",
- noiseVecIni, invMatrixUni, vCoords.c_str(), baseFrequencyUni);
-
- // Perturb the texcoords with three components of noise
- builder->fsCodeAppendf("\t\t%s += 0.1 * vec3(%s(%s + vec3( 0.0, 0.0, %s)),"
- "%s(%s + vec3( 43.0, 17.0, %s)),"
- "%s(%s + vec3(-17.0, -43.0, %s)));\n",
- noiseVecIni, noiseFuncName.c_str(), noiseVecIni, seedUni,
- noiseFuncName.c_str(), noiseVecIni, seedUni,
- noiseFuncName.c_str(), noiseVecIni, seedUni);
-
- builder->fsCodeAppendf("\t\t%s = vec4(0.0);\n", outputColor);
-
- builder->fsCodeAppendf("\t\tvec3 %s = vec3(1.0);\n", factors);
- builder->fsCodeAppendf("\t\tfloat %s = 0.0;\n", sum);
-
- // Loop over all octaves
- builder->fsCodeAppendf("\t\tfor (int octave = 0; octave < %d; ++octave) {\n", fNumOctaves);
-
- // Loop over the 4 channels
- builder->fsCodeAppendf("\t\t\tfor (int %s = 3; %s >= 0; --%s) {\n", channel, channel, channel);
-
- builder->fsCodeAppendf(
- "\t\t\t\t%s[channel] += %s.x * %s(%s * %s.yyy - vec3(%s[%s], %s[%s], %s * %s.z));\n",
- outputColor, factors, noiseFuncName.c_str(), noiseVecIni, factors, xOffsets, channel,
- yOffsets, channel, seedUni, factors);
-
- builder->fsCodeAppend("\t\t\t}\n"); // end of the for loop on channels
-
- builder->fsCodeAppendf("\t\t\t%s += %s.x;\n", sum, factors);
- builder->fsCodeAppendf("\t\t\t%s *= vec3(0.5, 2.0, 0.75);\n", factors);
-
- builder->fsCodeAppend("\t\t}\n"); // end of the for loop on octaves
-
- if (fType == SkPerlinNoiseShader::kFractalNoise_Type) {
- // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
- // by fractalNoise and (turbulenceFunctionResult) by turbulence.
- builder->fsCodeAppendf("\t\t%s = %s * vec4(0.5 / %s) + vec4(0.5);\n",
- outputColor, outputColor, sum);
- } else {
- builder->fsCodeAppendf("\t\t%s = abs(%s / vec4(%s));\n",
- outputColor, outputColor, sum);
- }
-
- builder->fsCodeAppendf("\t\t%s.a *= %s;\n", outputColor, alphaUni);
-
- // Clamp values
- builder->fsCodeAppendf("\t\t%s = clamp(%s, 0.0, 1.0);\n", outputColor, outputColor);
-
- // Pre-multiply the result
- builder->fsCodeAppendf("\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
- outputColor, outputColor, outputColor, outputColor);
+GrGLPerlinNoise::GrGLPerlinNoise(const GrBackendEffectFactory& factory, const GrDrawEffect& drawEffect)
+ : INHERITED (factory)
+ , fType(drawEffect.castEffect<GrPerlinNoiseEffect>().type())
+ , fStitchTiles(drawEffect.castEffect<GrPerlinNoiseEffect>().stitchTiles())
+ , fNumOctaves(drawEffect.castEffect<GrPerlinNoiseEffect>().numOctaves()) {
}
void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder,
@@ -1009,13 +685,14 @@ void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder,
const char* chanCoord = "chanCoord";
const char* stitchData = "stitchData";
const char* ratio = "ratio";
- const char* noiseXY = "noiseXY";
const char* noiseVec = "noiseVec";
const char* noiseSmooth = "noiseSmooth";
+ const char* floorVal = "floorVal";
const char* fractVal = "fractVal";
const char* uv = "uv";
const char* ab = "ab";
const char* latticeIdx = "latticeIdx";
+ const char* bcoords = "bcoords";
const char* lattice = "lattice";
const char* inc8bit = "0.00390625"; // 1.0 / 256.0
// This is the math to convert the two 16bit integer packed into rgba 8 bit input into a
@@ -1036,32 +713,35 @@ void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder,
SkString noiseCode;
- noiseCode.appendf("\tvec4 %s = vec4(floor(%s), fract(%s));", noiseXY, noiseVec, noiseVec);
+ noiseCode.appendf("\tvec4 %s;\n", floorVal);
+ noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec);
+ noiseCode.appendf("\t%s.zw = %s.xy + vec2(1.0);\n", floorVal, floorVal);
+ noiseCode.appendf("\tvec2 %s = fract(%s);\n", fractVal, noiseVec);
// smooth curve : t * t * (3 - 2 * t)
- noiseCode.appendf("\n\tvec2 %s = %s.zw * %s.zw * (vec2(3.0) - vec2(2.0) * %s.zw);",
- noiseSmooth, noiseXY, noiseXY, noiseXY);
+ noiseCode.appendf("\n\tvec2 %s = %s * %s * (vec2(3.0) - vec2(2.0) * %s);",
+ noiseSmooth, fractVal, fractVal, fractVal);
// Adjust frequencies if we're stitching tiles
if (fStitchTiles) {
noiseCode.appendf("\n\tif(%s.x >= %s.x) { %s.x -= %s.x; }",
- noiseXY, stitchData, noiseXY, stitchData);
- noiseCode.appendf("\n\tif(%s.x >= (%s.x - 1.0)) { %s.x -= (%s.x - 1.0); }",
- noiseXY, stitchData, noiseXY, stitchData);
+ floorVal, stitchData, floorVal, stitchData);
noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }",
- noiseXY, stitchData, noiseXY, stitchData);
- noiseCode.appendf("\n\tif(%s.y >= (%s.y - 1.0)) { %s.y -= (%s.y - 1.0); }",
- noiseXY, stitchData, noiseXY, stitchData);
+ floorVal, stitchData, floorVal, stitchData);
+ noiseCode.appendf("\n\tif(%s.z >= %s.x) { %s.z -= %s.x; }",
+ floorVal, stitchData, floorVal, stitchData);
+ noiseCode.appendf("\n\tif(%s.w >= %s.y) { %s.w -= %s.y; }",
+ floorVal, stitchData, floorVal, stitchData);
}
// Get texture coordinates and normalize
- noiseCode.appendf("\n\t%s.xy = fract(floor(mod(%s.xy, 256.0)) / vec2(256.0));\n",
- noiseXY, noiseXY);
+ noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / vec4(256.0));\n",
+ floorVal, floorVal);
// Get permutation for x
{
SkString xCoords("");
- xCoords.appendf("vec2(%s.x, 0.5)", noiseXY);
+ xCoords.appendf("vec2(%s.x, 0.5)", floorVal);
noiseCode.appendf("\n\tvec2 %s;\n\t%s.x = ", latticeIdx, latticeIdx);
builder->appendTextureLookup(&noiseCode, samplers[0], xCoords.c_str(), kVec2f_GrSLType);
@@ -1071,7 +751,7 @@ void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder,
// Get permutation for x + 1
{
SkString xCoords("");
- xCoords.appendf("vec2(fract(%s.x + %s), 0.5)", noiseXY, inc8bit);
+ xCoords.appendf("vec2(%s.z, 0.5)", floorVal);
noiseCode.appendf("\n\t%s.y = ", latticeIdx);
builder->appendTextureLookup(&noiseCode, samplers[0], xCoords.c_str(), kVec2f_GrSLType);
@@ -1090,15 +770,13 @@ void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder,
#endif
// Get (x,y) coordinates with the permutated x
- noiseCode.appendf("\n\t%s = fract(%s + %s.yy);", latticeIdx, latticeIdx, noiseXY);
-
- noiseCode.appendf("\n\tvec2 %s = %s.zw;", fractVal, noiseXY);
+ noiseCode.appendf("\n\tvec4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal);
noiseCode.appendf("\n\n\tvec2 %s;", uv);
// Compute u, at offset (0,0)
{
SkString latticeCoords("");
- latticeCoords.appendf("vec2(%s.x, %s)", latticeIdx, chanCoord);
+ latticeCoords.appendf("vec2(%s.x, %s)", bcoords, chanCoord);
noiseCode.appendf("\n\tvec4 %s = ", lattice);
builder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(),
kVec2f_GrSLType);
@@ -1110,7 +788,7 @@ void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder,
// Compute v, at offset (-1,0)
{
SkString latticeCoords("");
- latticeCoords.appendf("vec2(%s.y, %s)", latticeIdx, chanCoord);
+ latticeCoords.appendf("vec2(%s.y, %s)", bcoords, chanCoord);
noiseCode.append("\n\tlattice = ");
builder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(),
kVec2f_GrSLType);
@@ -1126,7 +804,7 @@ void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder,
// Compute v, at offset (-1,-1)
{
SkString latticeCoords("");
- latticeCoords.appendf("vec2(fract(%s.y + %s), %s)", latticeIdx, inc8bit, chanCoord);
+ latticeCoords.appendf("vec2(%s.w, %s)", bcoords, chanCoord);
noiseCode.append("\n\tlattice = ");
builder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(),
kVec2f_GrSLType);
@@ -1138,7 +816,7 @@ void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder,
// Compute u, at offset (0,-1)
{
SkString latticeCoords("");
- latticeCoords.appendf("vec2(fract(%s.x + %s), %s)", latticeIdx, inc8bit, chanCoord);
+ latticeCoords.appendf("vec2(%s.z, %s)", bcoords, chanCoord);
noiseCode.append("\n\tlattice = ");
builder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(),
kVec2f_GrSLType);
@@ -1229,14 +907,7 @@ void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder,
outputColor, outputColor, outputColor, outputColor);
}
-GrGLNoise::GrGLNoise(const GrBackendEffectFactory& factory, const GrDrawEffect& drawEffect)
- : INHERITED (factory)
- , fType(drawEffect.castEffect<GrPerlinNoiseEffect>().type())
- , fStitchTiles(drawEffect.castEffect<GrPerlinNoiseEffect>().stitchTiles())
- , fNumOctaves(drawEffect.castEffect<GrPerlinNoiseEffect>().numOctaves()) {
-}
-
-GrGLEffect::EffectKey GrGLNoise::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
+GrGLEffect::EffectKey GrGLPerlinNoise::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
const GrPerlinNoiseEffect& turbulence = drawEffect.castEffect<GrPerlinNoiseEffect>();
EffectKey key = turbulence.numOctaves();
@@ -1262,7 +933,9 @@ GrGLEffect::EffectKey GrGLNoise::GenKey(const GrDrawEffect& drawEffect, const Gr
return key;
}
-void GrGLNoise::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) {
+void GrGLPerlinNoise::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) {
+ INHERITED::setData(uman, drawEffect);
+
const GrPerlinNoiseEffect& turbulence = drawEffect.castEffect<GrPerlinNoiseEffect>();
const SkVector& baseFrequency = turbulence.baseFrequency();
@@ -1278,12 +951,7 @@ void GrGLNoise::setData(const GrGLUniformManager& uman, const GrDrawEffect& draw
invM.postConcat(invM); // Square the matrix
}
uman.setSkMatrix(fInvMatrixUni, invM);
-}
-void GrGLPerlinNoise::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) {
- INHERITED::setData(uman, drawEffect);
-
- const GrPerlinNoiseEffect& turbulence = drawEffect.castEffect<GrPerlinNoiseEffect>();
if (turbulence.stitchTiles()) {
const SkPerlinNoiseShader::StitchData& stitchData = turbulence.stitchData();
uman.set2f(fStitchDataUni, SkIntToScalar(stitchData.fWidth),
@@ -1291,17 +959,19 @@ void GrGLPerlinNoise::setData(const GrGLUniformManager& uman, const GrDrawEffect
}
}
-void GrGLSimplexNoise::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) {
- INHERITED::setData(uman, drawEffect);
-
- const GrSimplexNoiseEffect& turbulence = drawEffect.castEffect<GrSimplexNoiseEffect>();
- uman.set1f(fSeedUni, turbulence.seed());
-}
-
/////////////////////////////////////////////////////////////////////
-GrEffectRef* SkPerlinNoiseShader::asNewEffect(GrContext* context, const SkPaint& paint) const {
+bool SkPerlinNoiseShader::asNewEffect(GrContext* context, const SkPaint& paint,
+ const SkMatrix* externalLocalMatrix, GrColor* grColor,
+ GrEffectRef** grEffect) const {
SkASSERT(NULL != context);
+
+ *grColor = SkColor2GrColorJustAlpha(paint.getColor());
+
+ SkMatrix localMatrix = this->getLocalMatrix();
+ if (externalLocalMatrix) {
+ localMatrix.preConcat(*externalLocalMatrix);
+ }
if (0 == fNumOctaves) {
SkColor clearColor = 0;
@@ -1310,31 +980,24 @@ GrEffectRef* SkPerlinNoiseShader::asNewEffect(GrContext* context, const SkPaint&
}
SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(
clearColor, SkXfermode::kSrc_Mode));
- return cf->asNewEffect(context);
+ *grEffect = cf->asNewEffect(context);
+ return true;
}
// Either we don't stitch tiles, either we have a valid tile size
SkASSERT(!fStitchTiles || !fTileSize.isEmpty());
-#ifdef SK_USE_SIMPLEX_NOISE
- // Simplex noise is currently disabled but can be enabled by defining SK_USE_SIMPLEX_NOISE
- sk_ignore_unused_variable(context);
- GrEffectRef* effect =
- GrSimplexNoiseEffect::Create(fType, fPaintingData->fBaseFrequency,
- fNumOctaves, fStitchTiles, fSeed,
- this->getLocalMatrix(), paint.getAlpha());
-#else
GrTexture* permutationsTexture = GrLockAndRefCachedBitmapTexture(
- context, *fPaintingData->getPermutationsBitmap(), NULL);
+ context, fPaintingData->getPermutationsBitmap(), NULL);
GrTexture* noiseTexture = GrLockAndRefCachedBitmapTexture(
- context, *fPaintingData->getNoiseBitmap(), NULL);
+ context, fPaintingData->getNoiseBitmap(), NULL);
- GrEffectRef* effect = (NULL != permutationsTexture) && (NULL != noiseTexture) ?
+ *grEffect = (NULL != permutationsTexture) && (NULL != noiseTexture) ?
GrPerlinNoiseEffect::Create(fType, fPaintingData->fBaseFrequency,
fNumOctaves, fStitchTiles,
fPaintingData->fStitchDataInit,
permutationsTexture, noiseTexture,
- this->getLocalMatrix(), paint.getAlpha()) :
+ localMatrix, paint.getAlpha()) :
NULL;
// Unlock immediately, this is not great, but we don't have a way of
@@ -1346,21 +1009,22 @@ GrEffectRef* SkPerlinNoiseShader::asNewEffect(GrContext* context, const SkPaint&
if (NULL != noiseTexture) {
GrUnlockAndUnrefCachedBitmapTexture(noiseTexture);
}
-#endif
- return effect;
+ return true;
}
#else
-GrEffectRef* SkPerlinNoiseShader::asNewEffect(GrContext*, const SkPaint&) const {
+bool SkPerlinNoiseShader::asNewEffect(GrContext* context, const SkPaint& paint,
+ const SkMatrix* externalLocalMatrix, GrColor* grColor,
+ GrEffectRef** grEffect) const {
SkDEBUGFAIL("Should not call in GPU-less build");
- return NULL;
+ return false;
}
#endif
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkPerlinNoiseShader::toString(SkString* str) const {
str->append("SkPerlinNoiseShader: (");
diff --git a/chromium/third_party/skia/src/effects/SkPictureImageFilter.cpp b/chromium/third_party/skia/src/effects/SkPictureImageFilter.cpp
index 5b4af6548c0..2d2df9231ea 100644
--- a/chromium/third_party/skia/src/effects/SkPictureImageFilter.cpp
+++ b/chromium/third_party/skia/src/effects/SkPictureImageFilter.cpp
@@ -8,21 +8,22 @@
#include "SkPictureImageFilter.h"
#include "SkDevice.h"
#include "SkCanvas.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkValidationUtils.h"
SkPictureImageFilter::SkPictureImageFilter(SkPicture* picture)
: INHERITED(0, 0),
fPicture(picture),
- fRect(SkRect::MakeWH(picture ? SkIntToScalar(picture->width()) : 0,
- picture ? SkIntToScalar(picture->height()) : 0)) {
+ fCropRect(SkRect::MakeWH(picture ? SkIntToScalar(picture->width()) : 0,
+ picture ? SkIntToScalar(picture->height()) : 0)) {
SkSafeRef(fPicture);
}
-SkPictureImageFilter::SkPictureImageFilter(SkPicture* picture, const SkRect& rect)
+SkPictureImageFilter::SkPictureImageFilter(SkPicture* picture, const SkRect& cropRect)
: INHERITED(0, 0),
fPicture(picture),
- fRect(rect) {
+ fCropRect(cropRect) {
SkSafeRef(fPicture);
}
@@ -30,31 +31,47 @@ SkPictureImageFilter::~SkPictureImageFilter() {
SkSafeUnref(fPicture);
}
-SkPictureImageFilter::SkPictureImageFilter(SkFlattenableReadBuffer& buffer)
+SkPictureImageFilter::SkPictureImageFilter(SkReadBuffer& buffer)
: INHERITED(0, buffer),
fPicture(NULL) {
- // FIXME: unflatten picture here.
- buffer.readRect(&fRect);
+ if (!buffer.isCrossProcess()) {
+ if (buffer.readBool()) {
+ fPicture = SkPicture::CreateFromBuffer(buffer);
+ }
+ } else {
+ buffer.validate(!buffer.readBool());
+ }
+ buffer.readRect(&fCropRect);
}
-void SkPictureImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkPictureImageFilter::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
- // FIXME: flatten picture here.
- buffer.writeRect(fRect);
+ if (!buffer.isCrossProcess()) {
+ bool hasPicture = (fPicture != NULL);
+ buffer.writeBool(hasPicture);
+ if (hasPicture) {
+ fPicture->flatten(buffer);
+ }
+ } else {
+ buffer.writeBool(false);
+ }
+ buffer.writeRect(fCropRect);
}
-bool SkPictureImageFilter::onFilterImage(Proxy* proxy, const SkBitmap&, const SkMatrix& matrix,
- SkBitmap* result, SkIPoint* offset) {
+bool SkPictureImageFilter::onFilterImage(Proxy* proxy, const SkBitmap&, const Context& ctx,
+ SkBitmap* result, SkIPoint* offset) const {
if (!fPicture) {
+ offset->fX = offset->fY = 0;
return true;
}
SkRect floatBounds;
SkIRect bounds;
- matrix.mapRect(&floatBounds, fRect);
+ ctx.ctm().mapRect(&floatBounds, fCropRect);
floatBounds.roundOut(&bounds);
if (bounds.isEmpty()) {
+ offset->fX = offset->fY = 0;
return true;
}
@@ -67,11 +84,18 @@ bool SkPictureImageFilter::onFilterImage(Proxy* proxy, const SkBitmap&, const Sk
SkPaint paint;
canvas.translate(-SkIntToScalar(bounds.fLeft), -SkIntToScalar(bounds.fTop));
- canvas.concat(matrix);
- canvas.drawPicture(*fPicture);
+ canvas.concat(ctx.ctm());
+ canvas.drawPicture(fPicture);
*result = device.get()->accessBitmap(false);
- offset->fX += bounds.fLeft;
- offset->fY += bounds.fTop;
+ offset->fX = bounds.fLeft;
+ offset->fY = bounds.fTop;
+ return true;
+}
+
+bool SkPictureImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
+ SkIRect* dst) const {
+ *dst = src;
return true;
}
+
diff --git a/chromium/third_party/skia/src/effects/SkPixelXorXfermode.cpp b/chromium/third_party/skia/src/effects/SkPixelXorXfermode.cpp
index b9c96dc382a..129f1823d5f 100644
--- a/chromium/third_party/skia/src/effects/SkPixelXorXfermode.cpp
+++ b/chromium/third_party/skia/src/effects/SkPixelXorXfermode.cpp
@@ -9,7 +9,8 @@
#include "SkPixelXorXfermode.h"
#include "SkColorPriv.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkString.h"
// we always return an opaque color, 'cause I don't know what to do with
@@ -20,17 +21,17 @@ SkPMColor SkPixelXorXfermode::xferColor(SkPMColor src, SkPMColor dst) const {
return res;
}
-void SkPixelXorXfermode::flatten(SkFlattenableWriteBuffer& wb) const {
+void SkPixelXorXfermode::flatten(SkWriteBuffer& wb) const {
this->INHERITED::flatten(wb);
wb.writeColor(fOpColor);
}
-SkPixelXorXfermode::SkPixelXorXfermode(SkFlattenableReadBuffer& rb)
+SkPixelXorXfermode::SkPixelXorXfermode(SkReadBuffer& rb)
: INHERITED(rb) {
fOpColor = rb.readColor();
}
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkPixelXorXfermode::toString(SkString* str) const {
str->append("SkPixelXorXfermode: ");
str->appendHex(fOpColor);
diff --git a/chromium/third_party/skia/src/effects/SkRectShaderImageFilter.cpp b/chromium/third_party/skia/src/effects/SkRectShaderImageFilter.cpp
index 5c34547cb3b..bed017c3260 100644
--- a/chromium/third_party/skia/src/effects/SkRectShaderImageFilter.cpp
+++ b/chromium/third_party/skia/src/effects/SkRectShaderImageFilter.cpp
@@ -9,7 +9,8 @@
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkDevice.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkShader.h"
SkRectShaderImageFilter* SkRectShaderImageFilter::Create(SkShader* s, const SkRect& rect) {
@@ -34,12 +35,12 @@ SkRectShaderImageFilter::SkRectShaderImageFilter(SkShader* s, const CropRect* cr
s->ref();
}
-SkRectShaderImageFilter::SkRectShaderImageFilter(SkFlattenableReadBuffer& buffer)
+SkRectShaderImageFilter::SkRectShaderImageFilter(SkReadBuffer& buffer)
: INHERITED(1, buffer) {
fShader = buffer.readShader();
}
-void SkRectShaderImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkRectShaderImageFilter::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeFlattenable(fShader);
@@ -51,12 +52,11 @@ SkRectShaderImageFilter::~SkRectShaderImageFilter() {
bool SkRectShaderImageFilter::onFilterImage(Proxy* proxy,
const SkBitmap& source,
- const SkMatrix& ctm,
+ const Context& ctx,
SkBitmap* result,
- SkIPoint* offset) {
+ SkIPoint* offset) const {
SkIRect bounds;
- source.getBounds(&bounds);
- if (!this->applyCropRect(&bounds, ctm)) {
+ if (!this->applyCropRect(ctx, source, SkIPoint::Make(0, 0), &bounds)) {
return false;
}
@@ -66,15 +66,17 @@ bool SkRectShaderImageFilter::onFilterImage(Proxy* proxy,
return false;
}
SkCanvas canvas(device.get());
+
SkPaint paint;
- paint.setShader(fShader);
- SkMatrix matrix;
- matrix.setTranslate(-SkIntToScalar(bounds.fLeft), -SkIntToScalar(bounds.fTop));
- fShader->setLocalMatrix(matrix);
+ SkMatrix matrix(ctx.ctm());
+ matrix.postTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
+ paint.setShader(SkShader::CreateLocalMatrixShader(fShader, matrix))->unref();
+
SkRect rect = SkRect::MakeWH(SkIntToScalar(bounds.width()), SkIntToScalar(bounds.height()));
canvas.drawRect(rect, paint);
+
*result = device.get()->accessBitmap(false);
- offset->fX += bounds.fLeft;
- offset->fY += bounds.fTop;
+ offset->fX = bounds.fLeft;
+ offset->fY = bounds.fTop;
return true;
}
diff --git a/chromium/third_party/skia/src/effects/SkStippleMaskFilter.cpp b/chromium/third_party/skia/src/effects/SkStippleMaskFilter.cpp
index 14f30ec6510..4aceb110662 100644
--- a/chromium/third_party/skia/src/effects/SkStippleMaskFilter.cpp
+++ b/chromium/third_party/skia/src/effects/SkStippleMaskFilter.cpp
@@ -45,7 +45,7 @@ bool SkStippleMaskFilter::filterMask(SkMask* dst,
return true;
}
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkStippleMaskFilter::toString(SkString* str) const {
str->append("SkStippleMaskFilter: ()");
}
diff --git a/chromium/third_party/skia/src/effects/SkTableColorFilter.cpp b/chromium/third_party/skia/src/effects/SkTableColorFilter.cpp
index e15baf69284..6a9ab107954 100644
--- a/chromium/third_party/skia/src/effects/SkTableColorFilter.cpp
+++ b/chromium/third_party/skia/src/effects/SkTableColorFilter.cpp
@@ -2,7 +2,8 @@
#include "SkBitmap.h"
#include "SkTableColorFilter.h"
#include "SkColorPriv.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkUnPreMultiply.h"
#include "SkString.h"
@@ -48,7 +49,7 @@ public:
virtual void filterSpan(const SkPMColor src[], int count,
SkPMColor dst[]) const SK_OVERRIDE;
- SkDEVCODE(virtual void toString(SkString* str) const SK_OVERRIDE;)
+ SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTable_ColorFilter)
@@ -60,8 +61,8 @@ public:
};
protected:
- SkTable_ColorFilter(SkFlattenableReadBuffer& buffer);
- virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+ SkTable_ColorFilter(SkReadBuffer& buffer);
+ virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
private:
mutable const SkBitmap* fBitmap; // lazily allocated
@@ -151,7 +152,7 @@ void SkTable_ColorFilter::filterSpan(const SkPMColor src[], int count,
}
}
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkTable_ColorFilter::toString(SkString* str) const {
str->append("SkTable_ColorFilter");
}
@@ -166,7 +167,7 @@ static const uint8_t gCountNibBits[] = {
#include "SkPackBits.h"
-void SkTable_ColorFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkTable_ColorFilter::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
uint8_t storage[5*256];
@@ -180,7 +181,7 @@ void SkTable_ColorFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
buffer.writeByteArray(storage, size);
}
-SkTable_ColorFilter::SkTable_ColorFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
+SkTable_ColorFilter::SkTable_ColorFilter(SkReadBuffer& buffer) : INHERITED(buffer) {
fBitmap = NULL;
uint8_t storage[5*256];
@@ -189,6 +190,7 @@ SkTable_ColorFilter::SkTable_ColorFilter(SkFlattenableReadBuffer& buffer) : INHE
size_t size = buffer.getArrayCount();
SkASSERT(size <= sizeof(storage));
+ buffer.validate(size <= sizeof(storage));
buffer.readByteArray(storage, size);
SkDEBUGCODE(size_t raw = ) SkPackBits::Unpack8(storage, size, fStorage);
@@ -202,8 +204,7 @@ bool SkTable_ColorFilter::asComponentTable(SkBitmap* table) const {
if (table) {
if (NULL == fBitmap) {
SkBitmap* bmp = SkNEW(SkBitmap);
- bmp->setConfig(SkBitmap::kA8_Config, 256, 4, 256);
- bmp->allocPixels();
+ bmp->allocPixels(SkImageInfo::MakeA8(256, 4));
uint8_t* bitmapPixels = bmp->getAddr8(0, 0);
int offset = 0;
static const unsigned kFlags[] = { kA_Flag, kR_Flag, kG_Flag, kB_Flag };
diff --git a/chromium/third_party/skia/src/effects/SkTableMaskFilter.cpp b/chromium/third_party/skia/src/effects/SkTableMaskFilter.cpp
index 8d3b81a3119..602302e503c 100644
--- a/chromium/third_party/skia/src/effects/SkTableMaskFilter.cpp
+++ b/chromium/third_party/skia/src/effects/SkTableMaskFilter.cpp
@@ -8,7 +8,8 @@
#include "SkTableMaskFilter.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkString.h"
SkTableMaskFilter::SkTableMaskFilter() {
@@ -69,12 +70,12 @@ SkMask::Format SkTableMaskFilter::getFormat() const {
return SkMask::kA8_Format;
}
-void SkTableMaskFilter::flatten(SkFlattenableWriteBuffer& wb) const {
+void SkTableMaskFilter::flatten(SkWriteBuffer& wb) const {
this->INHERITED::flatten(wb);
wb.writeByteArray(fTable, 256);
}
-SkTableMaskFilter::SkTableMaskFilter(SkFlattenableReadBuffer& rb)
+SkTableMaskFilter::SkTableMaskFilter(SkReadBuffer& rb)
: INHERITED(rb) {
SkASSERT(256 == rb.getArrayCount());
rb.readByteArray(fTable, 256);
@@ -107,7 +108,7 @@ void SkTableMaskFilter::MakeClipTable(uint8_t table[256], uint8_t min,
SkFixed scale = (1 << 16) * 255 / (max - min);
memset(table, 0, min + 1);
for (int i = min + 1; i < max; i++) {
- int value = SkFixedRound(scale * (i - min));
+ int value = SkFixedRoundToInt(scale * (i - min));
SkASSERT(value <= 255);
table[i] = value;
}
@@ -128,7 +129,7 @@ void SkTableMaskFilter::MakeClipTable(uint8_t table[256], uint8_t min,
#endif
}
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkTableMaskFilter::toString(SkString* str) const {
str->append("SkTableMaskFilter: (");
diff --git a/chromium/third_party/skia/src/effects/SkTestImageFilters.cpp b/chromium/third_party/skia/src/effects/SkTestImageFilters.cpp
index cc6d1adc430..da88316654a 100755
--- a/chromium/third_party/skia/src/effects/SkTestImageFilters.cpp
+++ b/chromium/third_party/skia/src/effects/SkTestImageFilters.cpp
@@ -2,7 +2,8 @@
#include "SkTestImageFilters.h"
#include "SkCanvas.h"
#include "SkDevice.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
// Simple helper canvas that "takes ownership" of the provided device, so that
// when this canvas goes out of scope, so will its device. Could be replaced
@@ -21,8 +22,8 @@ public:
///////////////////////////////////////////////////////////////////////////////
bool SkDownSampleImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
- const SkMatrix&,
- SkBitmap* result, SkIPoint*) {
+ const Context&,
+ SkBitmap* result, SkIPoint*) const {
SkScalar scale = fScale;
if (scale > SK_Scalar1 || scale <= 0) {
return false;
@@ -70,13 +71,13 @@ bool SkDownSampleImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
return true;
}
-void SkDownSampleImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkDownSampleImageFilter::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeScalar(fScale);
}
-SkDownSampleImageFilter::SkDownSampleImageFilter(SkFlattenableReadBuffer& buffer)
+SkDownSampleImageFilter::SkDownSampleImageFilter(SkReadBuffer& buffer)
: INHERITED(1, buffer) {
fScale = buffer.readScalar();
buffer.validate(SkScalarIsFinite(fScale));
diff --git a/chromium/third_party/skia/src/effects/SkTileImageFilter.cpp b/chromium/third_party/skia/src/effects/SkTileImageFilter.cpp
index 73e5304adb3..73c0a581e98 100644
--- a/chromium/third_party/skia/src/effects/SkTileImageFilter.cpp
+++ b/chromium/third_party/skia/src/effects/SkTileImageFilter.cpp
@@ -9,37 +9,44 @@
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkDevice.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkMatrix.h"
#include "SkPaint.h"
#include "SkShader.h"
#include "SkValidationUtils.h"
-bool SkTileImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
- SkBitmap* dst, SkIPoint* offset) {
+bool SkTileImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
+ const Context& ctx,
+ SkBitmap* dst, SkIPoint* offset) const {
SkBitmap source = src;
SkImageFilter* input = getInput(0);
- SkIPoint localOffset = SkIPoint::Make(0, 0);
- if (input && !input->filterImage(proxy, src, ctm, &source, &localOffset)) {
+ SkIPoint srcOffset = SkIPoint::Make(0, 0);
+ if (input && !input->filterImage(proxy, src, ctx, &source, &srcOffset)) {
return false;
}
SkRect dstRect;
- ctm.mapRect(&dstRect, fDstRect);
- int w = SkScalarCeilToInt(dstRect.width());
- int h = SkScalarCeilToInt(dstRect.height());
+ ctx.ctm().mapRect(&dstRect, fDstRect);
+ SkIRect dstIRect;
+ dstRect.roundOut(&dstIRect);
+ int w = dstIRect.width();
+ int h = dstIRect.height();
if (!fSrcRect.width() || !fSrcRect.height() || !w || !h) {
return false;
}
SkRect srcRect;
- ctm.mapRect(&srcRect, fSrcRect);
+ ctx.ctm().mapRect(&srcRect, fSrcRect);
SkIRect srcIRect;
srcRect.roundOut(&srcIRect);
+ srcIRect.offset(-srcOffset);
SkBitmap subset;
SkIRect bounds;
source.getBounds(&bounds);
+
if (!srcIRect.intersect(bounds)) {
+ offset->fX = offset->fY = 0;
return true;
} else if (!source.extractSubset(&subset, srcIRect)) {
return false;
@@ -53,23 +60,40 @@ bool SkTileImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, const S
SkPaint paint;
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+ SkMatrix shaderMatrix;
+ shaderMatrix.setTranslate(SkIntToScalar(srcOffset.fX),
+ SkIntToScalar(srcOffset.fY));
SkAutoTUnref<SkShader> shader(SkShader::CreateBitmapShader(subset,
- SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode));
+ SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode,
+ &shaderMatrix));
paint.setShader(shader);
- dstRect.offset(SkIntToScalar(localOffset.fX), SkIntToScalar(localOffset.fY));
+ canvas.translate(-dstRect.fLeft, -dstRect.fTop);
canvas.drawRect(dstRect, paint);
*dst = device->accessBitmap(false);
+ offset->fX = dstIRect.fLeft;
+ offset->fY = dstIRect.fTop;
+ return true;
+}
+
+bool SkTileImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
+ SkIRect* dst) const {
+ SkRect srcRect;
+ ctm.mapRect(&srcRect, fSrcRect);
+ SkIRect srcIRect;
+ srcRect.roundOut(&srcIRect);
+ srcIRect.join(src);
+ *dst = srcIRect;
return true;
}
-SkTileImageFilter::SkTileImageFilter(SkFlattenableReadBuffer& buffer)
+SkTileImageFilter::SkTileImageFilter(SkReadBuffer& buffer)
: INHERITED(1, buffer) {
buffer.readRect(&fSrcRect);
buffer.readRect(&fDstRect);
buffer.validate(buffer.isValid() && SkIsValidRect(fSrcRect) && SkIsValidRect(fDstRect));
}
-void SkTileImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkTileImageFilter::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeRect(fSrcRect);
buffer.writeRect(fDstRect);
diff --git a/chromium/third_party/skia/src/effects/SkTransparentShader.cpp b/chromium/third_party/skia/src/effects/SkTransparentShader.cpp
index 1d7e80877e1..f290d0dcf8d 100644
--- a/chromium/third_party/skia/src/effects/SkTransparentShader.cpp
+++ b/chromium/third_party/skia/src/effects/SkTransparentShader.cpp
@@ -11,26 +11,33 @@
#include "SkColorPriv.h"
#include "SkString.h"
-bool SkTransparentShader::setContext(const SkBitmap& device,
- const SkPaint& paint,
- const SkMatrix& matrix) {
- fDevice = &device;
- fAlpha = paint.getAlpha();
+SkShader::Context* SkTransparentShader::onCreateContext(const ContextRec& rec,
+ void* storage) const {
+ return SkNEW_PLACEMENT_ARGS(storage, TransparentShaderContext, (*this, rec));
+}
- return this->INHERITED::setContext(device, paint, matrix);
+size_t SkTransparentShader::contextSize() const {
+ return sizeof(TransparentShaderContext);
}
-uint32_t SkTransparentShader::getFlags() {
+SkTransparentShader::TransparentShaderContext::TransparentShaderContext(
+ const SkTransparentShader& shader, const ContextRec& rec)
+ : INHERITED(shader, rec)
+ , fDevice(rec.fDevice) {}
+
+SkTransparentShader::TransparentShaderContext::~TransparentShaderContext() {}
+
+uint32_t SkTransparentShader::TransparentShaderContext::getFlags() const {
uint32_t flags = this->INHERITED::getFlags();
- switch (fDevice->config()) {
- case SkBitmap::kRGB_565_Config:
+ switch (fDevice->colorType()) {
+ case kRGB_565_SkColorType:
flags |= kHasSpan16_Flag;
- if (fAlpha == 255)
+ if (this->getPaintAlpha() == 255)
flags |= kOpaqueAlpha_Flag;
break;
- case SkBitmap::kARGB_8888_Config:
- if (fAlpha == 255 && fDevice->isOpaque())
+ case kN32_SkColorType:
+ if (this->getPaintAlpha() == 255 && fDevice->isOpaque())
flags |= kOpaqueAlpha_Flag;
break;
default:
@@ -39,11 +46,12 @@ uint32_t SkTransparentShader::getFlags() {
return flags;
}
-void SkTransparentShader::shadeSpan(int x, int y, SkPMColor span[], int count) {
- unsigned scale = SkAlpha255To256(fAlpha);
+void SkTransparentShader::TransparentShaderContext::shadeSpan(int x, int y, SkPMColor span[],
+ int count) {
+ unsigned scale = SkAlpha255To256(this->getPaintAlpha());
- switch (fDevice->config()) {
- case SkBitmap::kARGB_8888_Config:
+ switch (fDevice->colorType()) {
+ case kN32_SkColorType:
if (scale == 256) {
SkPMColor* src = fDevice->getAddr32(x, y);
if (src != span) {
@@ -56,14 +64,14 @@ void SkTransparentShader::shadeSpan(int x, int y, SkPMColor span[], int count) {
}
}
break;
- case SkBitmap::kRGB_565_Config: {
+ case kRGB_565_SkColorType: {
const uint16_t* src = fDevice->getAddr16(x, y);
if (scale == 256) {
for (int i = count - 1; i >= 0; --i) {
span[i] = SkPixel16ToPixel32(src[i]);
}
} else {
- unsigned alpha = fAlpha;
+ unsigned alpha = this->getPaintAlpha();
for (int i = count - 1; i >= 0; --i) {
uint16_t c = src[i];
unsigned r = SkPacked16ToR32(c);
@@ -78,10 +86,7 @@ void SkTransparentShader::shadeSpan(int x, int y, SkPMColor span[], int count) {
}
break;
}
- case SkBitmap::kIndex8_Config:
- SkDEBUGFAIL("index8 not supported as a destination device");
- break;
- case SkBitmap::kA8_Config: {
+ case kAlpha_8_SkColorType: {
const uint8_t* src = fDevice->getAddr8(x, y);
if (scale == 256) {
for (int i = count - 1; i >= 0; --i) {
@@ -94,13 +99,15 @@ void SkTransparentShader::shadeSpan(int x, int y, SkPMColor span[], int count) {
}
break;
}
- default: // to avoid warnings
+ default:
+ SkDEBUGFAIL("colorType not supported as a destination device");
break;
}
}
-void SkTransparentShader::shadeSpan16(int x, int y, uint16_t span[], int count) {
- SkASSERT(fDevice->config() == SkBitmap::kRGB_565_Config);
+void SkTransparentShader::TransparentShaderContext::shadeSpan16(int x, int y, uint16_t span[],
+ int count) {
+ SkASSERT(fDevice->colorType() == kRGB_565_SkColorType);
uint16_t* src = fDevice->getAddr16(x, y);
if (src != span) {
@@ -108,7 +115,7 @@ void SkTransparentShader::shadeSpan16(int x, int y, uint16_t span[], int count)
}
}
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkTransparentShader::toString(SkString* str) const {
str->append("SkTransparentShader: (");
diff --git a/chromium/third_party/skia/src/effects/SkXfermodeImageFilter.cpp b/chromium/third_party/skia/src/effects/SkXfermodeImageFilter.cpp
index 4674ff44aba..acb8fd381b8 100644
--- a/chromium/third_party/skia/src/effects/SkXfermodeImageFilter.cpp
+++ b/chromium/third_party/skia/src/effects/SkXfermodeImageFilter.cpp
@@ -9,13 +9,13 @@
#include "SkCanvas.h"
#include "SkDevice.h"
#include "SkColorPriv.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkXfermode.h"
#if SK_SUPPORT_GPU
#include "GrContext.h"
#include "effects/GrSimpleTextureEffect.h"
#include "SkGr.h"
-#include "SkImageFilterUtils.h"
#endif
///////////////////////////////////////////////////////////////////////////////
@@ -32,42 +32,46 @@ SkXfermodeImageFilter::~SkXfermodeImageFilter() {
SkSafeUnref(fMode);
}
-SkXfermodeImageFilter::SkXfermodeImageFilter(SkFlattenableReadBuffer& buffer)
+SkXfermodeImageFilter::SkXfermodeImageFilter(SkReadBuffer& buffer)
: INHERITED(2, buffer) {
fMode = buffer.readXfermode();
}
-void SkXfermodeImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkXfermodeImageFilter::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeFlattenable(fMode);
}
bool SkXfermodeImageFilter::onFilterImage(Proxy* proxy,
const SkBitmap& src,
- const SkMatrix& ctm,
+ const Context& ctx,
SkBitmap* dst,
- SkIPoint* offset) {
+ SkIPoint* offset) const {
SkBitmap background = src, foreground = src;
SkImageFilter* backgroundInput = getInput(0);
SkImageFilter* foregroundInput = getInput(1);
SkIPoint backgroundOffset = SkIPoint::Make(0, 0);
if (backgroundInput &&
- !backgroundInput->filterImage(proxy, src, ctm, &background, &backgroundOffset)) {
- return false;
+ !backgroundInput->filterImage(proxy, src, ctx, &background, &backgroundOffset)) {
+ background.reset();
}
SkIPoint foregroundOffset = SkIPoint::Make(0, 0);
if (foregroundInput &&
- !foregroundInput->filterImage(proxy, src, ctm, &foreground, &foregroundOffset)) {
- return false;
+ !foregroundInput->filterImage(proxy, src, ctx, &foreground, &foregroundOffset)) {
+ foreground.reset();
}
SkIRect bounds, foregroundBounds;
- background.getBounds(&bounds);
- bounds.offset(backgroundOffset);
- foreground.getBounds(&foregroundBounds);
- foregroundBounds.offset(foregroundOffset);
+ if (!applyCropRect(ctx, foreground, foregroundOffset, &foregroundBounds)) {
+ foregroundBounds.setEmpty();
+ foreground.reset();
+ }
+ if (!applyCropRect(ctx, background, backgroundOffset, &bounds)) {
+ bounds.setEmpty();
+ background.reset();
+ }
bounds.join(foregroundBounds);
- if (!applyCropRect(&bounds, ctm)) {
+ if (bounds.isEmpty()) {
return false;
}
@@ -88,30 +92,34 @@ bool SkXfermodeImageFilter::onFilterImage(Proxy* proxy,
paint.setColor(SK_ColorTRANSPARENT);
canvas.drawPaint(paint);
*dst = device->accessBitmap(false);
- offset->fX += bounds.left();
- offset->fY += bounds.top();
+ offset->fX = bounds.left();
+ offset->fY = bounds.top();
return true;
}
#if SK_SUPPORT_GPU
+bool SkXfermodeImageFilter::canFilterImageGPU() const {
+ return fMode && fMode->asNewEffect(NULL, NULL) && !cropRectIsSet();
+}
+
bool SkXfermodeImageFilter::filterImageGPU(Proxy* proxy,
const SkBitmap& src,
- const SkMatrix& ctm,
+ const Context& ctx,
SkBitmap* result,
- SkIPoint* offset) {
- SkBitmap background;
+ SkIPoint* offset) const {
+ SkBitmap background = src;
SkIPoint backgroundOffset = SkIPoint::Make(0, 0);
- if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &background,
- &backgroundOffset)) {
- return false;
+ if (getInput(0) && !getInput(0)->getInputResultGPU(proxy, src, ctx, &background,
+ &backgroundOffset)) {
+ return onFilterImage(proxy, src, ctx, result, offset);
}
GrTexture* backgroundTex = background.getTexture();
- SkBitmap foreground;
+ SkBitmap foreground = src;
SkIPoint foregroundOffset = SkIPoint::Make(0, 0);
- if (!SkImageFilterUtils::GetInputResultGPU(getInput(1), proxy, src, ctm, &foreground,
- &foregroundOffset)) {
- return false;
+ if (getInput(1) && !getInput(1)->getInputResultGPU(proxy, src, ctx, &foreground,
+ &foregroundOffset)) {
+ return onFilterImage(proxy, src, ctx, result, offset);
}
GrTexture* foregroundTex = foreground.getTexture();
GrContext* context = foregroundTex->getContext();
@@ -129,8 +137,9 @@ bool SkXfermodeImageFilter::filterImageGPU(Proxy* proxy,
GrContext::AutoRenderTarget art(context, dst->asRenderTarget());
- SkXfermode::Coeff sm, dm;
- if (!SkXfermode::AsNewEffectOrCoeff(fMode, &xferEffect, &sm, &dm, backgroundTex)) {
+ if (!fMode || !fMode->asNewEffect(&xferEffect, backgroundTex)) {
+ // canFilterImageGPU() should've taken care of this
+ SkASSERT(false);
return false;
}
@@ -141,25 +150,16 @@ bool SkXfermodeImageFilter::filterImageGPU(Proxy* proxy,
SkRect srcRect;
src.getBounds(&srcRect);
- if (NULL != xferEffect) {
- GrPaint paint;
- paint.addColorTextureEffect(foregroundTex, foregroundMatrix);
- paint.addColorEffect(xferEffect)->unref();
- context->drawRect(paint, srcRect);
- } else {
- GrPaint backgroundPaint;
- SkMatrix backgroundMatrix = GrEffect::MakeDivByTextureWHMatrix(backgroundTex);
- backgroundPaint.addColorTextureEffect(backgroundTex, backgroundMatrix);
- context->drawRect(backgroundPaint, srcRect);
-
- GrPaint foregroundPaint;
- foregroundPaint.setBlendFunc(sk_blend_to_grblend(sm), sk_blend_to_grblend(dm));
- foregroundPaint.addColorTextureEffect(foregroundTex, foregroundMatrix);
- context->drawRect(foregroundPaint, srcRect);
- }
- offset->fX += backgroundOffset.fX;
- offset->fY += backgroundOffset.fY;
- return SkImageFilterUtils::WrapTexture(dst, src.width(), src.height(), result);
+
+ GrPaint paint;
+ paint.addColorTextureEffect(foregroundTex, foregroundMatrix);
+ paint.addColorEffect(xferEffect)->unref();
+ context->drawRect(paint, srcRect);
+
+ offset->fX = backgroundOffset.fX;
+ offset->fY = backgroundOffset.fY;
+ WrapTexture(dst, src.width(), src.height(), result);
+ return true;
}
#endif
diff --git a/chromium/third_party/skia/src/effects/gradients/SkClampRange.cpp b/chromium/third_party/skia/src/effects/gradients/SkClampRange.cpp
index 3e2ca8e9320..398b02434fd 100644
--- a/chromium/third_party/skia/src/effects/gradients/SkClampRange.cpp
+++ b/chromium/third_party/skia/src/effects/gradients/SkClampRange.cpp
@@ -50,7 +50,6 @@ void SkClampRange::init(SkFixed fx0, SkFixed dx0, int count, int v0, int v1) {
fV0 = v0;
fV1 = v1;
- fOverflowed = false;
// special case 1 == count, as it is slightly common for skia
// and avoids us ever calling divide or 64bit multiply
@@ -63,7 +62,6 @@ void SkClampRange::init(SkFixed fx0, SkFixed dx0, int count, int v0, int v1) {
int64_t dx = dx0;
// start with ex equal to the last computed value
int64_t ex = fx + (count - 1) * dx;
- fOverflowed = overflows_fixed(ex);
if ((uint64_t)(fx | ex) <= 0xFFFF) {
fCount0 = fCount2 = 0;
@@ -86,9 +84,8 @@ void SkClampRange::init(SkFixed fx0, SkFixed dx0, int count, int v0, int v1) {
// now make ex be 1 past the last computed value
ex += dx;
- fOverflowed = overflows_fixed(ex);
// now check for over/under flow
- if (fOverflowed) {
+ if (overflows_fixed(ex)) {
int originalCount = count;
int64_t ccount;
bool swap = dx < 0;
diff --git a/chromium/third_party/skia/src/effects/gradients/SkClampRange.h b/chromium/third_party/skia/src/effects/gradients/SkClampRange.h
index 376dc93b4bd..09386d7e71b 100644
--- a/chromium/third_party/skia/src/effects/gradients/SkClampRange.h
+++ b/chromium/third_party/skia/src/effects/gradients/SkClampRange.h
@@ -27,7 +27,6 @@ struct SkClampRange {
SkFixed fFx1; // initial fx value for the fCount1 range.
// only valid if fCount1 > 0
int fV0, fV1;
- bool fOverflowed; // true if we had to clamp due to numerical overflow
void init(SkFixed fx, SkFixed dx, int count, int v0, int v1);
diff --git a/chromium/third_party/skia/src/effects/gradients/SkGradientShader.cpp b/chromium/third_party/skia/src/effects/gradients/SkGradientShader.cpp
index 5d200d18d35..038044d5618 100644
--- a/chromium/third_party/skia/src/effects/gradients/SkGradientShader.cpp
+++ b/chromium/third_party/skia/src/effects/gradients/SkGradientShader.cpp
@@ -12,24 +12,18 @@
#include "SkTwoPointConicalGradient.h"
#include "SkSweepGradient.h"
-SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc) {
+SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc, const SkMatrix* localMatrix)
+ : INHERITED(localMatrix)
+{
SkASSERT(desc.fCount > 1);
- fCacheAlpha = 256; // init to a value that paint.getAlpha() can't return
-
- fMapper = desc.fMapper;
- SkSafeRef(fMapper);
- fGradFlags = SkToU8(desc.fFlags);
+ fGradFlags = SkToU8(desc.fGradFlags);
SkASSERT((unsigned)desc.fTileMode < SkShader::kTileModeCount);
SkASSERT(SkShader::kTileModeCount == SK_ARRAY_COUNT(gTileProcs));
fTileMode = desc.fTileMode;
fTileProc = gTileProcs[desc.fTileMode];
- fCache16 = fCache16Storage = NULL;
- fCache32 = NULL;
- fCache32PixelRef = NULL;
-
/* Note: we let the caller skip the first and/or last position.
i.e. pos[0] = 0.3, pos[1] = 0.7
In these cases, we insert dummy entries to ensure that the final data
@@ -118,12 +112,14 @@ SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc) {
SkFixed dp = SK_Fixed1 / (desc.fCount - 1);
SkFixed p = dp;
SkFixed scale = (desc.fCount - 1) << 8; // (1 << 24) / dp
- for (int i = 1; i < desc.fCount; i++) {
+ for (int i = 1; i < desc.fCount - 1; i++) {
recs->fPos = p;
recs->fScale = scale;
recs += 1;
p += dp;
}
+ recs->fPos = SK_Fixed1;
+ recs->fScale = scale;
}
}
this->initCommon();
@@ -143,19 +139,21 @@ static uint32_t unpack_flags(uint32_t packed) {
return packed >> 4;
}
-SkGradientShaderBase::SkGradientShaderBase(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
- fCacheAlpha = 256;
-
- fMapper = buffer.readUnitMapper();
-
- fCache16 = fCache16Storage = NULL;
- fCache32 = NULL;
- fCache32PixelRef = NULL;
+SkGradientShaderBase::SkGradientShaderBase(SkReadBuffer& buffer) : INHERITED(buffer) {
+ if (buffer.isVersionLT(SkReadBuffer::kNoUnitMappers_Version)) {
+ // skip the old SkUnitMapper slot
+ buffer.skipFlattenable();
+ }
int colorCount = fColorCount = buffer.getArrayCount();
if (colorCount > kColorStorageCount) {
- size_t size = sizeof(SkColor) + sizeof(SkPMColor) + sizeof(Rec);
- fOrigColors = (SkColor*)sk_malloc_throw(size * colorCount);
+ size_t allocSize = (sizeof(SkColor) + sizeof(SkPMColor) + sizeof(Rec)) * colorCount;
+ if (buffer.validateAvailable(allocSize)) {
+ fOrigColors = reinterpret_cast<SkColor*>(sk_malloc_throw(allocSize));
+ } else {
+ fOrigColors = NULL;
+ colorCount = fColorCount = 0;
+ }
} else {
fOrigColors = fStorage;
}
@@ -181,18 +179,12 @@ SkGradientShaderBase::SkGradientShaderBase(SkFlattenableReadBuffer& buffer) : IN
}
SkGradientShaderBase::~SkGradientShaderBase() {
- if (fCache16Storage) {
- sk_free(fCache16Storage);
- }
- SkSafeUnref(fCache32PixelRef);
if (fOrigColors != fStorage) {
sk_free(fOrigColors);
}
- SkSafeUnref(fMapper);
}
void SkGradientShaderBase::initCommon() {
- fFlags = 0;
unsigned colorAlpha = 0xFF;
for (int i = 0; i < fColorCount; i++) {
colorAlpha &= SkColorGetA(fOrigColors[i]);
@@ -200,9 +192,8 @@ void SkGradientShaderBase::initCommon() {
fColorsAreOpaque = colorAlpha == 0xFF;
}
-void SkGradientShaderBase::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkGradientShaderBase::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
- buffer.writeFlattenable(fMapper);
buffer.writeColorArray(fOrigColors, fColorCount);
buffer.writeUInt(pack_mode_flags(fTileMode, fGradFlags));
if (fColorCount > 2) {
@@ -215,58 +206,94 @@ void SkGradientShaderBase::flatten(SkFlattenableWriteBuffer& buffer) const {
buffer.writeMatrix(fPtsToUnit);
}
-bool SkGradientShaderBase::isOpaque() const {
- return fColorsAreOpaque;
+SkGradientShaderBase::GpuColorType SkGradientShaderBase::getGpuColorType(SkColor colors[3]) const {
+ if (fColorCount <= 3) {
+ memcpy(colors, fOrigColors, fColorCount * sizeof(SkColor));
+ }
+
+ if (SkShader::kClamp_TileMode == fTileMode) {
+ if (2 == fColorCount) {
+ return kTwo_GpuColorType;
+ } else if (3 == fColorCount &&
+ (SkScalarAbs(
+ SkFixedToScalar(fRecs[1].fPos) - SK_ScalarHalf) < SK_Scalar1 / 1000)) {
+ return kThree_GpuColorType;
+ }
+ }
+ return kTexture_GpuColorType;
}
-bool SkGradientShaderBase::setContext(const SkBitmap& device,
- const SkPaint& paint,
- const SkMatrix& matrix) {
- if (!this->INHERITED::setContext(device, paint, matrix)) {
- return false;
+void SkGradientShaderBase::FlipGradientColors(SkColor* colorDst, Rec* recDst,
+ SkColor* colorSrc, Rec* recSrc,
+ int count) {
+ SkAutoSTArray<8, SkColor> colorsTemp(count);
+ for (int i = 0; i < count; ++i) {
+ int offset = count - i - 1;
+ colorsTemp[i] = colorSrc[offset];
+ }
+ if (count > 2) {
+ SkAutoSTArray<8, Rec> recsTemp(count);
+ for (int i = 0; i < count; ++i) {
+ int offset = count - i - 1;
+ recsTemp[i].fPos = SK_Fixed1 - recSrc[offset].fPos;
+ recsTemp[i].fScale = recSrc[offset].fScale;
+ }
+ memcpy(recDst, recsTemp.get(), count * sizeof(Rec));
}
+ memcpy(colorDst, colorsTemp.get(), count * sizeof(SkColor));
+}
+
+void SkGradientShaderBase::flipGradientColors() {
+ FlipGradientColors(fOrigColors, fRecs, fOrigColors, fRecs, fColorCount);
+}
+
+bool SkGradientShaderBase::isOpaque() const {
+ return fColorsAreOpaque;
+}
+SkGradientShaderBase::GradientShaderBaseContext::GradientShaderBaseContext(
+ const SkGradientShaderBase& shader, const ContextRec& rec)
+ : INHERITED(shader, rec)
+ , fCache(shader.refCache(getPaintAlpha()))
+{
const SkMatrix& inverse = this->getTotalInverse();
- if (!fDstToIndex.setConcat(fPtsToUnit, inverse)) {
- // need to keep our set/end context calls balanced.
- this->INHERITED::endContext();
- return false;
- }
+ fDstToIndex.setConcat(shader.fPtsToUnit, inverse);
fDstToIndexProc = fDstToIndex.getMapXYProc();
- fDstToIndexClass = (uint8_t)SkShader::ComputeMatrixClass(fDstToIndex);
+ fDstToIndexClass = (uint8_t)SkShader::Context::ComputeMatrixClass(fDstToIndex);
// now convert our colors in to PMColors
unsigned paintAlpha = this->getPaintAlpha();
fFlags = this->INHERITED::getFlags();
- if (fColorsAreOpaque && paintAlpha == 0xFF) {
+ if (shader.fColorsAreOpaque && paintAlpha == 0xFF) {
fFlags |= kOpaqueAlpha_Flag;
}
// we can do span16 as long as our individual colors are opaque,
// regardless of the paint's alpha
- if (fColorsAreOpaque) {
+ if (shader.fColorsAreOpaque) {
fFlags |= kHasSpan16_Flag;
}
+}
- this->setCacheAlpha(paintAlpha);
- return true;
+SkGradientShaderBase::GradientShaderCache::GradientShaderCache(
+ U8CPU alpha, const SkGradientShaderBase& shader)
+ : fCacheAlpha(alpha)
+ , fShader(shader)
+ , fCache16Inited(false)
+ , fCache32Inited(false)
+{
+ // Only initialize the cache in getCache16/32.
+ fCache16 = NULL;
+ fCache32 = NULL;
+ fCache16Storage = NULL;
+ fCache32PixelRef = NULL;
}
-void SkGradientShaderBase::setCacheAlpha(U8CPU alpha) const {
- // if the new alpha differs from the previous time we were called, inval our cache
- // this will trigger the cache to be rebuilt.
- // we don't care about the first time, since the cache ptrs will already be NULL
- if (fCacheAlpha != alpha) {
- fCache16 = NULL; // inval the cache
- fCache32 = NULL; // inval the cache
- fCacheAlpha = alpha; // record the new alpha
- // inform our subclasses
- if (fCache32PixelRef) {
- fCache32PixelRef->notifyPixelsChanged();
- }
- }
+SkGradientShaderBase::GradientShaderCache::~GradientShaderCache() {
+ sk_free(fCache16Storage);
+ SkSafeUnref(fCache32PixelRef);
}
#define Fixed_To_Dot8(x) (((x) + 0x80) >> 8)
@@ -275,8 +302,8 @@ void SkGradientShaderBase::setCacheAlpha(U8CPU alpha) const {
build a 16bit table as long as the original colors are opaque, even if the
paint specifies a non-opaque alpha.
*/
-void SkGradientShaderBase::Build16bitCache(uint16_t cache[], SkColor c0, SkColor c1,
- int count) {
+void SkGradientShaderBase::GradientShaderCache::Build16bitCache(
+ uint16_t cache[], SkColor c0, SkColor c1, int count) {
SkASSERT(count > 1);
SkASSERT(SkColorGetA(c0) == 0xFF);
SkASSERT(SkColorGetA(c1) == 0xFF);
@@ -324,8 +351,9 @@ void SkGradientShaderBase::Build16bitCache(uint16_t cache[], SkColor c0, SkColor
*/
typedef uint32_t SkUFixed;
-void SkGradientShaderBase::Build32bitCache(SkPMColor cache[], SkColor c0, SkColor c1,
- int count, U8CPU paintAlpha, uint32_t gradFlags) {
+void SkGradientShaderBase::GradientShaderCache::Build32bitCache(
+ SkPMColor cache[], SkColor c0, SkColor c1,
+ int count, U8CPU paintAlpha, uint32_t gradFlags) {
SkASSERT(count > 1);
// need to apply paintAlpha to our two endpoints
@@ -456,109 +484,90 @@ static inline int SkFixedToFFFF(SkFixed x) {
return x - (x >> 16);
}
-static inline U16CPU bitsTo16(unsigned x, const unsigned bits) {
- SkASSERT(x < (1U << bits));
- if (6 == bits) {
- return (x << 10) | (x << 4) | (x >> 2);
- }
- if (8 == bits) {
- return (x << 8) | x;
- }
- sk_throw();
- return 0;
+const uint16_t* SkGradientShaderBase::GradientShaderCache::getCache16() {
+ SkOnce(&fCache16Inited, &fCache16Mutex, SkGradientShaderBase::GradientShaderCache::initCache16,
+ this);
+ SkASSERT(fCache16);
+ return fCache16;
}
-const uint16_t* SkGradientShaderBase::getCache16() const {
- if (fCache16 == NULL) {
- // double the count for dither entries
- const int entryCount = kCache16Count * 2;
- const size_t allocSize = sizeof(uint16_t) * entryCount;
-
- if (fCache16Storage == NULL) { // set the storage and our working ptr
- fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize);
- }
- fCache16 = fCache16Storage;
- if (fColorCount == 2) {
- Build16bitCache(fCache16, fOrigColors[0], fOrigColors[1],
- kCache16Count);
- } else {
- Rec* rec = fRecs;
- int prevIndex = 0;
- for (int i = 1; i < fColorCount; i++) {
- int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache16Shift;
- SkASSERT(nextIndex < kCache16Count);
-
- if (nextIndex > prevIndex)
- Build16bitCache(fCache16 + prevIndex, fOrigColors[i-1], fOrigColors[i], nextIndex - prevIndex + 1);
- prevIndex = nextIndex;
- }
- }
-
- if (fMapper) {
- fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize);
- uint16_t* linear = fCache16; // just computed linear data
- uint16_t* mapped = fCache16Storage; // storage for mapped data
- SkUnitMapper* map = fMapper;
- for (int i = 0; i < kCache16Count; i++) {
- int index = map->mapUnit16(bitsTo16(i, kCache16Bits)) >> kCache16Shift;
- mapped[i] = linear[index];
- mapped[i + kCache16Count] = linear[index + kCache16Count];
- }
- sk_free(fCache16);
- fCache16 = fCache16Storage;
+void SkGradientShaderBase::GradientShaderCache::initCache16(GradientShaderCache* cache) {
+ // double the count for dither entries
+ const int entryCount = kCache16Count * 2;
+ const size_t allocSize = sizeof(uint16_t) * entryCount;
+
+ SkASSERT(NULL == cache->fCache16Storage);
+ cache->fCache16Storage = (uint16_t*)sk_malloc_throw(allocSize);
+ cache->fCache16 = cache->fCache16Storage;
+ if (cache->fShader.fColorCount == 2) {
+ Build16bitCache(cache->fCache16, cache->fShader.fOrigColors[0],
+ cache->fShader.fOrigColors[1], kCache16Count);
+ } else {
+ Rec* rec = cache->fShader.fRecs;
+ int prevIndex = 0;
+ for (int i = 1; i < cache->fShader.fColorCount; i++) {
+ int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache16Shift;
+ SkASSERT(nextIndex < kCache16Count);
+
+ if (nextIndex > prevIndex)
+ Build16bitCache(cache->fCache16 + prevIndex, cache->fShader.fOrigColors[i-1],
+ cache->fShader.fOrigColors[i], nextIndex - prevIndex + 1);
+ prevIndex = nextIndex;
}
}
- return fCache16;
}
-const SkPMColor* SkGradientShaderBase::getCache32() const {
- if (fCache32 == NULL) {
- SkImageInfo info;
- info.fWidth = kCache32Count;
- info.fHeight = 4; // for our 4 dither rows
- info.fAlphaType = kPremul_SkAlphaType;
- info.fColorType = kPMColor_SkColorType;
+const SkPMColor* SkGradientShaderBase::GradientShaderCache::getCache32() {
+ SkOnce(&fCache32Inited, &fCache32Mutex, SkGradientShaderBase::GradientShaderCache::initCache32,
+ this);
+ SkASSERT(fCache32);
+ return fCache32;
+}
- if (NULL == fCache32PixelRef) {
- fCache32PixelRef = SkMallocPixelRef::NewAllocate(info, 0, NULL);
- }
- fCache32 = (SkPMColor*)fCache32PixelRef->getAddr();
- if (fColorCount == 2) {
- Build32bitCache(fCache32, fOrigColors[0], fOrigColors[1],
- kCache32Count, fCacheAlpha, fGradFlags);
- } else {
- Rec* rec = fRecs;
- int prevIndex = 0;
- for (int i = 1; i < fColorCount; i++) {
- int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache32Shift;
- SkASSERT(nextIndex < kCache32Count);
-
- if (nextIndex > prevIndex)
- Build32bitCache(fCache32 + prevIndex, fOrigColors[i-1],
- fOrigColors[i], nextIndex - prevIndex + 1,
- fCacheAlpha, fGradFlags);
- prevIndex = nextIndex;
- }
+void SkGradientShaderBase::GradientShaderCache::initCache32(GradientShaderCache* cache) {
+ SkImageInfo info;
+ info.fWidth = kCache32Count;
+ info.fHeight = 4; // for our 4 dither rows
+ info.fAlphaType = kPremul_SkAlphaType;
+ info.fColorType = kN32_SkColorType;
+
+ SkASSERT(NULL == cache->fCache32PixelRef);
+ cache->fCache32PixelRef = SkMallocPixelRef::NewAllocate(info, 0, NULL);
+ cache->fCache32 = (SkPMColor*)cache->fCache32PixelRef->getAddr();
+ if (cache->fShader.fColorCount == 2) {
+ Build32bitCache(cache->fCache32, cache->fShader.fOrigColors[0],
+ cache->fShader.fOrigColors[1], kCache32Count, cache->fCacheAlpha,
+ cache->fShader.fGradFlags);
+ } else {
+ Rec* rec = cache->fShader.fRecs;
+ int prevIndex = 0;
+ for (int i = 1; i < cache->fShader.fColorCount; i++) {
+ int nextIndex = SkFixedToFFFF(rec[i].fPos) >> kCache32Shift;
+ SkASSERT(nextIndex < kCache32Count);
+
+ if (nextIndex > prevIndex)
+ Build32bitCache(cache->fCache32 + prevIndex, cache->fShader.fOrigColors[i-1],
+ cache->fShader.fOrigColors[i], nextIndex - prevIndex + 1,
+ cache->fCacheAlpha, cache->fShader.fGradFlags);
+ prevIndex = nextIndex;
}
+ }
+}
- if (fMapper) {
- SkMallocPixelRef* newPR = SkMallocPixelRef::NewAllocate(info, 0, NULL);
- SkPMColor* linear = fCache32; // just computed linear data
- SkPMColor* mapped = (SkPMColor*)newPR->getAddr(); // storage for mapped data
- SkUnitMapper* map = fMapper;
- for (int i = 0; i < kCache32Count; i++) {
- int index = map->mapUnit16((i << 8) | i) >> 8;
- mapped[i + kCache32Count*0] = linear[index + kCache32Count*0];
- mapped[i + kCache32Count*1] = linear[index + kCache32Count*1];
- mapped[i + kCache32Count*2] = linear[index + kCache32Count*2];
- mapped[i + kCache32Count*3] = linear[index + kCache32Count*3];
- }
- fCache32PixelRef->unref();
- fCache32PixelRef = newPR;
- fCache32 = (SkPMColor*)newPR->getAddr();
- }
+/*
+ * The gradient holds a cache for the most recent value of alpha. Successive
+ * callers with the same alpha value will share the same cache.
+ */
+SkGradientShaderBase::GradientShaderCache* SkGradientShaderBase::refCache(U8CPU alpha) const {
+ SkAutoMutexAcquire ama(fCacheMutex);
+ if (!fCache || fCache->getAlpha() != alpha) {
+ fCache.reset(SkNEW_ARGS(GradientShaderCache, (alpha, *this)));
}
- return fCache32;
+ // Increment the ref counter inside the mutex to ensure the returned pointer is still valid.
+ // Otherwise, the pointer may have been overwritten on a different thread before the object's
+ // ref count was incremented.
+ fCache.get()->ref();
+ return fCache;
}
/*
@@ -572,16 +581,7 @@ const SkPMColor* SkGradientShaderBase::getCache32() const {
void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const {
// our caller assumes no external alpha, so we ensure that our cache is
// built with 0xFF
- this->setCacheAlpha(0xFF);
-
- // don't have a way to put the mapper into our cache-key yet
- if (fMapper) {
- // force our cahce32pixelref to be built
- (void)this->getCache32();
- bitmap->setConfig(SkBitmap::kARGB_8888_Config, kCache32Count, 1);
- bitmap->setPixelRef(fCache32PixelRef);
- return;
- }
+ SkAutoTUnref<GradientShaderCache> cache(this->refCache(0xFF));
// build our key: [numColors + colors[] + {positions[]} + flags ]
int count = 1 + fColorCount + 1;
@@ -618,19 +618,31 @@ void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const {
if (!gCache->find(storage.get(), size, bitmap)) {
// force our cahce32pixelref to be built
- (void)this->getCache32();
- bitmap->setConfig(SkBitmap::kARGB_8888_Config, kCache32Count, 1);
- bitmap->setPixelRef(fCache32PixelRef);
+ (void)cache->getCache32();
+ bitmap->setInfo(SkImageInfo::MakeN32Premul(kCache32Count, 1));
+ bitmap->setPixelRef(cache->getCache32PixelRef());
gCache->add(storage.get(), size, *bitmap);
}
}
-void SkGradientShaderBase::commonAsAGradient(GradientInfo* info) const {
+void SkGradientShaderBase::commonAsAGradient(GradientInfo* info, bool flipGrad) const {
if (info) {
if (info->fColorCount >= fColorCount) {
+ SkColor* colorLoc;
+ Rec* recLoc;
+ if (flipGrad && (info->fColors || info->fColorOffsets)) {
+ SkAutoSTArray<8, SkColor> colorStorage(fColorCount);
+ SkAutoSTArray<8, Rec> recStorage(fColorCount);
+ colorLoc = colorStorage.get();
+ recLoc = recStorage.get();
+ FlipGradientColors(colorLoc, recLoc, fOrigColors, fRecs, fColorCount);
+ } else {
+ colorLoc = fOrigColors;
+ recLoc = fRecs;
+ }
if (info->fColors) {
- memcpy(info->fColors, fOrigColors, fColorCount * sizeof(SkColor));
+ memcpy(info->fColors, colorLoc, fColorCount * sizeof(SkColor));
}
if (info->fColorOffsets) {
if (fColorCount == 2) {
@@ -638,7 +650,7 @@ void SkGradientShaderBase::commonAsAGradient(GradientInfo* info) const {
info->fColorOffsets[1] = SK_Scalar1;
} else if (fColorCount > 2) {
for (int i = 0; i < fColorCount; ++i) {
- info->fColorOffsets[i] = SkFixedToScalar(fRecs[i].fPos);
+ info->fColorOffsets[i] = SkFixedToScalar(recLoc[i].fPos);
}
}
}
@@ -649,7 +661,7 @@ void SkGradientShaderBase::commonAsAGradient(GradientInfo* info) const {
}
}
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkGradientShaderBase::toString(SkString* str) const {
str->appendf("%d colors: ", fColorCount);
@@ -679,8 +691,6 @@ void SkGradientShaderBase::toString(SkString* str) const {
str->append(" ");
str->append(gTileModeName[fTileMode]);
- // TODO: add "fMapper->toString(str);" when SkUnitMapper::toString is added
-
this->INHERITED::toString(str);
}
#endif
@@ -705,46 +715,44 @@ void SkGradientShaderBase::toString(SkString* str) const {
static void desc_init(SkGradientShaderBase::Descriptor* desc,
const SkColor colors[],
const SkScalar pos[], int colorCount,
- SkShader::TileMode mode,
- SkUnitMapper* mapper, uint32_t flags) {
- desc->fColors = colors;
- desc->fPos = pos;
- desc->fCount = colorCount;
- desc->fTileMode = mode;
- desc->fMapper = mapper;
- desc->fFlags = flags;
+ SkShader::TileMode mode, uint32_t flags) {
+ desc->fColors = colors;
+ desc->fPos = pos;
+ desc->fCount = colorCount;
+ desc->fTileMode = mode;
+ desc->fGradFlags = flags;
}
SkShader* SkGradientShader::CreateLinear(const SkPoint pts[2],
const SkColor colors[],
const SkScalar pos[], int colorCount,
SkShader::TileMode mode,
- SkUnitMapper* mapper,
- uint32_t flags) {
+ uint32_t flags,
+ const SkMatrix* localMatrix) {
if (NULL == pts || NULL == colors || colorCount < 1) {
return NULL;
}
EXPAND_1_COLOR(colorCount);
SkGradientShaderBase::Descriptor desc;
- desc_init(&desc, colors, pos, colorCount, mode, mapper, flags);
- return SkNEW_ARGS(SkLinearGradient, (pts, desc));
+ desc_init(&desc, colors, pos, colorCount, mode, flags);
+ return SkNEW_ARGS(SkLinearGradient, (pts, desc, localMatrix));
}
SkShader* SkGradientShader::CreateRadial(const SkPoint& center, SkScalar radius,
const SkColor colors[],
const SkScalar pos[], int colorCount,
SkShader::TileMode mode,
- SkUnitMapper* mapper,
- uint32_t flags) {
+ uint32_t flags,
+ const SkMatrix* localMatrix) {
if (radius <= 0 || NULL == colors || colorCount < 1) {
return NULL;
}
EXPAND_1_COLOR(colorCount);
SkGradientShaderBase::Descriptor desc;
- desc_init(&desc, colors, pos, colorCount, mode, mapper, flags);
- return SkNEW_ARGS(SkRadialGradient, (center, radius, desc));
+ desc_init(&desc, colors, pos, colorCount, mode, flags);
+ return SkNEW_ARGS(SkRadialGradient, (center, radius, desc, localMatrix));
}
SkShader* SkGradientShader::CreateTwoPointRadial(const SkPoint& start,
@@ -755,17 +763,17 @@ SkShader* SkGradientShader::CreateTwoPointRadial(const SkPoint& start,
const SkScalar pos[],
int colorCount,
SkShader::TileMode mode,
- SkUnitMapper* mapper,
- uint32_t flags) {
+ uint32_t flags,
+ const SkMatrix* localMatrix) {
if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) {
return NULL;
}
EXPAND_1_COLOR(colorCount);
SkGradientShaderBase::Descriptor desc;
- desc_init(&desc, colors, pos, colorCount, mode, mapper, flags);
+ desc_init(&desc, colors, pos, colorCount, mode, flags);
return SkNEW_ARGS(SkTwoPointRadialGradient,
- (start, startRadius, end, endRadius, desc));
+ (start, startRadius, end, endRadius, desc, localMatrix));
}
SkShader* SkGradientShader::CreateTwoPointConical(const SkPoint& start,
@@ -776,35 +784,60 @@ SkShader* SkGradientShader::CreateTwoPointConical(const SkPoint& start,
const SkScalar pos[],
int colorCount,
SkShader::TileMode mode,
- SkUnitMapper* mapper,
- uint32_t flags) {
+ uint32_t flags,
+ const SkMatrix* localMatrix) {
if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) {
return NULL;
}
if (start == end && startRadius == endRadius) {
return SkNEW(SkEmptyShader);
}
+
EXPAND_1_COLOR(colorCount);
+ bool flipGradient = startRadius > endRadius;
+
SkGradientShaderBase::Descriptor desc;
- desc_init(&desc, colors, pos, colorCount, mode, mapper, flags);
- return SkNEW_ARGS(SkTwoPointConicalGradient,
- (start, startRadius, end, endRadius, desc));
+
+ if (!flipGradient) {
+ desc_init(&desc, colors, pos, colorCount, mode, flags);
+ return SkNEW_ARGS(SkTwoPointConicalGradient,
+ (start, startRadius, end, endRadius, flipGradient, desc, localMatrix));
+ } else {
+ SkAutoSTArray<8, SkColor> colorsNew(colorCount);
+ SkAutoSTArray<8, SkScalar> posNew(colorCount);
+ for (int i = 0; i < colorCount; ++i) {
+ colorsNew[i] = colors[colorCount - i - 1];
+ }
+
+ if (pos) {
+ for (int i = 0; i < colorCount; ++i) {
+ posNew[i] = 1 - pos[colorCount - i - 1];
+ }
+ desc_init(&desc, colorsNew.get(), posNew.get(), colorCount, mode, flags);
+ } else {
+ desc_init(&desc, colorsNew.get(), NULL, colorCount, mode, flags);
+ }
+
+ return SkNEW_ARGS(SkTwoPointConicalGradient,
+ (end, endRadius, start, startRadius, flipGradient, desc, localMatrix));
+ }
}
SkShader* SkGradientShader::CreateSweep(SkScalar cx, SkScalar cy,
const SkColor colors[],
const SkScalar pos[],
- int colorCount, SkUnitMapper* mapper,
- uint32_t flags) {
+ int colorCount,
+ uint32_t flags,
+ const SkMatrix* localMatrix) {
if (NULL == colors || colorCount < 1) {
return NULL;
}
EXPAND_1_COLOR(colorCount);
SkGradientShaderBase::Descriptor desc;
- desc_init(&desc, colors, pos, colorCount, SkShader::kClamp_TileMode, mapper, flags);
- return SkNEW_ARGS(SkSweepGradient, (cx, cy, desc));
+ desc_init(&desc, colors, pos, colorCount, SkShader::kClamp_TileMode, flags);
+ return SkNEW_ARGS(SkSweepGradient, (cx, cy, desc, localMatrix));
}
SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkGradientShader)
@@ -832,13 +865,13 @@ GrGLGradientEffect::~GrGLGradientEffect() { }
void GrGLGradientEffect::emitUniforms(GrGLShaderBuilder* builder, EffectKey key) {
- if (GrGradientEffect::kTwo_ColorType == ColorTypeFromKey(key)) { // 2 Color case
+ if (SkGradientShaderBase::kTwo_GpuColorType == ColorTypeFromKey(key)) { // 2 Color case
fColorStartUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
kVec4f_GrSLType, "GradientStartColor");
fColorEndUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
kVec4f_GrSLType, "GradientEndColor");
- } else if (GrGradientEffect::kThree_ColorType == ColorTypeFromKey(key)){ // 3 Color Case
+ } else if (SkGradientShaderBase::kThree_GpuColorType == ColorTypeFromKey(key)){ // 3 Color Case
fColorStartUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
kVec4f_GrSLType, "GradientStartColor");
fColorMidUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
@@ -880,7 +913,7 @@ void GrGLGradientEffect::setData(const GrGLUniformManager& uman,
const GrGradientEffect& e = drawEffect.castEffect<GrGradientEffect>();
- if (GrGradientEffect::kTwo_ColorType == e.getColorType()){
+ if (SkGradientShaderBase::kTwo_GpuColorType == e.getColorType()){
if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
set_mul_color_uni(uman, fColorStartUni, e.getColors(0));
@@ -890,7 +923,7 @@ void GrGLGradientEffect::setData(const GrGLUniformManager& uman,
set_color_uni(uman, fColorEndUni, e.getColors(1));
}
- } else if (GrGradientEffect::kThree_ColorType == e.getColorType()){
+ } else if (SkGradientShaderBase::kThree_GpuColorType == e.getColorType()){
if (GrGradientEffect::kBeforeInterp_PremulType == e.getPremulType()) {
set_mul_color_uni(uman, fColorStartUni, e.getColors(0));
@@ -917,9 +950,9 @@ GrGLEffect::EffectKey GrGLGradientEffect::GenBaseGradientKey(const GrDrawEffect&
EffectKey key = 0;
- if (GrGradientEffect::kTwo_ColorType == e.getColorType()) {
+ if (SkGradientShaderBase::kTwo_GpuColorType == e.getColorType()) {
key |= kTwoColorKey;
- } else if (GrGradientEffect::kThree_ColorType == e.getColorType()){
+ } else if (SkGradientShaderBase::kThree_GpuColorType == e.getColorType()){
key |= kThreeColorKey;
}
@@ -936,7 +969,7 @@ void GrGLGradientEffect::emitColor(GrGLShaderBuilder* builder,
const char* outputColor,
const char* inputColor,
const TextureSamplerArray& samplers) {
- if (GrGradientEffect::kTwo_ColorType == ColorTypeFromKey(key)){
+ if (SkGradientShaderBase::kTwo_GpuColorType == ColorTypeFromKey(key)){
builder->fsCodeAppendf("\tvec4 colorTemp = mix(%s, %s, clamp(%s, 0.0, 1.0));\n",
builder->getUniformVariable(fColorStartUni).c_str(),
builder->getUniformVariable(fColorEndUni).c_str(),
@@ -952,7 +985,7 @@ void GrGLGradientEffect::emitColor(GrGLShaderBuilder* builder,
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
(GrGLSLExpr4(inputColor) * GrGLSLExpr4("colorTemp")).c_str());
- } else if (GrGradientEffect::kThree_ColorType == ColorTypeFromKey(key)){
+ } else if (SkGradientShaderBase::kThree_GpuColorType == ColorTypeFromKey(key)){
builder->fsCodeAppendf("\tfloat oneMinus2t = 1.0 - (2.0 * (%s));\n",
gradientTValue);
builder->fsCodeAppendf("\tvec4 colorTemp = clamp(oneMinus2t, 0.0, 1.0) * %s;\n",
@@ -997,30 +1030,14 @@ GrGradientEffect::GrGradientEffect(GrContext* ctx,
fIsOpaque = shader.isOpaque();
- SkShader::GradientInfo info;
- SkScalar pos[3] = {0};
-
- info.fColorCount = 3;
- info.fColors = &fColors[0];
- info.fColorOffsets = &pos[0];
- shader.asAGradient(&info);
+ fColorType = shader.getGpuColorType(&fColors[0]);
// The two and three color specializations do not currently support tiling.
- bool foundSpecialCase = false;
- if (SkShader::kClamp_TileMode == info.fTileMode) {
- if (2 == info.fColorCount) {
- fRow = -1; // flag for no atlas
- fColorType = kTwo_ColorType;
- foundSpecialCase = true;
- } else if (3 == info.fColorCount &&
- (SkScalarAbs(pos[1] - SK_ScalarHalf) < SK_Scalar1 / 1000)) { // 3 color symmetric
- fRow = -1; // flag for no atlas
- fColorType = kThree_ColorType;
- foundSpecialCase = true;
- }
- }
- if (foundSpecialCase) {
- if (SkGradientShader::kInterpolateColorsInPremul_Flag & info.fGradientFlags) {
+ if (SkGradientShaderBase::kTwo_GpuColorType == fColorType ||
+ SkGradientShaderBase::kThree_GpuColorType == fColorType) {
+ fRow = -1;
+
+ if (SkGradientShader::kInterpolateColorsInPremul_Flag & shader.getGradFlags()) {
fPremulType = kBeforeInterp_PremulType;
} else {
fPremulType = kAfterInterp_PremulType;
@@ -1031,14 +1048,13 @@ GrGradientEffect::GrGradientEffect(GrContext* ctx,
fPremulType = kBeforeInterp_PremulType;
SkBitmap bitmap;
shader.getGradientTableBitmap(&bitmap);
- fColorType = kTexture_ColorType;
GrTextureStripAtlas::Desc desc;
desc.fWidth = bitmap.width();
desc.fHeight = 32;
desc.fRowHeight = bitmap.height();
desc.fContext = ctx;
- desc.fConfig = SkBitmapConfig2GrPixelConfig(bitmap.config());
+ desc.fConfig = SkImageInfo2GrPixelConfig(bitmap.info());
fAtlas = GrTextureStripAtlas::GetAtlas(desc);
SkASSERT(NULL != fAtlas);
@@ -1080,12 +1096,12 @@ bool GrGradientEffect::onIsEqual(const GrEffect& effect) const {
if (this->fColorType == s.getColorType()){
- if (kTwo_ColorType == fColorType) {
+ if (SkGradientShaderBase::kTwo_GpuColorType == fColorType) {
if (*this->getColors(0) != *s.getColors(0) ||
*this->getColors(1) != *s.getColors(1)) {
return false;
}
- } else if (kThree_ColorType == fColorType) {
+ } else if (SkGradientShaderBase::kThree_GpuColorType == fColorType) {
if (*this->getColors(0) != *s.getColors(0) ||
*this->getColors(1) != *s.getColors(1) ||
*this->getColors(2) != *s.getColors(2)) {
diff --git a/chromium/third_party/skia/src/effects/gradients/SkGradientShaderPriv.h b/chromium/third_party/skia/src/effects/gradients/SkGradientShaderPriv.h
index f45b7773ead..96135378032 100644
--- a/chromium/third_party/skia/src/effects/gradients/SkGradientShaderPriv.h
+++ b/chromium/third_party/skia/src/effects/gradients/SkGradientShaderPriv.h
@@ -11,13 +11,14 @@
#include "SkGradientShader.h"
#include "SkClampRange.h"
#include "SkColorPriv.h"
-#include "SkFlattenableBuffers.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkMallocPixelRef.h"
-#include "SkUnitMapper.h"
#include "SkUtils.h"
#include "SkTemplates.h"
#include "SkBitmapCache.h"
#include "SkShader.h"
+#include "SkOnce.h"
static inline void sk_memset32_dither(uint32_t dst[], uint32_t v0, uint32_t v1,
int count) {
@@ -92,16 +93,69 @@ public:
const SkScalar* fPos;
int fCount;
SkShader::TileMode fTileMode;
- SkUnitMapper* fMapper;
- uint32_t fFlags;
+ uint32_t fGradFlags;
};
public:
- SkGradientShaderBase(const Descriptor& desc);
+ SkGradientShaderBase(const Descriptor& desc, const SkMatrix* localMatrix);
virtual ~SkGradientShaderBase();
- virtual bool setContext(const SkBitmap&, const SkPaint&, const SkMatrix&) SK_OVERRIDE;
- virtual uint32_t getFlags() SK_OVERRIDE { return fFlags; }
+ // The cache is initialized on-demand when getCache16/32 is called.
+ class GradientShaderCache : public SkRefCnt {
+ public:
+ GradientShaderCache(U8CPU alpha, const SkGradientShaderBase& shader);
+ ~GradientShaderCache();
+
+ const uint16_t* getCache16();
+ const SkPMColor* getCache32();
+
+ SkMallocPixelRef* getCache32PixelRef() const { return fCache32PixelRef; }
+
+ unsigned getAlpha() const { return fCacheAlpha; }
+
+ private:
+ // Working pointers. If either is NULL, we need to recompute the corresponding cache values.
+ uint16_t* fCache16;
+ SkPMColor* fCache32;
+
+ uint16_t* fCache16Storage; // Storage for fCache16, allocated on demand.
+ SkMallocPixelRef* fCache32PixelRef;
+ const unsigned fCacheAlpha; // The alpha value we used when we computed the cache.
+ // Larger than 8bits so we can store uninitialized
+ // value.
+
+ const SkGradientShaderBase& fShader;
+
+ // Make sure we only initialize the caches once.
+ bool fCache16Inited, fCache32Inited;
+ SkMutex fCache16Mutex, fCache32Mutex;
+
+ static void initCache16(GradientShaderCache* cache);
+ static void initCache32(GradientShaderCache* cache);
+
+ static void Build16bitCache(uint16_t[], SkColor c0, SkColor c1, int count);
+ static void Build32bitCache(SkPMColor[], SkColor c0, SkColor c1, int count,
+ U8CPU alpha, uint32_t gradFlags);
+ };
+
+ class GradientShaderBaseContext : public SkShader::Context {
+ public:
+ GradientShaderBaseContext(const SkGradientShaderBase& shader, const ContextRec&);
+
+ virtual uint32_t getFlags() const SK_OVERRIDE { return fFlags; }
+
+ protected:
+ SkMatrix fDstToIndex;
+ SkMatrix::MapXYProc fDstToIndexProc;
+ uint8_t fDstToIndexClass;
+ uint8_t fFlags;
+
+ SkAutoTUnref<GradientShaderCache> fCache;
+
+ private:
+ typedef SkShader::Context INHERITED;
+ };
+
virtual bool isOpaque() const SK_OVERRIDE;
void getGradientTableBitmap(SkBitmap*) const;
@@ -127,21 +181,28 @@ public:
kDitherStride16 = kCache16Count,
};
+ enum GpuColorType {
+ kTwo_GpuColorType,
+ kThree_GpuColorType, // Symmetric three color
+ kTexture_GpuColorType
+ };
+
+ // Determines and returns the gradient is a two color gradient, symmetric three color gradient
+ // or other (texture gradient). If it is two or symmetric three color, the colors array will
+ // also be filled with the gradient colors
+ GpuColorType getGpuColorType(SkColor colors[3]) const;
+
+ uint32_t getGradFlags() const { return fGradFlags; }
protected:
- SkGradientShaderBase(SkFlattenableReadBuffer& );
- virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
- SK_DEVELOPER_TO_STRING()
+ SkGradientShaderBase(SkReadBuffer& );
+ virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
+ SK_TO_STRING_OVERRIDE()
- SkUnitMapper* fMapper;
SkMatrix fPtsToUnit; // set by subclass
- SkMatrix fDstToIndex;
- SkMatrix::MapXYProc fDstToIndexProc;
TileMode fTileMode;
TileProc fTileProc;
int fColorCount;
- uint8_t fDstToIndexClass;
- uint8_t fFlags;
uint8_t fGradFlags;
struct Rec {
@@ -150,10 +211,23 @@ protected:
};
Rec* fRecs;
- const uint16_t* getCache16() const;
- const SkPMColor* getCache32() const;
+ void commonAsAGradient(GradientInfo*, bool flipGrad = false) const;
+
+ /*
+ * Takes in pointers to gradient color and Rec info as colorSrc and recSrc respectively.
+ * Count is the number of colors in the gradient
+ * It will then flip all the color and rec information and return in their respective Dst
+ * pointers. It is assumed that space has already been allocated for the Dst pointers.
+ * The rec src and dst are only assumed to be valid if count > 2
+ */
+ static void FlipGradientColors(SkColor* colorDst, Rec* recDst,
+ SkColor* colorSrc, Rec* recSrc,
+ int count);
- void commonAsAGradient(GradientInfo*) const;
+ // V23_COMPATIBILITY_CODE
+ // Used for 2-pt conical gradients since we sort start/end cirlces by radius
+ // Assumes space has already been allocated for fOrigColors
+ void flipGradientColors();
private:
enum {
@@ -162,20 +236,13 @@ private:
kStorageSize = kColorStorageCount * (sizeof(SkColor) + sizeof(Rec))
};
SkColor fStorage[(kStorageSize + 3) >> 2];
- SkColor* fOrigColors; // original colors, before modulation by paint in setContext
+ SkColor* fOrigColors; // original colors, before modulation by paint in context.
bool fColorsAreOpaque;
- mutable uint16_t* fCache16; // working ptr. If this is NULL, we need to recompute the cache values
- mutable SkPMColor* fCache32; // working ptr. If this is NULL, we need to recompute the cache values
-
- mutable uint16_t* fCache16Storage; // storage for fCache16, allocated on demand
- mutable SkMallocPixelRef* fCache32PixelRef;
- mutable unsigned fCacheAlpha; // the alpha value we used when we computed the cache. larger than 8bits so we can store uninitialized value
+ GradientShaderCache* refCache(U8CPU alpha) const;
+ mutable SkMutex fCacheMutex;
+ mutable SkAutoTUnref<GradientShaderCache> fCache;
- static void Build16bitCache(uint16_t[], SkColor c0, SkColor c1, int count);
- static void Build32bitCache(SkPMColor[], SkColor c0, SkColor c1, int count,
- U8CPU alpha, uint32_t gradFlags);
- void setCacheAlpha(U8CPU alpha) const;
void initCommon();
typedef SkShader INHERITED;
@@ -250,13 +317,7 @@ public:
virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
- enum ColorType {
- kTwo_ColorType,
- kThree_ColorType,
- kTexture_ColorType
- };
-
- ColorType getColorType() const { return fColorType; }
+ SkGradientShaderBase::GpuColorType getColorType() const { return fColorType; }
enum PremulType {
kBeforeInterp_PremulType,
@@ -266,7 +327,7 @@ public:
PremulType getPremulType() const { return fPremulType; }
const SkColor* getColors(int pos) const {
- SkASSERT(fColorType != kTexture_ColorType);
+ SkASSERT(fColorType != SkGradientShaderBase::kTexture_GpuColorType);
SkASSERT((pos-1) <= fColorType);
return &fColors[pos];
}
@@ -293,18 +354,14 @@ protected:
private:
static const GrCoordSet kCoordSet = kLocal_GrCoordSet;
- enum {
- kMaxAnalyticColors = 3 // if more colors use texture
- };
-
GrCoordTransform fCoordTransform;
GrTextureAccess fTextureAccess;
SkScalar fYCoord;
GrTextureStripAtlas* fAtlas;
int fRow;
bool fIsOpaque;
- ColorType fColorType;
- SkColor fColors[kMaxAnalyticColors];
+ SkGradientShaderBase::GpuColorType fColorType;
+ SkColor fColors[3]; // More than 3 colors we use texture
PremulType fPremulType; // This only changes behavior for two and three color special cases.
// It is already baked into to the table for texture gradients.
typedef GrEffect INHERITED;
@@ -337,12 +394,12 @@ protected:
kBaseKeyBitCnt = (kPremulTypeKeyBitCnt + kColorKeyBitCnt)
};
- static GrGradientEffect::ColorType ColorTypeFromKey(EffectKey key){
+ static SkGradientShaderBase::GpuColorType ColorTypeFromKey(EffectKey key){
if (kTwoColorKey == (key & kColorKeyMask)) {
- return GrGradientEffect::kTwo_ColorType;
+ return SkGradientShaderBase::kTwo_GpuColorType;
} else if (kThreeColorKey == (key & kColorKeyMask)) {
- return GrGradientEffect::kThree_ColorType;
- } else {return GrGradientEffect::kTexture_ColorType;}
+ return SkGradientShaderBase::kThree_GpuColorType;
+ } else {return SkGradientShaderBase::kTexture_GpuColorType;}
}
static GrGradientEffect::PremulType PremulTypeFromKey(EffectKey key){
diff --git a/chromium/third_party/skia/src/effects/gradients/SkLinearGradient.cpp b/chromium/third_party/skia/src/effects/gradients/SkLinearGradient.cpp
index 5563a03f7e1..72b9d4792f5 100644
--- a/chromium/third_party/skia/src/effects/gradients/SkLinearGradient.cpp
+++ b/chromium/third_party/skia/src/effects/gradients/SkLinearGradient.cpp
@@ -52,42 +52,48 @@ static void pts_to_unit_matrix(const SkPoint pts[2], SkMatrix* matrix) {
///////////////////////////////////////////////////////////////////////////////
-SkLinearGradient::SkLinearGradient(const SkPoint pts[2], const Descriptor& desc)
- : SkGradientShaderBase(desc)
+SkLinearGradient::SkLinearGradient(const SkPoint pts[2], const Descriptor& desc,
+ const SkMatrix* localMatrix)
+ : SkGradientShaderBase(desc, localMatrix)
, fStart(pts[0])
, fEnd(pts[1]) {
pts_to_unit_matrix(pts, &fPtsToUnit);
}
-SkLinearGradient::SkLinearGradient(SkFlattenableReadBuffer& buffer)
+SkLinearGradient::SkLinearGradient(SkReadBuffer& buffer)
: INHERITED(buffer)
, fStart(buffer.readPoint())
, fEnd(buffer.readPoint()) {
}
-void SkLinearGradient::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkLinearGradient::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writePoint(fStart);
buffer.writePoint(fEnd);
}
-bool SkLinearGradient::setContext(const SkBitmap& device, const SkPaint& paint,
- const SkMatrix& matrix) {
- if (!this->INHERITED::setContext(device, paint, matrix)) {
- return false;
- }
+size_t SkLinearGradient::contextSize() const {
+ return sizeof(LinearGradientContext);
+}
+SkShader::Context* SkLinearGradient::onCreateContext(const ContextRec& rec, void* storage) const {
+ return SkNEW_PLACEMENT_ARGS(storage, LinearGradientContext, (*this, rec));
+}
+
+SkLinearGradient::LinearGradientContext::LinearGradientContext(
+ const SkLinearGradient& shader, const ContextRec& rec)
+ : INHERITED(shader, rec)
+{
unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
if ((fDstToIndex.getType() & ~mask) == 0) {
// when we dither, we are (usually) not const-in-Y
- if ((fFlags & SkShader::kHasSpan16_Flag) && !paint.isDither()) {
+ if ((fFlags & SkShader::kHasSpan16_Flag) && !rec.fPaint->isDither()) {
// only claim this if we do have a 16bit mode (i.e. none of our
// colors have alpha), and if we are not dithering (which obviously
// is not const in Y).
fFlags |= SkShader::kConstInY16_Flag;
}
}
- return true;
}
#define NO_CHECK_ITER \
@@ -196,14 +202,16 @@ void shadeSpan_linear_repeat(TileProc proc, SkFixed dx, SkFixed fx,
}
-void SkLinearGradient::shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC,
- int count) {
+void SkLinearGradient::LinearGradientContext::shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC,
+ int count) {
SkASSERT(count > 0);
+ const SkLinearGradient& linearGradient = static_cast<const SkLinearGradient&>(fShader);
+
SkPoint srcPt;
SkMatrix::MapXYProc dstProc = fDstToIndexProc;
- TileProc proc = fTileProc;
- const SkPMColor* SK_RESTRICT cache = this->getCache32();
+ TileProc proc = linearGradient.fTileProc;
+ const SkPMColor* SK_RESTRICT cache = fCache->getCache32();
int toggle = init_dither_toggle(x, y);
if (fDstToIndexClass != kPerspective_MatrixClass) {
@@ -223,12 +231,12 @@ void SkLinearGradient::shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC,
LinearShadeProc shadeProc = shadeSpan_linear_repeat;
if (0 == dx) {
shadeProc = shadeSpan_linear_vertical_lerp;
- } else if (SkShader::kClamp_TileMode == fTileMode) {
+ } else if (SkShader::kClamp_TileMode == linearGradient.fTileMode) {
shadeProc = shadeSpan_linear_clamp;
- } else if (SkShader::kMirror_TileMode == fTileMode) {
+ } else if (SkShader::kMirror_TileMode == linearGradient.fTileMode) {
shadeProc = shadeSpan_linear_mirror;
} else {
- SkASSERT(SkShader::kRepeat_TileMode == fTileMode);
+ SkASSERT(SkShader::kRepeat_TileMode == linearGradient.fTileMode);
}
(*shadeProc)(proc, dx, fx, dstC, cache, toggle, count);
} else {
@@ -377,14 +385,20 @@ void shadeSpan16_linear_repeat(TileProc proc, SkFixed dx, SkFixed fx,
}
}
-void SkLinearGradient::shadeSpan16(int x, int y,
- uint16_t* SK_RESTRICT dstC, int count) {
+static bool fixed_nearly_zero(SkFixed x) {
+ return SkAbs32(x) < (SK_Fixed1 >> 12);
+}
+
+void SkLinearGradient::LinearGradientContext::shadeSpan16(int x, int y,
+ uint16_t* SK_RESTRICT dstC, int count) {
SkASSERT(count > 0);
+ const SkLinearGradient& linearGradient = static_cast<const SkLinearGradient&>(fShader);
+
SkPoint srcPt;
SkMatrix::MapXYProc dstProc = fDstToIndexProc;
- TileProc proc = fTileProc;
- const uint16_t* SK_RESTRICT cache = this->getCache16();
+ TileProc proc = linearGradient.fTileProc;
+ const uint16_t* SK_RESTRICT cache = fCache->getCache16();
int toggle = init_dither_toggle16(x, y);
if (fDstToIndexClass != kPerspective_MatrixClass) {
@@ -402,14 +416,14 @@ void SkLinearGradient::shadeSpan16(int x, int y,
}
LinearShade16Proc shadeProc = shadeSpan16_linear_repeat;
- if (SkFixedNearlyZero(dx)) {
+ if (fixed_nearly_zero(dx)) {
shadeProc = shadeSpan16_linear_vertical;
- } else if (SkShader::kClamp_TileMode == fTileMode) {
+ } else if (SkShader::kClamp_TileMode == linearGradient.fTileMode) {
shadeProc = shadeSpan16_linear_clamp;
- } else if (SkShader::kMirror_TileMode == fTileMode) {
+ } else if (SkShader::kMirror_TileMode == linearGradient.fTileMode) {
shadeProc = shadeSpan16_linear_mirror;
} else {
- SkASSERT(SkShader::kRepeat_TileMode == fTileMode);
+ SkASSERT(SkShader::kRepeat_TileMode == linearGradient.fTileMode);
}
(*shadeProc)(proc, dx, fx, dstC, cache, toggle, count);
} else {
@@ -432,6 +446,7 @@ void SkLinearGradient::shadeSpan16(int x, int y,
#if SK_SUPPORT_GPU
#include "GrTBackendEffectFactory.h"
+#include "SkGr.h"
/////////////////////////////////////////////////////////////////////
@@ -513,7 +528,10 @@ GrEffectRef* GrLinearGradient::TestCreate(SkRandom* random,
colors, stops, colorCount,
tm));
SkPaint paint;
- return shader->asNewEffect(context, paint);
+ GrColor grColor;
+ GrEffectRef* effect;
+ shader->asNewEffect(context, paint, NULL, &grColor, &effect);
+ return effect;
}
/////////////////////////////////////////////////////////////////////
@@ -533,26 +551,42 @@ void GrGLLinearGradient::emitCode(GrGLShaderBuilder* builder,
/////////////////////////////////////////////////////////////////////
-GrEffectRef* SkLinearGradient::asNewEffect(GrContext* context, const SkPaint&) const {
+bool SkLinearGradient::asNewEffect(GrContext* context, const SkPaint& paint,
+ const SkMatrix* localMatrix, GrColor* grColor,
+ GrEffectRef** grEffect) const {
SkASSERT(NULL != context);
+
SkMatrix matrix;
if (!this->getLocalMatrix().invert(&matrix)) {
- return NULL;
+ return false;
+ }
+ if (localMatrix) {
+ SkMatrix inv;
+ if (!localMatrix->invert(&inv)) {
+ return false;
+ }
+ matrix.postConcat(inv);
}
matrix.postConcat(fPtsToUnit);
- return GrLinearGradient::Create(context, *this, matrix, fTileMode);
+
+ *grColor = SkColor2GrColorJustAlpha(paint.getColor());
+ *grEffect = GrLinearGradient::Create(context, *this, matrix, fTileMode);
+
+ return true;
}
#else
-GrEffectRef* SkLinearGradient::asNewEffect(GrContext*, const SkPaint&) const {
+bool SkLinearGradient::asNewEffect(GrContext* context, const SkPaint& paint,
+ const SkMatrix* localMatrix, GrColor* grColor,
+ GrEffectRef** grEffect) const {
SkDEBUGFAIL("Should not call in GPU-less build");
- return NULL;
+ return false;
}
#endif
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkLinearGradient::toString(SkString* str) const {
str->append("SkLinearGradient (");
diff --git a/chromium/third_party/skia/src/effects/gradients/SkLinearGradient.h b/chromium/third_party/skia/src/effects/gradients/SkLinearGradient.h
index 24c6caba7b3..f412a6897d2 100644
--- a/chromium/third_party/skia/src/effects/gradients/SkLinearGradient.h
+++ b/chromium/third_party/skia/src/effects/gradients/SkLinearGradient.h
@@ -1,4 +1,3 @@
-
/*
* Copyright 2012 Google Inc.
*
@@ -13,21 +12,34 @@
class SkLinearGradient : public SkGradientShaderBase {
public:
- SkLinearGradient(const SkPoint pts[2], const Descriptor&);
+ SkLinearGradient(const SkPoint pts[2], const Descriptor&, const SkMatrix* localMatrix);
+
+ virtual size_t contextSize() const SK_OVERRIDE;
+
+ class LinearGradientContext : public SkGradientShaderBase::GradientShaderBaseContext {
+ public:
+ LinearGradientContext(const SkLinearGradient&, const ContextRec&);
+ ~LinearGradientContext() {}
+
+ virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE;
+ virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count) SK_OVERRIDE;
+
+ private:
+ typedef SkGradientShaderBase::GradientShaderBaseContext INHERITED;
+ };
- virtual bool setContext(const SkBitmap&, const SkPaint&, const SkMatrix&) SK_OVERRIDE;
- virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE;
- virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count) SK_OVERRIDE;
virtual BitmapType asABitmap(SkBitmap*, SkMatrix*, TileMode*) const SK_OVERRIDE;
virtual GradientType asAGradient(GradientInfo* info) const SK_OVERRIDE;
- virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint&) const SK_OVERRIDE;
+ virtual bool asNewEffect(GrContext* context, const SkPaint& paint, const SkMatrix* localMatrix,
+ GrColor* grColor, GrEffectRef** grEffect) const SK_OVERRIDE;
- SK_DEVELOPER_TO_STRING()
+ SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLinearGradient)
protected:
- SkLinearGradient(SkFlattenableReadBuffer& buffer);
- virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE;
+ SkLinearGradient(SkReadBuffer& buffer);
+ virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE;
+ virtual Context* onCreateContext(const ContextRec&, void* storage) const SK_OVERRIDE;
private:
typedef SkGradientShaderBase INHERITED;
diff --git a/chromium/third_party/skia/src/effects/gradients/SkRadialGradient.cpp b/chromium/third_party/skia/src/effects/gradients/SkRadialGradient.cpp
index 9d60cf7634e..f0cb1612b05 100644
--- a/chromium/third_party/skia/src/effects/gradients/SkRadialGradient.cpp
+++ b/chromium/third_party/skia/src/effects/gradients/SkRadialGradient.cpp
@@ -12,7 +12,7 @@
#define kSQRT_TABLE_BITS 11
#define kSQRT_TABLE_SIZE (1 << kSQRT_TABLE_BITS)
-#if defined(SK_BUILD_FOR_WIN32) && defined(SK_DEBUG)
+#if 0
#include <stdio.h>
@@ -146,8 +146,8 @@ void shadeSpan16_radial_repeat(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar d
/////////////////////////////////////////////////////////////////////
SkRadialGradient::SkRadialGradient(const SkPoint& center, SkScalar radius,
- const Descriptor& desc)
- : SkGradientShaderBase(desc),
+ const Descriptor& desc, const SkMatrix* localMatrix)
+ : SkGradientShaderBase(desc, localMatrix),
fCenter(center),
fRadius(radius)
{
@@ -157,16 +157,30 @@ SkRadialGradient::SkRadialGradient(const SkPoint& center, SkScalar radius,
rad_to_unit_matrix(center, radius, &fPtsToUnit);
}
-void SkRadialGradient::shadeSpan16(int x, int y, uint16_t* dstCParam,
- int count) {
+size_t SkRadialGradient::contextSize() const {
+ return sizeof(RadialGradientContext);
+}
+
+SkShader::Context* SkRadialGradient::onCreateContext(const ContextRec& rec, void* storage) const {
+ return SkNEW_PLACEMENT_ARGS(storage, RadialGradientContext, (*this, rec));
+}
+
+SkRadialGradient::RadialGradientContext::RadialGradientContext(
+ const SkRadialGradient& shader, const ContextRec& rec)
+ : INHERITED(shader, rec) {}
+
+void SkRadialGradient::RadialGradientContext::shadeSpan16(int x, int y, uint16_t* dstCParam,
+ int count) {
SkASSERT(count > 0);
+ const SkRadialGradient& radialGradient = static_cast<const SkRadialGradient&>(fShader);
+
uint16_t* SK_RESTRICT dstC = dstCParam;
SkPoint srcPt;
SkMatrix::MapXYProc dstProc = fDstToIndexProc;
- TileProc proc = fTileProc;
- const uint16_t* SK_RESTRICT cache = this->getCache16();
+ TileProc proc = radialGradient.fTileProc;
+ const uint16_t* SK_RESTRICT cache = fCache->getCache16();
int toggle = init_dither_toggle16(x, y);
if (fDstToIndexClass != kPerspective_MatrixClass) {
@@ -187,12 +201,12 @@ void SkRadialGradient::shadeSpan16(int x, int y, uint16_t* dstCParam,
}
RadialShade16Proc shadeProc = shadeSpan16_radial_repeat;
- if (SkShader::kClamp_TileMode == fTileMode) {
+ if (SkShader::kClamp_TileMode == radialGradient.fTileMode) {
shadeProc = shadeSpan16_radial_clamp;
- } else if (SkShader::kMirror_TileMode == fTileMode) {
+ } else if (SkShader::kMirror_TileMode == radialGradient.fTileMode) {
shadeProc = shadeSpan16_radial_mirror;
} else {
- SkASSERT(SkShader::kRepeat_TileMode == fTileMode);
+ SkASSERT(SkShader::kRepeat_TileMode == radialGradient.fTileMode);
}
(*shadeProc)(srcPt.fX, sdx, srcPt.fY, sdy, dstC,
cache, toggle, count);
@@ -239,13 +253,13 @@ SkShader::GradientType SkRadialGradient::asAGradient(GradientInfo* info) const {
return kRadial_GradientType;
}
-SkRadialGradient::SkRadialGradient(SkFlattenableReadBuffer& buffer)
+SkRadialGradient::SkRadialGradient(SkReadBuffer& buffer)
: INHERITED(buffer),
fCenter(buffer.readPoint()),
fRadius(buffer.readScalar()) {
}
-void SkRadialGradient::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkRadialGradient::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writePoint(fCenter);
buffer.writeScalar(fRadius);
@@ -389,14 +403,16 @@ void shadeSpan_radial_repeat(SkScalar fx, SkScalar dx, SkScalar fy, SkScalar dy,
} // namespace
-void SkRadialGradient::shadeSpan(int x, int y,
- SkPMColor* SK_RESTRICT dstC, int count) {
+void SkRadialGradient::RadialGradientContext::shadeSpan(int x, int y,
+ SkPMColor* SK_RESTRICT dstC, int count) {
SkASSERT(count > 0);
+ const SkRadialGradient& radialGradient = static_cast<const SkRadialGradient&>(fShader);
+
SkPoint srcPt;
SkMatrix::MapXYProc dstProc = fDstToIndexProc;
- TileProc proc = fTileProc;
- const SkPMColor* SK_RESTRICT cache = this->getCache32();
+ TileProc proc = radialGradient.fTileProc;
+ const SkPMColor* SK_RESTRICT cache = fCache->getCache32();
int toggle = init_dither_toggle(x, y);
if (fDstToIndexClass != kPerspective_MatrixClass) {
@@ -416,12 +432,12 @@ void SkRadialGradient::shadeSpan(int x, int y,
}
RadialShadeProc shadeProc = shadeSpan_radial_repeat;
- if (SkShader::kClamp_TileMode == fTileMode) {
+ if (SkShader::kClamp_TileMode == radialGradient.fTileMode) {
shadeProc = shadeSpan_radial_clamp;
- } else if (SkShader::kMirror_TileMode == fTileMode) {
+ } else if (SkShader::kMirror_TileMode == radialGradient.fTileMode) {
shadeProc = shadeSpan_radial_mirror;
} else {
- SkASSERT(SkShader::kRepeat_TileMode == fTileMode);
+ SkASSERT(SkShader::kRepeat_TileMode == radialGradient.fTileMode);
}
(*shadeProc)(srcPt.fX, sdx, srcPt.fY, sdy, dstC, cache, count, toggle);
} else { // perspective case
@@ -442,6 +458,7 @@ void SkRadialGradient::shadeSpan(int x, int y,
#if SK_SUPPORT_GPU
#include "GrTBackendEffectFactory.h"
+#include "SkGr.h"
class GrGLRadialGradient : public GrGLGradientEffect {
public:
@@ -522,7 +539,10 @@ GrEffectRef* GrRadialGradient::TestCreate(SkRandom* random,
colors, stops, colorCount,
tm));
SkPaint paint;
- return shader->asNewEffect(context, paint);
+ GrColor grColor;
+ GrEffectRef* effect;
+ shader->asNewEffect(context, paint, NULL, &grColor, &effect);
+ return effect;
}
/////////////////////////////////////////////////////////////////////
@@ -543,27 +563,42 @@ void GrGLRadialGradient::emitCode(GrGLShaderBuilder* builder,
/////////////////////////////////////////////////////////////////////
-GrEffectRef* SkRadialGradient::asNewEffect(GrContext* context, const SkPaint&) const {
+bool SkRadialGradient::asNewEffect(GrContext* context, const SkPaint& paint,
+ const SkMatrix* localMatrix, GrColor* grColor,
+ GrEffectRef** grEffect) const {
SkASSERT(NULL != context);
-
+
SkMatrix matrix;
if (!this->getLocalMatrix().invert(&matrix)) {
- return NULL;
+ return false;
+ }
+ if (localMatrix) {
+ SkMatrix inv;
+ if (!localMatrix->invert(&inv)) {
+ return false;
+ }
+ matrix.postConcat(inv);
}
matrix.postConcat(fPtsToUnit);
- return GrRadialGradient::Create(context, *this, matrix, fTileMode);
+
+ *grColor = SkColor2GrColorJustAlpha(paint.getColor());
+ *grEffect = GrRadialGradient::Create(context, *this, matrix, fTileMode);
+
+ return true;
}
#else
-GrEffectRef* SkRadialGradient::asNewEffect(GrContext*, const SkPaint&) const {
+bool SkRadialGradient::asNewEffect(GrContext* context, const SkPaint& paint,
+ const SkMatrix* localMatrix, GrColor* grColor,
+ GrEffectRef** grEffect) const {
SkDEBUGFAIL("Should not call in GPU-less build");
- return NULL;
+ return false;
}
#endif
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkRadialGradient::toString(SkString* str) const {
str->append("SkRadialGradient: (");
diff --git a/chromium/third_party/skia/src/effects/gradients/SkRadialGradient.h b/chromium/third_party/skia/src/effects/gradients/SkRadialGradient.h
index fa0a969cf2b..197c967f4d2 100644
--- a/chromium/third_party/skia/src/effects/gradients/SkRadialGradient.h
+++ b/chromium/third_party/skia/src/effects/gradients/SkRadialGradient.h
@@ -13,23 +13,35 @@
class SkRadialGradient : public SkGradientShaderBase {
public:
- SkRadialGradient(const SkPoint& center, SkScalar radius, const Descriptor&);
- virtual void shadeSpan(int x, int y, SkPMColor* dstC, int count)
- SK_OVERRIDE;
- virtual void shadeSpan16(int x, int y, uint16_t* dstCParam,
- int count) SK_OVERRIDE;
+ SkRadialGradient(const SkPoint& center, SkScalar radius, const Descriptor&,
+ const SkMatrix* localMatrix);
+
+ virtual size_t contextSize() const SK_OVERRIDE;
+
+ class RadialGradientContext : public SkGradientShaderBase::GradientShaderBaseContext {
+ public:
+ RadialGradientContext(const SkRadialGradient&, const ContextRec&);
+
+ virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE;
+ virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count) SK_OVERRIDE;
+
+ private:
+ typedef SkGradientShaderBase::GradientShaderBaseContext INHERITED;
+ };
+
virtual BitmapType asABitmap(SkBitmap* bitmap,
SkMatrix* matrix,
TileMode* xy) const SK_OVERRIDE;
virtual GradientType asAGradient(GradientInfo* info) const SK_OVERRIDE;
- virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint&) const SK_OVERRIDE;
+ virtual bool asNewEffect(GrContext*, const SkPaint&, const SkMatrix*, GrColor*, GrEffectRef**) const SK_OVERRIDE;
- SK_DEVELOPER_TO_STRING()
+ SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkRadialGradient)
protected:
- SkRadialGradient(SkFlattenableReadBuffer& buffer);
- virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE;
+ SkRadialGradient(SkReadBuffer& buffer);
+ virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE;
+ virtual Context* onCreateContext(const ContextRec&, void* storage) const SK_OVERRIDE;
private:
typedef SkGradientShaderBase INHERITED;
diff --git a/chromium/third_party/skia/src/effects/gradients/SkSweepGradient.cpp b/chromium/third_party/skia/src/effects/gradients/SkSweepGradient.cpp
index c38205b844a..154e3a2f138 100644
--- a/chromium/third_party/skia/src/effects/gradients/SkSweepGradient.cpp
+++ b/chromium/third_party/skia/src/effects/gradients/SkSweepGradient.cpp
@@ -9,8 +9,8 @@
#include "SkSweepGradient.h"
SkSweepGradient::SkSweepGradient(SkScalar cx, SkScalar cy,
- const Descriptor& desc)
- : SkGradientShaderBase(desc)
+ const Descriptor& desc, const SkMatrix* localMatrix)
+ : SkGradientShaderBase(desc, localMatrix)
, fCenter(SkPoint::Make(cx, cy))
{
fPtsToUnit.setTranslate(-cx, -cy);
@@ -42,188 +42,29 @@ SkShader::GradientType SkSweepGradient::asAGradient(GradientInfo* info) const {
return kSweep_GradientType;
}
-SkSweepGradient::SkSweepGradient(SkFlattenableReadBuffer& buffer)
+SkSweepGradient::SkSweepGradient(SkReadBuffer& buffer)
: INHERITED(buffer),
fCenter(buffer.readPoint()) {
}
-void SkSweepGradient::flatten(SkFlattenableWriteBuffer& buffer) const {
+void SkSweepGradient::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writePoint(fCenter);
}
-#ifndef SK_SCALAR_IS_FLOAT
-#ifdef COMPUTE_SWEEP_TABLE
-#define PI 3.14159265
-static bool gSweepTableReady;
-static uint8_t gSweepTable[65];
-
-/* Our table stores precomputed values for atan: [0...1] -> [0..PI/4]
- We scale the results to [0..32]
-*/
-static const uint8_t* build_sweep_table() {
- if (!gSweepTableReady) {
- const int N = 65;
- const double DENOM = N - 1;
-
- for (int i = 0; i < N; i++)
- {
- double arg = i / DENOM;
- double v = atan(arg);
- int iv = (int)round(v * DENOM * 2 / PI);
-// printf("[%d] atan(%g) = %g %d\n", i, arg, v, iv);
- printf("%d, ", iv);
- gSweepTable[i] = iv;
- }
- gSweepTableReady = true;
- }
- return gSweepTable;
+size_t SkSweepGradient::contextSize() const {
+ return sizeof(SweepGradientContext);
}
-#else
-static const uint8_t gSweepTable[] = {
- 0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 9,
- 10, 11, 11, 12, 12, 13, 13, 14, 15, 15, 16, 16, 17, 17, 18, 18,
- 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 25, 26,
- 26, 27, 27, 27, 28, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31, 32,
- 32
-};
-static const uint8_t* build_sweep_table() { return gSweepTable; }
-#endif
-#endif
-
-// divide numer/denom, with a bias of 6bits. Assumes numer <= denom
-// and denom != 0. Since our table is 6bits big (+1), this is a nice fit.
-// Same as (but faster than) SkFixedDiv(numer, denom) >> 10
-
-//unsigned div_64(int numer, int denom);
-#ifndef SK_SCALAR_IS_FLOAT
-static unsigned div_64(int numer, int denom) {
- SkASSERT(numer <= denom);
- SkASSERT(numer > 0);
- SkASSERT(denom > 0);
-
- int nbits = SkCLZ(numer);
- int dbits = SkCLZ(denom);
- int bits = 6 - nbits + dbits;
- SkASSERT(bits <= 6);
-
- if (bits < 0) { // detect underflow
- return 0;
- }
-
- denom <<= dbits - 1;
- numer <<= nbits - 1;
-
- unsigned result = 0;
- // do the first one
- if ((numer -= denom) >= 0) {
- result = 1;
- } else {
- numer += denom;
- }
-
- // Now fall into our switch statement if there are more bits to compute
- if (bits > 0) {
- // make room for the rest of the answer bits
- result <<= bits;
- switch (bits) {
- case 6:
- if ((numer = (numer << 1) - denom) >= 0)
- result |= 32;
- else
- numer += denom;
- case 5:
- if ((numer = (numer << 1) - denom) >= 0)
- result |= 16;
- else
- numer += denom;
- case 4:
- if ((numer = (numer << 1) - denom) >= 0)
- result |= 8;
- else
- numer += denom;
- case 3:
- if ((numer = (numer << 1) - denom) >= 0)
- result |= 4;
- else
- numer += denom;
- case 2:
- if ((numer = (numer << 1) - denom) >= 0)
- result |= 2;
- else
- numer += denom;
- case 1:
- default: // not strictly need, but makes GCC make better ARM code
- if ((numer = (numer << 1) - denom) >= 0)
- result |= 1;
- else
- numer += denom;
- }
- }
- return result;
+SkShader::Context* SkSweepGradient::onCreateContext(const ContextRec& rec, void* storage) const {
+ return SkNEW_PLACEMENT_ARGS(storage, SweepGradientContext, (*this, rec));
}
-#endif
-
-// Given x,y in the first quadrant, return 0..63 for the angle [0..90]
-#ifndef SK_SCALAR_IS_FLOAT
-static unsigned atan_0_90(SkFixed y, SkFixed x) {
-#ifdef SK_DEBUG
- {
- static bool gOnce;
- if (!gOnce) {
- gOnce = true;
- SkASSERT(div_64(55, 55) == 64);
- SkASSERT(div_64(128, 256) == 32);
- SkASSERT(div_64(2326528, 4685824) == 31);
- SkASSERT(div_64(753664, 5210112) == 9);
- SkASSERT(div_64(229376, 4882432) == 3);
- SkASSERT(div_64(2, 64) == 2);
- SkASSERT(div_64(1, 64) == 1);
- // test that we handle underflow correctly
- SkASSERT(div_64(12345, 0x54321234) == 0);
- }
- }
-#endif
-
- SkASSERT(y > 0 && x > 0);
- const uint8_t* table = build_sweep_table();
-
- unsigned result;
- bool swap = (x < y);
- if (swap) {
- // first part of the atan(v) = PI/2 - atan(1/v) identity
- // since our div_64 and table want v <= 1, where v = y/x
- SkTSwap<SkFixed>(x, y);
- }
-
- result = div_64(y, x);
-#ifdef SK_DEBUG
- {
- unsigned result2 = SkDivBits(y, x, 6);
- SkASSERT(result2 == result ||
- (result == 1 && result2 == 0));
- }
-#endif
-
- SkASSERT(result < SK_ARRAY_COUNT(gSweepTable));
- result = table[result];
-
- if (swap) {
- // complete the atan(v) = PI/2 - atan(1/v) identity
- result = 64 - result;
- // pin to 63
- result -= result >> 6;
- }
-
- SkASSERT(result <= 63);
- return result;
-}
-#endif
+SkSweepGradient::SweepGradientContext::SweepGradientContext(
+ const SkSweepGradient& shader, const ContextRec& rec)
+ : INHERITED(shader, rec) {}
// returns angle in a circle [0..2PI) -> [0..255]
-#ifdef SK_SCALAR_IS_FLOAT
static unsigned SkATan2_255(float y, float x) {
// static const float g255Over2PI = 255 / (2 * SK_ScalarPI);
static const float g255Over2PI = 40.584510488433314f;
@@ -239,68 +80,12 @@ static unsigned SkATan2_255(float y, float x) {
SkASSERT(ir >= 0 && ir <= 255);
return ir;
}
-#else
-static unsigned SkATan2_255(SkFixed y, SkFixed x) {
- if (x == 0) {
- if (y == 0) {
- return 0;
- }
- return y < 0 ? 192 : 64;
- }
- if (y == 0) {
- return x < 0 ? 128 : 0;
- }
-
- /* Find the right quadrant for x,y
- Since atan_0_90 only handles the first quadrant, we rotate x,y
- appropriately before calling it, and then add the right amount
- to account for the real quadrant.
- quadrant 0 : add 0 | x > 0 && y > 0
- quadrant 1 : add 64 (90 degrees) | x < 0 && y > 0
- quadrant 2 : add 128 (180 degrees) | x < 0 && y < 0
- quadrant 3 : add 192 (270 degrees) | x > 0 && y < 0
-
- map x<0 to (1 << 6)
- map y<0 to (3 << 6)
- add = map_x ^ map_y
- */
- int xsign = x >> 31;
- int ysign = y >> 31;
- int add = ((-xsign) ^ (ysign & 3)) << 6;
-
-#ifdef SK_DEBUG
- if (0 == add)
- SkASSERT(x > 0 && y > 0);
- else if (64 == add)
- SkASSERT(x < 0 && y > 0);
- else if (128 == add)
- SkASSERT(x < 0 && y < 0);
- else if (192 == add)
- SkASSERT(x > 0 && y < 0);
- else
- SkDEBUGFAIL("bad value for add");
-#endif
-
- /* This ^ trick makes x, y positive, and the swap<> handles quadrants
- where we need to rotate x,y by 90 or -90
- */
- x = (x ^ xsign) - xsign;
- y = (y ^ ysign) - ysign;
- if (add & 64) { // quads 1 or 3 need to swap x,y
- SkTSwap<SkFixed>(x, y);
- }
-
- unsigned result = add + atan_0_90(y, x);
- SkASSERT(result < 256);
- return result;
-}
-#endif
-void SkSweepGradient::shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC,
- int count) {
+void SkSweepGradient::SweepGradientContext::shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC,
+ int count) {
SkMatrix::MapXYProc proc = fDstToIndexProc;
const SkMatrix& matrix = fDstToIndex;
- const SkPMColor* SK_RESTRICT cache = this->getCache32();
+ const SkPMColor* SK_RESTRICT cache = fCache->getCache32();
int toggle = init_dither_toggle(x, y);
SkPoint srcPt;
@@ -338,11 +123,11 @@ void SkSweepGradient::shadeSpan(int x, int y, SkPMColor* SK_RESTRICT dstC,
}
}
-void SkSweepGradient::shadeSpan16(int x, int y, uint16_t* SK_RESTRICT dstC,
- int count) {
+void SkSweepGradient::SweepGradientContext::shadeSpan16(int x, int y, uint16_t* SK_RESTRICT dstC,
+ int count) {
SkMatrix::MapXYProc proc = fDstToIndexProc;
const SkMatrix& matrix = fDstToIndex;
- const uint16_t* SK_RESTRICT cache = this->getCache16();
+ const uint16_t* SK_RESTRICT cache = fCache->getCache16();
int toggle = init_dither_toggle16(x, y);
SkPoint srcPt;
@@ -389,6 +174,7 @@ void SkSweepGradient::shadeSpan16(int x, int y, uint16_t* SK_RESTRICT dstC,
#if SK_SUPPORT_GPU
#include "GrTBackendEffectFactory.h"
+#include "SkGr.h"
class GrGLSweepGradient : public GrGLGradientEffect {
public:
@@ -462,7 +248,10 @@ GrEffectRef* GrSweepGradient::TestCreate(SkRandom* random,
SkAutoTUnref<SkShader> shader(SkGradientShader::CreateSweep(center.fX, center.fY,
colors, stops, colorCount));
SkPaint paint;
- return shader->asNewEffect(context, paint);
+ GrEffectRef* effect;
+ GrColor grColor;
+ shader->asNewEffect(context, paint, NULL, &grColor, &effect);
+ return effect;
}
/////////////////////////////////////////////////////////////////////
@@ -476,33 +265,59 @@ void GrGLSweepGradient::emitCode(GrGLShaderBuilder* builder,
const TextureSamplerArray& samplers) {
this->emitUniforms(builder, key);
SkString coords2D = builder->ensureFSCoords2D(coords, 0);
+ const GrGLContextInfo ctxInfo = builder->ctxInfo();
SkString t;
- t.printf("atan(- %s.y, - %s.x) * 0.1591549430918 + 0.5", coords2D.c_str(), coords2D.c_str());
+ // 0.1591549430918 is 1/(2*pi), used since atan returns values [-pi, pi]
+ // On Intel GPU there is an issue where it reads the second arguement to atan "- %s.x" as an int
+ // thus must us -1.0 * %s.x to work correctly
+ if (kIntel_GrGLVendor != ctxInfo.vendor()){
+ t.printf("atan(- %s.y, - %s.x) * 0.1591549430918 + 0.5",
+ coords2D.c_str(), coords2D.c_str());
+ } else {
+ t.printf("atan(- %s.y, -1.0 * %s.x) * 0.1591549430918 + 0.5",
+ coords2D.c_str(), coords2D.c_str());
+ }
this->emitColor(builder, t.c_str(), key,
outputColor, inputColor, samplers);
}
/////////////////////////////////////////////////////////////////////
-GrEffectRef* SkSweepGradient::asNewEffect(GrContext* context, const SkPaint&) const {
+bool SkSweepGradient::asNewEffect(GrContext* context, const SkPaint& paint,
+ const SkMatrix* localMatrix, GrColor* grColor,
+ GrEffectRef** grEffect) const {
+
SkMatrix matrix;
if (!this->getLocalMatrix().invert(&matrix)) {
- return NULL;
+ return false;
+ }
+ if (localMatrix) {
+ SkMatrix inv;
+ if (!localMatrix->invert(&inv)) {
+ return false;
+ }
+ matrix.postConcat(inv);
}
matrix.postConcat(fPtsToUnit);
- return GrSweepGradient::Create(context, *this, matrix);
+
+ *grEffect = GrSweepGradient::Create(context, *this, matrix);
+ *grColor = SkColor2GrColorJustAlpha(paint.getColor());
+
+ return true;
}
#else
-GrEffectRef* SkSweepGradient::asNewEffect(GrContext*, const SkPaint&) const {
+bool SkSweepGradient::asNewEffect(GrContext* context, const SkPaint& paint,
+ const SkMatrix* localMatrix, GrColor* grColor,
+ GrEffectRef** grEffect) const {
SkDEBUGFAIL("Should not call in GPU-less build");
- return NULL;
+ return false;
}
#endif
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkSweepGradient::toString(SkString* str) const {
str->append("SkSweepGradient: (");
diff --git a/chromium/third_party/skia/src/effects/gradients/SkSweepGradient.h b/chromium/third_party/skia/src/effects/gradients/SkSweepGradient.h
index 8b685bc2093..0b12e718eac 100644
--- a/chromium/third_party/skia/src/effects/gradients/SkSweepGradient.h
+++ b/chromium/third_party/skia/src/effects/gradients/SkSweepGradient.h
@@ -13,9 +13,21 @@
class SkSweepGradient : public SkGradientShaderBase {
public:
- SkSweepGradient(SkScalar cx, SkScalar cy, const Descriptor&);
- virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE;
- virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count) SK_OVERRIDE;
+ SkSweepGradient(SkScalar cx, SkScalar cy, const Descriptor&,
+ const SkMatrix* localMatrix);
+
+ virtual size_t contextSize() const SK_OVERRIDE;
+
+ class SweepGradientContext : public SkGradientShaderBase::GradientShaderBaseContext {
+ public:
+ SweepGradientContext(const SkSweepGradient& shader, const ContextRec&);
+
+ virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE;
+ virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count) SK_OVERRIDE;
+
+ private:
+ typedef SkGradientShaderBase::GradientShaderBaseContext INHERITED;
+ };
virtual BitmapType asABitmap(SkBitmap* bitmap,
SkMatrix* matrix,
@@ -23,18 +35,21 @@ public:
virtual GradientType asAGradient(GradientInfo* info) const SK_OVERRIDE;
- virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint&) const SK_OVERRIDE;
+ virtual bool asNewEffect(GrContext*, const SkPaint&, const SkMatrix*, GrColor*, GrEffectRef**)
+ const SK_OVERRIDE;
- SK_DEVELOPER_TO_STRING()
+ SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSweepGradient)
protected:
- SkSweepGradient(SkFlattenableReadBuffer& buffer);
- virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE;
+ SkSweepGradient(SkReadBuffer& buffer);
+ virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE;
+ virtual Context* onCreateContext(const ContextRec&, void* storage) const SK_OVERRIDE;
private:
- typedef SkGradientShaderBase INHERITED;
const SkPoint fCenter;
+
+ typedef SkGradientShaderBase INHERITED;
};
#endif
diff --git a/chromium/third_party/skia/src/effects/gradients/SkTwoPointConicalGradient.cpp b/chromium/third_party/skia/src/effects/gradients/SkTwoPointConicalGradient.cpp
index a9bd1c27627..4421b90a3ae 100644
--- a/chromium/third_party/skia/src/effects/gradients/SkTwoPointConicalGradient.cpp
+++ b/chromium/third_party/skia/src/effects/gradients/SkTwoPointConicalGradient.cpp
@@ -6,6 +6,19 @@
*/
#include "SkTwoPointConicalGradient.h"
+#include "SkTwoPointConicalGradient_gpu.h"
+
+struct TwoPtRadialContext {
+ const TwoPtRadial& fRec;
+ float fRelX, fRelY;
+ const float fIncX, fIncY;
+ float fB;
+ const float fDB;
+
+ TwoPtRadialContext(const TwoPtRadial& rec, SkScalar fx, SkScalar fy,
+ SkScalar dfx, SkScalar dfy);
+ SkFixed nextT();
+};
static int valid_divide(float numer, float denom, float* ratio) {
SkASSERT(ratio);
@@ -18,7 +31,7 @@ static int valid_divide(float numer, float denom, float* ratio) {
// Return the number of distinct real roots, and write them into roots[] in
// ascending order
-static int find_quad_roots(float A, float B, float C, float roots[2]) {
+static int find_quad_roots(float A, float B, float C, float roots[2], bool descendingOrder = false) {
SkASSERT(roots);
if (A == 0) {
@@ -52,6 +65,9 @@ static int find_quad_roots(float A, float B, float C, float roots[2]) {
float r1 = C / Q;
roots[0] = r0 < r1 ? r0 : r1;
roots[1] = r0 > r1 ? r0 : r1;
+ if (descendingOrder) {
+ SkTSwap(roots[0], roots[1]);
+ }
return 2;
}
@@ -62,7 +78,8 @@ static float lerp(float x, float dx, float t) {
static float sqr(float x) { return x * x; }
void TwoPtRadial::init(const SkPoint& center0, SkScalar rad0,
- const SkPoint& center1, SkScalar rad1) {
+ const SkPoint& center1, SkScalar rad1,
+ bool flipped) {
fCenterX = SkScalarToFloat(center0.fX);
fCenterY = SkScalarToFloat(center0.fY);
fDCenterX = SkScalarToFloat(center1.fX) - fCenterX;
@@ -73,49 +90,52 @@ void TwoPtRadial::init(const SkPoint& center0, SkScalar rad0,
fA = sqr(fDCenterX) + sqr(fDCenterY) - sqr(fDRadius);
fRadius2 = sqr(fRadius);
fRDR = fRadius * fDRadius;
-}
-void TwoPtRadial::setup(SkScalar fx, SkScalar fy, SkScalar dfx, SkScalar dfy) {
- fRelX = SkScalarToFloat(fx) - fCenterX;
- fRelY = SkScalarToFloat(fy) - fCenterY;
- fIncX = SkScalarToFloat(dfx);
- fIncY = SkScalarToFloat(dfy);
- fB = -2 * (fDCenterX * fRelX + fDCenterY * fRelY + fRDR);
- fDB = -2 * (fDCenterX * fIncX + fDCenterY * fIncY);
+ fFlipped = flipped;
}
-SkFixed TwoPtRadial::nextT() {
+TwoPtRadialContext::TwoPtRadialContext(const TwoPtRadial& rec, SkScalar fx, SkScalar fy,
+ SkScalar dfx, SkScalar dfy)
+ : fRec(rec)
+ , fRelX(SkScalarToFloat(fx) - rec.fCenterX)
+ , fRelY(SkScalarToFloat(fy) - rec.fCenterY)
+ , fIncX(SkScalarToFloat(dfx))
+ , fIncY(SkScalarToFloat(dfy))
+ , fB(-2 * (rec.fDCenterX * fRelX + rec.fDCenterY * fRelY + rec.fRDR))
+ , fDB(-2 * (rec.fDCenterX * fIncX + rec.fDCenterY * fIncY)) {}
+
+SkFixed TwoPtRadialContext::nextT() {
float roots[2];
- float C = sqr(fRelX) + sqr(fRelY) - fRadius2;
- int countRoots = find_quad_roots(fA, fB, C, roots);
+ float C = sqr(fRelX) + sqr(fRelY) - fRec.fRadius2;
+ int countRoots = find_quad_roots(fRec.fA, fB, C, roots, fRec.fFlipped);
fRelX += fIncX;
fRelY += fIncY;
fB += fDB;
if (0 == countRoots) {
- return kDontDrawT;
+ return TwoPtRadial::kDontDrawT;
}
// Prefer the bigger t value if both give a radius(t) > 0
// find_quad_roots returns the values sorted, so we start with the last
float t = roots[countRoots - 1];
- float r = lerp(fRadius, fDRadius, t);
+ float r = lerp(fRec.fRadius, fRec.fDRadius, t);
if (r <= 0) {
t = roots[0]; // might be the same as roots[countRoots-1]
- r = lerp(fRadius, fDRadius, t);
+ r = lerp(fRec.fRadius, fRec.fDRadius, t);
if (r <= 0) {
- return kDontDrawT;
+ return TwoPtRadial::kDontDrawT;
}
}
return SkFloatToFixed(t);
}
-typedef void (*TwoPointConicalProc)(TwoPtRadial* rec, SkPMColor* dstC,
+typedef void (*TwoPointConicalProc)(TwoPtRadialContext* rec, SkPMColor* dstC,
const SkPMColor* cache, int toggle, int count);
-static void twopoint_clamp(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC,
+static void twopoint_clamp(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC,
const SkPMColor* SK_RESTRICT cache, int toggle,
int count) {
for (; count > 0; --count) {
@@ -132,7 +152,7 @@ static void twopoint_clamp(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC,
}
}
-static void twopoint_repeat(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC,
+static void twopoint_repeat(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC,
const SkPMColor* SK_RESTRICT cache, int toggle,
int count) {
for (; count > 0; --count) {
@@ -149,7 +169,7 @@ static void twopoint_repeat(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC,
}
}
-static void twopoint_mirror(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC,
+static void twopoint_mirror(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC,
const SkPMColor* SK_RESTRICT cache, int toggle,
int count) {
for (; count > 0; --count) {
@@ -167,7 +187,7 @@ static void twopoint_mirror(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC,
}
void SkTwoPointConicalGradient::init() {
- fRec.init(fCenter1, fRadius1, fCenter2, fRadius2);
+ fRec.init(fCenter1, fRadius1, fCenter2, fRadius2, fFlippedGrad);
fPtsToUnit.reset();
}
@@ -176,12 +196,14 @@ void SkTwoPointConicalGradient::init() {
SkTwoPointConicalGradient::SkTwoPointConicalGradient(
const SkPoint& start, SkScalar startRadius,
const SkPoint& end, SkScalar endRadius,
- const Descriptor& desc)
- : SkGradientShaderBase(desc),
+ bool flippedGrad, const Descriptor& desc,
+ const SkMatrix* localMatrix)
+ : SkGradientShaderBase(desc, localMatrix),
fCenter1(start),
fCenter2(end),
fRadius1(startRadius),
- fRadius2(endRadius) {
+ fRadius2(endRadius),
+ fFlippedGrad(flippedGrad) {
// this is degenerate, and should be caught by our caller
SkASSERT(fCenter1 != fCenter2 || fRadius1 != fRadius2);
this->init();
@@ -194,8 +216,32 @@ bool SkTwoPointConicalGradient::isOpaque() const {
return false;
}
-void SkTwoPointConicalGradient::shadeSpan(int x, int y, SkPMColor* dstCParam,
- int count) {
+size_t SkTwoPointConicalGradient::contextSize() const {
+ return sizeof(TwoPointConicalGradientContext);
+}
+
+SkShader::Context* SkTwoPointConicalGradient::onCreateContext(const ContextRec& rec,
+ void* storage) const {
+ return SkNEW_PLACEMENT_ARGS(storage, TwoPointConicalGradientContext, (*this, rec));
+}
+
+SkTwoPointConicalGradient::TwoPointConicalGradientContext::TwoPointConicalGradientContext(
+ const SkTwoPointConicalGradient& shader, const ContextRec& rec)
+ : INHERITED(shader, rec)
+{
+ // we don't have a span16 proc
+ fFlags &= ~kHasSpan16_Flag;
+
+ // in general, we might discard based on computed-radius, so clear
+ // this flag (todo: sometimes we can detect that we never discard...)
+ fFlags &= ~kOpaqueAlpha_Flag;
+}
+
+void SkTwoPointConicalGradient::TwoPointConicalGradientContext::shadeSpan(
+ int x, int y, SkPMColor* dstCParam, int count) {
+ const SkTwoPointConicalGradient& twoPointConicalGradient =
+ static_cast<const SkTwoPointConicalGradient&>(fShader);
+
int toggle = init_dither_toggle(x, y);
SkASSERT(count > 0);
@@ -204,15 +250,15 @@ void SkTwoPointConicalGradient::shadeSpan(int x, int y, SkPMColor* dstCParam,
SkMatrix::MapXYProc dstProc = fDstToIndexProc;
- const SkPMColor* SK_RESTRICT cache = this->getCache32();
+ const SkPMColor* SK_RESTRICT cache = fCache->getCache32();
TwoPointConicalProc shadeProc = twopoint_repeat;
- if (SkShader::kClamp_TileMode == fTileMode) {
+ if (SkShader::kClamp_TileMode == twoPointConicalGradient.fTileMode) {
shadeProc = twopoint_clamp;
- } else if (SkShader::kMirror_TileMode == fTileMode) {
+ } else if (SkShader::kMirror_TileMode == twoPointConicalGradient.fTileMode) {
shadeProc = twopoint_mirror;
} else {
- SkASSERT(SkShader::kRepeat_TileMode == fTileMode);
+ SkASSERT(SkShader::kRepeat_TileMode == twoPointConicalGradient.fTileMode);
}
if (fDstToIndexClass != kPerspective_MatrixClass) {
@@ -233,16 +279,16 @@ void SkTwoPointConicalGradient::shadeSpan(int x, int y, SkPMColor* dstCParam,
dy = fDstToIndex.getSkewY();
}
- fRec.setup(fx, fy, dx, dy);
- (*shadeProc)(&fRec, dstC, cache, toggle, count);
+ TwoPtRadialContext rec(twoPointConicalGradient.fRec, fx, fy, dx, dy);
+ (*shadeProc)(&rec, dstC, cache, toggle, count);
} else { // perspective case
SkScalar dstX = SkIntToScalar(x) + SK_ScalarHalf;
SkScalar dstY = SkIntToScalar(y) + SK_ScalarHalf;
for (; count > 0; --count) {
SkPoint srcPt;
dstProc(fDstToIndex, dstX, dstY, &srcPt);
- fRec.setup(srcPt.fX, srcPt.fY, 0, 0);
- (*shadeProc)(&fRec, dstC, cache, toggle, 1);
+ TwoPtRadialContext rec(twoPointConicalGradient.fRec, srcPt.fX, srcPt.fY, 0, 0);
+ (*shadeProc)(&rec, dstC, cache, toggle, 1);
dstX += SK_Scalar1;
toggle = next_dither_toggle(toggle);
@@ -251,23 +297,6 @@ void SkTwoPointConicalGradient::shadeSpan(int x, int y, SkPMColor* dstCParam,
}
}
-bool SkTwoPointConicalGradient::setContext(const SkBitmap& device,
- const SkPaint& paint,
- const SkMatrix& matrix) {
- if (!this->INHERITED::setContext(device, paint, matrix)) {
- return false;
- }
-
- // we don't have a span16 proc
- fFlags &= ~kHasSpan16_Flag;
-
- // in general, we might discard based on computed-radius, so clear
- // this flag (todo: sometimes we can detect that we never discard...)
- fFlags &= ~kOpaqueAlpha_Flag;
-
- return true;
-}
-
SkShader::BitmapType SkTwoPointConicalGradient::asABitmap(
SkBitmap* bitmap, SkMatrix* matrix, SkShader::TileMode* xy) const {
SkPoint diff = fCenter2 - fCenter1;
@@ -297,420 +326,84 @@ SkShader::BitmapType SkTwoPointConicalGradient::asABitmap(
return kTwoPointConical_BitmapType;
}
+// Returns the original non-sorted version of the gradient
SkShader::GradientType SkTwoPointConicalGradient::asAGradient(
GradientInfo* info) const {
if (info) {
- commonAsAGradient(info);
+ commonAsAGradient(info, fFlippedGrad);
info->fPoint[0] = fCenter1;
info->fPoint[1] = fCenter2;
info->fRadius[0] = fRadius1;
info->fRadius[1] = fRadius2;
+ if (fFlippedGrad) {
+ SkTSwap(info->fPoint[0], info->fPoint[1]);
+ SkTSwap(info->fRadius[0], info->fRadius[1]);
+ }
}
return kConical_GradientType;
}
SkTwoPointConicalGradient::SkTwoPointConicalGradient(
- SkFlattenableReadBuffer& buffer)
+ SkReadBuffer& buffer)
: INHERITED(buffer),
fCenter1(buffer.readPoint()),
fCenter2(buffer.readPoint()),
fRadius1(buffer.readScalar()),
fRadius2(buffer.readScalar()) {
+ if (buffer.isVersionLT(SkReadBuffer::kGradientFlippedFlag_Version)) {
+ // V23_COMPATIBILITY_CODE
+ // Sort gradient by radius size for old pictures
+ if (fRadius2 < fRadius1) {
+ SkTSwap(fCenter1, fCenter2);
+ SkTSwap(fRadius1, fRadius2);
+ this->flipGradientColors();
+ fFlippedGrad = true;
+ } else {
+ fFlippedGrad = false;
+ }
+ } else {
+ fFlippedGrad = buffer.readBool();
+ }
this->init();
};
void SkTwoPointConicalGradient::flatten(
- SkFlattenableWriteBuffer& buffer) const {
+ SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writePoint(fCenter1);
buffer.writePoint(fCenter2);
buffer.writeScalar(fRadius1);
buffer.writeScalar(fRadius2);
+ buffer.writeBool(fFlippedGrad);
}
-/////////////////////////////////////////////////////////////////////
-
#if SK_SUPPORT_GPU
-#include "GrTBackendEffectFactory.h"
-
-// For brevity
-typedef GrGLUniformManager::UniformHandle UniformHandle;
-
-class GrGLConical2Gradient : public GrGLGradientEffect {
-public:
-
- GrGLConical2Gradient(const GrBackendEffectFactory& factory, const GrDrawEffect&);
- virtual ~GrGLConical2Gradient() { }
-
- virtual void emitCode(GrGLShaderBuilder*,
- const GrDrawEffect&,
- EffectKey,
- const char* outputColor,
- const char* inputColor,
- const TransformedCoordsArray&,
- const TextureSamplerArray&) SK_OVERRIDE;
- virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
-
- static EffectKey GenKey(const GrDrawEffect&, const GrGLCaps& caps);
-
-protected:
-
- UniformHandle fParamUni;
-
- const char* fVSVaryingName;
- const char* fFSVaryingName;
-
- bool fIsDegenerate;
-
- // @{
- /// Values last uploaded as uniforms
-
- SkScalar fCachedCenter;
- SkScalar fCachedRadius;
- SkScalar fCachedDiffRadius;
-
- // @}
-
-private:
-
- typedef GrGLGradientEffect INHERITED;
-
-};
-
-/////////////////////////////////////////////////////////////////////
-
-class GrConical2Gradient : public GrGradientEffect {
-public:
-
- static GrEffectRef* Create(GrContext* ctx,
- const SkTwoPointConicalGradient& shader,
- const SkMatrix& matrix,
- SkShader::TileMode tm) {
- AutoEffectUnref effect(SkNEW_ARGS(GrConical2Gradient, (ctx, shader, matrix, tm)));
- return CreateEffectRef(effect);
- }
-
- virtual ~GrConical2Gradient() { }
-
- static const char* Name() { return "Two-Point Conical Gradient"; }
- virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
- return GrTBackendEffectFactory<GrConical2Gradient>::getInstance();
- }
-
- // The radial gradient parameters can collapse to a linear (instead of quadratic) equation.
- bool isDegenerate() const { return SkScalarAbs(fDiffRadius) == SkScalarAbs(fCenterX1); }
- SkScalar center() const { return fCenterX1; }
- SkScalar diffRadius() const { return fDiffRadius; }
- SkScalar radius() const { return fRadius0; }
-
- typedef GrGLConical2Gradient GLEffect;
-
-private:
- virtual bool onIsEqual(const GrEffect& sBase) const SK_OVERRIDE {
- const GrConical2Gradient& s = CastEffect<GrConical2Gradient>(sBase);
- return (INHERITED::onIsEqual(sBase) &&
- this->fCenterX1 == s.fCenterX1 &&
- this->fRadius0 == s.fRadius0 &&
- this->fDiffRadius == s.fDiffRadius);
- }
-
- GrConical2Gradient(GrContext* ctx,
- const SkTwoPointConicalGradient& shader,
- const SkMatrix& matrix,
- SkShader::TileMode tm)
- : INHERITED(ctx, shader, matrix, tm)
- , fCenterX1(shader.getCenterX1())
- , fRadius0(shader.getStartRadius())
- , fDiffRadius(shader.getDiffRadius()) {
- // We pass the linear part of the quadratic as a varying.
- // float b = -2.0 * (fCenterX1 * x + fRadius0 * fDiffRadius * z)
- fBTransform = this->getCoordTransform();
- SkMatrix& bMatrix = *fBTransform.accessMatrix();
- SkScalar r0dr = SkScalarMul(fRadius0, fDiffRadius);
- bMatrix[SkMatrix::kMScaleX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMScaleX]) +
- SkScalarMul(r0dr, bMatrix[SkMatrix::kMPersp0]));
- bMatrix[SkMatrix::kMSkewX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMSkewX]) +
- SkScalarMul(r0dr, bMatrix[SkMatrix::kMPersp1]));
- bMatrix[SkMatrix::kMTransX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMTransX]) +
- SkScalarMul(r0dr, bMatrix[SkMatrix::kMPersp2]));
- this->addCoordTransform(&fBTransform);
- }
-
- GR_DECLARE_EFFECT_TEST;
-
- // @{
- // Cache of values - these can change arbitrarily, EXCEPT
- // we shouldn't change between degenerate and non-degenerate?!
-
- GrCoordTransform fBTransform;
- SkScalar fCenterX1;
- SkScalar fRadius0;
- SkScalar fDiffRadius;
-
- // @}
-
- typedef GrGradientEffect INHERITED;
-};
-
-GR_DEFINE_EFFECT_TEST(GrConical2Gradient);
-
-GrEffectRef* GrConical2Gradient::TestCreate(SkRandom* random,
- GrContext* context,
- const GrDrawTargetCaps&,
- GrTexture**) {
- SkPoint center1 = {random->nextUScalar1(), random->nextUScalar1()};
- SkScalar radius1 = random->nextUScalar1();
- SkPoint center2;
- SkScalar radius2;
- do {
- center2.set(random->nextUScalar1(), random->nextUScalar1());
- radius2 = random->nextUScalar1 ();
- // If the circles are identical the factory will give us an empty shader.
- } while (radius1 == radius2 && center1 == center2);
-
- SkColor colors[kMaxRandomGradientColors];
- SkScalar stopsArray[kMaxRandomGradientColors];
- SkScalar* stops = stopsArray;
- SkShader::TileMode tm;
- int colorCount = RandomGradientParams(random, colors, &stops, &tm);
- SkAutoTUnref<SkShader> shader(SkGradientShader::CreateTwoPointConical(center1, radius1,
- center2, radius2,
- colors, stops, colorCount,
- tm));
- SkPaint paint;
- return shader->asNewEffect(context, paint);
-}
-
-
-/////////////////////////////////////////////////////////////////////
-
-GrGLConical2Gradient::GrGLConical2Gradient(const GrBackendEffectFactory& factory,
- const GrDrawEffect& drawEffect)
- : INHERITED(factory)
- , fVSVaryingName(NULL)
- , fFSVaryingName(NULL)
- , fCachedCenter(SK_ScalarMax)
- , fCachedRadius(-SK_ScalarMax)
- , fCachedDiffRadius(-SK_ScalarMax) {
-
- const GrConical2Gradient& data = drawEffect.castEffect<GrConical2Gradient>();
- fIsDegenerate = data.isDegenerate();
-}
-
-void GrGLConical2Gradient::emitCode(GrGLShaderBuilder* builder,
- const GrDrawEffect&,
- EffectKey key,
- const char* outputColor,
- const char* inputColor,
- const TransformedCoordsArray& coords,
- const TextureSamplerArray& samplers) {
- this->emitUniforms(builder, key);
- fParamUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_Visibility,
- kFloat_GrSLType, "Conical2FSParams", 6);
-
- SkString cName("c");
- SkString ac4Name("ac4");
- SkString dName("d");
- SkString qName("q");
- SkString r0Name("r0");
- SkString r1Name("r1");
- SkString tName("t");
- SkString p0; // 4a
- SkString p1; // 1/a
- SkString p2; // distance between centers
- SkString p3; // start radius
- SkString p4; // start radius squared
- SkString p5; // difference in radii (r1 - r0)
-
- builder->getUniformVariable(fParamUni).appendArrayAccess(0, &p0);
- builder->getUniformVariable(fParamUni).appendArrayAccess(1, &p1);
- builder->getUniformVariable(fParamUni).appendArrayAccess(2, &p2);
- builder->getUniformVariable(fParamUni).appendArrayAccess(3, &p3);
- builder->getUniformVariable(fParamUni).appendArrayAccess(4, &p4);
- builder->getUniformVariable(fParamUni).appendArrayAccess(5, &p5);
-
- // We interpolate the linear component in coords[1].
- SkASSERT(coords[0].type() == coords[1].type());
- const char* coords2D;
- SkString bVar;
- if (kVec3f_GrSLType == coords[0].type()) {
- builder->fsCodeAppendf("\tvec3 interpolants = vec3(%s.xy, %s.x) / %s.z;\n",
- coords[0].c_str(), coords[1].c_str(), coords[0].c_str());
- coords2D = "interpolants.xy";
- bVar = "interpolants.z";
- } else {
- coords2D = coords[0].c_str();
- bVar.printf("%s.x", coords[1].c_str());
- }
-
- // output will default to transparent black (we simply won't write anything
- // else to it if invalid, instead of discarding or returning prematurely)
- builder->fsCodeAppendf("\t%s = vec4(0.0,0.0,0.0,0.0);\n", outputColor);
-
- // c = (x^2)+(y^2) - params[4]
- builder->fsCodeAppendf("\tfloat %s = dot(%s, %s) - %s;\n",
- cName.c_str(), coords2D, coords2D, p4.c_str());
-
- // Non-degenerate case (quadratic)
- if (!fIsDegenerate) {
-
- // ac4 = params[0] * c
- builder->fsCodeAppendf("\tfloat %s = %s * %s;\n", ac4Name.c_str(), p0.c_str(),
- cName.c_str());
-
- // d = b^2 - ac4
- builder->fsCodeAppendf("\tfloat %s = %s * %s - %s;\n", dName.c_str(),
- bVar.c_str(), bVar.c_str(), ac4Name.c_str());
-
- // only proceed if discriminant is >= 0
- builder->fsCodeAppendf("\tif (%s >= 0.0) {\n", dName.c_str());
-
- // intermediate value we'll use to compute the roots
- // q = -0.5 * (b +/- sqrt(d))
- builder->fsCodeAppendf("\t\tfloat %s = -0.5 * (%s + (%s < 0.0 ? -1.0 : 1.0)"
- " * sqrt(%s));\n", qName.c_str(), bVar.c_str(),
- bVar.c_str(), dName.c_str());
-
- // compute both roots
- // r0 = q * params[1]
- builder->fsCodeAppendf("\t\tfloat %s = %s * %s;\n", r0Name.c_str(),
- qName.c_str(), p1.c_str());
- // r1 = c / q
- builder->fsCodeAppendf("\t\tfloat %s = %s / %s;\n", r1Name.c_str(),
- cName.c_str(), qName.c_str());
-
- // Note: If there are two roots that both generate radius(t) > 0, the
- // Canvas spec says to choose the larger t.
-
- // so we'll look at the larger one first:
- builder->fsCodeAppendf("\t\tfloat %s = max(%s, %s);\n", tName.c_str(),
- r0Name.c_str(), r1Name.c_str());
-
- // if r(t) > 0, then we're done; t will be our x coordinate
- builder->fsCodeAppendf("\t\tif (%s * %s + %s > 0.0) {\n", tName.c_str(),
- p5.c_str(), p3.c_str());
-
- builder->fsCodeAppend("\t\t");
- this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, samplers);
-
- // otherwise, if r(t) for the larger root was <= 0, try the other root
- builder->fsCodeAppend("\t\t} else {\n");
- builder->fsCodeAppendf("\t\t\t%s = min(%s, %s);\n", tName.c_str(),
- r0Name.c_str(), r1Name.c_str());
-
- // if r(t) > 0 for the smaller root, then t will be our x coordinate
- builder->fsCodeAppendf("\t\t\tif (%s * %s + %s > 0.0) {\n",
- tName.c_str(), p5.c_str(), p3.c_str());
-
- builder->fsCodeAppend("\t\t\t");
- this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, samplers);
-
- // end if (r(t) > 0) for smaller root
- builder->fsCodeAppend("\t\t\t}\n");
- // end if (r(t) > 0), else, for larger root
- builder->fsCodeAppend("\t\t}\n");
- // end if (discriminant >= 0)
- builder->fsCodeAppend("\t}\n");
- } else {
-
- // linear case: t = -c/b
- builder->fsCodeAppendf("\tfloat %s = -(%s / %s);\n", tName.c_str(),
- cName.c_str(), bVar.c_str());
-
- // if r(t) > 0, then t will be the x coordinate
- builder->fsCodeAppendf("\tif (%s * %s + %s > 0.0) {\n", tName.c_str(),
- p5.c_str(), p3.c_str());
- builder->fsCodeAppend("\t");
- this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, samplers);
- builder->fsCodeAppend("\t}\n");
- }
-}
-
-void GrGLConical2Gradient::setData(const GrGLUniformManager& uman,
- const GrDrawEffect& drawEffect) {
- INHERITED::setData(uman, drawEffect);
- const GrConical2Gradient& data = drawEffect.castEffect<GrConical2Gradient>();
- SkASSERT(data.isDegenerate() == fIsDegenerate);
- SkScalar centerX1 = data.center();
- SkScalar radius0 = data.radius();
- SkScalar diffRadius = data.diffRadius();
-
- if (fCachedCenter != centerX1 ||
- fCachedRadius != radius0 ||
- fCachedDiffRadius != diffRadius) {
-
- SkScalar a = SkScalarMul(centerX1, centerX1) - diffRadius * diffRadius;
-
- // When we're in the degenerate (linear) case, the second
- // value will be INF but the program doesn't read it. (We
- // use the same 6 uniforms even though we don't need them
- // all in the linear case just to keep the code complexity
- // down).
- float values[6] = {
- SkScalarToFloat(a * 4),
- 1.f / (SkScalarToFloat(a)),
- SkScalarToFloat(centerX1),
- SkScalarToFloat(radius0),
- SkScalarToFloat(SkScalarMul(radius0, radius0)),
- SkScalarToFloat(diffRadius)
- };
-
- uman.set1fv(fParamUni, 6, values);
- fCachedCenter = centerX1;
- fCachedRadius = radius0;
- fCachedDiffRadius = diffRadius;
- }
-}
+#include "SkGr.h"
-GrGLEffect::EffectKey GrGLConical2Gradient::GenKey(const GrDrawEffect& drawEffect,
- const GrGLCaps&) {
- enum {
- kIsDegenerate = 1 << kBaseKeyBitCnt,
- };
-
- EffectKey key = GenBaseGradientKey(drawEffect);
- if (drawEffect.castEffect<GrConical2Gradient>().isDegenerate()) {
- key |= kIsDegenerate;
- }
- return key;
-}
-
-/////////////////////////////////////////////////////////////////////
-
-GrEffectRef* SkTwoPointConicalGradient::asNewEffect(GrContext* context, const SkPaint&) const {
+bool SkTwoPointConicalGradient::asNewEffect(GrContext* context, const SkPaint& paint,
+ const SkMatrix* localMatrix, GrColor* grColor,
+ GrEffectRef** grEffect) const {
SkASSERT(NULL != context);
SkASSERT(fPtsToUnit.isIdentity());
- // invert the localM, translate to center1, rotate so center2 is on x axis.
- SkMatrix matrix;
- if (!this->getLocalMatrix().invert(&matrix)) {
- return NULL;
- }
- matrix.postTranslate(-fCenter1.fX, -fCenter1.fY);
-
- SkPoint diff = fCenter2 - fCenter1;
- SkScalar diffLen = diff.length();
- if (0 != diffLen) {
- SkScalar invDiffLen = SkScalarInvert(diffLen);
- SkMatrix rot;
- rot.setSinCos(-SkScalarMul(invDiffLen, diff.fY),
- SkScalarMul(invDiffLen, diff.fX));
- matrix.postConcat(rot);
- }
- return GrConical2Gradient::Create(context, *this, matrix, fTileMode);
+ *grEffect = Gr2PtConicalGradientEffect::Create(context, *this, fTileMode, localMatrix);
+ *grColor = SkColor2GrColorJustAlpha(paint.getColor());
+ return true;
}
#else
-GrEffectRef* SkTwoPointConicalGradient::asNewEffect(GrContext*, const SkPaint&) const {
+bool SkTwoPointConicalGradient::asNewEffect(GrContext* context, const SkPaint& paint,
+ const SkMatrix* localMatrix, GrColor* grColor,
+ GrEffectRef** grEffect) const {
SkDEBUGFAIL("Should not call in GPU-less build");
- return NULL;
+ return false;
}
#endif
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkTwoPointConicalGradient::toString(SkString* str) const {
str->append("SkTwoPointConicalGradient: (");
diff --git a/chromium/third_party/skia/src/effects/gradients/SkTwoPointConicalGradient.h b/chromium/third_party/skia/src/effects/gradients/SkTwoPointConicalGradient.h
index 1358f0b2ac4..f345d08e31b 100644
--- a/chromium/third_party/skia/src/effects/gradients/SkTwoPointConicalGradient.h
+++ b/chromium/third_party/skia/src/effects/gradients/SkTwoPointConicalGradient.h
@@ -6,11 +6,13 @@
* found in the LICENSE file.
*/
- #ifndef SkTwoPointConicalGradient_DEFINED
- #define SkTwoPointConicalGradient_DEFINED
+#ifndef SkTwoPointConicalGradient_DEFINED
+#define SkTwoPointConicalGradient_DEFINED
#include "SkGradientShaderPriv.h"
+// TODO(dominikg): Worth making it truly immutable (i.e. set values in constructor)?
+// Should only be initialized once via init(). Immutable afterwards.
struct TwoPtRadial {
enum {
kDontDrawT = 0x80000000
@@ -23,16 +25,11 @@ struct TwoPtRadial {
float fA;
float fRadius2;
float fRDR;
+ bool fFlipped;
void init(const SkPoint& center0, SkScalar rad0,
- const SkPoint& center1, SkScalar rad1);
-
- // used by setup and nextT
- float fRelX, fRelY, fIncX, fIncY;
- float fB, fDB;
-
- void setup(SkScalar fx, SkScalar fy, SkScalar dfx, SkScalar dfy);
- SkFixed nextT();
+ const SkPoint& center1, SkScalar rad1,
+ bool flipped);
static bool DontDrawT(SkFixed t) {
return kDontDrawT == (uint32_t)t;
@@ -47,38 +44,55 @@ class SkTwoPointConicalGradient : public SkGradientShaderBase {
public:
SkTwoPointConicalGradient(const SkPoint& start, SkScalar startRadius,
const SkPoint& end, SkScalar endRadius,
- const Descriptor&);
+ bool flippedGrad, const Descriptor&,
+ const SkMatrix* localMatrix);
+
+
+ virtual size_t contextSize() const SK_OVERRIDE;
- virtual void shadeSpan(int x, int y, SkPMColor* dstCParam,
- int count) SK_OVERRIDE;
- virtual bool setContext(const SkBitmap& device,
- const SkPaint& paint,
- const SkMatrix& matrix) SK_OVERRIDE;
+ class TwoPointConicalGradientContext : public SkGradientShaderBase::GradientShaderBaseContext {
+ public:
+ TwoPointConicalGradientContext(const SkTwoPointConicalGradient&, const ContextRec&);
+ ~TwoPointConicalGradientContext() {}
+
+ virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE;
+
+ private:
+ typedef SkGradientShaderBase::GradientShaderBaseContext INHERITED;
+ };
virtual BitmapType asABitmap(SkBitmap* bitmap,
SkMatrix* matrix,
TileMode* xy) const;
virtual SkShader::GradientType asAGradient(GradientInfo* info) const SK_OVERRIDE;
- virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint& paint) const SK_OVERRIDE;
+ virtual bool asNewEffect(GrContext*, const SkPaint&, const SkMatrix*, GrColor* grColor,
+ GrEffectRef**) const SK_OVERRIDE;
virtual bool isOpaque() const SK_OVERRIDE;
SkScalar getCenterX1() const { return SkPoint::Distance(fCenter1, fCenter2); }
SkScalar getStartRadius() const { return fRadius1; }
SkScalar getDiffRadius() const { return fRadius2 - fRadius1; }
+ const SkPoint& getStartCenter() const { return fCenter1; }
+ const SkPoint& getEndCenter() const { return fCenter2; }
+ SkScalar getEndRadius() const { return fRadius2; }
+ bool isFlippedGrad() const { return fFlippedGrad; }
- SK_DEVELOPER_TO_STRING()
+ SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTwoPointConicalGradient)
protected:
- SkTwoPointConicalGradient(SkFlattenableReadBuffer& buffer);
- virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE;
+ SkTwoPointConicalGradient(SkReadBuffer& buffer);
+ virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE;
+ virtual Context* onCreateContext(const ContextRec&, void* storage) const SK_OVERRIDE;
private:
+ SkPoint fCenter1;
+ SkPoint fCenter2;
+ SkScalar fRadius1;
+ SkScalar fRadius2;
+ bool fFlippedGrad;
+
typedef SkGradientShaderBase INHERITED;
- const SkPoint fCenter1;
- const SkPoint fCenter2;
- const SkScalar fRadius1;
- const SkScalar fRadius2;
};
#endif
diff --git a/chromium/third_party/skia/src/effects/gradients/SkTwoPointConicalGradient_gpu.cpp b/chromium/third_party/skia/src/effects/gradients/SkTwoPointConicalGradient_gpu.cpp
new file mode 100644
index 00000000000..4f9f7584678
--- /dev/null
+++ b/chromium/third_party/skia/src/effects/gradients/SkTwoPointConicalGradient_gpu.cpp
@@ -0,0 +1,1330 @@
+
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkTwoPointConicalGradient_gpu.h"
+
+#include "SkTwoPointConicalGradient.h"
+
+#if SK_SUPPORT_GPU
+#include "GrTBackendEffectFactory.h"
+// For brevity
+typedef GrGLUniformManager::UniformHandle UniformHandle;
+
+static const SkScalar kErrorTol = 0.00001f;
+static const SkScalar kEdgeErrorTol = 5.f * kErrorTol;
+
+/**
+ * We have three general cases for 2pt conical gradients. First we always assume that
+ * the start radius <= end radius. Our first case (kInside_) is when the start circle
+ * is completely enclosed by the end circle. The second case (kOutside_) is the case
+ * when the start circle is either completely outside the end circle or the circles
+ * overlap. The final case (kEdge_) is when the start circle is inside the end one,
+ * but the two are just barely touching at 1 point along their edges.
+ */
+enum ConicalType {
+ kInside_ConicalType,
+ kOutside_ConicalType,
+ kEdge_ConicalType,
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static void set_matrix_edge_conical(const SkTwoPointConicalGradient& shader,
+ SkMatrix* invLMatrix) {
+ // Inverse of the current local matrix is passed in then,
+ // translate to center1, rotate so center2 is on x axis.
+ const SkPoint& center1 = shader.getStartCenter();
+ const SkPoint& center2 = shader.getEndCenter();
+
+ invLMatrix->postTranslate(-center1.fX, -center1.fY);
+
+ SkPoint diff = center2 - center1;
+ SkScalar diffLen = diff.length();
+ if (0 != diffLen) {
+ SkScalar invDiffLen = SkScalarInvert(diffLen);
+ SkMatrix rot;
+ rot.setSinCos(-SkScalarMul(invDiffLen, diff.fY),
+ SkScalarMul(invDiffLen, diff.fX));
+ invLMatrix->postConcat(rot);
+ }
+}
+
+class GLEdge2PtConicalEffect;
+
+class Edge2PtConicalEffect : public GrGradientEffect {
+public:
+
+ static GrEffectRef* Create(GrContext* ctx,
+ const SkTwoPointConicalGradient& shader,
+ const SkMatrix& matrix,
+ SkShader::TileMode tm) {
+ AutoEffectUnref effect(SkNEW_ARGS(Edge2PtConicalEffect, (ctx, shader, matrix, tm)));
+ return CreateEffectRef(effect);
+ }
+
+ virtual ~Edge2PtConicalEffect() {}
+
+ static const char* Name() { return "Two-Point Conical Gradient Edge Touching"; }
+ virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
+
+ // The radial gradient parameters can collapse to a linear (instead of quadratic) equation.
+ SkScalar center() const { return fCenterX1; }
+ SkScalar diffRadius() const { return fDiffRadius; }
+ SkScalar radius() const { return fRadius0; }
+
+ typedef GLEdge2PtConicalEffect GLEffect;
+
+private:
+ virtual bool onIsEqual(const GrEffect& sBase) const SK_OVERRIDE {
+ const Edge2PtConicalEffect& s = CastEffect<Edge2PtConicalEffect>(sBase);
+ return (INHERITED::onIsEqual(sBase) &&
+ this->fCenterX1 == s.fCenterX1 &&
+ this->fRadius0 == s.fRadius0 &&
+ this->fDiffRadius == s.fDiffRadius);
+ }
+
+ Edge2PtConicalEffect(GrContext* ctx,
+ const SkTwoPointConicalGradient& shader,
+ const SkMatrix& matrix,
+ SkShader::TileMode tm)
+ : INHERITED(ctx, shader, matrix, tm),
+ fCenterX1(shader.getCenterX1()),
+ fRadius0(shader.getStartRadius()),
+ fDiffRadius(shader.getDiffRadius()){
+ // We should only be calling this shader if we are degenerate case with touching circles
+ // When deciding if we are in edge case, we scaled by the end radius for cases when the
+ // start radius was close to zero, otherwise we scaled by the start radius
+ SkASSERT(SkScalarAbs(SkScalarAbs(fDiffRadius) - SkScalarAbs(fCenterX1)) <
+ kEdgeErrorTol * (fRadius0 < kErrorTol ? shader.getEndRadius() : fRadius0));
+
+ // We pass the linear part of the quadratic as a varying.
+ // float b = -2.0 * (fCenterX1 * x + fRadius0 * fDiffRadius * z)
+ fBTransform = this->getCoordTransform();
+ SkMatrix& bMatrix = *fBTransform.accessMatrix();
+ SkScalar r0dr = SkScalarMul(fRadius0, fDiffRadius);
+ bMatrix[SkMatrix::kMScaleX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMScaleX]) +
+ SkScalarMul(r0dr, bMatrix[SkMatrix::kMPersp0]));
+ bMatrix[SkMatrix::kMSkewX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMSkewX]) +
+ SkScalarMul(r0dr, bMatrix[SkMatrix::kMPersp1]));
+ bMatrix[SkMatrix::kMTransX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMTransX]) +
+ SkScalarMul(r0dr, bMatrix[SkMatrix::kMPersp2]));
+ this->addCoordTransform(&fBTransform);
+ }
+
+ GR_DECLARE_EFFECT_TEST;
+
+ // @{
+ // Cache of values - these can change arbitrarily, EXCEPT
+ // we shouldn't change between degenerate and non-degenerate?!
+
+ GrCoordTransform fBTransform;
+ SkScalar fCenterX1;
+ SkScalar fRadius0;
+ SkScalar fDiffRadius;
+
+ // @}
+
+ typedef GrGradientEffect INHERITED;
+};
+
+class GLEdge2PtConicalEffect : public GrGLGradientEffect {
+public:
+ GLEdge2PtConicalEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&);
+ virtual ~GLEdge2PtConicalEffect() { }
+
+ virtual void emitCode(GrGLShaderBuilder*,
+ const GrDrawEffect&,
+ EffectKey,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray&) SK_OVERRIDE;
+ virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
+
+ static EffectKey GenKey(const GrDrawEffect&, const GrGLCaps& caps);
+
+protected:
+ UniformHandle fParamUni;
+
+ const char* fVSVaryingName;
+ const char* fFSVaryingName;
+
+ // @{
+ /// Values last uploaded as uniforms
+
+ SkScalar fCachedRadius;
+ SkScalar fCachedDiffRadius;
+
+ // @}
+
+private:
+ typedef GrGLGradientEffect INHERITED;
+
+};
+
+const GrBackendEffectFactory& Edge2PtConicalEffect::getFactory() const {
+ return GrTBackendEffectFactory<Edge2PtConicalEffect>::getInstance();
+}
+
+GR_DEFINE_EFFECT_TEST(Edge2PtConicalEffect);
+
+GrEffectRef* Edge2PtConicalEffect::TestCreate(SkRandom* random,
+ GrContext* context,
+ const GrDrawTargetCaps&,
+ GrTexture**) {
+ SkPoint center1 = {random->nextUScalar1(), random->nextUScalar1()};
+ SkScalar radius1 = random->nextUScalar1();
+ SkPoint center2;
+ SkScalar radius2;
+ do {
+ center2.set(random->nextUScalar1(), random->nextUScalar1());
+ // If the circles are identical the factory will give us an empty shader.
+ // This will happen if we pick identical centers
+ } while (center1 == center2);
+
+ // Below makes sure that circle one is contained within circle two
+ // and both circles are touching on an edge
+ SkPoint diff = center2 - center1;
+ SkScalar diffLen = diff.length();
+ radius2 = radius1 + diffLen;
+
+ SkColor colors[kMaxRandomGradientColors];
+ SkScalar stopsArray[kMaxRandomGradientColors];
+ SkScalar* stops = stopsArray;
+ SkShader::TileMode tm;
+ int colorCount = RandomGradientParams(random, colors, &stops, &tm);
+ SkAutoTUnref<SkShader> shader(SkGradientShader::CreateTwoPointConical(center1, radius1,
+ center2, radius2,
+ colors, stops, colorCount,
+ tm));
+ SkPaint paint;
+ GrEffectRef* effect;
+ GrColor grColor;
+ shader->asNewEffect(context, paint, NULL, &grColor, &effect);
+ return effect;
+}
+
+GLEdge2PtConicalEffect::GLEdge2PtConicalEffect(const GrBackendEffectFactory& factory,
+ const GrDrawEffect& drawEffect)
+ : INHERITED(factory)
+ , fVSVaryingName(NULL)
+ , fFSVaryingName(NULL)
+ , fCachedRadius(-SK_ScalarMax)
+ , fCachedDiffRadius(-SK_ScalarMax) {}
+
+void GLEdge2PtConicalEffect::emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect&,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray& coords,
+ const TextureSamplerArray& samplers) {
+ this->emitUniforms(builder, key);
+ fParamUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_Visibility,
+ kFloat_GrSLType, "Conical2FSParams", 3);
+
+ SkString cName("c");
+ SkString tName("t");
+ SkString p0; // start radius
+ SkString p1; // start radius squared
+ SkString p2; // difference in radii (r1 - r0)
+
+ builder->getUniformVariable(fParamUni).appendArrayAccess(0, &p0);
+ builder->getUniformVariable(fParamUni).appendArrayAccess(1, &p1);
+ builder->getUniformVariable(fParamUni).appendArrayAccess(2, &p2);
+
+ // We interpolate the linear component in coords[1].
+ SkASSERT(coords[0].type() == coords[1].type());
+ const char* coords2D;
+ SkString bVar;
+ if (kVec3f_GrSLType == coords[0].type()) {
+ builder->fsCodeAppendf("\tvec3 interpolants = vec3(%s.xy / %s.z, %s.x / %s.z);\n",
+ coords[0].c_str(), coords[0].c_str(), coords[1].c_str(), coords[1].c_str());
+ coords2D = "interpolants.xy";
+ bVar = "interpolants.z";
+ } else {
+ coords2D = coords[0].c_str();
+ bVar.printf("%s.x", coords[1].c_str());
+ }
+
+ // output will default to transparent black (we simply won't write anything
+ // else to it if invalid, instead of discarding or returning prematurely)
+ builder->fsCodeAppendf("\t%s = vec4(0.0,0.0,0.0,0.0);\n", outputColor);
+
+ // c = (x^2)+(y^2) - params[1]
+ builder->fsCodeAppendf("\tfloat %s = dot(%s, %s) - %s;\n",
+ cName.c_str(), coords2D, coords2D, p1.c_str());
+
+ // linear case: t = -c/b
+ builder->fsCodeAppendf("\tfloat %s = -(%s / %s);\n", tName.c_str(),
+ cName.c_str(), bVar.c_str());
+
+ // if r(t) > 0, then t will be the x coordinate
+ builder->fsCodeAppendf("\tif (%s * %s + %s > 0.0) {\n", tName.c_str(),
+ p2.c_str(), p0.c_str());
+ builder->fsCodeAppend("\t");
+ this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, samplers);
+ builder->fsCodeAppend("\t}\n");
+}
+
+void GLEdge2PtConicalEffect::setData(const GrGLUniformManager& uman,
+ const GrDrawEffect& drawEffect) {
+ INHERITED::setData(uman, drawEffect);
+ const Edge2PtConicalEffect& data = drawEffect.castEffect<Edge2PtConicalEffect>();
+ SkScalar radius0 = data.radius();
+ SkScalar diffRadius = data.diffRadius();
+
+ if (fCachedRadius != radius0 ||
+ fCachedDiffRadius != diffRadius) {
+
+ float values[3] = {
+ SkScalarToFloat(radius0),
+ SkScalarToFloat(SkScalarMul(radius0, radius0)),
+ SkScalarToFloat(diffRadius)
+ };
+
+ uman.set1fv(fParamUni, 3, values);
+ fCachedRadius = radius0;
+ fCachedDiffRadius = diffRadius;
+ }
+}
+
+GrGLEffect::EffectKey GLEdge2PtConicalEffect::GenKey(const GrDrawEffect& drawEffect,
+ const GrGLCaps&) {
+ return GenBaseGradientKey(drawEffect);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Focal Conical Gradients
+//////////////////////////////////////////////////////////////////////////////
+
+static ConicalType set_matrix_focal_conical(const SkTwoPointConicalGradient& shader,
+ SkMatrix* invLMatrix, SkScalar* focalX) {
+ // Inverse of the current local matrix is passed in then,
+ // translate, scale, and rotate such that endCircle is unit circle on x-axis,
+ // and focal point is at the origin.
+ ConicalType conicalType;
+ const SkPoint& focal = shader.getStartCenter();
+ const SkPoint& centerEnd = shader.getEndCenter();
+ SkScalar radius = shader.getEndRadius();
+ SkScalar invRadius = 1.f / radius;
+
+ SkMatrix matrix;
+
+ matrix.setTranslate(-centerEnd.fX, -centerEnd.fY);
+ matrix.postScale(invRadius, invRadius);
+
+ SkPoint focalTrans;
+ matrix.mapPoints(&focalTrans, &focal, 1);
+ *focalX = focalTrans.length();
+
+ if (0.f != *focalX) {
+ SkScalar invFocalX = SkScalarInvert(*focalX);
+ SkMatrix rot;
+ rot.setSinCos(-SkScalarMul(invFocalX, focalTrans.fY),
+ SkScalarMul(invFocalX, focalTrans.fX));
+ matrix.postConcat(rot);
+ }
+
+ matrix.postTranslate(-(*focalX), 0.f);
+
+ // If the focal point is touching the edge of the circle it will
+ // cause a degenerate case that must be handled separately
+ // kEdgeErrorTol = 5 * kErrorTol was picked after manual testing the
+ // stability trade off versus the linear approx used in the Edge Shader
+ if (SkScalarAbs(1.f - (*focalX)) < kEdgeErrorTol) {
+ return kEdge_ConicalType;
+ }
+
+ // Scale factor 1 / (1 - focalX * focalX)
+ SkScalar oneMinusF2 = 1.f - SkScalarMul(*focalX, *focalX);
+ SkScalar s = SkScalarDiv(1.f, oneMinusF2);
+
+
+ if (s >= 0.f) {
+ conicalType = kInside_ConicalType;
+ matrix.postScale(s, s * SkScalarSqrt(oneMinusF2));
+ } else {
+ conicalType = kOutside_ConicalType;
+ matrix.postScale(s, s);
+ }
+
+ invLMatrix->postConcat(matrix);
+
+ return conicalType;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+class GLFocalOutside2PtConicalEffect;
+
+class FocalOutside2PtConicalEffect : public GrGradientEffect {
+public:
+
+ static GrEffectRef* Create(GrContext* ctx,
+ const SkTwoPointConicalGradient& shader,
+ const SkMatrix& matrix,
+ SkShader::TileMode tm,
+ SkScalar focalX) {
+ AutoEffectUnref effect(SkNEW_ARGS(FocalOutside2PtConicalEffect, (ctx, shader, matrix, tm, focalX)));
+ return CreateEffectRef(effect);
+ }
+
+ virtual ~FocalOutside2PtConicalEffect() { }
+
+ static const char* Name() { return "Two-Point Conical Gradient Focal Outside"; }
+ virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
+
+ bool isFlipped() const { return fIsFlipped; }
+ SkScalar focal() const { return fFocalX; }
+
+ typedef GLFocalOutside2PtConicalEffect GLEffect;
+
+private:
+ virtual bool onIsEqual(const GrEffect& sBase) const SK_OVERRIDE {
+ const FocalOutside2PtConicalEffect& s = CastEffect<FocalOutside2PtConicalEffect>(sBase);
+ return (INHERITED::onIsEqual(sBase) &&
+ this->fFocalX == s.fFocalX &&
+ this->fIsFlipped == s.fIsFlipped);
+ }
+
+ FocalOutside2PtConicalEffect(GrContext* ctx,
+ const SkTwoPointConicalGradient& shader,
+ const SkMatrix& matrix,
+ SkShader::TileMode tm,
+ SkScalar focalX)
+ : INHERITED(ctx, shader, matrix, tm), fFocalX(focalX), fIsFlipped(shader.isFlippedGrad()) {}
+
+ GR_DECLARE_EFFECT_TEST;
+
+ SkScalar fFocalX;
+ bool fIsFlipped;
+
+ typedef GrGradientEffect INHERITED;
+};
+
+class GLFocalOutside2PtConicalEffect : public GrGLGradientEffect {
+public:
+ GLFocalOutside2PtConicalEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&);
+ virtual ~GLFocalOutside2PtConicalEffect() { }
+
+ virtual void emitCode(GrGLShaderBuilder*,
+ const GrDrawEffect&,
+ EffectKey,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray&) SK_OVERRIDE;
+ virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
+
+ static EffectKey GenKey(const GrDrawEffect&, const GrGLCaps& caps);
+
+protected:
+ UniformHandle fParamUni;
+
+ const char* fVSVaryingName;
+ const char* fFSVaryingName;
+
+ bool fIsFlipped;
+
+ // @{
+ /// Values last uploaded as uniforms
+
+ SkScalar fCachedFocal;
+
+ // @}
+
+private:
+ typedef GrGLGradientEffect INHERITED;
+
+};
+
+const GrBackendEffectFactory& FocalOutside2PtConicalEffect::getFactory() const {
+ return GrTBackendEffectFactory<FocalOutside2PtConicalEffect>::getInstance();
+}
+
+GR_DEFINE_EFFECT_TEST(FocalOutside2PtConicalEffect);
+
+GrEffectRef* FocalOutside2PtConicalEffect::TestCreate(SkRandom* random,
+ GrContext* context,
+ const GrDrawTargetCaps&,
+ GrTexture**) {
+ SkPoint center1 = {random->nextUScalar1(), random->nextUScalar1()};
+ SkScalar radius1 = 0.f;
+ SkPoint center2;
+ SkScalar radius2;
+ do {
+ center2.set(random->nextUScalar1(), random->nextUScalar1());
+ // Need to make sure the centers are not the same or else focal point will be inside
+ } while (center1 == center2);
+ SkPoint diff = center2 - center1;
+ SkScalar diffLen = diff.length();
+ // Below makes sure that the focal point is not contained within circle two
+ radius2 = random->nextRangeF(0.f, diffLen);
+
+ SkColor colors[kMaxRandomGradientColors];
+ SkScalar stopsArray[kMaxRandomGradientColors];
+ SkScalar* stops = stopsArray;
+ SkShader::TileMode tm;
+ int colorCount = RandomGradientParams(random, colors, &stops, &tm);
+ SkAutoTUnref<SkShader> shader(SkGradientShader::CreateTwoPointConical(center1, radius1,
+ center2, radius2,
+ colors, stops, colorCount,
+ tm));
+ SkPaint paint;
+ GrEffectRef* effect;
+ GrColor grColor;
+ shader->asNewEffect(context, paint, NULL, &grColor, &effect);
+ return effect;
+}
+
+GLFocalOutside2PtConicalEffect::GLFocalOutside2PtConicalEffect(const GrBackendEffectFactory& factory,
+ const GrDrawEffect& drawEffect)
+ : INHERITED(factory)
+ , fVSVaryingName(NULL)
+ , fFSVaryingName(NULL)
+ , fCachedFocal(SK_ScalarMax) {
+ const FocalOutside2PtConicalEffect& data = drawEffect.castEffect<FocalOutside2PtConicalEffect>();
+ fIsFlipped = data.isFlipped();
+}
+
+void GLFocalOutside2PtConicalEffect::emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect&,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray& coords,
+ const TextureSamplerArray& samplers) {
+ this->emitUniforms(builder, key);
+ fParamUni = builder->addUniformArray(GrGLShaderBuilder::kFragment_Visibility,
+ kFloat_GrSLType, "Conical2FSParams", 2);
+ SkString tName("t");
+ SkString p0; // focalX
+ SkString p1; // 1 - focalX * focalX
+
+ builder->getUniformVariable(fParamUni).appendArrayAccess(0, &p0);
+ builder->getUniformVariable(fParamUni).appendArrayAccess(1, &p1);
+
+ // if we have a vec3 from being in perspective, convert it to a vec2 first
+ SkString coords2DString = builder->ensureFSCoords2D(coords, 0);
+ const char* coords2D = coords2DString.c_str();
+
+ // t = p.x * focal.x +/- sqrt(p.x^2 + (1 - focal.x^2) * p.y^2)
+
+ // output will default to transparent black (we simply won't write anything
+ // else to it if invalid, instead of discarding or returning prematurely)
+ builder->fsCodeAppendf("\t%s = vec4(0.0,0.0,0.0,0.0);\n", outputColor);
+
+ builder->fsCodeAppendf("\tfloat xs = %s.x * %s.x;\n", coords2D, coords2D);
+ builder->fsCodeAppendf("\tfloat ys = %s.y * %s.y;\n", coords2D, coords2D);
+ builder->fsCodeAppendf("\tfloat d = xs + %s * ys;\n", p1.c_str());
+
+ // Must check to see if we flipped the circle order (to make sure start radius < end radius)
+ // If so we must also flip sign on sqrt
+ if (!fIsFlipped) {
+ builder->fsCodeAppendf("\tfloat %s = %s.x * %s + sqrt(d);\n", tName.c_str(),
+ coords2D, p0.c_str());
+ } else {
+ builder->fsCodeAppendf("\tfloat %s = %s.x * %s - sqrt(d);\n", tName.c_str(),
+ coords2D, p0.c_str());
+ }
+
+ builder->fsCodeAppendf("\tif (%s >= 0.0 && d >= 0.0) {\n", tName.c_str());
+ builder->fsCodeAppend("\t\t");
+ this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, samplers);
+ builder->fsCodeAppend("\t}\n");
+}
+
+void GLFocalOutside2PtConicalEffect::setData(const GrGLUniformManager& uman,
+ const GrDrawEffect& drawEffect) {
+ INHERITED::setData(uman, drawEffect);
+ const FocalOutside2PtConicalEffect& data = drawEffect.castEffect<FocalOutside2PtConicalEffect>();
+ SkASSERT(data.isFlipped() == fIsFlipped);
+ SkScalar focal = data.focal();
+
+ if (fCachedFocal != focal) {
+ SkScalar oneMinus2F = 1.f - SkScalarMul(focal, focal);
+
+ float values[2] = {
+ SkScalarToFloat(focal),
+ SkScalarToFloat(oneMinus2F),
+ };
+
+ uman.set1fv(fParamUni, 2, values);
+ fCachedFocal = focal;
+ }
+}
+
+GrGLEffect::EffectKey GLFocalOutside2PtConicalEffect::GenKey(const GrDrawEffect& drawEffect,
+ const GrGLCaps&) {
+ enum {
+ kIsFlipped = 1 << kBaseKeyBitCnt,
+ };
+
+ EffectKey key = GenBaseGradientKey(drawEffect);
+
+ if (drawEffect.castEffect<FocalOutside2PtConicalEffect>().isFlipped()) {
+ key |= kIsFlipped;
+ }
+ return key;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+class GLFocalInside2PtConicalEffect;
+
+class FocalInside2PtConicalEffect : public GrGradientEffect {
+public:
+
+ static GrEffectRef* Create(GrContext* ctx,
+ const SkTwoPointConicalGradient& shader,
+ const SkMatrix& matrix,
+ SkShader::TileMode tm,
+ SkScalar focalX) {
+ AutoEffectUnref effect(SkNEW_ARGS(FocalInside2PtConicalEffect, (ctx, shader, matrix, tm, focalX)));
+ return CreateEffectRef(effect);
+ }
+
+ virtual ~FocalInside2PtConicalEffect() {}
+
+ static const char* Name() { return "Two-Point Conical Gradient Focal Inside"; }
+ virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
+
+ SkScalar focal() const { return fFocalX; }
+
+ typedef GLFocalInside2PtConicalEffect GLEffect;
+
+private:
+ virtual bool onIsEqual(const GrEffect& sBase) const SK_OVERRIDE {
+ const FocalInside2PtConicalEffect& s = CastEffect<FocalInside2PtConicalEffect>(sBase);
+ return (INHERITED::onIsEqual(sBase) &&
+ this->fFocalX == s.fFocalX);
+ }
+
+ FocalInside2PtConicalEffect(GrContext* ctx,
+ const SkTwoPointConicalGradient& shader,
+ const SkMatrix& matrix,
+ SkShader::TileMode tm,
+ SkScalar focalX)
+ : INHERITED(ctx, shader, matrix, tm), fFocalX(focalX) {}
+
+ GR_DECLARE_EFFECT_TEST;
+
+ SkScalar fFocalX;
+
+ typedef GrGradientEffect INHERITED;
+};
+
+class GLFocalInside2PtConicalEffect : public GrGLGradientEffect {
+public:
+ GLFocalInside2PtConicalEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&);
+ virtual ~GLFocalInside2PtConicalEffect() {}
+
+ virtual void emitCode(GrGLShaderBuilder*,
+ const GrDrawEffect&,
+ EffectKey,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray&) SK_OVERRIDE;
+ virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
+
+ static EffectKey GenKey(const GrDrawEffect&, const GrGLCaps& caps);
+
+protected:
+ UniformHandle fFocalUni;
+
+ const char* fVSVaryingName;
+ const char* fFSVaryingName;
+
+ // @{
+ /// Values last uploaded as uniforms
+
+ SkScalar fCachedFocal;
+
+ // @}
+
+private:
+ typedef GrGLGradientEffect INHERITED;
+
+};
+
+const GrBackendEffectFactory& FocalInside2PtConicalEffect::getFactory() const {
+ return GrTBackendEffectFactory<FocalInside2PtConicalEffect>::getInstance();
+}
+
+GR_DEFINE_EFFECT_TEST(FocalInside2PtConicalEffect);
+
+GrEffectRef* FocalInside2PtConicalEffect::TestCreate(SkRandom* random,
+ GrContext* context,
+ const GrDrawTargetCaps&,
+ GrTexture**) {
+ SkPoint center1 = {random->nextUScalar1(), random->nextUScalar1()};
+ SkScalar radius1 = 0.f;
+ SkPoint center2;
+ SkScalar radius2;
+ do {
+ center2.set(random->nextUScalar1(), random->nextUScalar1());
+ // Below makes sure radius2 is larger enouch such that the focal point
+ // is inside the end circle
+ SkScalar increase = random->nextUScalar1();
+ SkPoint diff = center2 - center1;
+ SkScalar diffLen = diff.length();
+ radius2 = diffLen + increase;
+ // If the circles are identical the factory will give us an empty shader.
+ } while (radius1 == radius2 && center1 == center2);
+
+ SkColor colors[kMaxRandomGradientColors];
+ SkScalar stopsArray[kMaxRandomGradientColors];
+ SkScalar* stops = stopsArray;
+ SkShader::TileMode tm;
+ int colorCount = RandomGradientParams(random, colors, &stops, &tm);
+ SkAutoTUnref<SkShader> shader(SkGradientShader::CreateTwoPointConical(center1, radius1,
+ center2, radius2,
+ colors, stops, colorCount,
+ tm));
+ SkPaint paint;
+ GrColor grColor;
+ GrEffectRef* grEffect;
+ shader->asNewEffect(context, paint, NULL, &grColor, &grEffect);
+ return grEffect;
+}
+
+GLFocalInside2PtConicalEffect::GLFocalInside2PtConicalEffect(const GrBackendEffectFactory& factory,
+ const GrDrawEffect& drawEffect)
+ : INHERITED(factory)
+ , fVSVaryingName(NULL)
+ , fFSVaryingName(NULL)
+ , fCachedFocal(SK_ScalarMax) {}
+
+void GLFocalInside2PtConicalEffect::emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect&,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray& coords,
+ const TextureSamplerArray& samplers) {
+ this->emitUniforms(builder, key);
+ fFocalUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kFloat_GrSLType, "Conical2FSParams");
+ SkString tName("t");
+
+ // this is the distance along x-axis from the end center to focal point in
+ // transformed coordinates
+ GrGLShaderVar focal = builder->getUniformVariable(fFocalUni);
+
+ // if we have a vec3 from being in perspective, convert it to a vec2 first
+ SkString coords2DString = builder->ensureFSCoords2D(coords, 0);
+ const char* coords2D = coords2DString.c_str();
+
+ // t = p.x * focalX + length(p)
+ builder->fsCodeAppendf("\tfloat %s = %s.x * %s + length(%s);\n", tName.c_str(),
+ coords2D, focal.c_str(), coords2D);
+
+ this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, samplers);
+}
+
+void GLFocalInside2PtConicalEffect::setData(const GrGLUniformManager& uman,
+ const GrDrawEffect& drawEffect) {
+ INHERITED::setData(uman, drawEffect);
+ const FocalInside2PtConicalEffect& data = drawEffect.castEffect<FocalInside2PtConicalEffect>();
+ SkScalar focal = data.focal();
+
+ if (fCachedFocal != focal) {
+ uman.set1f(fFocalUni, SkScalarToFloat(focal));
+ fCachedFocal = focal;
+ }
+}
+
+GrGLEffect::EffectKey GLFocalInside2PtConicalEffect::GenKey(const GrDrawEffect& drawEffect,
+ const GrGLCaps&) {
+ return GenBaseGradientKey(drawEffect);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Circle Conical Gradients
+//////////////////////////////////////////////////////////////////////////////
+
+struct CircleConicalInfo {
+ SkPoint fCenterEnd;
+ SkScalar fA;
+ SkScalar fB;
+ SkScalar fC;
+};
+
+// Returns focal distance along x-axis in transformed coords
+static ConicalType set_matrix_circle_conical(const SkTwoPointConicalGradient& shader,
+ SkMatrix* invLMatrix, CircleConicalInfo* info) {
+ // Inverse of the current local matrix is passed in then,
+ // translate and scale such that start circle is on the origin and has radius 1
+ const SkPoint& centerStart = shader.getStartCenter();
+ const SkPoint& centerEnd = shader.getEndCenter();
+ SkScalar radiusStart = shader.getStartRadius();
+ SkScalar radiusEnd = shader.getEndRadius();
+
+ SkMatrix matrix;
+
+ matrix.setTranslate(-centerStart.fX, -centerStart.fY);
+
+ SkScalar invStartRad = 1.f / radiusStart;
+ matrix.postScale(invStartRad, invStartRad);
+
+ radiusEnd /= radiusStart;
+
+ SkPoint centerEndTrans;
+ matrix.mapPoints(&centerEndTrans, &centerEnd, 1);
+
+ SkScalar A = centerEndTrans.fX * centerEndTrans.fX + centerEndTrans.fY * centerEndTrans.fY
+ - radiusEnd * radiusEnd + 2 * radiusEnd - 1;
+
+ // Check to see if start circle is inside end circle with edges touching.
+ // If touching we return that it is of kEdge_ConicalType, and leave the matrix setting
+ // to the edge shader. kEdgeErrorTol = 5 * kErrorTol was picked after manual testing
+ // so that C = 1 / A is stable, and the linear approximation used in the Edge shader is
+ // still accurate.
+ if (SkScalarAbs(A) < kEdgeErrorTol) {
+ return kEdge_ConicalType;
+ }
+
+ SkScalar C = 1.f / A;
+ SkScalar B = (radiusEnd - 1.f) * C;
+
+ matrix.postScale(C, C);
+
+ invLMatrix->postConcat(matrix);
+
+ info->fCenterEnd = centerEndTrans;
+ info->fA = A;
+ info->fB = B;
+ info->fC = C;
+
+ // if A ends up being negative, the start circle is contained completely inside the end cirlce
+ if (A < 0.f) {
+ return kInside_ConicalType;
+ }
+ return kOutside_ConicalType;
+}
+
+class GLCircleInside2PtConicalEffect;
+
+class CircleInside2PtConicalEffect : public GrGradientEffect {
+public:
+
+ static GrEffectRef* Create(GrContext* ctx,
+ const SkTwoPointConicalGradient& shader,
+ const SkMatrix& matrix,
+ SkShader::TileMode tm,
+ const CircleConicalInfo& info) {
+ AutoEffectUnref effect(SkNEW_ARGS(CircleInside2PtConicalEffect, (ctx, shader, matrix, tm, info)));
+ return CreateEffectRef(effect);
+ }
+
+ virtual ~CircleInside2PtConicalEffect() {}
+
+ static const char* Name() { return "Two-Point Conical Gradient Inside"; }
+ virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
+
+ SkScalar centerX() const { return fInfo.fCenterEnd.fX; }
+ SkScalar centerY() const { return fInfo.fCenterEnd.fY; }
+ SkScalar A() const { return fInfo.fA; }
+ SkScalar B() const { return fInfo.fB; }
+ SkScalar C() const { return fInfo.fC; }
+
+ typedef GLCircleInside2PtConicalEffect GLEffect;
+
+private:
+ virtual bool onIsEqual(const GrEffect& sBase) const SK_OVERRIDE {
+ const CircleInside2PtConicalEffect& s = CastEffect<CircleInside2PtConicalEffect>(sBase);
+ return (INHERITED::onIsEqual(sBase) &&
+ this->fInfo.fCenterEnd == s.fInfo.fCenterEnd &&
+ this->fInfo.fA == s.fInfo.fA &&
+ this->fInfo.fB == s.fInfo.fB &&
+ this->fInfo.fC == s.fInfo.fC);
+ }
+
+ CircleInside2PtConicalEffect(GrContext* ctx,
+ const SkTwoPointConicalGradient& shader,
+ const SkMatrix& matrix,
+ SkShader::TileMode tm,
+ const CircleConicalInfo& info)
+ : INHERITED(ctx, shader, matrix, tm), fInfo(info) {}
+
+ GR_DECLARE_EFFECT_TEST;
+
+ const CircleConicalInfo fInfo;
+
+ typedef GrGradientEffect INHERITED;
+};
+
+class GLCircleInside2PtConicalEffect : public GrGLGradientEffect {
+public:
+ GLCircleInside2PtConicalEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&);
+ virtual ~GLCircleInside2PtConicalEffect() {}
+
+ virtual void emitCode(GrGLShaderBuilder*,
+ const GrDrawEffect&,
+ EffectKey,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray&) SK_OVERRIDE;
+ virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
+
+ static EffectKey GenKey(const GrDrawEffect&, const GrGLCaps& caps);
+
+protected:
+ UniformHandle fCenterUni;
+ UniformHandle fParamUni;
+
+ const char* fVSVaryingName;
+ const char* fFSVaryingName;
+
+ // @{
+ /// Values last uploaded as uniforms
+
+ SkScalar fCachedCenterX;
+ SkScalar fCachedCenterY;
+ SkScalar fCachedA;
+ SkScalar fCachedB;
+ SkScalar fCachedC;
+
+ // @}
+
+private:
+ typedef GrGLGradientEffect INHERITED;
+
+};
+
+const GrBackendEffectFactory& CircleInside2PtConicalEffect::getFactory() const {
+ return GrTBackendEffectFactory<CircleInside2PtConicalEffect>::getInstance();
+}
+
+GR_DEFINE_EFFECT_TEST(CircleInside2PtConicalEffect);
+
+GrEffectRef* CircleInside2PtConicalEffect::TestCreate(SkRandom* random,
+ GrContext* context,
+ const GrDrawTargetCaps&,
+ GrTexture**) {
+ SkPoint center1 = {random->nextUScalar1(), random->nextUScalar1()};
+ SkScalar radius1 = random->nextUScalar1() + 0.0001f; // make sure radius1 != 0
+ SkPoint center2;
+ SkScalar radius2;
+ do {
+ center2.set(random->nextUScalar1(), random->nextUScalar1());
+ // Below makes sure that circle one is contained within circle two
+ SkScalar increase = random->nextUScalar1();
+ SkPoint diff = center2 - center1;
+ SkScalar diffLen = diff.length();
+ radius2 = radius1 + diffLen + increase;
+ // If the circles are identical the factory will give us an empty shader.
+ } while (radius1 == radius2 && center1 == center2);
+
+ SkColor colors[kMaxRandomGradientColors];
+ SkScalar stopsArray[kMaxRandomGradientColors];
+ SkScalar* stops = stopsArray;
+ SkShader::TileMode tm;
+ int colorCount = RandomGradientParams(random, colors, &stops, &tm);
+ SkAutoTUnref<SkShader> shader(SkGradientShader::CreateTwoPointConical(center1, radius1,
+ center2, radius2,
+ colors, stops, colorCount,
+ tm));
+ SkPaint paint;
+ GrColor grColor;
+ GrEffectRef* grEffect;
+ shader->asNewEffect(context, paint, NULL, &grColor, &grEffect);
+ return grEffect;
+}
+
+GLCircleInside2PtConicalEffect::GLCircleInside2PtConicalEffect(const GrBackendEffectFactory& factory,
+ const GrDrawEffect& drawEffect)
+ : INHERITED(factory)
+ , fVSVaryingName(NULL)
+ , fFSVaryingName(NULL)
+ , fCachedCenterX(SK_ScalarMax)
+ , fCachedCenterY(SK_ScalarMax)
+ , fCachedA(SK_ScalarMax)
+ , fCachedB(SK_ScalarMax)
+ , fCachedC(SK_ScalarMax) {}
+
+void GLCircleInside2PtConicalEffect::emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect&,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray& coords,
+ const TextureSamplerArray& samplers) {
+ this->emitUniforms(builder, key);
+ fCenterUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kVec2f_GrSLType, "Conical2FSCenter");
+ fParamUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kVec3f_GrSLType, "Conical2FSParams");
+ SkString tName("t");
+
+ GrGLShaderVar center = builder->getUniformVariable(fCenterUni);
+ // params.x = A
+ // params.y = B
+ // params.z = C
+ GrGLShaderVar params = builder->getUniformVariable(fParamUni);
+
+ // if we have a vec3 from being in perspective, convert it to a vec2 first
+ SkString coords2DString = builder->ensureFSCoords2D(coords, 0);
+ const char* coords2D = coords2DString.c_str();
+
+ // p = coords2D
+ // e = center end
+ // r = radius end
+ // A = dot(e, e) - r^2 + 2 * r - 1
+ // B = (r -1) / A
+ // C = 1 / A
+ // d = dot(e, p) + B
+ // t = d +/- sqrt(d^2 - A * dot(p, p) + C)
+ builder->fsCodeAppendf("\tfloat pDotp = dot(%s, %s);\n", coords2D, coords2D);
+ builder->fsCodeAppendf("\tfloat d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(), params.c_str());
+ builder->fsCodeAppendf("\tfloat %s = d + sqrt(d * d - %s.x * pDotp + %s.z);\n",
+ tName.c_str(), params.c_str(), params.c_str());
+
+ this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, samplers);
+}
+
+void GLCircleInside2PtConicalEffect::setData(const GrGLUniformManager& uman,
+ const GrDrawEffect& drawEffect) {
+ INHERITED::setData(uman, drawEffect);
+ const CircleInside2PtConicalEffect& data = drawEffect.castEffect<CircleInside2PtConicalEffect>();
+ SkScalar centerX = data.centerX();
+ SkScalar centerY = data.centerY();
+ SkScalar A = data.A();
+ SkScalar B = data.B();
+ SkScalar C = data.C();
+
+ if (fCachedCenterX != centerX || fCachedCenterY != centerY ||
+ fCachedA != A || fCachedB != B || fCachedC != C) {
+
+ uman.set2f(fCenterUni, SkScalarToFloat(centerX), SkScalarToFloat(centerY));
+ uman.set3f(fParamUni, SkScalarToFloat(A), SkScalarToFloat(B), SkScalarToFloat(C));
+
+ fCachedCenterX = centerX;
+ fCachedCenterY = centerY;
+ fCachedA = A;
+ fCachedB = B;
+ fCachedC = C;
+ }
+}
+
+GrGLEffect::EffectKey GLCircleInside2PtConicalEffect::GenKey(const GrDrawEffect& drawEffect,
+ const GrGLCaps&) {
+ EffectKey key = GenBaseGradientKey(drawEffect);
+ return key;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+class GLCircleOutside2PtConicalEffect;
+
+class CircleOutside2PtConicalEffect : public GrGradientEffect {
+public:
+
+ static GrEffectRef* Create(GrContext* ctx,
+ const SkTwoPointConicalGradient& shader,
+ const SkMatrix& matrix,
+ SkShader::TileMode tm,
+ const CircleConicalInfo& info) {
+ AutoEffectUnref effect(SkNEW_ARGS(CircleOutside2PtConicalEffect, (ctx, shader, matrix, tm, info)));
+ return CreateEffectRef(effect);
+ }
+
+ virtual ~CircleOutside2PtConicalEffect() {}
+
+ static const char* Name() { return "Two-Point Conical Gradient Outside"; }
+ virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
+
+ SkScalar centerX() const { return fInfo.fCenterEnd.fX; }
+ SkScalar centerY() const { return fInfo.fCenterEnd.fY; }
+ SkScalar A() const { return fInfo.fA; }
+ SkScalar B() const { return fInfo.fB; }
+ SkScalar C() const { return fInfo.fC; }
+ SkScalar tLimit() const { return fTLimit; }
+ bool isFlipped() const { return fIsFlipped; }
+
+ typedef GLCircleOutside2PtConicalEffect GLEffect;
+
+private:
+ virtual bool onIsEqual(const GrEffect& sBase) const SK_OVERRIDE {
+ const CircleOutside2PtConicalEffect& s = CastEffect<CircleOutside2PtConicalEffect>(sBase);
+ return (INHERITED::onIsEqual(sBase) &&
+ this->fInfo.fCenterEnd == s.fInfo.fCenterEnd &&
+ this->fInfo.fA == s.fInfo.fA &&
+ this->fInfo.fB == s.fInfo.fB &&
+ this->fInfo.fC == s.fInfo.fC &&
+ this->fTLimit == s.fTLimit &&
+ this->fIsFlipped == s.fIsFlipped);
+ }
+
+ CircleOutside2PtConicalEffect(GrContext* ctx,
+ const SkTwoPointConicalGradient& shader,
+ const SkMatrix& matrix,
+ SkShader::TileMode tm,
+ const CircleConicalInfo& info)
+ : INHERITED(ctx, shader, matrix, tm), fInfo(info) {
+ if (shader.getStartRadius() != shader.getEndRadius()) {
+ fTLimit = SkScalarDiv(shader.getStartRadius(), (shader.getStartRadius() - shader.getEndRadius()));
+ } else {
+ fTLimit = SK_ScalarMin;
+ }
+
+ fIsFlipped = shader.isFlippedGrad();
+ }
+
+ GR_DECLARE_EFFECT_TEST;
+
+ const CircleConicalInfo fInfo;
+ SkScalar fTLimit;
+ bool fIsFlipped;
+
+ typedef GrGradientEffect INHERITED;
+};
+
+class GLCircleOutside2PtConicalEffect : public GrGLGradientEffect {
+public:
+ GLCircleOutside2PtConicalEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&);
+ virtual ~GLCircleOutside2PtConicalEffect() {}
+
+ virtual void emitCode(GrGLShaderBuilder*,
+ const GrDrawEffect&,
+ EffectKey,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray&) SK_OVERRIDE;
+ virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
+
+ static EffectKey GenKey(const GrDrawEffect&, const GrGLCaps& caps);
+
+protected:
+ UniformHandle fCenterUni;
+ UniformHandle fParamUni;
+
+ const char* fVSVaryingName;
+ const char* fFSVaryingName;
+
+ bool fIsFlipped;
+
+ // @{
+ /// Values last uploaded as uniforms
+
+ SkScalar fCachedCenterX;
+ SkScalar fCachedCenterY;
+ SkScalar fCachedA;
+ SkScalar fCachedB;
+ SkScalar fCachedC;
+ SkScalar fCachedTLimit;
+
+ // @}
+
+private:
+ typedef GrGLGradientEffect INHERITED;
+
+};
+
+const GrBackendEffectFactory& CircleOutside2PtConicalEffect::getFactory() const {
+ return GrTBackendEffectFactory<CircleOutside2PtConicalEffect>::getInstance();
+}
+
+GR_DEFINE_EFFECT_TEST(CircleOutside2PtConicalEffect);
+
+GrEffectRef* CircleOutside2PtConicalEffect::TestCreate(SkRandom* random,
+ GrContext* context,
+ const GrDrawTargetCaps&,
+ GrTexture**) {
+ SkPoint center1 = {random->nextUScalar1(), random->nextUScalar1()};
+ SkScalar radius1 = random->nextUScalar1() + 0.0001f; // make sure radius1 != 0
+ SkPoint center2;
+ SkScalar radius2;
+ SkScalar diffLen;
+ do {
+ center2.set(random->nextUScalar1(), random->nextUScalar1());
+ // If the circles share a center than we can't be in the outside case
+ } while (center1 == center2);
+ SkPoint diff = center2 - center1;
+ diffLen = diff.length();
+ // Below makes sure that circle one is not contained within circle two
+ // and have radius2 >= radius to match sorting on cpu side
+ radius2 = radius1 + random->nextRangeF(0.f, diffLen);
+
+ SkColor colors[kMaxRandomGradientColors];
+ SkScalar stopsArray[kMaxRandomGradientColors];
+ SkScalar* stops = stopsArray;
+ SkShader::TileMode tm;
+ int colorCount = RandomGradientParams(random, colors, &stops, &tm);
+ SkAutoTUnref<SkShader> shader(SkGradientShader::CreateTwoPointConical(center1, radius1,
+ center2, radius2,
+ colors, stops, colorCount,
+ tm));
+ SkPaint paint;
+ GrColor grColor;
+ GrEffectRef* grEffect;
+ shader->asNewEffect(context, paint, NULL, &grColor, &grEffect);
+ return grEffect;
+}
+
+GLCircleOutside2PtConicalEffect::GLCircleOutside2PtConicalEffect(const GrBackendEffectFactory& factory,
+ const GrDrawEffect& drawEffect)
+ : INHERITED(factory)
+ , fVSVaryingName(NULL)
+ , fFSVaryingName(NULL)
+ , fCachedCenterX(SK_ScalarMax)
+ , fCachedCenterY(SK_ScalarMax)
+ , fCachedA(SK_ScalarMax)
+ , fCachedB(SK_ScalarMax)
+ , fCachedC(SK_ScalarMax)
+ , fCachedTLimit(SK_ScalarMax) {
+ const CircleOutside2PtConicalEffect& data = drawEffect.castEffect<CircleOutside2PtConicalEffect>();
+ fIsFlipped = data.isFlipped();
+ }
+
+void GLCircleOutside2PtConicalEffect::emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect&,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray& coords,
+ const TextureSamplerArray& samplers) {
+ this->emitUniforms(builder, key);
+ fCenterUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kVec2f_GrSLType, "Conical2FSCenter");
+ fParamUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kVec4f_GrSLType, "Conical2FSParams");
+ SkString tName("t");
+
+ GrGLShaderVar center = builder->getUniformVariable(fCenterUni);
+ // params.x = A
+ // params.y = B
+ // params.z = C
+ GrGLShaderVar params = builder->getUniformVariable(fParamUni);
+
+ // if we have a vec3 from being in perspective, convert it to a vec2 first
+ SkString coords2DString = builder->ensureFSCoords2D(coords, 0);
+ const char* coords2D = coords2DString.c_str();
+
+ // output will default to transparent black (we simply won't write anything
+ // else to it if invalid, instead of discarding or returning prematurely)
+ builder->fsCodeAppendf("\t%s = vec4(0.0,0.0,0.0,0.0);\n", outputColor);
+
+ // p = coords2D
+ // e = center end
+ // r = radius end
+ // A = dot(e, e) - r^2 + 2 * r - 1
+ // B = (r -1) / A
+ // C = 1 / A
+ // d = dot(e, p) + B
+ // t = d +/- sqrt(d^2 - A * dot(p, p) + C)
+
+ builder->fsCodeAppendf("\tfloat pDotp = dot(%s, %s);\n", coords2D, coords2D);
+ builder->fsCodeAppendf("\tfloat d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(), params.c_str());
+ builder->fsCodeAppendf("\tfloat deter = d * d - %s.x * pDotp + %s.z;\n", params.c_str(), params.c_str());
+
+ // Must check to see if we flipped the circle order (to make sure start radius < end radius)
+ // If so we must also flip sign on sqrt
+ if (!fIsFlipped) {
+ builder->fsCodeAppendf("\tfloat %s = d + sqrt(deter);\n", tName.c_str());
+ } else {
+ builder->fsCodeAppendf("\tfloat %s = d - sqrt(deter);\n", tName.c_str());
+ }
+
+ builder->fsCodeAppendf("\tif (%s >= %s.w && deter >= 0.0) {\n", tName.c_str(), params.c_str());
+ builder->fsCodeAppend("\t\t");
+ this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, samplers);
+ builder->fsCodeAppend("\t}\n");
+}
+
+void GLCircleOutside2PtConicalEffect::setData(const GrGLUniformManager& uman,
+ const GrDrawEffect& drawEffect) {
+ INHERITED::setData(uman, drawEffect);
+ const CircleOutside2PtConicalEffect& data = drawEffect.castEffect<CircleOutside2PtConicalEffect>();
+ SkASSERT(data.isFlipped() == fIsFlipped);
+ SkScalar centerX = data.centerX();
+ SkScalar centerY = data.centerY();
+ SkScalar A = data.A();
+ SkScalar B = data.B();
+ SkScalar C = data.C();
+ SkScalar tLimit = data.tLimit();
+
+ if (fCachedCenterX != centerX || fCachedCenterY != centerY ||
+ fCachedA != A || fCachedB != B || fCachedC != C || fCachedTLimit != tLimit) {
+
+ uman.set2f(fCenterUni, SkScalarToFloat(centerX), SkScalarToFloat(centerY));
+ uman.set4f(fParamUni, SkScalarToFloat(A), SkScalarToFloat(B), SkScalarToFloat(C),
+ SkScalarToFloat(tLimit));
+
+ fCachedCenterX = centerX;
+ fCachedCenterY = centerY;
+ fCachedA = A;
+ fCachedB = B;
+ fCachedC = C;
+ fCachedTLimit = tLimit;
+ }
+}
+
+GrGLEffect::EffectKey GLCircleOutside2PtConicalEffect::GenKey(const GrDrawEffect& drawEffect,
+ const GrGLCaps&) {
+ enum {
+ kIsFlipped = 1 << kBaseKeyBitCnt,
+ };
+
+ EffectKey key = GenBaseGradientKey(drawEffect);
+
+ if (drawEffect.castEffect<CircleOutside2PtConicalEffect>().isFlipped()) {
+ key |= kIsFlipped;
+ }
+ return key;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+GrEffectRef* Gr2PtConicalGradientEffect::Create(GrContext* ctx,
+ const SkTwoPointConicalGradient& shader,
+ SkShader::TileMode tm,
+ const SkMatrix* localMatrix) {
+ SkMatrix matrix;
+ if (!shader.getLocalMatrix().invert(&matrix)) {
+ return NULL;
+ }
+ if (localMatrix) {
+ SkMatrix inv;
+ if (!localMatrix->invert(&inv)) {
+ return NULL;
+ }
+ matrix.postConcat(inv);
+ }
+
+ if (shader.getStartRadius() < kErrorTol) {
+ SkScalar focalX;
+ ConicalType type = set_matrix_focal_conical(shader, &matrix, &focalX);
+ if (type == kInside_ConicalType) {
+ return FocalInside2PtConicalEffect::Create(ctx, shader, matrix, tm, focalX);
+ } else if(type == kEdge_ConicalType) {
+ set_matrix_edge_conical(shader, &matrix);
+ return Edge2PtConicalEffect::Create(ctx, shader, matrix, tm);
+ } else {
+ return FocalOutside2PtConicalEffect::Create(ctx, shader, matrix, tm, focalX);
+ }
+ }
+
+ CircleConicalInfo info;
+ ConicalType type = set_matrix_circle_conical(shader, &matrix, &info);
+
+ if (type == kInside_ConicalType) {
+ return CircleInside2PtConicalEffect::Create(ctx, shader, matrix, tm, info);
+ } else if (type == kEdge_ConicalType) {
+ set_matrix_edge_conical(shader, &matrix);
+ return Edge2PtConicalEffect::Create(ctx, shader, matrix, tm);
+ } else {
+ return CircleOutside2PtConicalEffect::Create(ctx, shader, matrix, tm, info);
+ }
+}
+
+#endif
diff --git a/chromium/third_party/skia/src/effects/gradients/SkTwoPointConicalGradient_gpu.h b/chromium/third_party/skia/src/effects/gradients/SkTwoPointConicalGradient_gpu.h
new file mode 100644
index 00000000000..2b0f0612d78
--- /dev/null
+++ b/chromium/third_party/skia/src/effects/gradients/SkTwoPointConicalGradient_gpu.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkTwoPointConicalGradient_gpu_DEFINED
+#define SkTwoPointConicalGradient_gpu_DEFINED
+
+#include "SkGradientShaderPriv.h"
+
+class GrEffectRef;
+class SkTwoPointConicalGradient;
+
+namespace Gr2PtConicalGradientEffect {
+ /**
+ * Creates an effect that produces a two point conical gradient based on the
+ * shader passed in.
+ */
+ GrEffectRef* Create(GrContext* ctx, const SkTwoPointConicalGradient& shader,
+ SkShader::TileMode tm, const SkMatrix* localMatrix);
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/effects/gradients/SkTwoPointRadialGradient.cpp b/chromium/third_party/skia/src/effects/gradients/SkTwoPointRadialGradient.cpp
index 207f3db6537..e3d89960c65 100644
--- a/chromium/third_party/skia/src/effects/gradients/SkTwoPointRadialGradient.cpp
+++ b/chromium/third_party/skia/src/effects/gradients/SkTwoPointRadialGradient.cpp
@@ -6,7 +6,7 @@
* found in the LICENSE file.
*/
- #include "SkTwoPointRadialGradient.h"
+#include "SkTwoPointRadialGradient.h"
/* Two-point radial gradients are specified by two circles, each with a center
point and radius. The gradient can be considered to be a series of
@@ -170,8 +170,8 @@ void shadeSpan_twopoint_repeat(SkScalar fx, SkScalar dx,
SkTwoPointRadialGradient::SkTwoPointRadialGradient(
const SkPoint& start, SkScalar startRadius,
const SkPoint& end, SkScalar endRadius,
- const Descriptor& desc)
- : SkGradientShaderBase(desc),
+ const Descriptor& desc, const SkMatrix* localMatrix)
+ : SkGradientShaderBase(desc, localMatrix),
fCenter1(start),
fCenter2(end),
fRadius1(startRadius),
@@ -220,23 +220,47 @@ SkShader::GradientType SkTwoPointRadialGradient::asAGradient(
return kRadial2_GradientType;
}
-void SkTwoPointRadialGradient::shadeSpan(int x, int y, SkPMColor* dstCParam,
- int count) {
+size_t SkTwoPointRadialGradient::contextSize() const {
+ return sizeof(TwoPointRadialGradientContext);
+}
+
+SkShader::Context* SkTwoPointRadialGradient::onCreateContext(const ContextRec& rec,
+ void* storage) const {
+ // For now, we might have divided by zero, so detect that.
+ if (0 == fDiffRadius) {
+ return NULL;
+ }
+ return SkNEW_PLACEMENT_ARGS(storage, TwoPointRadialGradientContext, (*this, rec));
+}
+
+SkTwoPointRadialGradient::TwoPointRadialGradientContext::TwoPointRadialGradientContext(
+ const SkTwoPointRadialGradient& shader, const ContextRec& rec)
+ : INHERITED(shader, rec)
+{
+ // we don't have a span16 proc
+ fFlags &= ~kHasSpan16_Flag;
+}
+
+void SkTwoPointRadialGradient::TwoPointRadialGradientContext::shadeSpan(
+ int x, int y, SkPMColor* dstCParam, int count) {
SkASSERT(count > 0);
+ const SkTwoPointRadialGradient& twoPointRadialGradient =
+ static_cast<const SkTwoPointRadialGradient&>(fShader);
+
SkPMColor* SK_RESTRICT dstC = dstCParam;
// Zero difference between radii: fill with transparent black.
- if (fDiffRadius == 0) {
+ if (twoPointRadialGradient.fDiffRadius == 0) {
sk_bzero(dstC, count * sizeof(*dstC));
return;
}
SkMatrix::MapXYProc dstProc = fDstToIndexProc;
- TileProc proc = fTileProc;
- const SkPMColor* SK_RESTRICT cache = this->getCache32();
+ TileProc proc = twoPointRadialGradient.fTileProc;
+ const SkPMColor* SK_RESTRICT cache = fCache->getCache32();
- SkScalar foura = fA * 4;
- bool posRoot = fDiffRadius < 0;
+ SkScalar foura = twoPointRadialGradient.fA * 4;
+ bool posRoot = twoPointRadialGradient.fDiffRadius < 0;
if (fDstToIndexClass != kPerspective_MatrixClass) {
SkPoint srcPt;
dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
@@ -254,21 +278,23 @@ void SkTwoPointRadialGradient::shadeSpan(int x, int y, SkPMColor* dstCParam,
dx = fDstToIndex.getScaleX();
dy = fDstToIndex.getSkewY();
}
- SkScalar b = (SkScalarMul(fDiff.fX, fx) +
- SkScalarMul(fDiff.fY, fy) - fStartRadius) * 2;
- SkScalar db = (SkScalarMul(fDiff.fX, dx) +
- SkScalarMul(fDiff.fY, dy)) * 2;
+ SkScalar b = (SkScalarMul(twoPointRadialGradient.fDiff.fX, fx) +
+ SkScalarMul(twoPointRadialGradient.fDiff.fY, fy) -
+ twoPointRadialGradient.fStartRadius) * 2;
+ SkScalar db = (SkScalarMul(twoPointRadialGradient.fDiff.fX, dx) +
+ SkScalarMul(twoPointRadialGradient.fDiff.fY, dy)) * 2;
TwoPointRadialShadeProc shadeProc = shadeSpan_twopoint_repeat;
- if (SkShader::kClamp_TileMode == fTileMode) {
+ if (SkShader::kClamp_TileMode == twoPointRadialGradient.fTileMode) {
shadeProc = shadeSpan_twopoint_clamp;
- } else if (SkShader::kMirror_TileMode == fTileMode) {
+ } else if (SkShader::kMirror_TileMode == twoPointRadialGradient.fTileMode) {
shadeProc = shadeSpan_twopoint_mirror;
} else {
- SkASSERT(SkShader::kRepeat_TileMode == fTileMode);
+ SkASSERT(SkShader::kRepeat_TileMode == twoPointRadialGradient.fTileMode);
}
(*shadeProc)(fx, dx, fy, dy, b, db,
- fSr2D2, foura, fOneOverTwoA, posRoot,
+ twoPointRadialGradient.fSr2D2, foura,
+ twoPointRadialGradient.fOneOverTwoA, posRoot,
dstC, cache, count);
} else { // perspective case
SkScalar dstX = SkIntToScalar(x);
@@ -278,10 +304,11 @@ void SkTwoPointRadialGradient::shadeSpan(int x, int y, SkPMColor* dstCParam,
dstProc(fDstToIndex, dstX, dstY, &srcPt);
SkScalar fx = srcPt.fX;
SkScalar fy = srcPt.fY;
- SkScalar b = (SkScalarMul(fDiff.fX, fx) +
- SkScalarMul(fDiff.fY, fy) - fStartRadius) * 2;
- SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura,
- fOneOverTwoA, posRoot);
+ SkScalar b = (SkScalarMul(twoPointRadialGradient.fDiff.fX, fx) +
+ SkScalarMul(twoPointRadialGradient.fDiff.fY, fy) -
+ twoPointRadialGradient.fStartRadius) * 2;
+ SkFixed t = two_point_radial(b, fx, fy, twoPointRadialGradient.fSr2D2, foura,
+ twoPointRadialGradient.fOneOverTwoA, posRoot);
SkFixed index = proc(t);
SkASSERT(index <= 0xFFFF);
*dstC++ = cache[index >> SkGradientShaderBase::kCache32Shift];
@@ -290,24 +317,7 @@ void SkTwoPointRadialGradient::shadeSpan(int x, int y, SkPMColor* dstCParam,
}
}
-bool SkTwoPointRadialGradient::setContext( const SkBitmap& device,
- const SkPaint& paint,
- const SkMatrix& matrix){
- // For now, we might have divided by zero, so detect that
- if (0 == fDiffRadius) {
- return false;
- }
-
- if (!this->INHERITED::setContext(device, paint, matrix)) {
- return false;
- }
-
- // we don't have a span16 proc
- fFlags &= ~kHasSpan16_Flag;
- return true;
-}
-
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkTwoPointRadialGradient::toString(SkString* str) const {
str->append("SkTwoPointRadialGradient: (");
@@ -334,7 +344,7 @@ void SkTwoPointRadialGradient::toString(SkString* str) const {
#endif
SkTwoPointRadialGradient::SkTwoPointRadialGradient(
- SkFlattenableReadBuffer& buffer)
+ SkReadBuffer& buffer)
: INHERITED(buffer),
fCenter1(buffer.readPoint()),
fCenter2(buffer.readPoint()),
@@ -344,7 +354,7 @@ SkTwoPointRadialGradient::SkTwoPointRadialGradient(
};
void SkTwoPointRadialGradient::flatten(
- SkFlattenableWriteBuffer& buffer) const {
+ SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writePoint(fCenter1);
buffer.writePoint(fCenter2);
@@ -373,6 +383,7 @@ void SkTwoPointRadialGradient::init() {
#if SK_SUPPORT_GPU
#include "GrTBackendEffectFactory.h"
+#include "SkGr.h"
// For brevity
typedef GrGLUniformManager::UniformHandle UniformHandle;
@@ -520,7 +531,10 @@ GrEffectRef* GrRadial2Gradient::TestCreate(SkRandom* random,
colors, stops, colorCount,
tm));
SkPaint paint;
- return shader->asNewEffect(context, paint);
+ GrEffectRef* effect;
+ GrColor grColor;
+ shader->asNewEffect(context, paint, NULL, &grColor, &effect);
+ return effect;
}
/////////////////////////////////////////////////////////////////////
@@ -660,12 +674,22 @@ GrGLEffect::EffectKey GrGLRadial2Gradient::GenKey(const GrDrawEffect& drawEffect
/////////////////////////////////////////////////////////////////////
-GrEffectRef* SkTwoPointRadialGradient::asNewEffect(GrContext* context, const SkPaint&) const {
+bool SkTwoPointRadialGradient::asNewEffect(GrContext* context, const SkPaint& paint,
+ const SkMatrix* localMatrix, GrColor* grColor,
+ GrEffectRef** grEffect) const {
SkASSERT(NULL != context);
+
// invert the localM, translate to center1 (fPtsToUni), rotate so center2 is on x axis.
SkMatrix matrix;
if (!this->getLocalMatrix().invert(&matrix)) {
- return NULL;
+ return false;
+ }
+ if (localMatrix) {
+ SkMatrix inv;
+ if (!localMatrix->invert(&inv)) {
+ return false;
+ }
+ matrix.postConcat(inv);
}
matrix.postConcat(fPtsToUnit);
@@ -678,14 +702,19 @@ GrEffectRef* SkTwoPointRadialGradient::asNewEffect(GrContext* context, const SkP
matrix.postConcat(rot);
}
- return GrRadial2Gradient::Create(context, *this, matrix, fTileMode);
+ *grColor = SkColor2GrColorJustAlpha(paint.getColor());
+ *grEffect = GrRadial2Gradient::Create(context, *this, matrix, fTileMode);
+
+ return true;
}
#else
-GrEffectRef* SkTwoPointRadialGradient::asNewEffect(GrContext*, const SkPaint&) const {
+bool SkTwoPointRadialGradient::asNewEffect(GrContext* context, const SkPaint& paint,
+ const SkMatrix* localMatrix, GrColor* grColor,
+ GrEffectRef** grEffect) const {
SkDEBUGFAIL("Should not call in GPU-less build");
- return NULL;
+ return false;
}
#endif
diff --git a/chromium/third_party/skia/src/effects/gradients/SkTwoPointRadialGradient.h b/chromium/third_party/skia/src/effects/gradients/SkTwoPointRadialGradient.h
index 444c23dd709..8916754062b 100644
--- a/chromium/third_party/skia/src/effects/gradients/SkTwoPointRadialGradient.h
+++ b/chromium/third_party/skia/src/effects/gradients/SkTwoPointRadialGradient.h
@@ -15,33 +15,40 @@ class SkTwoPointRadialGradient : public SkGradientShaderBase {
public:
SkTwoPointRadialGradient(const SkPoint& start, SkScalar startRadius,
const SkPoint& end, SkScalar endRadius,
- const Descriptor&);
+ const Descriptor&, const SkMatrix* localMatrix);
virtual BitmapType asABitmap(SkBitmap* bitmap,
SkMatrix* matrix,
TileMode* xy) const SK_OVERRIDE;
virtual GradientType asAGradient(GradientInfo* info) const SK_OVERRIDE;
- virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint&) const SK_OVERRIDE;
+ virtual bool asNewEffect(GrContext* context, const SkPaint&, const SkMatrix*, GrColor*,
+ GrEffectRef**) const SK_OVERRIDE;
- virtual void shadeSpan(int x, int y, SkPMColor* dstCParam,
- int count) SK_OVERRIDE;
- virtual bool setContext(const SkBitmap& device,
- const SkPaint& paint,
- const SkMatrix& matrix) SK_OVERRIDE;
+ virtual size_t contextSize() const SK_OVERRIDE;
+
+ class TwoPointRadialGradientContext : public SkGradientShaderBase::GradientShaderBaseContext {
+ public:
+ TwoPointRadialGradientContext(const SkTwoPointRadialGradient&, const ContextRec&);
+
+ virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE;
+
+ private:
+ typedef SkGradientShaderBase::GradientShaderBaseContext INHERITED;
+ };
SkScalar getCenterX1() const { return fDiff.length(); }
SkScalar getStartRadius() const { return fStartRadius; }
SkScalar getDiffRadius() const { return fDiffRadius; }
- SK_DEVELOPER_TO_STRING()
+ SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTwoPointRadialGradient)
protected:
- SkTwoPointRadialGradient(SkFlattenableReadBuffer& buffer);
- virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE;
+ SkTwoPointRadialGradient(SkReadBuffer& buffer);
+ virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE;
+ virtual Context* onCreateContext(const ContextRec&, void* storage) const SK_OVERRIDE;
private:
- typedef SkGradientShaderBase INHERITED;
const SkPoint fCenter1;
const SkPoint fCenter2;
const SkScalar fRadius1;
@@ -50,6 +57,8 @@ private:
SkScalar fStartRadius, fDiffRadius, fSr2D2, fA, fOneOverTwoA;
void init();
+
+ typedef SkGradientShaderBase INHERITED;
};
#endif
diff --git a/chromium/third_party/skia/src/fonts/SkFontMgr_fontconfig.cpp b/chromium/third_party/skia/src/fonts/SkFontMgr_fontconfig.cpp
index a0ca7e4f333..2ffe8e3e86f 100644
--- a/chromium/third_party/skia/src/fonts/SkFontMgr_fontconfig.cpp
+++ b/chromium/third_party/skia/src/fonts/SkFontMgr_fontconfig.cpp
@@ -12,12 +12,45 @@
#include "SkMath.h"
#include "SkString.h"
#include "SkTDArray.h"
+#include "SkThread.h"
// for now we pull these in directly. eventually we will solely rely on the
// SkFontConfigInterface instance.
#include <fontconfig/fontconfig.h>
#include <unistd.h>
+namespace {
+
+// Fontconfig is not threadsafe before 2.10.91. Before that, we lock with a global mutex.
+// See skia:1497 for background.
+SK_DECLARE_STATIC_MUTEX(gFCMutex);
+static bool gFCSafeToUse;
+
+struct FCLocker {
+ FCLocker() {
+ if (FcGetVersion() < 21091) { // We assume FcGetVersion() has always been thread safe.
+ gFCMutex.acquire();
+ fUnlock = true;
+ } else {
+ fUnlock = false;
+ }
+ gFCSafeToUse = true;
+ }
+
+ ~FCLocker() {
+ if (fUnlock) {
+ gFCSafeToUse = false;
+ gFCMutex.release();
+ }
+ }
+
+private:
+ bool fUnlock;
+};
+
+} // namespace
+
+
// Defined in SkFontHost_FreeType.cpp
bool find_name_and_attributes(SkStream* stream, SkString* name,
SkTypeface::Style* style, bool* isFixedWidth);
@@ -40,6 +73,7 @@ static bool is_lower(char c) {
}
static int get_int(FcPattern* pattern, const char field[]) {
+ SkASSERT(gFCSafeToUse);
int value;
if (FcPatternGetInteger(pattern, field, 0, &value) != FcResultMatch) {
value = SK_MinS32;
@@ -48,6 +82,7 @@ static int get_int(FcPattern* pattern, const char field[]) {
}
static const char* get_name(FcPattern* pattern, const char field[]) {
+ SkASSERT(gFCSafeToUse);
const char* name;
if (FcPatternGetString(pattern, field, 0, (FcChar8**)&name) != FcResultMatch) {
name = "";
@@ -56,6 +91,7 @@ static const char* get_name(FcPattern* pattern, const char field[]) {
}
static bool valid_pattern(FcPattern* pattern) {
+ SkASSERT(gFCSafeToUse);
FcBool is_scalable;
if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &is_scalable) != FcResultMatch || !is_scalable) {
return false;
@@ -184,39 +220,31 @@ class SkFontMgr_fontconfig : public SkFontMgr {
SkAutoTUnref<SkFontConfigInterface> fFCI;
SkDataTable* fFamilyNames;
- void init() {
- if (!fFamilyNames) {
- fFamilyNames = fFCI->getFamilyNames();
- }
- }
public:
SkFontMgr_fontconfig(SkFontConfigInterface* fci)
: fFCI(fci)
- , fFamilyNames(NULL) {}
+ , fFamilyNames(fFCI->getFamilyNames()) {}
virtual ~SkFontMgr_fontconfig() {
SkSafeUnref(fFamilyNames);
}
protected:
- virtual int onCountFamilies() {
- this->init();
+ virtual int onCountFamilies() const SK_OVERRIDE {
return fFamilyNames->count();
}
- virtual void onGetFamilyName(int index, SkString* familyName) {
- this->init();
+ virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE {
familyName->set(fFamilyNames->atStr(index));
}
- virtual SkFontStyleSet* onCreateStyleSet(int index) {
- this->init();
+ virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE {
return this->onMatchFamily(fFamilyNames->atStr(index));
}
- virtual SkFontStyleSet* onMatchFamily(const char familyName[]) {
- this->init();
+ virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE {
+ FCLocker lock;
FcPattern* pattern = FcPatternCreate();
@@ -261,13 +289,13 @@ protected:
}
virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
- const SkFontStyle&) { return NULL; }
+ const SkFontStyle&) const SK_OVERRIDE { return NULL; }
virtual SkTypeface* onMatchFaceStyle(const SkTypeface*,
- const SkFontStyle&) { return NULL; }
+ const SkFontStyle&) const SK_OVERRIDE { return NULL; }
- virtual SkTypeface* onCreateFromData(SkData*, int ttcIndex) { return NULL; }
+ virtual SkTypeface* onCreateFromData(SkData*, int ttcIndex) const SK_OVERRIDE { return NULL; }
- virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) {
+ virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE {
const size_t length = stream->getLength();
if (!length) {
return NULL;
@@ -283,17 +311,18 @@ protected:
return NULL;
}
- SkTypeface* face = SkNEW_ARGS(FontConfigTypeface, (style, isFixedWidth, stream));
+ SkTypeface* face = FontConfigTypeface::Create(style, isFixedWidth, stream);
return face;
}
- virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) {
+ virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE {
SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL;
}
virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
- unsigned styleBits) SK_OVERRIDE {
+ unsigned styleBits) const SK_OVERRIDE {
+ FCLocker lock;
return FontConfigTypeface::LegacyCreateTypeface(NULL, familyName,
(SkTypeface::Style)styleBits);
}
diff --git a/chromium/third_party/skia/src/fonts/SkFontMgr_indirect.cpp b/chromium/third_party/skia/src/fonts/SkFontMgr_indirect.cpp
new file mode 100644
index 00000000000..54f2de82901
--- /dev/null
+++ b/chromium/third_party/skia/src/fonts/SkFontMgr_indirect.cpp
@@ -0,0 +1,297 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkFontMgr_indirect.h"
+
+#include "SkDataTable.h"
+#include "SkFontStyle.h"
+#include "SkOnce.h"
+#include "SkStream.h"
+#include "SkTSearch.h"
+#include "SkTypeface.h"
+
+class SkData;
+class SkString;
+
+class SkStyleSet_Indirect : public SkFontStyleSet {
+public:
+ /** Takes ownership of the SkRemotableFontIdentitySet. */
+ SkStyleSet_Indirect(const SkFontMgr_Indirect* owner, int familyIndex,
+ SkRemotableFontIdentitySet* data)
+ : fOwner(SkRef(owner)), fFamilyIndex(familyIndex), fData(data)
+ { }
+
+ virtual int count() SK_OVERRIDE { return fData->count(); }
+
+ virtual void getStyle(int index, SkFontStyle* fs, SkString* style) SK_OVERRIDE {
+ if (fs) {
+ *fs = fData->at(index).fFontStyle;
+ }
+ if (style) {
+ // TODO: is this useful? Current locale?
+ style->reset();
+ }
+ }
+
+ virtual SkTypeface* createTypeface(int index) SK_OVERRIDE {
+ return fOwner->createTypefaceFromFontId(fData->at(index));
+ }
+
+ virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE {
+ if (fFamilyIndex >= 0) {
+ SkFontIdentity id = fOwner->fProxy->matchIndexStyle(fFamilyIndex, pattern);
+ return fOwner->createTypefaceFromFontId(id);
+ }
+
+ // If this SkStyleSet was created via onMatchFamily we would need a call like
+ // fOwner->fProxy->matchNameStyle(fFamilyName, pattern);
+ // but would not activate fonts (only consider fonts which would come back from matchName).
+
+ // CSS policy sounds good.
+ struct Score {
+ int score;
+ int index;
+ };
+
+ // Width has the greatest priority.
+ // If the value of pattern.width is 5 (normal) or less,
+ // narrower width values are checked first, then wider values.
+ // If the value of pattern.width is greater than 5 (normal),
+ // wider values are checked first, followed by narrower values.
+
+ // Italic/Oblique has the next highest priority.
+ // If italic requested and there is some italic font, use it.
+ // If oblique requested and there is some oblique font, use it.
+ // If italic requested and there is some oblique font, use it.
+ // If oblique requested and there is some italic font, use it.
+
+ // Exact match.
+ // If pattern.weight < 400, weights below pattern.weight are checked
+ // in descending order followed by weights above pattern.weight
+ // in ascending order until a match is found.
+ // If pattern.weight > 500, weights above pattern.weight are checked
+ // in ascending order followed by weights below pattern.weight
+ // in descending order until a match is found.
+ // If pattern.weight is 400, 500 is checked first
+ // and then the rule for pattern.weight < 400 is used.
+ // If pattern.weight is 500, 400 is checked first
+ // and then the rule for pattern.weight < 400 is used
+
+ Score maxScore = { 0, 0 };
+ for (int i = 0; i < fData->count(); ++i) {
+ const SkFontStyle& current = fData->at(i).fFontStyle;
+ Score currentScore = { 0, i };
+
+ // CSS stretch. (This is the width.)
+ // This has the highest priority.
+ if (pattern.width() <= SkFontStyle::kNormal_Width) {
+ if (current.width() <= pattern.width()) {
+ currentScore.score += 10 - pattern.width() + current.width();
+ } else {
+ currentScore.score += 10 - current.width();
+ }
+ } else {
+ if (current.width() > pattern.width()) {
+ currentScore.score += 10 + pattern.width() - current.width();
+ } else {
+ currentScore.score += current.width();
+ }
+ }
+ currentScore.score *= 1002;
+
+ // CSS style (italic/oblique)
+ // Being italic trumps all valid weights which are not italic.
+ // Note that newer specs differentiate between italic and oblique.
+ if (pattern.isItalic() && current.isItalic()) {
+ currentScore.score += 1001;
+ }
+
+ // Synthetics (weight/style) [no stretch synthetic?]
+
+ // The 'closer' to the target weight, the higher the score.
+ // 1000 is the 'heaviest' recognized weight
+ if (pattern.weight() == current.weight()) {
+ currentScore.score += 1000;
+ } else if (pattern.weight() <= 500) {
+ if (pattern.weight() >= 400 && pattern.weight() < 450) {
+ if (current.weight() >= 450 && current.weight() <= 500) {
+ // Artificially boost the 500 weight.
+ // TODO: determine correct number to use.
+ currentScore.score += 500;
+ }
+ }
+ if (current.weight() <= pattern.weight()) {
+ currentScore.score += 1000 - pattern.weight() + current.weight();
+ } else {
+ currentScore.score += 1000 - current.weight();
+ }
+ } else if (pattern.weight() > 500) {
+ if (current.weight() > pattern.weight()) {
+ currentScore.score += 1000 + pattern.weight() - current.weight();
+ } else {
+ currentScore.score += current.weight();
+ }
+ }
+
+ if (currentScore.score > maxScore.score) {
+ maxScore = currentScore;
+ }
+ }
+
+ return this->createTypeface(maxScore.index);
+ }
+private:
+ SkAutoTUnref<const SkFontMgr_Indirect> fOwner;
+ int fFamilyIndex;
+ SkAutoTUnref<SkRemotableFontIdentitySet> fData;
+};
+
+void SkFontMgr_Indirect::set_up_family_names(const SkFontMgr_Indirect* self) {
+ self->fFamilyNames.reset(self->fProxy->getFamilyNames());
+}
+
+int SkFontMgr_Indirect::onCountFamilies() const {
+ SkOnce(&fFamilyNamesInited, &fFamilyNamesMutex, SkFontMgr_Indirect::set_up_family_names, this);
+ return fFamilyNames->count();
+}
+
+void SkFontMgr_Indirect::onGetFamilyName(int index, SkString* familyName) const {
+ SkOnce(&fFamilyNamesInited, &fFamilyNamesMutex, SkFontMgr_Indirect::set_up_family_names, this);
+ if (index >= fFamilyNames->count()) {
+ familyName->reset();
+ return;
+ }
+ familyName->set(fFamilyNames->atStr(index));
+}
+
+SkFontStyleSet* SkFontMgr_Indirect::onCreateStyleSet(int index) const {
+ SkRemotableFontIdentitySet* set = fProxy->getIndex(index);
+ if (NULL == set) {
+ return NULL;
+ }
+ return SkNEW_ARGS(SkStyleSet_Indirect, (this, index, set));
+}
+
+SkFontStyleSet* SkFontMgr_Indirect::onMatchFamily(const char familyName[]) const {
+ return SkNEW_ARGS(SkStyleSet_Indirect, (this, -1, fProxy->matchName(familyName)));
+}
+
+SkTypeface* SkFontMgr_Indirect::createTypefaceFromFontId(const SkFontIdentity& id) const {
+ if (id.fDataId == SkFontIdentity::kInvalidDataId) {
+ return NULL;
+ }
+
+ SkAutoMutexAcquire ama(fDataCacheMutex);
+
+ SkAutoTUnref<SkTypeface> dataTypeface;
+ int dataTypefaceIndex = 0;
+ for (int i = 0; i < fDataCache.count(); ++i) {
+ const DataEntry& entry = fDataCache[i];
+ if (entry.fDataId == id.fDataId) {
+ if (entry.fTtcIndex == id.fTtcIndex &&
+ !entry.fTypeface->weak_expired() && entry.fTypeface->try_ref())
+ {
+ return entry.fTypeface;
+ }
+ if (dataTypeface.get() == NULL &&
+ !entry.fTypeface->weak_expired() && entry.fTypeface->try_ref())
+ {
+ dataTypeface.reset(entry.fTypeface);
+ dataTypefaceIndex = entry.fTtcIndex;
+ }
+ }
+
+ if (entry.fTypeface->weak_expired()) {
+ fDataCache.removeShuffle(i);
+ --i;
+ }
+ }
+
+ // No exact match, but did find a data match.
+ if (dataTypeface.get() != NULL) {
+ SkAutoTUnref<SkStream> stream(dataTypeface->openStream(NULL));
+ if (stream.get() != NULL) {
+ return fImpl->createFromStream(stream.get(), dataTypefaceIndex);
+ }
+ }
+
+ // No data match, request data and add entry.
+ SkAutoTUnref<SkStreamAsset> stream(fProxy->getData(id.fDataId));
+ if (stream.get() == NULL) {
+ return NULL;
+ }
+
+ SkAutoTUnref<SkTypeface> typeface(fImpl->createFromStream(stream, id.fTtcIndex));
+ if (typeface.get() == NULL) {
+ return NULL;
+ }
+
+ DataEntry& newEntry = fDataCache.push_back();
+ typeface->weak_ref();
+ newEntry.fDataId = id.fDataId;
+ newEntry.fTtcIndex = id.fTtcIndex;
+ newEntry.fTypeface = typeface.get(); // weak reference passed to new entry.
+
+ return typeface.detach();
+}
+
+SkTypeface* SkFontMgr_Indirect::onMatchFamilyStyle(const char familyName[],
+ const SkFontStyle& fontStyle) const {
+ SkFontIdentity id = fProxy->matchNameStyle(familyName, fontStyle);
+ return this->createTypefaceFromFontId(id);
+}
+
+SkTypeface* SkFontMgr_Indirect::onMatchFamilyStyleCharacter(const char familyName[],
+ const SkFontStyle& style,
+ const char bpc47[],
+ uint32_t character) const {
+ SkFontIdentity id = fProxy->matchNameStyleCharacter(familyName, style, bpc47, character);
+ return this->createTypefaceFromFontId(id);
+}
+
+SkTypeface* SkFontMgr_Indirect::onMatchFaceStyle(const SkTypeface* familyMember,
+ const SkFontStyle& fontStyle) const {
+ SkString familyName;
+ familyMember->getFamilyName(&familyName);
+ return this->matchFamilyStyle(familyName.c_str(), fontStyle);
+}
+
+SkTypeface* SkFontMgr_Indirect::onCreateFromStream(SkStream* stream, int ttcIndex) const {
+ return fImpl->createFromStream(stream, ttcIndex);
+}
+
+SkTypeface* SkFontMgr_Indirect::onCreateFromFile(const char path[], int ttcIndex) const {
+ return fImpl->createFromFile(path, ttcIndex);
+}
+
+SkTypeface* SkFontMgr_Indirect::onCreateFromData(SkData* data, int ttcIndex) const {
+ return fImpl->createFromData(data, ttcIndex);
+}
+
+SkTypeface* SkFontMgr_Indirect::onLegacyCreateTypeface(const char familyName[],
+ unsigned styleBits) const {
+ bool bold = SkToBool(styleBits & SkTypeface::kBold);
+ bool italic = SkToBool(styleBits & SkTypeface::kItalic);
+ SkFontStyle style = SkFontStyle(bold ? SkFontStyle::kBold_Weight
+ : SkFontStyle::kNormal_Weight,
+ SkFontStyle::kNormal_Width,
+ italic ? SkFontStyle::kItalic_Slant
+ : SkFontStyle::kUpright_Slant);
+
+ SkAutoTUnref<SkTypeface> face(this->matchFamilyStyle(familyName, style));
+
+ if (NULL == face.get()) {
+ face.reset(this->matchFamilyStyle(NULL, style));
+ }
+
+ if (NULL == face.get()) {
+ SkFontIdentity fontId = this->fProxy->matchIndexStyle(0, style);
+ face.reset(this->createTypefaceFromFontId(fontId));
+ }
+
+ return face.detach();
+}
diff --git a/chromium/third_party/skia/src/fonts/SkGScalerContext.cpp b/chromium/third_party/skia/src/fonts/SkGScalerContext.cpp
index 551b01c9611..e1ab921337d 100644
--- a/chromium/third_party/skia/src/fonts/SkGScalerContext.cpp
+++ b/chromium/third_party/skia/src/fonts/SkGScalerContext.cpp
@@ -119,9 +119,8 @@ void SkGScalerContext::generateImage(const SkGlyph& glyph) {
fProxy->getPath(glyph, &path);
SkBitmap bm;
- bm.setConfig(SkBitmap::kARGB_8888_Config, glyph.fWidth, glyph.fHeight,
- glyph.rowBytes());
- bm.setPixels(glyph.fImage);
+ bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight),
+ glyph.fImage, glyph.rowBytes());
bm.eraseColor(0);
SkCanvas canvas(bm);
diff --git a/chromium/third_party/skia/src/fonts/SkRemotableFontMgr.cpp b/chromium/third_party/skia/src/fonts/SkRemotableFontMgr.cpp
new file mode 100644
index 00000000000..633e91458bb
--- /dev/null
+++ b/chromium/third_party/skia/src/fonts/SkRemotableFontMgr.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkRemotableFontMgr.h"
+
+#include "SkLazyPtr.h"
+
+SkRemotableFontIdentitySet::SkRemotableFontIdentitySet(int count, SkFontIdentity** data)
+ : fCount(count), fData(count)
+{
+ SkASSERT(data);
+ *data = fData;
+}
+
+SkRemotableFontIdentitySet* SkRemotableFontIdentitySet::NewEmptyImpl() {
+ return SkNEW(SkRemotableFontIdentitySet);
+}
+
+SkRemotableFontIdentitySet* SkRemotableFontIdentitySet::NewEmpty() {
+ SK_DECLARE_STATIC_LAZY_PTR(SkRemotableFontIdentitySet, empty, NewEmptyImpl);
+ return SkRef(empty.get());
+}
diff --git a/chromium/third_party/skia/src/gpu/FlingState.cpp b/chromium/third_party/skia/src/gpu/FlingState.cpp
deleted file mode 100644
index f0db5016bde..00000000000
--- a/chromium/third_party/skia/src/gpu/FlingState.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-
-/*
- * Copyright 2010 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-
-#include "FlingState.h"
-#include "SkMatrix.h"
-#include "SkTime.h"
-
-#define DISCRETIZE_TRANSLATE_TO_AVOID_FLICKER true
-
-static const float MAX_FLING_SPEED = 1500;
-
-static float pin_max_fling(float speed) {
- if (speed > MAX_FLING_SPEED) {
- speed = MAX_FLING_SPEED;
- }
- return speed;
-}
-
-static double getseconds() {
- return SkTime::GetMSecs() * 0.001;
-}
-
-// returns +1 or -1, depending on the sign of x
-// returns +1 if x is zero
-static SkScalar SkScalarSign(SkScalar x) {
- SkScalar sign = SK_Scalar1;
- if (x < 0) {
- sign = -sign;
- }
- return sign;
-}
-
-static void unit_axis_align(SkVector* unit) {
- const SkScalar TOLERANCE = SkDoubleToScalar(0.15);
- if (SkScalarAbs(unit->fX) < TOLERANCE) {
- unit->fX = 0;
- unit->fY = SkScalarSign(unit->fY);
- } else if (SkScalarAbs(unit->fY) < TOLERANCE) {
- unit->fX = SkScalarSign(unit->fX);
- unit->fY = 0;
- }
-}
-
-void FlingState::reset(float sx, float sy) {
- fActive = true;
- fDirection.set(sx, sy);
- fSpeed0 = SkPoint::Normalize(&fDirection);
- fSpeed0 = pin_max_fling(fSpeed0);
- fTime0 = getseconds();
-
- unit_axis_align(&fDirection);
-// printf("---- speed %g dir %g %g\n", fSpeed0, fDirection.fX, fDirection.fY);
-}
-
-bool FlingState::evaluateMatrix(SkMatrix* matrix) {
- if (!fActive) {
- return false;
- }
-
- const float t = getseconds() - fTime0;
- const float MIN_SPEED = 2;
- const float K0 = 5.0;
- const float K1 = 0.02;
- const float speed = fSpeed0 * (sk_float_exp(- K0 * t) - K1);
- if (speed <= MIN_SPEED) {
- fActive = false;
- return false;
- }
- float dist = (fSpeed0 - speed) / K0;
-
-// printf("---- time %g speed %g dist %g\n", t, speed, dist);
- float tx = fDirection.fX * dist;
- float ty = fDirection.fY * dist;
- if (DISCRETIZE_TRANSLATE_TO_AVOID_FLICKER) {
- tx = sk_float_round2int(tx);
- ty = sk_float_round2int(ty);
- }
- matrix->setTranslate(tx, ty);
-// printf("---- evaluate (%g %g)\n", tx, ty);
-
- return true;
-}
-
-////////////////////////////////////////
-
-GrAnimateFloat::GrAnimateFloat() : fTime0(0) {}
-
-void GrAnimateFloat::start(float v0, float v1, float duration) {
- fValue0 = v0;
- fValue1 = v1;
- fDuration = duration;
- if (duration > 0) {
- fTime0 = SkTime::GetMSecs();
- if (!fTime0) {
- fTime0 = 1; // time0 is our sentinel
- }
- } else {
- fTime0 = 0;
- }
-}
-
-float GrAnimateFloat::evaluate() {
- if (!fTime0) {
- return fValue1;
- }
-
- double elapsed = (SkTime::GetMSecs() - fTime0) * 0.001;
- if (elapsed >= fDuration) {
- fTime0 = 0;
- return fValue1;
- }
-
- double t = elapsed / fDuration;
- if (true) {
- t = (3 - 2 * t) * t * t;
- }
- return fValue0 + t * (fValue1 - fValue0);
-}
diff --git a/chromium/third_party/skia/src/gpu/GrAAConvexPathRenderer.cpp b/chromium/third_party/skia/src/gpu/GrAAConvexPathRenderer.cpp
index a8af5599910..d0f6e0ef64d 100644
--- a/chromium/third_party/skia/src/gpu/GrAAConvexPathRenderer.cpp
+++ b/chromium/third_party/skia/src/gpu/GrAAConvexPathRenderer.cpp
@@ -16,7 +16,7 @@
#include "GrTBackendEffectFactory.h"
#include "SkString.h"
#include "SkStrokeRec.h"
-#include "SkTrace.h"
+#include "SkTraceEvent.h"
#include "gl/GrGLEffect.h"
#include "gl/GrGLSL.h"
@@ -35,12 +35,12 @@ struct Segment {
} fType;
// line uses one pt, quad uses 2 pts
- GrPoint fPts[2];
+ SkPoint fPts[2];
// normal to edge ending at each pt
- GrVec fNorms[2];
+ SkVector fNorms[2];
// is the corner where the previous segment meets this segment
// sharp. If so, fMid is a normalized bisector facing outward.
- GrVec fMid;
+ SkVector fMid;
int countPoints() {
GR_STATIC_ASSERT(0 == kLine && 1 == kQuad);
@@ -118,11 +118,11 @@ static void compute_vectors(SegmentArray* segments,
int count = segments->count();
// Make the normals point towards the outside
- GrPoint::Side normSide;
+ SkPoint::Side normSide;
if (dir == SkPath::kCCW_Direction) {
- normSide = GrPoint::kRight_Side;
+ normSide = SkPoint::kRight_Side;
} else {
- normSide = GrPoint::kLeft_Side;
+ normSide = SkPoint::kLeft_Side;
}
*vCount = 0;
@@ -133,7 +133,7 @@ static void compute_vectors(SegmentArray* segments,
int b = (a + 1) % count;
Segment& segb = (*segments)[b];
- const GrPoint* prevPt = &sega.endPt();
+ const SkPoint* prevPt = &sega.endPt();
int n = segb.countPoints();
for (int p = 0; p < n; ++p) {
segb.fNorms[p] = segb.fPts[p] - *prevPt;
@@ -173,15 +173,15 @@ struct DegenerateTestData {
kLine,
kNonDegenerate
} fStage;
- GrPoint fFirstPoint;
- GrVec fLineNormal;
+ SkPoint fFirstPoint;
+ SkVector fLineNormal;
SkScalar fLineC;
};
static const SkScalar kClose = (SK_Scalar1 / 16);
static const SkScalar kCloseSqd = SkScalarMul(kClose, kClose);
-static void update_degenerate_test(DegenerateTestData* data, const GrPoint& pt) {
+static void update_degenerate_test(DegenerateTestData* data, const SkPoint& pt) {
switch (data->fStage) {
case DegenerateTestData::kInitial:
data->fFirstPoint = pt;
@@ -203,7 +203,7 @@ static void update_degenerate_test(DegenerateTestData* data, const GrPoint& pt)
case DegenerateTestData::kNonDegenerate:
break;
default:
- GrCrash("Unexpected degenerate test stage.");
+ SkFAIL("Unexpected degenerate test stage.");
}
}
@@ -288,7 +288,7 @@ static bool get_segments(const SkPath& path,
}
for (;;) {
- GrPoint pts[4];
+ SkPoint pts[4];
SkPath::Verb verb = iter.next(pts);
switch (verb) {
case SkPath::kMove_Verb:
@@ -330,8 +330,8 @@ static bool get_segments(const SkPath& path,
}
struct QuadVertex {
- GrPoint fPos;
- GrPoint fUV;
+ SkPoint fPos;
+ SkPoint fUV;
SkScalar fD0;
SkScalar fD1;
};
@@ -439,9 +439,9 @@ static void create_vertices(const SegmentArray& segments,
*v += 5;
*i += 9;
} else {
- GrPoint qpts[] = {sega.endPt(), segb.fPts[0], segb.fPts[1]};
+ SkPoint qpts[] = {sega.endPt(), segb.fPts[0], segb.fPts[1]};
- GrVec midVec = segb.fNorms[0] + segb.fNorms[1];
+ SkVector midVec = segb.fNorms[0] + segb.fNorms[1];
midVec.normalize();
verts[*v + 0].fPos = fanPt;
@@ -468,7 +468,7 @@ static void create_vertices(const SegmentArray& segments,
verts[*v + 5].fD1 = -SK_ScalarMax/100;
GrPathUtils::QuadUVMatrix toUV(qpts);
- toUV.apply<6, sizeof(QuadVertex), sizeof(GrPoint)>(verts + *v);
+ toUV.apply<6, sizeof(QuadVertex), sizeof(SkPoint)>(verts + *v);
idxs[*i + 0] = *v + 3;
idxs[*i + 1] = *v + 1;
@@ -618,7 +618,7 @@ namespace {
// position + edge
extern const GrVertexAttrib gPathAttribs[] = {
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
- {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}
+ {kVec4f_GrVertexAttribType, sizeof(SkPoint), kEffect_GrVertexAttribBinding}
};
};
diff --git a/chromium/third_party/skia/src/gpu/GrAAHairLinePathRenderer.cpp b/chromium/third_party/skia/src/gpu/GrAAHairLinePathRenderer.cpp
index 2b5428c47d7..0014bbe4a04 100644
--- a/chromium/third_party/skia/src/gpu/GrAAHairLinePathRenderer.cpp
+++ b/chromium/third_party/skia/src/gpu/GrAAHairLinePathRenderer.cpp
@@ -50,7 +50,7 @@ static const size_t kLineSegIdxSBufize = kIdxsPerLineSeg *
kNumLineSegsInIdxBuffer;
static bool push_quad_index_data(GrIndexBuffer* qIdxBuffer) {
- uint16_t* data = (uint16_t*) qIdxBuffer->lock();
+ uint16_t* data = (uint16_t*) qIdxBuffer->map();
bool tempData = NULL == data;
if (tempData) {
data = SkNEW_ARRAY(uint16_t, kNumQuadsInIdxBuffer * kIdxsPerQuad);
@@ -86,13 +86,13 @@ static bool push_quad_index_data(GrIndexBuffer* qIdxBuffer) {
delete[] data;
return ret;
} else {
- qIdxBuffer->unlock();
+ qIdxBuffer->unmap();
return true;
}
}
static bool push_line_index_data(GrIndexBuffer* lIdxBuffer) {
- uint16_t* data = (uint16_t*) lIdxBuffer->lock();
+ uint16_t* data = (uint16_t*) lIdxBuffer->map();
bool tempData = NULL == data;
if (tempData) {
data = SkNEW_ARRAY(uint16_t, kNumLineSegsInIdxBuffer * kIdxsPerLineSeg);
@@ -139,7 +139,7 @@ static bool push_line_index_data(GrIndexBuffer* lIdxBuffer) {
delete[] data;
return ret;
} else {
- lIdxBuffer->unlock();
+ lIdxBuffer->unmap();
return true;
}
}
@@ -300,19 +300,10 @@ int num_quad_subdivs(const SkPoint p[3]) {
// = log4(d*d/tol*tol)/2
// = log2(d*d/tol*tol)
-#ifdef SK_SCALAR_IS_FLOAT
// +1 since we're ignoring the mantissa contribution.
int log = get_float_exp(dsqd/(gSubdivTol*gSubdivTol)) + 1;
- log = GrMin(GrMax(0, log), kMaxSub);
+ log = SkTMin(SkTMax(0, log), kMaxSub);
return log;
-#else
- SkScalar log = SkScalarLog(
- SkScalarDiv(dsqd,
- SkScalarMul(gSubdivTol, gSubdivTol)));
- static const SkScalar conv = SkScalarInvert(SkScalarLog(2));
- log = SkScalarMul(log, conv);
- return GrMin(GrMax(0, SkScalarCeilToInt(log)),kMaxSub);
-#endif
}
}
@@ -342,8 +333,8 @@ int generate_lines_and_quads(const SkPath& path,
bool persp = m.hasPerspective();
for (;;) {
- GrPoint pathPts[4];
- GrPoint devPts[4];
+ SkPoint pathPts[4];
+ SkPoint devPts[4];
SkPath::Verb verb = iter.next(pathPts);
switch (verb) {
case SkPath::kConic_Verb: {
@@ -495,26 +486,26 @@ int generate_lines_and_quads(const SkPath& path,
}
struct LineVertex {
- GrPoint fPos;
+ SkPoint fPos;
GrColor fCoverage;
};
struct BezierVertex {
- GrPoint fPos;
+ SkPoint fPos;
union {
struct {
SkScalar fK;
SkScalar fL;
SkScalar fM;
} fConic;
- GrVec fQuadCoord;
+ SkVector fQuadCoord;
struct {
SkScalar fBogus[4];
};
};
};
-GR_STATIC_ASSERT(sizeof(BezierVertex) == 3 * sizeof(GrPoint));
+GR_STATIC_ASSERT(sizeof(BezierVertex) == 3 * sizeof(SkPoint));
void intersect_lines(const SkPoint& ptA, const SkVector& normA,
const SkPoint& ptB, const SkVector& normB,
@@ -537,7 +528,7 @@ void intersect_lines(const SkPoint& ptA, const SkVector& normA,
void set_uv_quad(const SkPoint qpts[3], BezierVertex verts[kVertsPerQuad]) {
// this should be in the src space, not dev coords, when we have perspective
GrPathUtils::QuadUVMatrix DevToUV(qpts);
- DevToUV.apply<kVertsPerQuad, sizeof(BezierVertex), sizeof(GrPoint)>(verts);
+ DevToUV.apply<kVertsPerQuad, sizeof(BezierVertex), sizeof(SkPoint)>(verts);
}
void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice,
@@ -717,13 +708,13 @@ namespace {
// position + edge
extern const GrVertexAttrib gHairlineBezierAttribs[] = {
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
- {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}
+ {kVec4f_GrVertexAttribType, sizeof(SkPoint), kEffect_GrVertexAttribBinding}
};
// position + coverage
extern const GrVertexAttrib gHairlineLineAttribs[] = {
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
- {kVec4ub_GrVertexAttribType, sizeof(GrPoint), kCoverage_GrVertexAttribBinding},
+ {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kCoverage_GrVertexAttribBinding},
};
};
@@ -958,7 +949,7 @@ bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
target->setIndexSourceToBuffer(fLinesIndexBuffer);
int lines = 0;
while (lines < lineCnt) {
- int n = GrMin(lineCnt - lines, kNumLineSegsInIdxBuffer);
+ int n = SkTMin(lineCnt - lines, kNumLineSegsInIdxBuffer);
target->drawIndexed(kTriangles_GrPrimitiveType,
kVertsPerLineSeg*lines, // startV
0, // startI
@@ -1006,7 +997,7 @@ bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
kVertsPerQuad * quadCnt + kVertsPerQuad * conicCnt));
if (quadCnt > 0) {
- GrEffectRef* hairQuadEffect = GrQuadEffect::Create(kHairAA_GrBezierEdgeType,
+ GrEffectRef* hairQuadEffect = GrQuadEffect::Create(kHairlineAA_GrEffectEdgeType,
*target->caps());
SkASSERT(NULL != hairQuadEffect);
GrDrawState::AutoRestoreEffects are(drawState);
@@ -1014,7 +1005,7 @@ bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
drawState->addCoverageEffect(hairQuadEffect, kEdgeAttrIndex)->unref();
int quads = 0;
while (quads < quadCnt) {
- int n = GrMin(quadCnt - quads, kNumQuadsInIdxBuffer);
+ int n = SkTMin(quadCnt - quads, kNumQuadsInIdxBuffer);
target->drawIndexed(kTriangles_GrPrimitiveType,
kVertsPerQuad*quads, // startV
0, // startI
@@ -1027,13 +1018,13 @@ bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
if (conicCnt > 0) {
GrDrawState::AutoRestoreEffects are(drawState);
- GrEffectRef* hairConicEffect = GrConicEffect::Create(kHairAA_GrBezierEdgeType,
+ GrEffectRef* hairConicEffect = GrConicEffect::Create(kHairlineAA_GrEffectEdgeType,
*target->caps());
SkASSERT(NULL != hairConicEffect);
drawState->addCoverageEffect(hairConicEffect, 1, 2)->unref();
int conics = 0;
while (conics < conicCnt) {
- int n = GrMin(conicCnt - conics, kNumQuadsInIdxBuffer);
+ int n = SkTMin(conicCnt - conics, kNumQuadsInIdxBuffer);
target->drawIndexed(kTriangles_GrPrimitiveType,
kVertsPerQuad*(quadCnt + conics), // startV
0, // startI
diff --git a/chromium/third_party/skia/src/gpu/GrAARectRenderer.cpp b/chromium/third_party/skia/src/gpu/GrAARectRenderer.cpp
index 2c21f09f000..497b3cfbb8d 100644
--- a/chromium/third_party/skia/src/gpu/GrAARectRenderer.cpp
+++ b/chromium/third_party/skia/src/gpu/GrAARectRenderer.cpp
@@ -261,12 +261,12 @@ namespace {
extern const GrVertexAttrib gAARectCoverageAttribs[] = {
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
- {kVec4ub_GrVertexAttribType, sizeof(GrPoint), kCoverage_GrVertexAttribBinding},
+ {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kCoverage_GrVertexAttribBinding},
};
extern const GrVertexAttrib gAARectColorAttribs[] = {
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
- {kVec4ub_GrVertexAttribType, sizeof(GrPoint), kColor_GrVertexAttribBinding},
+ {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding},
};
static void set_aa_rect_vertex_attributes(GrDrawState* drawState, bool useCoverage) {
@@ -277,7 +277,7 @@ static void set_aa_rect_vertex_attributes(GrDrawState* drawState, bool useCovera
}
}
-static void set_inset_fan(GrPoint* pts, size_t stride,
+static void set_inset_fan(SkPoint* pts, size_t stride,
const SkRect& r, SkScalar dx, SkScalar dy) {
pts->setRectFan(r.fLeft + dx, r.fTop + dy,
r.fRight - dx, r.fBottom - dy, stride);
@@ -299,7 +299,7 @@ static const uint16_t gFillAARectIdx[] = {
4, 5, 6, 6, 7, 4,
};
-static const int kIndicesPerAAFillRect = GR_ARRAY_COUNT(gFillAARectIdx);
+static const int kIndicesPerAAFillRect = SK_ARRAY_COUNT(gFillAARectIdx);
static const int kVertsPerAAFillRect = 8;
static const int kNumAAFillRectsInIndexBuffer = 256;
@@ -311,7 +311,7 @@ GrIndexBuffer* GrAARectRenderer::aaFillRectIndexBuffer(GrGpu* gpu) {
if (NULL == fAAFillRectIndexBuffer) {
fAAFillRectIndexBuffer = gpu->createIndexBuffer(kAAFillRectIndexBufferSize, false);
if (NULL != fAAFillRectIndexBuffer) {
- uint16_t* data = (uint16_t*) fAAFillRectIndexBuffer->lock();
+ uint16_t* data = (uint16_t*) fAAFillRectIndexBuffer->map();
bool useTempData = (NULL == data);
if (useTempData) {
data = SkNEW_ARRAY(uint16_t, kNumAAFillRectsInIndexBuffer * kIndicesPerAAFillRect);
@@ -327,11 +327,11 @@ GrIndexBuffer* GrAARectRenderer::aaFillRectIndexBuffer(GrGpu* gpu) {
}
if (useTempData) {
if (!fAAFillRectIndexBuffer->updateData(data, kAAFillRectIndexBufferSize)) {
- GrCrash("Can't get AA Fill Rect indices into buffer!");
+ SkFAIL("Can't get AA Fill Rect indices into buffer!");
}
SkDELETE_ARRAY(data);
} else {
- fAAFillRectIndexBuffer->unlock();
+ fAAFillRectIndexBuffer->unmap();
}
}
}
@@ -414,8 +414,8 @@ static const uint16_t gBevelStrokeAARectIdx[] = {
};
int GrAARectRenderer::aaStrokeRectIndexCount(bool miterStroke) {
- return miterStroke ? GR_ARRAY_COUNT(gMiterStrokeAARectIdx) :
- GR_ARRAY_COUNT(gBevelStrokeAARectIdx);
+ return miterStroke ? SK_ARRAY_COUNT(gMiterStrokeAARectIdx) :
+ SK_ARRAY_COUNT(gBevelStrokeAARectIdx);
}
GrIndexBuffer* GrAARectRenderer::aaStrokeRectIndexBuffer(GrGpu* gpu, bool miterStroke) {
@@ -474,10 +474,10 @@ void GrAARectRenderer::geometryFillAARect(GrGpu* gpu,
intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
size_t vsize = drawState->getVertexSize();
- SkASSERT(sizeof(GrPoint) + sizeof(GrColor) == vsize);
+ SkASSERT(sizeof(SkPoint) + sizeof(GrColor) == vsize);
- GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts);
- GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize);
+ SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts);
+ SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + 4 * vsize);
SkScalar inset = SkMinScalar(devRect.width(), SK_Scalar1);
inset = SK_ScalarHalf * SkMinScalar(inset, devRect.height());
@@ -531,7 +531,7 @@ void GrAARectRenderer::geometryFillAARect(GrGpu* gpu,
*((SkPoint*)((intptr_t)fan0Pos + 3 * vsize)) += vec[0] - vec[1];
}
- verts += sizeof(GrPoint);
+ verts += sizeof(SkPoint);
for (int i = 0; i < 4; ++i) {
*reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
}
@@ -571,30 +571,30 @@ namespace {
// Rotated
struct RectVertex {
- GrPoint fPos;
- GrPoint fCenter;
- GrPoint fDir;
- GrPoint fWidthHeight;
+ SkPoint fPos;
+ SkPoint fCenter;
+ SkPoint fDir;
+ SkPoint fWidthHeight;
};
// Rotated
extern const GrVertexAttrib gAARectVertexAttribs[] = {
{ kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding },
- { kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding },
- { kVec2f_GrVertexAttribType, 3*sizeof(GrPoint), kEffect_GrVertexAttribBinding }
+ { kVec4f_GrVertexAttribType, sizeof(SkPoint), kEffect_GrVertexAttribBinding },
+ { kVec2f_GrVertexAttribType, 3*sizeof(SkPoint), kEffect_GrVertexAttribBinding }
};
// Axis Aligned
struct AARectVertex {
- GrPoint fPos;
- GrPoint fOffset;
- GrPoint fWidthHeight;
+ SkPoint fPos;
+ SkPoint fOffset;
+ SkPoint fWidthHeight;
};
// Axis Aligned
extern const GrVertexAttrib gAAAARectVertexAttribs[] = {
{ kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding },
- { kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding },
+ { kVec4f_GrVertexAttribType, sizeof(SkPoint), kEffect_GrVertexAttribBinding },
};
};
@@ -695,7 +695,7 @@ void GrAARectRenderer::shaderFillAlignedAARect(GrGpu* gpu,
devRect.fBottom + SK_ScalarHalf
};
- GrPoint widthHeight = {
+ SkPoint widthHeight = {
SkScalarHalf(devRect.width()) + SK_ScalarHalf,
SkScalarHalf(devRect.height()) + SK_ScalarHalf
};
@@ -726,10 +726,10 @@ void GrAARectRenderer::strokeAARect(GrGpu* gpu,
const SkRect& rect,
const SkMatrix& combinedMatrix,
const SkRect& devRect,
- const SkStrokeRec* stroke,
+ const SkStrokeRec& stroke,
bool useVertexCoverage) {
- GrVec devStrokeSize;
- SkScalar width = stroke->getWidth();
+ SkVector devStrokeSize;
+ SkScalar width = stroke.getWidth();
if (width > 0) {
devStrokeSize.set(width, width);
combinedMatrix.mapVectors(&devStrokeSize, 1);
@@ -755,7 +755,7 @@ void GrAARectRenderer::strokeAARect(GrGpu* gpu,
{
SkScalar w = devRect.width() - dx;
SkScalar h = devRect.height() - dy;
- spare = GrMin(w, h);
+ spare = SkTMin(w, h);
}
SkRect devOutside(devRect);
@@ -763,7 +763,7 @@ void GrAARectRenderer::strokeAARect(GrGpu* gpu,
bool miterStroke = true;
// small miter limit means right angles show bevel...
- if (stroke->getJoin() != SkPaint::kMiter_Join || stroke->getMiter() < SK_ScalarSqrt2) {
+ if (stroke.getJoin() != SkPaint::kMiter_Join || stroke.getMiter() < SK_ScalarSqrt2) {
miterStroke = false;
}
@@ -818,15 +818,15 @@ void GrAARectRenderer::geometryStrokeAARect(GrGpu* gpu,
intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
size_t vsize = drawState->getVertexSize();
- SkASSERT(sizeof(GrPoint) + sizeof(GrColor) == vsize);
+ SkASSERT(sizeof(SkPoint) + sizeof(GrColor) == vsize);
// We create vertices for four nested rectangles. There are two ramps from 0 to full
// coverage, one on the exterior of the stroke and the other on the interior.
// The following pointers refer to the four rects, from outermost to innermost.
- GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts);
- GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + outerVertexNum * vsize);
- GrPoint* fan2Pos = reinterpret_cast<GrPoint*>(verts + 2 * outerVertexNum * vsize);
- GrPoint* fan3Pos = reinterpret_cast<GrPoint*>(verts + (2 * outerVertexNum + innerVertexNum) * vsize);
+ SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts);
+ SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + outerVertexNum * vsize);
+ SkPoint* fan2Pos = reinterpret_cast<SkPoint*>(verts + 2 * outerVertexNum * vsize);
+ SkPoint* fan3Pos = reinterpret_cast<SkPoint*>(verts + (2 * outerVertexNum + innerVertexNum) * vsize);
#ifndef SK_IGNORE_THIN_STROKED_RECT_FIX
// TODO: this only really works if the X & Y margins are the same all around
@@ -853,8 +853,8 @@ void GrAARectRenderer::geometryStrokeAARect(GrGpu* gpu,
// innermost
set_inset_fan(fan3Pos, vsize, devInside, SK_ScalarHalf, SK_ScalarHalf);
} else {
- GrPoint* fan0AssistPos = reinterpret_cast<GrPoint*>(verts + 4 * vsize);
- GrPoint* fan1AssistPos = reinterpret_cast<GrPoint*>(verts + (outerVertexNum + 4) * vsize);
+ SkPoint* fan0AssistPos = reinterpret_cast<SkPoint*>(verts + 4 * vsize);
+ SkPoint* fan1AssistPos = reinterpret_cast<SkPoint*>(verts + (outerVertexNum + 4) * vsize);
// outermost
set_inset_fan(fan0Pos, vsize, devOutside, -SK_ScalarHalf, -SK_ScalarHalf);
set_inset_fan(fan0AssistPos, vsize, devOutsideAssist, -SK_ScalarHalf, -SK_ScalarHalf);
@@ -868,7 +868,7 @@ void GrAARectRenderer::geometryStrokeAARect(GrGpu* gpu,
}
// The outermost rect has 0 coverage
- verts += sizeof(GrPoint);
+ verts += sizeof(SkPoint);
for (int i = 0; i < outerVertexNum; ++i) {
*reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
}
diff --git a/chromium/third_party/skia/src/gpu/GrAARectRenderer.h b/chromium/third_party/skia/src/gpu/GrAARectRenderer.h
index 3e7e980e593..faaf7e20be8 100644
--- a/chromium/third_party/skia/src/gpu/GrAARectRenderer.h
+++ b/chromium/third_party/skia/src/gpu/GrAARectRenderer.h
@@ -65,7 +65,7 @@ public:
const SkRect& rect,
const SkMatrix& combinedMatrix,
const SkRect& devRect,
- const SkStrokeRec* stroke,
+ const SkStrokeRec& stroke,
bool useVertexCoverage);
// First rect is outer; second rect is inner
diff --git a/chromium/third_party/skia/src/gpu/GrAddPathRenderers_none.cpp b/chromium/third_party/skia/src/gpu/GrAddPathRenderers_none.cpp
deleted file mode 100644
index 02da7107246..00000000000
--- a/chromium/third_party/skia/src/gpu/GrAddPathRenderers_none.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#include "GrPathRenderer.h"
-
-
-void GrPathRenderer::AddPathRenderers(GrContext*,
- GrPathRendererChain::UsageFlags,
- GrPathRendererChain*) {}
diff --git a/chromium/third_party/skia/src/gpu/GrAllocPool.cpp b/chromium/third_party/skia/src/gpu/GrAllocPool.cpp
index d7b553176d8..c92ebbd121a 100644
--- a/chromium/third_party/skia/src/gpu/GrAllocPool.cpp
+++ b/chromium/third_party/skia/src/gpu/GrAllocPool.cpp
@@ -42,7 +42,7 @@ struct GrAllocPool::Block {
size_t release(size_t bytes) {
SkASSERT(bytes > 0);
- size_t free = GrMin(bytes, fBytesTotal - fBytesFree);
+ size_t free = SkTMin(bytes, fBytesTotal - fBytesFree);
fBytesFree += free;
fPtr -= free;
return bytes - free;
@@ -55,7 +55,7 @@ struct GrAllocPool::Block {
GrAllocPool::GrAllocPool(size_t blockSize) {
fBlock = NULL;
- fMinBlockSize = GrMax(blockSize, GrAllocPool_MIN_BLOCK_SIZE);
+ fMinBlockSize = SkTMax(blockSize, GrAllocPool_MIN_BLOCK_SIZE);
SkDEBUGCODE(fBlocksAllocated = 0;)
}
@@ -80,7 +80,7 @@ void* GrAllocPool::alloc(size_t size) {
this->validate();
if (!fBlock || !fBlock->canAlloc(size)) {
- size_t blockSize = GrMax(fMinBlockSize, size);
+ size_t blockSize = SkTMax(fMinBlockSize, size);
fBlock = Block::Create(blockSize, fBlock);
SkDEBUGCODE(fBlocksAllocated += 1;)
}
diff --git a/chromium/third_party/skia/src/gpu/GrAllocPool.h b/chromium/third_party/skia/src/gpu/GrAllocPool.h
index 07ba05fd917..4fc826569eb 100644
--- a/chromium/third_party/skia/src/gpu/GrAllocPool.h
+++ b/chromium/third_party/skia/src/gpu/GrAllocPool.h
@@ -10,7 +10,7 @@
#include "SkTypes.h"
-class GrAllocPool : public SkNoncopyable {
+class GrAllocPool : SkNoncopyable {
public:
GrAllocPool(size_t blockSize = 0);
~GrAllocPool();
diff --git a/chromium/third_party/skia/src/gpu/GrAllocator.h b/chromium/third_party/skia/src/gpu/GrAllocator.h
index f2afec8e467..a2ad408e072 100755..100644
--- a/chromium/third_party/skia/src/gpu/GrAllocator.h
+++ b/chromium/third_party/skia/src/gpu/GrAllocator.h
@@ -13,7 +13,7 @@
#include "SkTArray.h"
#include "SkTypes.h"
-class GrAllocator : public SkNoncopyable {
+class GrAllocator : SkNoncopyable {
public:
~GrAllocator() {
reset();
@@ -80,7 +80,7 @@ public:
* removes all added items
*/
void reset() {
- int blockCount = GrMax((unsigned)1,
+ int blockCount = SkTMax((unsigned)1,
GrUIDivRoundUp(fCount, fItemsPerBlock));
for (int i = 1; i < blockCount; ++i) {
sk_free(fBlocks[i]);
@@ -153,7 +153,7 @@ private:
};
template <typename T>
-class GrTAllocator : public SkNoncopyable {
+class GrTAllocator : SkNoncopyable {
public:
virtual ~GrTAllocator() { this->reset(); };
diff --git a/chromium/third_party/skia/src/gpu/GrAtlas.cpp b/chromium/third_party/skia/src/gpu/GrAtlas.cpp
index dd362908d3f..ea5ad50a39e 100644
--- a/chromium/third_party/skia/src/gpu/GrAtlas.cpp
+++ b/chromium/third_party/skia/src/gpu/GrAtlas.cpp
@@ -10,37 +10,10 @@
#include "GrContext.h"
#include "GrGpu.h"
#include "GrRectanizer.h"
-
-#if 0
-#define GR_PLOT_WIDTH 8
-#define GR_PLOT_HEIGHT 4
-#define GR_ATLAS_WIDTH 256
-#define GR_ATLAS_HEIGHT 256
-
-#define GR_ATLAS_TEXTURE_WIDTH (GR_PLOT_WIDTH * GR_ATLAS_WIDTH)
-#define GR_ATLAS_TEXTURE_HEIGHT (GR_PLOT_HEIGHT * GR_ATLAS_HEIGHT)
-
-#else
-
-#define GR_ATLAS_TEXTURE_WIDTH 1024
-#define GR_ATLAS_TEXTURE_HEIGHT 2048
-
-#define GR_ATLAS_WIDTH 256
-#define GR_ATLAS_HEIGHT 256
-
-#define GR_PLOT_WIDTH (GR_ATLAS_TEXTURE_WIDTH / GR_ATLAS_WIDTH)
-#define GR_PLOT_HEIGHT (GR_ATLAS_TEXTURE_HEIGHT / GR_ATLAS_HEIGHT)
-
-#endif
+#include "GrTracing.h"
///////////////////////////////////////////////////////////////////////////////
-#define BORDER 1
-
-#ifdef SK_DEBUG
- static int gCounter;
-#endif
-
// for testing
#define FONT_CACHE_STATS 0
#if FONT_CACHE_STATS
@@ -48,67 +21,82 @@ static int g_UploadCount = 0;
#endif
GrPlot::GrPlot() : fDrawToken(NULL, 0)
- , fNext(NULL)
, fTexture(NULL)
+ , fRects(NULL)
, fAtlasMgr(NULL)
, fBytesPerPixel(1)
+ , fDirty(false)
+ , fBatchUploads(false)
{
- fRects = GrRectanizer::Factory(GR_ATLAS_WIDTH - BORDER,
- GR_ATLAS_HEIGHT - BORDER);
fOffset.set(0, 0);
}
GrPlot::~GrPlot() {
+ SkDELETE_ARRAY(fPlotData);
+ fPlotData = NULL;
delete fRects;
}
-static inline void adjust_for_offset(GrIPoint16* loc, const GrIPoint16& offset) {
- loc->fX += offset.fX * GR_ATLAS_WIDTH;
- loc->fY += offset.fY * GR_ATLAS_HEIGHT;
+void GrPlot::init(GrAtlasMgr* mgr, int offX, int offY, int width, int height, size_t bpp,
+ bool batchUploads) {
+ fRects = GrRectanizer::Factory(width, height);
+ fAtlasMgr = mgr;
+ fOffset.set(offX * width, offY * height);
+ fBytesPerPixel = bpp;
+ fPlotData = NULL;
+ fDirtyRect.setEmpty();
+ fDirty = false;
+ fBatchUploads = batchUploads;
}
-static inline uint8_t* zero_fill(uint8_t* ptr, size_t count) {
- sk_bzero(ptr, count);
- return ptr + count;
+static inline void adjust_for_offset(SkIPoint16* loc, const SkIPoint16& offset) {
+ loc->fX += offset.fX;
+ loc->fY += offset.fY;
}
bool GrPlot::addSubImage(int width, int height, const void* image,
- GrIPoint16* loc) {
- if (!fRects->addRect(width + BORDER, height + BORDER, loc)) {
+ SkIPoint16* loc) {
+ float percentFull = fRects->percentFull();
+ if (!fRects->addRect(width, height, loc)) {
return false;
}
- SkAutoSMalloc<1024> storage;
- int dstW = width + 2*BORDER;
- int dstH = height + 2*BORDER;
- if (BORDER) {
- const size_t dstRB = dstW * fBytesPerPixel;
- uint8_t* dst = (uint8_t*)storage.reset(dstH * dstRB);
- sk_bzero(dst, dstRB); // zero top row
- dst += dstRB;
- for (int y = 0; y < height; y++) {
- dst = zero_fill(dst, fBytesPerPixel); // zero left edge
- memcpy(dst, image, width * fBytesPerPixel);
- dst += width * fBytesPerPixel;
- dst = zero_fill(dst, fBytesPerPixel); // zero right edge
- image = (const void*)((const char*)image + width * fBytesPerPixel);
+ // if batching uploads, create backing memory on first use
+ // once the plot is nearly full we will revert to uploading each subimage individually
+ int plotWidth = fRects->width();
+ int plotHeight = fRects->height();
+ if (fBatchUploads && NULL == fPlotData && 0.0f == percentFull) {
+ fPlotData = SkNEW_ARRAY(unsigned char, fBytesPerPixel*plotWidth*plotHeight);
+ memset(fPlotData, 0, fBytesPerPixel*plotWidth*plotHeight);
+ }
+
+ // if we have backing memory, copy to the memory and set for future upload
+ if (NULL != fPlotData) {
+ const unsigned char* imagePtr = (const unsigned char*) image;
+ // point ourselves at the right starting spot
+ unsigned char* dataPtr = fPlotData;
+ dataPtr += fBytesPerPixel*plotWidth*loc->fY;
+ dataPtr += fBytesPerPixel*loc->fX;
+ // copy into the data buffer
+ for (int i = 0; i < height; ++i) {
+ memcpy(dataPtr, imagePtr, fBytesPerPixel*width);
+ dataPtr += fBytesPerPixel*plotWidth;
+ imagePtr += fBytesPerPixel*width;
}
- sk_bzero(dst, dstRB); // zero bottom row
- image = storage.get();
+
+ fDirtyRect.join(loc->fX, loc->fY, loc->fX + width, loc->fY + height);
+ adjust_for_offset(loc, fOffset);
+ fDirty = true;
+ // otherwise, just upload the image directly
+ } else {
+ adjust_for_offset(loc, fOffset);
+ GrContext* context = fTexture->getContext();
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), "GrPlot::uploadToTexture");
+ context->writeTexturePixels(fTexture,
+ loc->fX, loc->fY, width, height,
+ fTexture->config(), image, 0,
+ GrContext::kDontFlush_PixelOpsFlag);
}
- adjust_for_offset(loc, fOffset);
- GrContext* context = fTexture->getContext();
- // We pass the flag that does not force a flush. We assume our caller is
- // smart and hasn't referenced the part of the texture we're about to update
- // since the last flush.
- context->writeTexturePixels(fTexture,
- loc->fX, loc->fY, dstW, dstH,
- fTexture->config(), image, 0,
- GrContext::kDontFlush_PixelOpsFlag);
-
- // now tell the caller to skip the top/left BORDER
- loc->fX += BORDER;
- loc->fY += BORDER;
#if FONT_CACHE_STATS
++g_UploadCount;
@@ -117,29 +105,81 @@ bool GrPlot::addSubImage(int width, int height, const void* image,
return true;
}
+void GrPlot::uploadToTexture() {
+ static const float kNearlyFullTolerance = 0.85f;
+
+ // should only do this if batching is enabled
+ SkASSERT(fBatchUploads);
+
+ if (fDirty) {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), "GrPlot::uploadToTexture");
+ SkASSERT(NULL != fTexture);
+ GrContext* context = fTexture->getContext();
+ // We pass the flag that does not force a flush. We assume our caller is
+ // smart and hasn't referenced the part of the texture we're about to update
+ // since the last flush.
+ size_t rowBytes = fBytesPerPixel*fRects->width();
+ const unsigned char* dataPtr = fPlotData;
+ dataPtr += rowBytes*fDirtyRect.fTop;
+ dataPtr += fBytesPerPixel*fDirtyRect.fLeft;
+ context->writeTexturePixels(fTexture,
+ fOffset.fX + fDirtyRect.fLeft, fOffset.fY + fDirtyRect.fTop,
+ fDirtyRect.width(), fDirtyRect.height(),
+ fTexture->config(), dataPtr,
+ rowBytes,
+ GrContext::kDontFlush_PixelOpsFlag);
+ fDirtyRect.setEmpty();
+ fDirty = false;
+ // If the Plot is nearly full, anything else we add will probably be small and one
+ // at a time, so free up the memory and after this upload any new images directly.
+ if (fRects->percentFull() > kNearlyFullTolerance) {
+ SkDELETE_ARRAY(fPlotData);
+ fPlotData = NULL;
+ }
+ }
+}
+
+void GrPlot::resetRects() {
+ SkASSERT(NULL != fRects);
+ fRects->reset();
+}
+
///////////////////////////////////////////////////////////////////////////////
-GrAtlasMgr::GrAtlasMgr(GrGpu* gpu, GrPixelConfig config) {
- fGpu = gpu;
+GrAtlasMgr::GrAtlasMgr(GrGpu* gpu, GrPixelConfig config,
+ const SkISize& backingTextureSize,
+ int numPlotsX, int numPlotsY, bool batchUploads) {
+ fGpu = SkRef(gpu);
fPixelConfig = config;
- gpu->ref();
+ fBackingTextureSize = backingTextureSize;
+ fNumPlotsX = numPlotsX;
+ fNumPlotsY = numPlotsY;
+ fBatchUploads = batchUploads;
fTexture = NULL;
+ int textureWidth = fBackingTextureSize.width();
+ int textureHeight = fBackingTextureSize.height();
+
+ int plotWidth = textureWidth / fNumPlotsX;
+ int plotHeight = textureHeight / fNumPlotsY;
+
+ SkASSERT(plotWidth * fNumPlotsX == textureWidth);
+ SkASSERT(plotHeight * fNumPlotsY == textureHeight);
+
+ // We currently do not support compressed atlases...
+ SkASSERT(!GrPixelConfigIsCompressed(config));
+
// set up allocated plots
size_t bpp = GrBytesPerPixel(fPixelConfig);
- fPlots = SkNEW_ARRAY(GrPlot, (GR_PLOT_WIDTH*GR_PLOT_HEIGHT));
- fFreePlots = NULL;
- GrPlot* currPlot = fPlots;
- for (int y = GR_PLOT_HEIGHT-1; y >= 0; --y) {
- for (int x = GR_PLOT_WIDTH-1; x >= 0; --x) {
- currPlot->fAtlasMgr = this;
- currPlot->fOffset.set(x, y);
- currPlot->fBytesPerPixel = bpp;
-
- // add to free list
- currPlot->fNext = fFreePlots;
- fFreePlots = currPlot;
+ fPlotArray = SkNEW_ARRAY(GrPlot, (fNumPlotsX*fNumPlotsY));
+
+ GrPlot* currPlot = fPlotArray;
+ for (int y = numPlotsY-1; y >= 0; --y) {
+ for (int x = numPlotsX-1; x >= 0; --x) {
+ currPlot->init(this, x, y, plotWidth, plotHeight, bpp, batchUploads);
+ // build LRU list
+ fPlotList.addToHead(currPlot);
++currPlot;
}
}
@@ -147,7 +187,7 @@ GrAtlasMgr::GrAtlasMgr(GrGpu* gpu, GrPixelConfig config) {
GrAtlasMgr::~GrAtlasMgr() {
SkSafeUnref(fTexture);
- SkDELETE_ARRAY(fPlots);
+ SkDELETE_ARRAY(fPlotArray);
fGpu->unref();
#if FONT_CACHE_STATS
@@ -155,31 +195,35 @@ GrAtlasMgr::~GrAtlasMgr() {
#endif
}
+void GrAtlasMgr::moveToHead(GrPlot* plot) {
+ if (fPlotList.head() == plot) {
+ return;
+ }
+
+ fPlotList.remove(plot);
+ fPlotList.addToHead(plot);
+};
+
GrPlot* GrAtlasMgr::addToAtlas(GrAtlas* atlas,
int width, int height, const void* image,
- GrIPoint16* loc) {
- // iterate through entire plot list, see if we can find a hole
- GrPlot* plotIter = atlas->fPlots;
- while (plotIter) {
- if (plotIter->addSubImage(width, height, image, loc)) {
- return plotIter;
+ SkIPoint16* loc) {
+ // iterate through entire plot list for this atlas, see if we can find a hole
+ // last one was most recently added and probably most empty
+ for (int i = atlas->fPlots.count()-1; i >= 0; --i) {
+ GrPlot* plot = atlas->fPlots[i];
+ if (plot->addSubImage(width, height, image, loc)) {
+ this->moveToHead(plot);
+ return plot;
}
- plotIter = plotIter->fNext;
- }
-
- // If the above fails, then either we have no starting plot, or the current
- // plot list is full. Either way we need to allocate a new plot
- GrPlot* newPlot = this->allocPlot();
- if (NULL == newPlot) {
- return NULL;
}
+ // before we get a new plot, make sure we have a backing texture
if (NULL == fTexture) {
// TODO: Update this to use the cache rather than directly creating a texture.
GrTextureDesc desc;
desc.fFlags = kDynamicUpdate_GrTextureFlagBit;
- desc.fWidth = GR_ATLAS_TEXTURE_WIDTH;
- desc.fHeight = GR_ATLAS_TEXTURE_HEIGHT;
+ desc.fWidth = fBackingTextureSize.width();
+ desc.fHeight = fBackingTextureSize.height();
desc.fConfig = fPixelConfig;
fTexture = fGpu->createTexture(desc, NULL, 0);
@@ -187,75 +231,63 @@ GrPlot* GrAtlasMgr::addToAtlas(GrAtlas* atlas,
return NULL;
}
}
- // be sure to set texture for fast lookup
- newPlot->fTexture = fTexture;
- if (!newPlot->addSubImage(width, height, image, loc)) {
- this->freePlot(newPlot);
- return NULL;
+ // now look through all allocated plots for one we can share, in MRU order
+ GrPlotList::Iter plotIter;
+ plotIter.init(fPlotList, GrPlotList::Iter::kHead_IterStart);
+ GrPlot* plot;
+ while (NULL != (plot = plotIter.get())) {
+ // make sure texture is set for quick lookup
+ plot->fTexture = fTexture;
+ if (plot->addSubImage(width, height, image, loc)) {
+ this->moveToHead(plot);
+ // new plot for atlas, put at end of array
+ *(atlas->fPlots.append()) = plot;
+ return plot;
+ }
+ plotIter.next();
}
- // new plot, put at head
- newPlot->fNext = atlas->fPlots;
- atlas->fPlots = newPlot;
-
- return newPlot;
+ // If the above fails, then the current plot list has no room
+ return NULL;
}
-bool GrAtlasMgr::removeUnusedPlots(GrAtlas* atlas) {
-
- // GrPlot** is used so that the head element can be easily
- // modified when the first element is deleted
- GrPlot** plotRef = &atlas->fPlots;
- GrPlot* plot = atlas->fPlots;
- bool removed = false;
- while (NULL != plot) {
- if (plot->drawToken().isIssued()) {
- *plotRef = plot->fNext;
- this->freePlot(plot);
- plot = *plotRef;
- removed = true;
- } else {
- plotRef = &plot->fNext;
- plot = plot->fNext;
+bool GrAtlasMgr::removePlot(GrAtlas* atlas, const GrPlot* plot) {
+ // iterate through plot list for this atlas
+ int count = atlas->fPlots.count();
+ for (int i = 0; i < count; ++i) {
+ if (plot == atlas->fPlots[i]) {
+ atlas->fPlots.remove(i);
+ return true;
}
}
- return removed;
+ return false;
}
-void GrAtlasMgr::deletePlotList(GrPlot* plot) {
- while (NULL != plot) {
- GrPlot* next = plot->fNext;
- this->freePlot(plot);
- plot = next;
- }
-}
-
-GrPlot* GrAtlasMgr::allocPlot() {
- if (NULL == fFreePlots) {
- return NULL;
- } else {
- GrPlot* alloc = fFreePlots;
- fFreePlots = alloc->fNext;
-#ifdef SK_DEBUG
-// GrPrintf(" GrPlot %p [%d %d] %d\n", this, alloc->fOffset.fX, alloc->fOffset.fY, gCounter);
- gCounter += 1;
-#endif
- return alloc;
+// get a plot that's not being used by the current draw
+GrPlot* GrAtlasMgr::getUnusedPlot() {
+ GrPlotList::Iter plotIter;
+ plotIter.init(fPlotList, GrPlotList::Iter::kTail_IterStart);
+ GrPlot* plot;
+ while (NULL != (plot = plotIter.get())) {
+ if (plot->drawToken().isIssued()) {
+ return plot;
+ }
+ plotIter.prev();
}
+ return NULL;
}
-void GrAtlasMgr::freePlot(GrPlot* plot) {
- SkASSERT(this == plot->fAtlasMgr);
-
- plot->fRects->reset();
- plot->fNext = fFreePlots;
- fFreePlots = plot;
-
-#ifdef SK_DEBUG
- --gCounter;
-// GrPrintf("~GrPlot %p [%d %d] %d\n", this, plot->fOffset.fX, plot->fOffset.fY, gCounter);
-#endif
+void GrAtlasMgr::uploadPlotsToTexture() {
+ if (fBatchUploads) {
+ GrPlotList::Iter plotIter;
+ plotIter.init(fPlotList, GrPlotList::Iter::kHead_IterStart);
+ GrPlot* plot;
+ while (NULL != (plot = plotIter.get())) {
+ plot->uploadToTexture();
+ plotIter.next();
+ }
+ }
}
diff --git a/chromium/third_party/skia/src/gpu/GrAtlas.h b/chromium/third_party/skia/src/gpu/GrAtlas.h
index 3d6869817d2..47048a81c7c 100644
--- a/chromium/third_party/skia/src/gpu/GrAtlas.h
+++ b/chromium/third_party/skia/src/gpu/GrAtlas.h
@@ -10,7 +10,7 @@
#define GrAtlas_DEFINED
-#include "GrPoint.h"
+#include "SkPoint.h"
#include "GrTexture.h"
#include "GrDrawTarget.h"
@@ -31,77 +31,92 @@ class GrAtlas;
class GrPlot {
public:
- int getOffsetX() const { return fOffset.fX; }
- int getOffsetY() const { return fOffset.fY; }
+ SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrPlot);
GrTexture* texture() const { return fTexture; }
- bool addSubImage(int width, int height, const void*, GrIPoint16*);
+ bool addSubImage(int width, int height, const void*, SkIPoint16*);
GrDrawTarget::DrawToken drawToken() const { return fDrawToken; }
void setDrawToken(GrDrawTarget::DrawToken draw) { fDrawToken = draw; }
+ void uploadToTexture();
+
+ void resetRects();
+
private:
GrPlot();
~GrPlot(); // does not try to delete the fNext field
+ void init(GrAtlasMgr* mgr, int offX, int offY, int width, int height, size_t bpp,
+ bool batchUploads);
// for recycling
GrDrawTarget::DrawToken fDrawToken;
- GrPlot* fNext;
-
+ unsigned char* fPlotData;
GrTexture* fTexture;
GrRectanizer* fRects;
GrAtlasMgr* fAtlasMgr;
- GrIPoint16 fOffset;
+ SkIPoint16 fOffset; // the offset of the plot in the backing texture
size_t fBytesPerPixel;
+ SkIRect fDirtyRect;
+ bool fDirty;
+ bool fBatchUploads;
friend class GrAtlasMgr;
};
+typedef SkTInternalLList<GrPlot> GrPlotList;
+
class GrAtlasMgr {
public:
- GrAtlasMgr(GrGpu*, GrPixelConfig);
+ GrAtlasMgr(GrGpu*, GrPixelConfig, const SkISize& backingTextureSize,
+ int numPlotsX, int numPlotsY, bool batchUploads);
~GrAtlasMgr();
// add subimage of width, height dimensions to atlas
// returns the containing GrPlot and location relative to the backing texture
- GrPlot* addToAtlas(GrAtlas*, int width, int height, const void*, GrIPoint16*);
+ GrPlot* addToAtlas(GrAtlas*, int width, int height, const void*, SkIPoint16*);
- // free up any plots that are not waiting on a draw call
- bool removeUnusedPlots(GrAtlas* atlas);
+ // remove reference to this plot
+ bool removePlot(GrAtlas* atlas, const GrPlot* plot);
- // to be called by ~GrAtlas()
- void deletePlotList(GrPlot* plot);
+ // get a plot that's not being used by the current draw
+ // this allows us to overwrite this plot without flushing
+ GrPlot* getUnusedPlot();
GrTexture* getTexture() const {
return fTexture;
}
+ void uploadPlotsToTexture();
+
private:
- GrPlot* allocPlot();
- void freePlot(GrPlot* plot);
+ void moveToHead(GrPlot* plot);
GrGpu* fGpu;
GrPixelConfig fPixelConfig;
GrTexture* fTexture;
+ SkISize fBackingTextureSize;
+ int fNumPlotsX;
+ int fNumPlotsY;
+ bool fBatchUploads;
// allocated array of GrPlots
- GrPlot* fPlots;
- // linked list of free GrPlots
- GrPlot* fFreePlots;
+ GrPlot* fPlotArray;
+ // LRU list of GrPlots
+ GrPlotList fPlotList;
};
class GrAtlas {
public:
- GrAtlas(GrAtlasMgr* mgr) : fPlots(NULL), fAtlasMgr(mgr) { }
- ~GrAtlas() { fAtlasMgr->deletePlotList(fPlots); }
+ GrAtlas() { }
+ ~GrAtlas() { }
- bool isEmpty() { return NULL == fPlots; }
+ bool isEmpty() { return 0 == fPlots.count(); }
private:
- GrPlot* fPlots;
- GrAtlasMgr* fAtlasMgr;
+ SkTDArray<GrPlot*> fPlots;
friend class GrAtlasMgr;
};
diff --git a/chromium/third_party/skia/src/gpu/GrBitmapTextContext.cpp b/chromium/third_party/skia/src/gpu/GrBitmapTextContext.cpp
index a43c4a28746..25c13ec8d1a 100755
--- a/chromium/third_party/skia/src/gpu/GrBitmapTextContext.cpp
+++ b/chromium/third_party/skia/src/gpu/GrBitmapTextContext.cpp
@@ -10,6 +10,7 @@
#include "GrDrawTarget.h"
#include "GrFontScaler.h"
#include "GrIndexBuffer.h"
+#include "GrStrokeInfo.h"
#include "GrTextStrike.h"
#include "GrTextStrike_impl.h"
#include "SkColorPriv.h"
@@ -18,31 +19,59 @@
#include "SkStrokeRec.h"
#include "effects/GrCustomCoordsTextureEffect.h"
-static const int kGlyphCoordsAttributeIndex = 1;
+#include "SkAutoKern.h"
+#include "SkDraw.h"
+#include "SkDrawProcs.h"
+#include "SkGlyphCache.h"
+#include "SkGpuDevice.h"
+#include "SkGr.h"
+#include "SkTextMapStateProc.h"
SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false,
"Dump the contents of the font cache before every purge.");
-GrBitmapTextContext::GrBitmapTextContext(GrContext* context, const GrPaint& paint,
- SkColor color) :
- GrTextContext(context, paint) {
- fAutoMatrix.setIdentity(fContext, &fPaint);
+static const int kGlyphCoordsNoColorAttributeIndex = 1;
+static const int kGlyphCoordsWithColorAttributeIndex = 2;
- fSkPaintColor = color;
+namespace {
+// position + texture coord
+extern const GrVertexAttrib gTextVertexAttribs[] = {
+ {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
+ {kVec2f_GrVertexAttribType, sizeof(SkPoint) , kEffect_GrVertexAttribBinding}
+};
+
+// position + color + texture coord
+extern const GrVertexAttrib gTextVertexWithColorAttribs[] = {
+ {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
+ {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding},
+ {kVec2f_GrVertexAttribType, sizeof(SkPoint) + sizeof(GrColor), kEffect_GrVertexAttribBinding}
+};
+};
+
+GrBitmapTextContext::GrBitmapTextContext(GrContext* context,
+ const SkDeviceProperties& properties)
+ : GrTextContext(context, properties) {
fStrike = NULL;
fCurrTexture = NULL;
fCurrVertex = 0;
+ fEffectTextureGenID = 0;
fVertices = NULL;
fMaxVertices = 0;
+
+ fVertexBounds.setLargestInverted();
}
GrBitmapTextContext::~GrBitmapTextContext() {
this->flushGlyphs();
}
+bool GrBitmapTextContext::canDraw(const SkPaint& paint) {
+ return !SkDraw::ShouldDrawTextAsPaths(paint, fContext->getMatrix());
+}
+
static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) {
unsigned r = SkColorGetR(c);
unsigned g = SkColorGetG(c);
@@ -61,76 +90,348 @@ void GrBitmapTextContext::flushGlyphs() {
if (fCurrVertex > 0) {
// setup our sampler state for our text texture/atlas
- SkASSERT(GrIsALIGN4(fCurrVertex));
+ SkASSERT(SkIsAlign4(fCurrVertex));
SkASSERT(fCurrTexture);
GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNone_FilterMode);
+ uint32_t textureGenID = fCurrTexture->getGenerationID();
+
+ if (textureGenID != fEffectTextureGenID) {
+ fCachedEffect.reset(GrCustomCoordsTextureEffect::Create(fCurrTexture, params));
+ fEffectTextureGenID = textureGenID;
+ }
+
// This effect could be stored with one of the cache objects (atlas?)
- drawState->addCoverageEffect(
- GrCustomCoordsTextureEffect::Create(fCurrTexture, params),
- kGlyphCoordsAttributeIndex)->unref();
-
- if (NULL != fStrike && kARGB_GrMaskFormat == fStrike->getMaskFormat()) {
- drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
- drawState->setColor(0xffffffff);
- } else if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) {
- if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() ||
- kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() ||
- fPaint.numColorStages()) {
- GrPrintf("LCD Text will not draw correctly.\n");
+ int coordsIdx = drawState->hasColorVertexAttribute() ? kGlyphCoordsWithColorAttributeIndex :
+ kGlyphCoordsNoColorAttributeIndex;
+ drawState->addCoverageEffect(fCachedEffect.get(), coordsIdx);
+ SkASSERT(NULL != fStrike);
+ switch (fStrike->getMaskFormat()) {
+ // Color bitmap text
+ case kARGB_GrMaskFormat:
+ SkASSERT(!drawState->hasColorVertexAttribute());
+ drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
+ drawState->setColor(0xffffffff);
+ break;
+ // LCD text
+ case kA888_GrMaskFormat:
+ case kA565_GrMaskFormat: {
+ if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() ||
+ kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() ||
+ fPaint.numColorStages()) {
+ GrPrintf("LCD Text will not draw correctly.\n");
+ }
+ SkASSERT(!drawState->hasColorVertexAttribute());
+ // We don't use the GrPaint's color in this case because it's been premultiplied by
+ // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by
+ // the mask texture color. The end result is that we get
+ // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor
+ int a = SkColorGetA(fSkPaint.getColor());
+ // paintAlpha
+ drawState->setColor(SkColorSetARGB(a, a, a, a));
+ // paintColor
+ drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaint.getColor()));
+ drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
+ break;
}
- // We don't use the GrPaint's color in this case because it's been premultiplied by
- // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by
- // the mask texture color. The end result is that we get
- // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor
- int a = SkColorGetA(fSkPaintColor);
- // paintAlpha
- drawState->setColor(SkColorSetARGB(a, a, a, a));
- // paintColor
- drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaintColor));
- drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
- } else {
- // set back to normal in case we took LCD path previously.
- drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
- drawState->setColor(fPaint.getColor());
+ // Grayscale/BW text
+ case kA8_GrMaskFormat:
+ // set back to normal in case we took LCD path previously.
+ drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
+ //drawState->setColor(fPaint.getColor());
+ // We're using per-vertex color.
+ SkASSERT(drawState->hasColorVertexAttribute());
+ drawState->setColor(0xFFFFFFFF);
+ break;
+ default:
+ SkFAIL("Unexepected mask format.");
}
-
int nGlyphs = fCurrVertex / 4;
fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType,
nGlyphs,
- 4, 6);
+ 4, 6, &fVertexBounds);
fDrawTarget->resetVertexSource();
fVertices = NULL;
fMaxVertices = 0;
fCurrVertex = 0;
+ fVertexBounds.setLargestInverted();
SkSafeSetNull(fCurrTexture);
}
}
-namespace {
+inline void GrBitmapTextContext::init(const GrPaint& paint, const SkPaint& skPaint) {
+ GrTextContext::init(paint, skPaint);
-// position + texture coord
-extern const GrVertexAttrib gTextVertexAttribs[] = {
- {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
- {kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}
-};
+ fStrike = NULL;
-};
+ fCurrTexture = NULL;
+ fCurrVertex = 0;
+
+ fVertices = NULL;
+ fMaxVertices = 0;
+}
+
+inline void GrBitmapTextContext::finish() {
+ this->flushGlyphs();
+
+ GrTextContext::finish();
+}
+
+void GrBitmapTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint,
+ const char text[], size_t byteLength,
+ SkScalar x, SkScalar y) {
+ SkASSERT(byteLength == 0 || text != NULL);
+
+ // nothing to draw
+ if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) {
+ return;
+ }
+
+ this->init(paint, skPaint);
+
+ SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
+
+ SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &fContext->getMatrix());
+ SkGlyphCache* cache = autoCache.getCache();
+ GrFontScaler* fontScaler = GetGrFontScaler(cache);
+
+ // transform our starting point
+ {
+ SkPoint loc;
+ fContext->getMatrix().mapXY(x, y, &loc);
+ x = loc.fX;
+ y = loc.fY;
+ }
+
+ // need to measure first
+ if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
+ SkVector stop;
+
+ MeasureText(cache, glyphCacheProc, text, byteLength, &stop);
+
+ SkScalar stopX = stop.fX;
+ SkScalar stopY = stop.fY;
+
+ if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
+ stopX = SkScalarHalf(stopX);
+ stopY = SkScalarHalf(stopY);
+ }
+ x -= stopX;
+ y -= stopY;
+ }
+
+ const char* stop = text + byteLength;
+
+ SkAutoKern autokern;
+
+ SkFixed fxMask = ~0;
+ SkFixed fyMask = ~0;
+ SkFixed halfSampleX, halfSampleY;
+ if (cache->isSubpixel()) {
+ halfSampleX = halfSampleY = (SK_FixedHalf >> SkGlyph::kSubBits);
+ SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(fContext->getMatrix());
+ if (kX_SkAxisAlignment == baseline) {
+ fyMask = 0;
+ halfSampleY = SK_FixedHalf;
+ } else if (kY_SkAxisAlignment == baseline) {
+ fxMask = 0;
+ halfSampleX = SK_FixedHalf;
+ }
+ } else {
+ halfSampleX = halfSampleY = SK_FixedHalf;
+ }
+
+ SkFixed fx = SkScalarToFixed(x) + halfSampleX;
+ SkFixed fy = SkScalarToFixed(y) + halfSampleY;
+
+ GrContext::AutoMatrix autoMatrix;
+ autoMatrix.setIdentity(fContext, &fPaint);
+
+ while (text < stop) {
+ const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
+
+ fx += autokern.adjust(glyph);
+
+ if (glyph.fWidth) {
+ this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+ glyph.getSubXFixed(),
+ glyph.getSubYFixed()),
+ SkFixedFloorToFixed(fx),
+ SkFixedFloorToFixed(fy),
+ fontScaler);
+ }
+
+ fx += glyph.fAdvanceX;
+ fy += glyph.fAdvanceY;
+ }
+
+ this->finish();
+}
+
+void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPaint,
+ const char text[], size_t byteLength,
+ const SkScalar pos[], SkScalar constY,
+ int scalarsPerPosition) {
+ SkASSERT(byteLength == 0 || text != NULL);
+ SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
+
+ // nothing to draw
+ if (text == NULL || byteLength == 0/* || fRC->isEmpty()*/) {
+ return;
+ }
+
+ this->init(paint, skPaint);
+
+ SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
+
+ SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &fContext->getMatrix());
+ SkGlyphCache* cache = autoCache.getCache();
+ GrFontScaler* fontScaler = GetGrFontScaler(cache);
+
+ // store original matrix before we reset, so we can use it to transform positions
+ SkMatrix ctm = fContext->getMatrix();
+ GrContext::AutoMatrix autoMatrix;
+ autoMatrix.setIdentity(fContext, &fPaint);
+
+ const char* stop = text + byteLength;
+ SkTextAlignProc alignProc(fSkPaint.getTextAlign());
+ SkTextMapStateProc tmsProc(ctm, constY, scalarsPerPosition);
+ SkFixed halfSampleX = 0, halfSampleY = 0;
+
+ if (cache->isSubpixel()) {
+ // maybe we should skip the rounding if linearText is set
+ SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(ctm);
+
+ SkFixed fxMask = ~0;
+ SkFixed fyMask = ~0;
+ if (kX_SkAxisAlignment == baseline) {
+ fyMask = 0;
+#ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
+ halfSampleY = SK_FixedHalf;
+#endif
+ } else if (kY_SkAxisAlignment == baseline) {
+ fxMask = 0;
+#ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
+ halfSampleX = SK_FixedHalf;
+#endif
+ }
+
+ if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
+ while (text < stop) {
+ SkPoint tmsLoc;
+ tmsProc(pos, &tmsLoc);
+ SkFixed fx = SkScalarToFixed(tmsLoc.fX) + halfSampleX;
+ SkFixed fy = SkScalarToFixed(tmsLoc.fY) + halfSampleY;
+
+ const SkGlyph& glyph = glyphCacheProc(cache, &text,
+ fx & fxMask, fy & fyMask);
+
+ if (glyph.fWidth) {
+ this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+ glyph.getSubXFixed(),
+ glyph.getSubYFixed()),
+ SkFixedFloorToFixed(fx),
+ SkFixedFloorToFixed(fy),
+ fontScaler);
+ }
+ pos += scalarsPerPosition;
+ }
+ } else {
+ while (text < stop) {
+ const char* currentText = text;
+ const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0);
+
+ if (metricGlyph.fWidth) {
+ SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;)
+ SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;)
+ SkPoint tmsLoc;
+ tmsProc(pos, &tmsLoc);
+ SkIPoint fixedLoc;
+ alignProc(tmsLoc, metricGlyph, &fixedLoc);
+
+ SkFixed fx = fixedLoc.fX + halfSampleX;
+ SkFixed fy = fixedLoc.fY + halfSampleY;
+
+ // have to call again, now that we've been "aligned"
+ const SkGlyph& glyph = glyphCacheProc(cache, &currentText,
+ fx & fxMask, fy & fyMask);
+ // the assumption is that the metrics haven't changed
+ SkASSERT(prevAdvX == glyph.fAdvanceX);
+ SkASSERT(prevAdvY == glyph.fAdvanceY);
+ SkASSERT(glyph.fWidth);
+
+ this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+ glyph.getSubXFixed(),
+ glyph.getSubYFixed()),
+ SkFixedFloorToFixed(fx),
+ SkFixedFloorToFixed(fy),
+ fontScaler);
+ }
+ pos += scalarsPerPosition;
+ }
+ }
+ } else { // not subpixel
+
+ if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
+ while (text < stop) {
+ // the last 2 parameters are ignored
+ const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
+
+ if (glyph.fWidth) {
+ SkPoint tmsLoc;
+ tmsProc(pos, &tmsLoc);
+
+ SkFixed fx = SkScalarToFixed(tmsLoc.fX) + SK_FixedHalf; //halfSampleX;
+ SkFixed fy = SkScalarToFixed(tmsLoc.fY) + SK_FixedHalf; //halfSampleY;
+ this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+ glyph.getSubXFixed(),
+ glyph.getSubYFixed()),
+ SkFixedFloorToFixed(fx),
+ SkFixedFloorToFixed(fy),
+ fontScaler);
+ }
+ pos += scalarsPerPosition;
+ }
+ } else {
+ while (text < stop) {
+ // the last 2 parameters are ignored
+ const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
+
+ if (glyph.fWidth) {
+ SkPoint tmsLoc;
+ tmsProc(pos, &tmsLoc);
+
+ SkIPoint fixedLoc;
+ alignProc(tmsLoc, glyph, &fixedLoc);
+
+ SkFixed fx = fixedLoc.fX + SK_FixedHalf; //halfSampleX;
+ SkFixed fy = fixedLoc.fY + SK_FixedHalf; //halfSampleY;
+ this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+ glyph.getSubXFixed(),
+ glyph.getSubYFixed()),
+ SkFixedFloorToFixed(fx),
+ SkFixedFloorToFixed(fy),
+ fontScaler);
+ }
+ pos += scalarsPerPosition;
+ }
+ }
+ }
+
+ this->finish();
+}
void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
- GrFixed vx, GrFixed vy,
+ SkFixed vx, SkFixed vy,
GrFontScaler* scaler) {
if (NULL == fDrawTarget) {
return;
}
+
if (NULL == fStrike) {
-#if SK_DISTANCEFIELD_FONTS
fStrike = fContext->getFontCache()->getStrike(scaler, false);
-#else
- fStrike = fContext->getFontCache()->getStrike(scaler);
-#endif
}
GrGlyph* glyph = fStrike->getGlyph(packed, scaler);
@@ -142,8 +443,8 @@ void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
vy += SkIntToFixed(glyph->fBounds.fTop);
// keep them as ints until we've done the clip-test
- GrFixed width = glyph->fBounds.width();
- GrFixed height = glyph->fBounds.height();
+ SkFixed width = glyph->fBounds.width();
+ SkFixed height = glyph->fBounds.height();
// check if we clipped out
if (true || NULL == glyph->fPlot) {
@@ -156,13 +457,13 @@ void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
}
if (NULL == glyph->fPlot) {
- if (fStrike->getGlyphAtlas(glyph, scaler)) {
+ if (fStrike->addGlyphToAtlas(glyph, scaler)) {
goto HAS_ATLAS;
}
// try to clear out an unused plot before we flush
- fContext->getFontCache()->freePlotExceptFor(fStrike);
- if (fStrike->getGlyphAtlas(glyph, scaler)) {
+ if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
+ fStrike->addGlyphToAtlas(glyph, scaler)) {
goto HAS_ATLAS;
}
@@ -172,14 +473,13 @@ void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
#endif
}
- // before we purge the cache, we must flush any accumulated draws
+ // flush any accumulated draws to allow us to free up a plot
this->flushGlyphs();
fContext->flush();
- // try to purge
- fContext->getFontCache()->purgeExceptFor(fStrike);
- // need to use new flush count here
- if (fStrike->getGlyphAtlas(glyph, scaler)) {
+ // we should have an unused plot now
+ if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
+ fStrike->addGlyphToAtlas(glyph, scaler)) {
goto HAS_ATLAS;
}
@@ -199,8 +499,8 @@ void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
SkFixedToScalar(vy - SkIntToFixed(glyph->fBounds.fTop)));
GrPaint tmpPaint(fPaint);
am.setPreConcat(fContext, translate, &tmpPaint);
- SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
- fContext->drawPath(tmpPaint, *glyph->fPath, stroke);
+ GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle);
+ fContext->drawPath(tmpPaint, *glyph->fPath, strokeInfo);
return;
}
@@ -222,18 +522,30 @@ HAS_ATLAS:
fCurrTexture->ref();
}
+ bool useColorVerts = kA8_GrMaskFormat == fStrike->getMaskFormat();
+
if (NULL == fVertices) {
// If we need to reserve vertices allow the draw target to suggest
// a number of verts to reserve and whether to perform a flush.
fMaxVertices = kMinRequestedVerts;
- fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
- SK_ARRAY_COUNT(gTextVertexAttribs));
+ if (useColorVerts) {
+ fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
+ SK_ARRAY_COUNT(gTextVertexWithColorAttribs));
+ } else {
+ fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
+ SK_ARRAY_COUNT(gTextVertexAttribs));
+ }
bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL);
if (flush) {
this->flushGlyphs();
fContext->flush();
- fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
- SK_ARRAY_COUNT(gTextVertexAttribs));
+ if (useColorVerts) {
+ fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
+ SK_ARRAY_COUNT(gTextVertexWithColorAttribs));
+ } else {
+ fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
+ SK_ARRAY_COUNT(gTextVertexAttribs));
+ }
}
fMaxVertices = kDefaultRequestedVerts;
// ignore return, no point in flushing again.
@@ -248,24 +560,46 @@ HAS_ATLAS:
}
bool success = fDrawTarget->reserveVertexAndIndexSpace(fMaxVertices,
0,
- GrTCast<void**>(&fVertices),
+ &fVertices,
NULL);
GrAlwaysAssert(success);
- SkASSERT(2*sizeof(GrPoint) == fDrawTarget->getDrawState().getVertexSize());
}
- GrFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX);
- GrFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY);
-
- fVertices[2*fCurrVertex].setRectFan(SkFixedToFloat(vx),
- SkFixedToFloat(vy),
- SkFixedToFloat(vx + width),
- SkFixedToFloat(vy + height),
- 2 * sizeof(SkPoint));
- fVertices[2*fCurrVertex+1].setRectFan(SkFixedToFloat(texture->normalizeFixedX(tx)),
- SkFixedToFloat(texture->normalizeFixedY(ty)),
- SkFixedToFloat(texture->normalizeFixedX(tx + width)),
- SkFixedToFloat(texture->normalizeFixedY(ty + height)),
- 2 * sizeof(SkPoint));
+ SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX);
+ SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY);
+
+ SkRect r;
+ r.fLeft = SkFixedToFloat(vx);
+ r.fTop = SkFixedToFloat(vy);
+ r.fRight = SkFixedToFloat(vx + width);
+ r.fBottom = SkFixedToFloat(vy + height);
+
+ fVertexBounds.growToInclude(r);
+
+ size_t vertSize = useColorVerts ? (2 * sizeof(SkPoint) + sizeof(GrColor)) :
+ (2 * sizeof(SkPoint));
+
+ SkASSERT(vertSize == fDrawTarget->getDrawState().getVertexSize());
+
+ SkPoint* positions = reinterpret_cast<SkPoint*>(
+ reinterpret_cast<intptr_t>(fVertices) + vertSize * fCurrVertex);
+ positions->setRectFan(r.fLeft, r.fTop, r.fRight, r.fBottom, vertSize);
+
+ // The texture coords are last in both the with and without color vertex layouts.
+ SkPoint* textureCoords = reinterpret_cast<SkPoint*>(
+ reinterpret_cast<intptr_t>(positions) + vertSize - sizeof(SkPoint));
+ textureCoords->setRectFan(SkFixedToFloat(texture->normalizeFixedX(tx)),
+ SkFixedToFloat(texture->normalizeFixedY(ty)),
+ SkFixedToFloat(texture->normalizeFixedX(tx + width)),
+ SkFixedToFloat(texture->normalizeFixedY(ty + height)),
+ vertSize);
+ if (useColorVerts) {
+ // color comes after position.
+ GrColor* colors = reinterpret_cast<GrColor*>(positions + 1);
+ for (int i = 0; i < 4; ++i) {
+ *colors = fPaint.getColor();
+ colors = reinterpret_cast<GrColor*>(reinterpret_cast<intptr_t>(colors) + vertSize);
+ }
+ }
fCurrVertex += 4;
}
diff --git a/chromium/third_party/skia/src/gpu/GrBitmapTextContext.h b/chromium/third_party/skia/src/gpu/GrBitmapTextContext.h
new file mode 100644
index 00000000000..836cc76a0dd
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/GrBitmapTextContext.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrBitmapTextContext_DEFINED
+#define GrBitmapTextContext_DEFINED
+
+#include "GrTextContext.h"
+
+class GrTextStrike;
+class GrAtlasMgr;
+
+/*
+ * This class implements GrTextContext using standard bitmap fonts
+ */
+class GrBitmapTextContext : public GrTextContext {
+public:
+ GrBitmapTextContext(GrContext*, const SkDeviceProperties&);
+ virtual ~GrBitmapTextContext();
+
+ virtual void drawText(const GrPaint&, const SkPaint&, const char text[], size_t byteLength,
+ SkScalar x, SkScalar y) SK_OVERRIDE;
+ virtual void drawPosText(const GrPaint&, const SkPaint&,
+ const char text[], size_t byteLength,
+ const SkScalar pos[], SkScalar constY,
+ int scalarsPerPosition) SK_OVERRIDE;
+
+ virtual bool canDraw(const SkPaint& paint) SK_OVERRIDE;
+
+private:
+ GrTextStrike* fStrike;
+
+ void init(const GrPaint&, const SkPaint&);
+ void drawPackedGlyph(GrGlyph::PackedID, SkFixed left, SkFixed top, GrFontScaler*);
+ void flushGlyphs(); // automatically called by destructor
+ void finish();
+
+ enum {
+ kMinRequestedGlyphs = 1,
+ kDefaultRequestedGlyphs = 64,
+ kMinRequestedVerts = kMinRequestedGlyphs * 4,
+ kDefaultRequestedVerts = kDefaultRequestedGlyphs * 4,
+ };
+
+ void* fVertices;
+ int32_t fMaxVertices;
+ GrTexture* fCurrTexture;
+ SkAutoTUnref<GrEffectRef> fCachedEffect;
+ uint32_t fEffectTextureGenID;
+ int fCurrVertex;
+ SkRect fVertexBounds;
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/GrBufferAllocPool.cpp b/chromium/third_party/skia/src/gpu/GrBufferAllocPool.cpp
index b34fe8a8e34..03d43c9b932 100644
--- a/chromium/third_party/skia/src/gpu/GrBufferAllocPool.cpp
+++ b/chromium/third_party/skia/src/gpu/GrBufferAllocPool.cpp
@@ -28,7 +28,7 @@ GrBufferAllocPool::GrBufferAllocPool(GrGpu* gpu,
bool frequentResetHint,
size_t blockSize,
int preallocBufferCnt) :
- fBlocks(GrMax(8, 2*preallocBufferCnt)) {
+ fBlocks(SkTMax(8, 2*preallocBufferCnt)) {
SkASSERT(NULL != gpu);
fGpu = gpu;
@@ -38,7 +38,7 @@ GrBufferAllocPool::GrBufferAllocPool(GrGpu* gpu,
fBufferType = bufferType;
fFrequentResetHint = frequentResetHint;
fBufferPtr = NULL;
- fMinBlockSize = GrMax(GrBufferAllocPool_MIN_BLOCK_SIZE, blockSize);
+ fMinBlockSize = SkTMax(GrBufferAllocPool_MIN_BLOCK_SIZE, blockSize);
fBytesInUse = 0;
@@ -56,8 +56,8 @@ GrBufferAllocPool::~GrBufferAllocPool() {
VALIDATE();
if (fBlocks.count()) {
GrGeometryBuffer* buffer = fBlocks.back().fBuffer;
- if (buffer->isLocked()) {
- buffer->unlock();
+ if (buffer->isMapped()) {
+ buffer->unmap();
}
}
while (!fBlocks.empty()) {
@@ -79,8 +79,8 @@ void GrBufferAllocPool::reset() {
fBytesInUse = 0;
if (fBlocks.count()) {
GrGeometryBuffer* buffer = fBlocks.back().fBuffer;
- if (buffer->isLocked()) {
- buffer->unlock();
+ if (buffer->isMapped()) {
+ buffer->unmap();
}
}
// fPreallocBuffersInUse will be decremented down to zero in the while loop
@@ -101,16 +101,16 @@ void GrBufferAllocPool::reset() {
VALIDATE();
}
-void GrBufferAllocPool::unlock() {
+void GrBufferAllocPool::unmap() {
VALIDATE();
if (NULL != fBufferPtr) {
BufferBlock& block = fBlocks.back();
- if (block.fBuffer->isLocked()) {
- block.fBuffer->unlock();
+ if (block.fBuffer->isMapped()) {
+ block.fBuffer->unmap();
} else {
- size_t flushSize = block.fBuffer->sizeInBytes() - block.fBytesFree;
- flushCpuData(fBlocks.back().fBuffer, flushSize);
+ size_t flushSize = block.fBuffer->gpuMemorySize() - block.fBytesFree;
+ this->flushCpuData(fBlocks.back().fBuffer, flushSize);
}
fBufferPtr = NULL;
}
@@ -121,21 +121,21 @@ void GrBufferAllocPool::unlock() {
void GrBufferAllocPool::validate(bool unusedBlockAllowed) const {
if (NULL != fBufferPtr) {
SkASSERT(!fBlocks.empty());
- if (fBlocks.back().fBuffer->isLocked()) {
+ if (fBlocks.back().fBuffer->isMapped()) {
GrGeometryBuffer* buf = fBlocks.back().fBuffer;
- SkASSERT(buf->lockPtr() == fBufferPtr);
+ SkASSERT(buf->mapPtr() == fBufferPtr);
} else {
SkASSERT(fCpuData.get() == fBufferPtr);
}
} else {
- SkASSERT(fBlocks.empty() || !fBlocks.back().fBuffer->isLocked());
+ SkASSERT(fBlocks.empty() || !fBlocks.back().fBuffer->isMapped());
}
size_t bytesInUse = 0;
for (int i = 0; i < fBlocks.count() - 1; ++i) {
- SkASSERT(!fBlocks[i].fBuffer->isLocked());
+ SkASSERT(!fBlocks[i].fBuffer->isMapped());
}
for (int i = 0; i < fBlocks.count(); ++i) {
- size_t bytes = fBlocks[i].fBuffer->sizeInBytes() - fBlocks[i].fBytesFree;
+ size_t bytes = fBlocks[i].fBuffer->gpuMemorySize() - fBlocks[i].fBytesFree;
bytesInUse += bytes;
SkASSERT(bytes || unusedBlockAllowed);
}
@@ -161,7 +161,7 @@ void* GrBufferAllocPool::makeSpace(size_t size,
if (NULL != fBufferPtr) {
BufferBlock& back = fBlocks.back();
- size_t usedBytes = back.fBuffer->sizeInBytes() - back.fBytesFree;
+ size_t usedBytes = back.fBuffer->gpuMemorySize() - back.fBytesFree;
size_t pad = GrSizeAlignUpPad(usedBytes,
alignment);
if ((size + pad) <= back.fBytesFree) {
@@ -201,7 +201,7 @@ int GrBufferAllocPool::currentBufferItems(size_t itemSize) const {
VALIDATE();
if (NULL != fBufferPtr) {
const BufferBlock& back = fBlocks.back();
- size_t usedBytes = back.fBuffer->sizeInBytes() - back.fBytesFree;
+ size_t usedBytes = back.fBuffer->gpuMemorySize() - back.fBytesFree;
size_t pad = GrSizeAlignUpPad(usedBytes, itemSize);
return static_cast<int>((back.fBytesFree - pad) / itemSize);
} else if (fPreallocBuffersInUse < fPreallocBuffers.count()) {
@@ -231,14 +231,14 @@ void GrBufferAllocPool::putBack(size_t bytes) {
// caller shouldnt try to put back more than they've taken
SkASSERT(!fBlocks.empty());
BufferBlock& block = fBlocks.back();
- size_t bytesUsed = block.fBuffer->sizeInBytes() - block.fBytesFree;
+ size_t bytesUsed = block.fBuffer->gpuMemorySize() - block.fBytesFree;
if (bytes >= bytesUsed) {
bytes -= bytesUsed;
fBytesInUse -= bytesUsed;
// if we locked a vb to satisfy the make space and we're releasing
- // beyond it, then unlock it.
- if (block.fBuffer->isLocked()) {
- block.fBuffer->unlock();
+ // beyond it, then unmap it.
+ if (block.fBuffer->isMapped()) {
+ block.fBuffer->unmap();
}
this->destroyBlock();
} else {
@@ -258,7 +258,7 @@ void GrBufferAllocPool::putBack(size_t bytes) {
bool GrBufferAllocPool::createBlock(size_t requestSize) {
- size_t size = GrMax(requestSize, fMinBlockSize);
+ size_t size = SkTMax(requestSize, fMinBlockSize);
SkASSERT(size >= GrBufferAllocPool_MIN_BLOCK_SIZE);
VALIDATE();
@@ -286,33 +286,33 @@ bool GrBufferAllocPool::createBlock(size_t requestSize) {
if (NULL != fBufferPtr) {
SkASSERT(fBlocks.count() > 1);
BufferBlock& prev = fBlocks.fromBack(1);
- if (prev.fBuffer->isLocked()) {
- prev.fBuffer->unlock();
+ if (prev.fBuffer->isMapped()) {
+ prev.fBuffer->unmap();
} else {
flushCpuData(prev.fBuffer,
- prev.fBuffer->sizeInBytes() - prev.fBytesFree);
+ prev.fBuffer->gpuMemorySize() - prev.fBytesFree);
}
fBufferPtr = NULL;
}
SkASSERT(NULL == fBufferPtr);
- // If the buffer is CPU-backed we lock it because it is free to do so and saves a copy.
- // Otherwise when buffer locking is supported:
- // a) If the frequently reset hint is set we only lock when the requested size meets a
+ // If the buffer is CPU-backed we map it because it is free to do so and saves a copy.
+ // Otherwise when buffer mapping is supported:
+ // a) If the frequently reset hint is set we only map when the requested size meets a
// threshold (since we don't expect it is likely that we will see more vertex data)
- // b) If the hint is not set we lock if the buffer size is greater than the threshold.
- bool attemptLock = block.fBuffer->isCPUBacked();
- if (!attemptLock && fGpu->caps()->bufferLockSupport()) {
+ // b) If the hint is not set we map if the buffer size is greater than the threshold.
+ bool attemptMap = block.fBuffer->isCPUBacked();
+ if (!attemptMap && GrDrawTargetCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags()) {
if (fFrequentResetHint) {
- attemptLock = requestSize > GR_GEOM_BUFFER_LOCK_THRESHOLD;
+ attemptMap = requestSize > GR_GEOM_BUFFER_MAP_THRESHOLD;
} else {
- attemptLock = size > GR_GEOM_BUFFER_LOCK_THRESHOLD;
+ attemptMap = size > GR_GEOM_BUFFER_MAP_THRESHOLD;
}
}
- if (attemptLock) {
- fBufferPtr = block.fBuffer->lock();
+ if (attemptMap) {
+ fBufferPtr = block.fBuffer->map();
}
if (NULL == fBufferPtr) {
@@ -337,7 +337,7 @@ void GrBufferAllocPool::destroyBlock() {
--fPreallocBuffersInUse;
}
}
- SkASSERT(!block.fBuffer->isLocked());
+ SkASSERT(!block.fBuffer->isMapped());
block.fBuffer->unref();
fBlocks.pop_back();
fBufferPtr = NULL;
@@ -346,17 +346,17 @@ void GrBufferAllocPool::destroyBlock() {
void GrBufferAllocPool::flushCpuData(GrGeometryBuffer* buffer,
size_t flushSize) {
SkASSERT(NULL != buffer);
- SkASSERT(!buffer->isLocked());
+ SkASSERT(!buffer->isMapped());
SkASSERT(fCpuData.get() == fBufferPtr);
- SkASSERT(flushSize <= buffer->sizeInBytes());
+ SkASSERT(flushSize <= buffer->gpuMemorySize());
VALIDATE(true);
- if (fGpu->caps()->bufferLockSupport() &&
- flushSize > GR_GEOM_BUFFER_LOCK_THRESHOLD) {
- void* data = buffer->lock();
+ if (GrDrawTargetCaps::kNone_MapFlags != fGpu->caps()->mapBufferFlags() &&
+ flushSize > GR_GEOM_BUFFER_MAP_THRESHOLD) {
+ void* data = buffer->map();
if (NULL != data) {
memcpy(data, fBufferPtr, flushSize);
- buffer->unlock();
+ buffer->unmap();
return;
}
}
diff --git a/chromium/third_party/skia/src/gpu/GrBufferAllocPool.h b/chromium/third_party/skia/src/gpu/GrBufferAllocPool.h
index 809fa5f4265..291d781ac6c 100644
--- a/chromium/third_party/skia/src/gpu/GrBufferAllocPool.h
+++ b/chromium/third_party/skia/src/gpu/GrBufferAllocPool.h
@@ -20,20 +20,20 @@ class GrGpu;
*
* The pool allows a client to make space for geometry and then put back excess
* space if it over allocated. When a client is ready to draw from the pool
- * it calls unlock on the pool ensure buffers are ready for drawing. The pool
+ * it calls unmap on the pool ensure buffers are ready for drawing. The pool
* can be reset after drawing is completed to recycle space.
*
* At creation time a minimum per-buffer size can be specified. Additionally,
* a number of buffers to preallocate can be specified. These will
* be allocated at the min size and kept around until the pool is destroyed.
*/
-class GrBufferAllocPool : public SkNoncopyable {
+class GrBufferAllocPool : SkNoncopyable {
public:
/**
- * Ensures all buffers are unlocked and have all data written to them.
+ * Ensures all buffers are unmapped and have all data written to them.
* Call before drawing using buffers from the pool.
*/
- void unlock();
+ void unmap();
/**
* Invalidates all the data in the pool, unrefs non-preallocated buffers.
@@ -77,7 +77,7 @@ protected:
* @param gpu The GrGpu used to create the buffers.
* @param bufferType The type of buffers to create.
* @param frequentResetHint A hint that indicates that the pool
- * should expect frequent unlock() calls
+ * should expect frequent unmap() calls
* (as opposed to many makeSpace / acquires
* between resets).
* @param bufferSize The minimum size of created buffers.
@@ -109,11 +109,11 @@ protected:
* data is given to the caller. The buffer may or may not be locked. The
* returned ptr remains valid until any of the following:
* *makeSpace is called again.
- * *unlock is called.
+ * *unmap is called.
* *reset is called.
* *this object is destroyed.
*
- * Once unlock on the pool is called the data is guaranteed to be in the
+ * Once unmap on the pool is called the data is guaranteed to be in the
* buffer at the offset indicated by offset. Until that time it may be
* in temporary storage and/or the buffer may be locked.
*
@@ -190,7 +190,7 @@ public:
*
* @param gpu The GrGpu used to create the vertex buffers.
* @param frequentResetHint A hint that indicates that the pool
- * should expect frequent unlock() calls
+ * should expect frequent unmap() calls
* (as opposed to many makeSpace / acquires
* between resets).
* @param bufferSize The minimum size of created VBs This value
@@ -209,11 +209,11 @@ public:
* the vertices given to the caller. The buffer may or may not be locked.
* The returned ptr remains valid until any of the following:
* *makeSpace is called again.
- * *unlock is called.
+ * *unmap is called.
* *reset is called.
* *this object is destroyed.
*
- * Once unlock on the pool is called the vertices are guaranteed to be in
+ * Once unmap on the pool is called the vertices are guaranteed to be in
* the buffer at the offset indicated by startVertex. Until that time they
* may be in temporary storage and/or the buffer may be locked.
*
@@ -278,7 +278,7 @@ public:
*
* @param gpu The GrGpu used to create the index buffers.
* @param frequentResetHint A hint that indicates that the pool
- * should expect frequent unlock() calls
+ * should expect frequent unmap() calls
* (as opposed to many makeSpace / acquires
* between resets).
* @param bufferSize The minimum size of created IBs This value
@@ -297,11 +297,11 @@ public:
* the indices is given to the caller. The buffer may or may not be locked.
* The returned ptr remains valid until any of the following:
* *makeSpace is called again.
- * *unlock is called.
+ * *unmap is called.
* *reset is called.
* *this object is destroyed.
*
- * Once unlock on the pool is called the indices are guaranteed to be in the
+ * Once unmap on the pool is called the indices are guaranteed to be in the
* buffer at the offset indicated by startIndex. Until that time they may be
* in temporary storage and/or the buffer may be locked.
*
diff --git a/chromium/third_party/skia/src/gpu/GrCacheID.cpp b/chromium/third_party/skia/src/gpu/GrCacheID.cpp
index 87917ac995e..8d0be0da5a9 100644
--- a/chromium/third_party/skia/src/gpu/GrCacheID.cpp
+++ b/chromium/third_party/skia/src/gpu/GrCacheID.cpp
@@ -27,7 +27,7 @@ GrCacheID::Domain GrCacheID::GenerateDomain() {
int32_t domain = sk_atomic_inc(&gNextDomain);
if (domain >= 1 << (8 * sizeof(Domain))) {
- GrCrash("Too many Cache Domains");
+ SkFAIL("Too many Cache Domains");
}
return static_cast<Domain>(domain);
diff --git a/chromium/third_party/skia/src/gpu/GrCacheable.cpp b/chromium/third_party/skia/src/gpu/GrCacheable.cpp
new file mode 100644
index 00000000000..120be78f080
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/GrCacheable.cpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "GrCacheable.h"
+
+uint32_t GrCacheable::getGenerationID() const {
+ static int32_t gPathRefGenerationID;
+ while (!fGenID) {
+ fGenID = static_cast<uint32_t>(sk_atomic_inc(&gPathRefGenerationID) + 1);
+ }
+ return fGenID;
+}
diff --git a/chromium/third_party/skia/src/gpu/GrClipData.cpp b/chromium/third_party/skia/src/gpu/GrClipData.cpp
index 22b43710f88..40bdec8877a 100644
--- a/chromium/third_party/skia/src/gpu/GrClipData.cpp
+++ b/chromium/third_party/skia/src/gpu/GrClipData.cpp
@@ -18,15 +18,15 @@
* the result of purely intersections of rects (with an initial replace)
* isIntersectionOfRects will be set to true.
*/
-void GrClipData::getConservativeBounds(const GrSurface* surface,
+void GrClipData::getConservativeBounds(int width, int height,
SkIRect* devResult,
bool* isIntersectionOfRects) const {
SkRect devBounds;
fClipStack->getConservativeBounds(-fOrigin.fX,
-fOrigin.fY,
- surface->width(),
- surface->height(),
+ width,
+ height,
&devBounds,
isIntersectionOfRects);
diff --git a/chromium/third_party/skia/src/gpu/GrClipMaskCache.h b/chromium/third_party/skia/src/gpu/GrClipMaskCache.h
index 213e2823e37..b332c7be9b9 100644
--- a/chromium/third_party/skia/src/gpu/GrClipMaskCache.h
+++ b/chromium/third_party/skia/src/gpu/GrClipMaskCache.h
@@ -18,7 +18,7 @@ class GrTexture;
* The stencil buffer stores the last clip path - providing a single entry
* "cache". This class provides similar functionality for AA clip paths
*/
-class GrClipMaskCache : public SkNoncopyable {
+class GrClipMaskCache : SkNoncopyable {
public:
GrClipMaskCache();
diff --git a/chromium/third_party/skia/src/gpu/GrClipMaskManager.cpp b/chromium/third_party/skia/src/gpu/GrClipMaskManager.cpp
index 4fd746f3fa4..a878894c599 100644
--- a/chromium/third_party/skia/src/gpu/GrClipMaskManager.cpp
+++ b/chromium/third_party/skia/src/gpu/GrClipMaskManager.cpp
@@ -18,6 +18,8 @@
#include "GrStencilBuffer.h"
#include "GrSWMaskHelper.h"
#include "effects/GrTextureDomain.h"
+#include "effects/GrConvexPolyEffect.h"
+#include "effects/GrRRectEffect.h"
#include "SkRasterClip.h"
#include "SkStrokeRec.h"
#include "SkTLazy.h"
@@ -93,23 +95,124 @@ bool GrClipMaskManager::useSWOnlyPath(const ElementList& elements) {
for (ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) {
const Element* element = iter.get();
// rects can always be drawn directly w/o using the software path
- // so only paths need to be checked
- if (Element::kPath_Type == element->getType() &&
- path_needs_SW_renderer(this->getContext(), fGpu,
- element->getPath(),
- stroke,
- element->isAA())) {
- return true;
+ // Skip rrects once we're drawing them directly.
+ if (Element::kRect_Type != element->getType()) {
+ SkPath path;
+ element->asPath(&path);
+ if (path_needs_SW_renderer(this->getContext(), fGpu, path, stroke, element->isAA())) {
+ return true;
+ }
}
}
return false;
}
+bool GrClipMaskManager::installClipEffects(const ElementList& elements,
+ GrDrawState::AutoRestoreEffects* are,
+ const SkVector& clipToRTOffset,
+ const SkRect* drawBounds) {
+
+ GrDrawState* drawState = fGpu->drawState();
+ SkRect boundsInClipSpace;
+ if (NULL != drawBounds) {
+ boundsInClipSpace = *drawBounds;
+ boundsInClipSpace.offset(-clipToRTOffset.fX, -clipToRTOffset.fY);
+ }
+
+ are->set(drawState);
+ GrRenderTarget* rt = drawState->getRenderTarget();
+ ElementList::Iter iter(elements);
+
+ bool setARE = false;
+ bool failed = false;
+
+ while (NULL != iter.get()) {
+ SkRegion::Op op = iter.get()->getOp();
+ bool invert;
+ bool skip = false;
+ switch (op) {
+ case SkRegion::kReplace_Op:
+ SkASSERT(iter.get() == elements.head());
+ // Fallthrough, handled same as intersect.
+ case SkRegion::kIntersect_Op:
+ invert = false;
+ if (NULL != drawBounds && iter.get()->contains(boundsInClipSpace)) {
+ skip = true;
+ }
+ break;
+ case SkRegion::kDifference_Op:
+ invert = true;
+ // We don't currently have a cheap test for whether a rect is fully outside an
+ // element's primitive, so don't attempt to set skip.
+ break;
+ default:
+ failed = true;
+ break;
+ }
+ if (failed) {
+ break;
+ }
+
+ if (!skip) {
+ GrEffectEdgeType edgeType;
+ if (GR_AA_CLIP && iter.get()->isAA()) {
+ if (rt->isMultisampled()) {
+ // Coverage based AA clips don't place nicely with MSAA.
+ failed = true;
+ break;
+ }
+ edgeType = invert ? kInverseFillAA_GrEffectEdgeType : kFillAA_GrEffectEdgeType;
+ } else {
+ edgeType = invert ? kInverseFillBW_GrEffectEdgeType : kFillBW_GrEffectEdgeType;
+ }
+ SkAutoTUnref<GrEffectRef> effect;
+ switch (iter.get()->getType()) {
+ case SkClipStack::Element::kPath_Type:
+ effect.reset(GrConvexPolyEffect::Create(edgeType, iter.get()->getPath(),
+ &clipToRTOffset));
+ break;
+ case SkClipStack::Element::kRRect_Type: {
+ SkRRect rrect = iter.get()->getRRect();
+ rrect.offset(clipToRTOffset.fX, clipToRTOffset.fY);
+ effect.reset(GrRRectEffect::Create(edgeType, rrect));
+ break;
+ }
+ case SkClipStack::Element::kRect_Type: {
+ SkRect rect = iter.get()->getRect();
+ rect.offset(clipToRTOffset.fX, clipToRTOffset.fY);
+ effect.reset(GrConvexPolyEffect::Create(edgeType, rect));
+ break;
+ }
+ default:
+ break;
+ }
+ if (effect) {
+ if (!setARE) {
+ are->set(fGpu->drawState());
+ setARE = true;
+ }
+ fGpu->drawState()->addCoverageEffect(effect);
+ } else {
+ failed = true;
+ break;
+ }
+ }
+ iter.next();
+ }
+
+ if (failed) {
+ are->set(NULL);
+ }
+
+ return !failed;
+}
+
////////////////////////////////////////////////////////////////////////////////
// sort out what kind of clip mask needs to be created: alpha, stencil,
// scissor, or entirely software
bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn,
- GrDrawState::AutoRestoreEffects* are) {
+ GrDrawState::AutoRestoreEffects* are,
+ const SkRect* devBounds) {
fCurrClipMaskType = kNone_ClipMaskType;
ElementList elements(16);
@@ -117,7 +220,6 @@ bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn,
InitialState initialState;
SkIRect clipSpaceIBounds;
bool requiresAA;
- bool isRect = false;
GrDrawState* drawState = fGpu->drawState();
@@ -140,7 +242,6 @@ bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn,
if (elements.isEmpty()) {
if (kAllIn_InitialState == initialState) {
ignoreClip = clipSpaceIBounds == clipSpaceRTIBounds;
- isRect = true;
} else {
return false;
}
@@ -153,9 +254,33 @@ bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn,
return true;
}
-#if GR_AA_CLIP
- // TODO: catch isRect && requiresAA and use clip planes if available rather than a mask.
+ // An element count of 4 was chosen because of the common pattern in Blink of:
+ // isect RR
+ // diff RR
+ // isect convex_poly
+ // isect convex_poly
+ // when drawing rounded div borders. This could probably be tuned based on a
+ // configuration's relative costs of switching RTs to generate a mask vs
+ // longer shaders.
+ if (elements.count() <= 4) {
+ SkVector clipToRTOffset = { SkIntToScalar(-clipDataIn->fOrigin.fX),
+ SkIntToScalar(-clipDataIn->fOrigin.fY) };
+ if (elements.isEmpty() ||
+ (requiresAA && this->installClipEffects(elements, are, clipToRTOffset, devBounds))) {
+ SkIRect scissorSpaceIBounds(clipSpaceIBounds);
+ scissorSpaceIBounds.offset(-clipDataIn->fOrigin);
+ if (NULL == devBounds ||
+ !SkRect::Make(scissorSpaceIBounds).contains(*devBounds)) {
+ fGpu->enableScissor(scissorSpaceIBounds);
+ } else {
+ fGpu->disableScissor();
+ }
+ this->setGpuStencil();
+ return true;
+ }
+ }
+#if GR_AA_CLIP
// If MSAA is enabled we can do everything in the stencil buffer.
if (0 == rt->numSamples() && requiresAA) {
GrTexture* result = NULL;
@@ -196,16 +321,6 @@ bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn,
// "incorrectly" clearing the AA cache.
fAACache.reset();
- // If the clip is a rectangle then just set the scissor. Otherwise, create
- // a stencil mask.
- if (isRect) {
- SkIRect clipRect = clipSpaceIBounds;
- clipRect.offset(-clipDataIn->fOrigin);
- fGpu->enableScissor(clipRect);
- this->setGpuStencil();
- return true;
- }
-
// use the stencil clip if we can't represent the clip as a rectangle.
SkIPoint clipSpaceToStencilSpaceOffset = -clipDataIn->fOrigin;
this->createStencilClipMask(genID,
@@ -276,7 +391,11 @@ bool GrClipMaskManager::drawElement(GrTexture* target,
drawState->setRenderTarget(target->asRenderTarget());
+ // TODO: Draw rrects directly here.
switch (element->getType()) {
+ case Element::kEmpty_Type:
+ SkDEBUGFAIL("Should never get here with an empty element.");
+ break;
case Element::kRect_Type:
// TODO: Do rects directly to the accumulator using a aa-rect GrEffect that covers the
// entire mask bounds and writes 0 outside the rect.
@@ -291,28 +410,25 @@ bool GrClipMaskManager::drawElement(GrTexture* target,
fGpu->drawSimpleRect(element->getRect(), NULL);
}
return true;
- case Element::kPath_Type: {
- SkTCopyOnFirstWrite<SkPath> path(element->getPath());
- if (path->isInverseFillType()) {
- path.writable()->toggleInverseFillType();
+ default: {
+ SkPath path;
+ element->asPath(&path);
+ if (path.isInverseFillType()) {
+ path.toggleInverseFillType();
}
SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
if (NULL == pr) {
GrPathRendererChain::DrawType type;
type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_DrawType :
GrPathRendererChain::kColor_DrawType;
- pr = this->getContext()->getPathRenderer(*path, stroke, fGpu, false, type);
+ pr = this->getContext()->getPathRenderer(path, stroke, fGpu, false, type);
}
if (NULL == pr) {
return false;
}
- pr->drawPath(element->getPath(), stroke, fGpu, element->isAA());
+ pr->drawPath(path, stroke, fGpu, element->isAA());
break;
}
- default:
- // something is wrong if we're trying to draw an empty element.
- GrCrash("Unexpected element type");
- return false;
}
return true;
}
@@ -323,25 +439,22 @@ bool GrClipMaskManager::canStencilAndDrawElement(GrTexture* target,
GrDrawState* drawState = fGpu->drawState();
drawState->setRenderTarget(target->asRenderTarget());
- switch (element->getType()) {
- case Element::kRect_Type:
- return true;
- case Element::kPath_Type: {
- SkTCopyOnFirstWrite<SkPath> path(element->getPath());
- if (path->isInverseFillType()) {
- path.writable()->toggleInverseFillType();
- }
- SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
- GrPathRendererChain::DrawType type = element->isAA() ?
- GrPathRendererChain::kStencilAndColorAntiAlias_DrawType :
- GrPathRendererChain::kStencilAndColor_DrawType;
- *pr = this->getContext()->getPathRenderer(*path, stroke, fGpu, false, type);
- return NULL != *pr;
+ if (Element::kRect_Type == element->getType()) {
+ return true;
+ } else {
+ // We shouldn't get here with an empty clip element.
+ SkASSERT(Element::kEmpty_Type != element->getType());
+ SkPath path;
+ element->asPath(&path);
+ if (path.isInverseFillType()) {
+ path.toggleInverseFillType();
}
- default:
- // something is wrong if we're trying to draw an empty element.
- GrCrash("Unexpected element type");
- return false;
+ SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
+ GrPathRendererChain::DrawType type = element->isAA() ?
+ GrPathRendererChain::kStencilAndColorAntiAlias_DrawType :
+ GrPathRendererChain::kStencilAndColor_DrawType;
+ *pr = this->getContext()->getPathRenderer(path, stroke, fGpu, false, type);
+ return NULL != *pr;
}
}
@@ -389,36 +502,39 @@ void GrClipMaskManager::getTemp(int width, int height, GrAutoScratchTexture* tem
}
////////////////////////////////////////////////////////////////////////////////
-// Handles caching & allocation (if needed) of a clip alpha-mask texture for both the sw-upload
-// or gpu-rendered cases. Returns true if there is no more work to be done (i.e., we got a cache
-// hit)
-bool GrClipMaskManager::getMaskTexture(int32_t elementsGenID,
- const SkIRect& clipSpaceIBounds,
- GrTexture** result,
- bool willUpload) {
+// Return the texture currently in the cache if it exists. Otherwise, return NULL
+GrTexture* GrClipMaskManager::getCachedMaskTexture(int32_t elementsGenID,
+ const SkIRect& clipSpaceIBounds) {
bool cached = fAACache.canReuse(elementsGenID, clipSpaceIBounds);
if (!cached) {
+ return NULL;
+ }
- // There isn't a suitable entry in the cache so we create a new texture to store the mask.
- // Since we are setting up the cache we know the last lookup was a miss. Free up the
- // currently cached mask so it can be reused.
- fAACache.reset();
+ return fAACache.getLastMask();
+}
- GrTextureDesc desc;
- desc.fFlags = willUpload ? kNone_GrTextureFlags : kRenderTarget_GrTextureFlagBit;
- desc.fWidth = clipSpaceIBounds.width();
- desc.fHeight = clipSpaceIBounds.height();
- desc.fConfig = kRGBA_8888_GrPixelConfig;
- if (willUpload || this->getContext()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
- // We would always like A8 but it isn't supported on all platforms
- desc.fConfig = kAlpha_8_GrPixelConfig;
- }
+////////////////////////////////////////////////////////////////////////////////
+// Allocate a texture in the texture cache. This function returns the texture
+// allocated (or NULL on error).
+GrTexture* GrClipMaskManager::allocMaskTexture(int32_t elementsGenID,
+ const SkIRect& clipSpaceIBounds,
+ bool willUpload) {
+ // Since we are setting up the cache we should free up the
+ // currently cached mask so it can be reused.
+ fAACache.reset();
- fAACache.acquireMask(elementsGenID, desc, clipSpaceIBounds);
+ GrTextureDesc desc;
+ desc.fFlags = willUpload ? kNone_GrTextureFlags : kRenderTarget_GrTextureFlagBit;
+ desc.fWidth = clipSpaceIBounds.width();
+ desc.fHeight = clipSpaceIBounds.height();
+ desc.fConfig = kRGBA_8888_GrPixelConfig;
+ if (willUpload || this->getContext()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
+ // We would always like A8 but it isn't supported on all platforms
+ desc.fConfig = kAlpha_8_GrPixelConfig;
}
- *result = fAACache.getLastMask();
- return cached;
+ fAACache.acquireMask(elementsGenID, desc, clipSpaceIBounds);
+ return fAACache.getLastMask();
}
////////////////////////////////////////////////////////////////////////////////
@@ -429,12 +545,15 @@ GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID,
const SkIRect& clipSpaceIBounds) {
SkASSERT(kNone_ClipMaskType == fCurrClipMaskType);
- GrTexture* result;
- if (this->getMaskTexture(elementsGenID, clipSpaceIBounds, &result, false)) {
+ // First, check for cached texture
+ GrTexture* result = this->getCachedMaskTexture(elementsGenID, clipSpaceIBounds);
+ if (NULL != result) {
fCurrClipMaskType = kAlpha_ClipMaskType;
return result;
}
+ // There's no texture in the cache. Let's try to allocate it then.
+ result = this->allocMaskTexture(elementsGenID, clipSpaceIBounds, false);
if (NULL == result) {
fAACache.reset();
return NULL;
@@ -644,18 +763,17 @@ bool GrClipMaskManager::createStencilClipMask(int32_t elementsGenID,
SkRegion::Op op = element->getOp();
GrPathRenderer* pr = NULL;
- SkTCopyOnFirstWrite<SkPath> clipPath;
+ SkPath clipPath;
if (Element::kRect_Type == element->getType()) {
stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport;
fillInverted = false;
} else {
- SkASSERT(Element::kPath_Type == element->getType());
- clipPath.init(element->getPath());
- fillInverted = clipPath->isInverseFillType();
+ element->asPath(&clipPath);
+ fillInverted = clipPath.isInverseFillType();
if (fillInverted) {
- clipPath.writable()->toggleInverseFillType();
+ clipPath.toggleInverseFillType();
}
- pr = this->getContext()->getPathRenderer(*clipPath,
+ pr = this->getContext()->getPathRenderer(clipPath,
stroke,
fGpu,
false,
@@ -696,13 +814,12 @@ bool GrClipMaskManager::createStencilClipMask(int32_t elementsGenID,
*drawState->stencil() = gDrawToStencil;
fGpu->drawSimpleRect(element->getRect(), NULL);
} else {
- SkASSERT(Element::kPath_Type == element->getType());
- if (!clipPath->isEmpty()) {
+ if (!clipPath.isEmpty()) {
if (canRenderDirectToStencil) {
*drawState->stencil() = gDrawToStencil;
- pr->drawPath(*clipPath, stroke, fGpu, false);
+ pr->drawPath(clipPath, stroke, fGpu, false);
} else {
- pr->stencilPath(*clipPath, stroke, fGpu);
+ pr->stencilPath(clipPath, stroke, fGpu);
}
}
}
@@ -718,9 +835,8 @@ bool GrClipMaskManager::createStencilClipMask(int32_t elementsGenID,
SET_RANDOM_COLOR
fGpu->drawSimpleRect(element->getRect(), NULL);
} else {
- SkASSERT(Element::kPath_Type == element->getType());
SET_RANDOM_COLOR
- pr->drawPath(*clipPath, stroke, fGpu, false);
+ pr->drawPath(clipPath, stroke, fGpu, false);
}
} else {
SET_RANDOM_COLOR
@@ -890,7 +1006,7 @@ void GrClipMaskManager::adjustStencilParams(GrStencilSettings* settings,
funcRef = clipBit;
break;
default:
- GrCrash("Unknown stencil func");
+ SkFAIL("Unknown stencil func");
}
} else {
funcMask &= userBits;
@@ -929,16 +1045,11 @@ GrTexture* GrClipMaskManager::createSoftwareClipMask(int32_t elementsGenID,
const SkIRect& clipSpaceIBounds) {
SkASSERT(kNone_ClipMaskType == fCurrClipMaskType);
- GrTexture* result;
- if (this->getMaskTexture(elementsGenID, clipSpaceIBounds, &result, true)) {
+ GrTexture* result = this->getCachedMaskTexture(elementsGenID, clipSpaceIBounds);
+ if (NULL != result) {
return result;
}
- if (NULL == result) {
- fAACache.reset();
- return NULL;
- }
-
// The mask texture may be larger than necessary. We round out the clip space bounds and pin
// the top left corner of the resulting rect to the top left of the texture.
SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpaceIBounds.height());
@@ -970,24 +1081,10 @@ GrTexture* GrClipMaskManager::createSoftwareClipMask(int32_t elementsGenID,
helper.draw(temp, SkRegion::kXOR_Op, false, 0xFF);
}
- if (Element::kRect_Type == element->getType()) {
- // convert the rect to a path so we can invert the fill
- SkPath temp;
- temp.addRect(element->getRect());
- temp.setFillType(SkPath::kInverseEvenOdd_FillType);
-
- helper.draw(temp, stroke, SkRegion::kReplace_Op,
- element->isAA(),
- 0x00);
- } else {
- SkASSERT(Element::kPath_Type == element->getType());
- SkPath clipPath = element->getPath();
- clipPath.toggleInverseFillType();
- helper.draw(clipPath, stroke,
- SkRegion::kReplace_Op,
- element->isAA(),
- 0x00);
- }
+ SkPath clipPath;
+ element->asPath(&clipPath);
+ clipPath.toggleInverseFillType();
+ helper.draw(clipPath, stroke, SkRegion::kReplace_Op, element->isAA(), 0x00);
continue;
}
@@ -997,11 +1094,18 @@ GrTexture* GrClipMaskManager::createSoftwareClipMask(int32_t elementsGenID,
if (Element::kRect_Type == element->getType()) {
helper.draw(element->getRect(), op, element->isAA(), 0xFF);
} else {
- SkASSERT(Element::kPath_Type == element->getType());
- helper.draw(element->getPath(), stroke, op, element->isAA(), 0xFF);
+ SkPath path;
+ element->asPath(&path);
+ helper.draw(path, stroke, op, element->isAA(), 0xFF);
}
}
+ // Allocate clip mask texture
+ result = this->allocMaskTexture(elementsGenID, clipSpaceIBounds, true);
+ if (NULL == result) {
+ fAACache.reset();
+ return NULL;
+ }
helper.toTexture(result);
fCurrClipMaskType = kAlpha_ClipMaskType;
diff --git a/chromium/third_party/skia/src/gpu/GrClipMaskManager.h b/chromium/third_party/skia/src/gpu/GrClipMaskManager.h
index f44a8e7b227..c3a21fd8a2b 100644
--- a/chromium/third_party/skia/src/gpu/GrClipMaskManager.h
+++ b/chromium/third_party/skia/src/gpu/GrClipMaskManager.h
@@ -36,7 +36,7 @@ class SkPath;
* mask can be represented as a rectangle then scissoring is used. In all
* cases scissoring is used to bound the range of the clip mask.
*/
-class GrClipMaskManager : public SkNoncopyable {
+class GrClipMaskManager : SkNoncopyable {
public:
GrClipMaskManager()
: fGpu(NULL)
@@ -46,9 +46,12 @@ public:
/**
* Creates a clip mask if necessary as a stencil buffer or alpha texture
* and sets the GrGpu's scissor and stencil state. If the return is false
- * then the draw can be skipped.
+ * then the draw can be skipped. The AutoRestoreEffects is initialized by
+ * the manager when it must install additional effects to implement the
+ * clip. devBounds is optional but can help optimize clipping.
*/
- bool setupClipping(const GrClipData* clipDataIn, GrDrawState::AutoRestoreEffects*);
+ bool setupClipping(const GrClipData* clipDataIn, GrDrawState::AutoRestoreEffects*,
+ const SkRect* devBounds);
void releaseResources();
@@ -102,6 +105,13 @@ private:
GrClipMaskCache fAACache; // cache for the AA path
+ // Attempts to install a series of coverage effects to implement the clip. Return indicates
+ // whether the element list was successfully converted to effects.
+ bool installClipEffects(const GrReducedClip::ElementList&,
+ GrDrawState::AutoRestoreEffects*,
+ const SkVector& clipOffset,
+ const SkRect* devBounds);
+
// Draws the clip into the stencil buffer
bool createStencilClipMask(int32_t elementsGenID,
GrReducedClip::InitialState initialState,
@@ -120,13 +130,16 @@ private:
const GrReducedClip::ElementList& elements,
const SkIRect& clipSpaceIBounds);
- // Gets a texture to use for the clip mask. If true is returned then a cached mask was found
- // that already contains the rasterization of the clip stack, otherwise an uninitialized texture
- // is returned. 'willUpload' is set when the alpha mask needs to be uploaded from the CPU.
- bool getMaskTexture(int32_t elementsGenID,
- const SkIRect& clipSpaceIBounds,
- GrTexture** result,
- bool willUpload);
+ // Returns the cached mask texture if it matches the elementsGenID and the clipSpaceIBounds.
+ // Returns NULL if not found.
+ GrTexture* getCachedMaskTexture(int32_t elementsGenID, const SkIRect& clipSpaceIBounds);
+
+
+ // Handles allocation (if needed) of a clip alpha-mask texture for both the sw-upload
+ // or gpu-rendered cases.
+ GrTexture* allocMaskTexture(int32_t elementsGenID,
+ const SkIRect& clipSpaceIBounds,
+ bool willUpload);
bool useSWOnlyPath(const GrReducedClip::ElementList& elements);
diff --git a/chromium/third_party/skia/src/gpu/GrContext.cpp b/chromium/third_party/skia/src/gpu/GrContext.cpp
index 0eb8c5b7580..6c90c178d3e 100644
--- a/chromium/third_party/skia/src/gpu/GrContext.cpp
+++ b/chromium/third_party/skia/src/gpu/GrContext.cpp
@@ -9,8 +9,9 @@
#include "GrContext.h"
-#include "effects/GrSingleTextureEffect.h"
#include "effects/GrConfigConversionEffect.h"
+#include "effects/GrDashingEffect.h"
+#include "effects/GrSingleTextureEffect.h"
#include "GrAARectRenderer.h"
#include "GrBufferAllocPool.h"
@@ -18,19 +19,25 @@
#include "GrDrawTargetCaps.h"
#include "GrIndexBuffer.h"
#include "GrInOrderDrawBuffer.h"
+#include "GrLayerCache.h"
#include "GrOvalRenderer.h"
#include "GrPathRenderer.h"
#include "GrPathUtils.h"
#include "GrResourceCache.h"
#include "GrSoftwarePathRenderer.h"
#include "GrStencilBuffer.h"
+#include "GrStrokeInfo.h"
#include "GrTextStrike.h"
+#include "GrTraceMarker.h"
+#include "GrTracing.h"
+#include "SkDashPathPriv.h"
+#include "SkGr.h"
#include "SkRTConf.h"
#include "SkRRect.h"
#include "SkStrokeRec.h"
#include "SkTLazy.h"
#include "SkTLS.h"
-#include "SkTrace.h"
+#include "SkTraceEvent.h"
// It can be useful to set this to false to test whether a bug is caused by using the
// InOrderDrawBuffer, to compare performance of using/not using InOrderDrawBuffer, or to make
@@ -91,7 +98,7 @@ GrContext::GrContext() {
fClip = NULL;
fPathRendererChain = NULL;
fSoftwarePathRenderer = NULL;
- fTextureCache = NULL;
+ fResourceCache = NULL;
fFontCache = NULL;
fDrawBuffer = NULL;
fDrawBufferVBAllocPool = NULL;
@@ -101,6 +108,7 @@ GrContext::GrContext() {
fOvalRenderer = NULL;
fViewMatrix.reset();
fMaxTextureSizeOverride = 1 << 20;
+ fGpuTracingEnabled = false;
}
bool GrContext::init(GrBackend backend, GrBackendContext backendContext) {
@@ -114,13 +122,14 @@ bool GrContext::init(GrBackend backend, GrBackendContext backendContext) {
fDrawState = SkNEW(GrDrawState);
fGpu->setDrawState(fDrawState);
- fTextureCache = SkNEW_ARGS(GrResourceCache,
- (MAX_RESOURCE_CACHE_COUNT,
- MAX_RESOURCE_CACHE_BYTES));
- fTextureCache->setOverbudgetCallback(OverbudgetCB, this);
+ fResourceCache = SkNEW_ARGS(GrResourceCache, (MAX_RESOURCE_CACHE_COUNT,
+ MAX_RESOURCE_CACHE_BYTES));
+ fResourceCache->setOverbudgetCallback(OverbudgetCB, this);
fFontCache = SkNEW_ARGS(GrFontCache, (fGpu));
+ fLayerCache.reset(SkNEW_ARGS(GrLayerCache, (fGpu)));
+
fLastDrawWasBuffered = kNo_BufferedDraw;
fAARectRenderer = SkNEW(GrAARectRenderer);
@@ -148,8 +157,8 @@ GrContext::~GrContext() {
// of them before freeing the texture cache
fGpu->purgeResources();
- delete fTextureCache;
- fTextureCache = NULL;
+ delete fResourceCache;
+ fResourceCache = NULL;
delete fFontCache;
delete fDrawBuffer;
delete fDrawBufferVBAllocPool;
@@ -191,9 +200,10 @@ void GrContext::contextDestroyed() {
fAARectRenderer->reset();
fOvalRenderer->reset();
- fTextureCache->purgeAllUnlocked();
+ fResourceCache->purgeAllUnlocked();
fFontCache->freeAll();
+ fLayerCache->freeAll();
fGpu->markContextDirty();
}
@@ -209,15 +219,21 @@ void GrContext::freeGpuResources() {
fAARectRenderer->reset();
fOvalRenderer->reset();
- fTextureCache->purgeAllUnlocked();
+ fResourceCache->purgeAllUnlocked();
fFontCache->freeAll();
+ fLayerCache->freeAll();
// a path renderer may be holding onto resources
SkSafeSetNull(fPathRendererChain);
SkSafeSetNull(fSoftwarePathRenderer);
}
-size_t GrContext::getGpuTextureCacheBytes() const {
- return fTextureCache->getCachedResourceBytes();
+void GrContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const {
+ if (NULL != resourceCount) {
+ *resourceCount = fResourceCache->getCachedResourceCount();
+ }
+ if (NULL != resourceBytes) {
+ *resourceBytes = fResourceCache->getCachedResourceBytes();
+ }
}
////////////////////////////////////////////////////////////////////////////////
@@ -225,8 +241,8 @@ size_t GrContext::getGpuTextureCacheBytes() const {
GrTexture* GrContext::findAndRefTexture(const GrTextureDesc& desc,
const GrCacheID& cacheID,
const GrTextureParams* params) {
- GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, cacheID);
- GrResource* resource = fTextureCache->find(resourceKey);
+ GrResourceKey resourceKey = GrTextureImpl::ComputeKey(fGpu, params, desc, cacheID);
+ GrCacheable* resource = fResourceCache->find(resourceKey);
SkSafeRef(resource);
return static_cast<GrTexture*>(resource);
}
@@ -234,8 +250,8 @@ GrTexture* GrContext::findAndRefTexture(const GrTextureDesc& desc,
bool GrContext::isTextureInCache(const GrTextureDesc& desc,
const GrCacheID& cacheID,
const GrTextureParams* params) const {
- GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, cacheID);
- return fTextureCache->hasKey(resourceKey);
+ GrResourceKey resourceKey = GrTextureImpl::ComputeKey(fGpu, params, desc, cacheID);
+ return fResourceCache->hasKey(resourceKey);
}
void GrContext::addStencilBuffer(GrStencilBuffer* sb) {
@@ -244,7 +260,7 @@ void GrContext::addStencilBuffer(GrStencilBuffer* sb) {
GrResourceKey resourceKey = GrStencilBuffer::ComputeKey(sb->width(),
sb->height(),
sb->numSamples());
- fTextureCache->addResource(resourceKey, sb);
+ fResourceCache->addResource(resourceKey, sb);
}
GrStencilBuffer* GrContext::findStencilBuffer(int width, int height,
@@ -252,31 +268,29 @@ GrStencilBuffer* GrContext::findStencilBuffer(int width, int height,
GrResourceKey resourceKey = GrStencilBuffer::ComputeKey(width,
height,
sampleCnt);
- GrResource* resource = fTextureCache->find(resourceKey);
+ GrCacheable* resource = fResourceCache->find(resourceKey);
return static_cast<GrStencilBuffer*>(resource);
}
-static void stretchImage(void* dst,
- int dstW,
- int dstH,
- void* src,
- int srcW,
- int srcH,
- size_t bpp) {
- GrFixed dx = (srcW << 16) / dstW;
- GrFixed dy = (srcH << 16) / dstH;
+static void stretch_image(void* dst,
+ int dstW,
+ int dstH,
+ const void* src,
+ int srcW,
+ int srcH,
+ size_t bpp) {
+ SkFixed dx = (srcW << 16) / dstW;
+ SkFixed dy = (srcH << 16) / dstH;
- GrFixed y = dy >> 1;
+ SkFixed y = dy >> 1;
size_t dstXLimit = dstW*bpp;
for (int j = 0; j < dstH; ++j) {
- GrFixed x = dx >> 1;
- void* srcRow = (uint8_t*)src + (y>>16)*srcW*bpp;
- void* dstRow = (uint8_t*)dst + j*dstW*bpp;
+ SkFixed x = dx >> 1;
+ const uint8_t* srcRow = reinterpret_cast<const uint8_t *>(src) + (y>>16)*srcW*bpp;
+ uint8_t* dstRow = reinterpret_cast<uint8_t *>(dst) + j*dstW*bpp;
for (size_t i = 0; i < dstXLimit; i += bpp) {
- memcpy((uint8_t*) dstRow + i,
- (uint8_t*) srcRow + (x>>16)*bpp,
- bpp);
+ memcpy(dstRow + i, srcRow + (x>>16)*bpp, bpp);
x += dx;
}
y += dy;
@@ -288,7 +302,7 @@ namespace {
// position + local coordinate
extern const GrVertexAttrib gVertexAttribs[] = {
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
- {kVec2f_GrVertexAttribType, sizeof(GrPoint), kLocalCoord_GrVertexAttribBinding}
+ {kVec2f_GrVertexAttribType, sizeof(SkPoint), kLocalCoord_GrVertexAttribBinding}
};
};
@@ -297,7 +311,7 @@ extern const GrVertexAttrib gVertexAttribs[] = {
// the current hardware. Resize the texture to be a POT
GrTexture* GrContext::createResizedTexture(const GrTextureDesc& desc,
const GrCacheID& cacheID,
- void* srcData,
+ const void* srcData,
size_t rowBytes,
bool filter) {
SkAutoTUnref<GrTexture> clampedTexture(this->findAndRefTexture(desc, cacheID, NULL));
@@ -335,9 +349,9 @@ GrTexture* GrContext::createResizedTexture(const GrTextureDesc& desc,
GrDrawTarget::AutoReleaseGeometry arg(fGpu, 4, 0);
if (arg.succeeded()) {
- GrPoint* verts = (GrPoint*) arg.vertices();
- verts[0].setIRectFan(0, 0, texture->width(), texture->height(), 2 * sizeof(GrPoint));
- verts[1].setIRectFan(0, 0, 1, 1, 2 * sizeof(GrPoint));
+ SkPoint* verts = (SkPoint*) arg.vertices();
+ verts[0].setIRectFan(0, 0, texture->width(), texture->height(), 2 * sizeof(SkPoint));
+ verts[1].setIRectFan(0, 0, 1, 1, 2 * sizeof(SkPoint));
fGpu->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
}
} else {
@@ -350,15 +364,18 @@ GrTexture* GrContext::createResizedTexture(const GrTextureDesc& desc,
// no longer need to clamp at min RT size.
rtDesc.fWidth = GrNextPow2(desc.fWidth);
rtDesc.fHeight = GrNextPow2(desc.fHeight);
+
+ // We shouldn't be resizing a compressed texture.
+ SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig));
+
size_t bpp = GrBytesPerPixel(desc.fConfig);
SkAutoSMalloc<128*128*4> stretchedPixels(bpp * rtDesc.fWidth * rtDesc.fHeight);
- stretchImage(stretchedPixels.get(), rtDesc.fWidth, rtDesc.fHeight,
- srcData, desc.fWidth, desc.fHeight, bpp);
+ stretch_image(stretchedPixels.get(), rtDesc.fWidth, rtDesc.fHeight,
+ srcData, desc.fWidth, desc.fHeight, bpp);
size_t stretchedRowBytes = rtDesc.fWidth * bpp;
- SkDEBUGCODE(GrTexture* texture = )fGpu->createTexture(rtDesc, stretchedPixels.get(),
- stretchedRowBytes);
+ texture = fGpu->createTexture(rtDesc, stretchedPixels.get(), stretchedRowBytes);
SkASSERT(NULL != texture);
}
@@ -368,27 +385,28 @@ GrTexture* GrContext::createResizedTexture(const GrTextureDesc& desc,
GrTexture* GrContext::createTexture(const GrTextureParams* params,
const GrTextureDesc& desc,
const GrCacheID& cacheID,
- void* srcData,
+ const void* srcData,
size_t rowBytes,
GrResourceKey* cacheKey) {
- SK_TRACE_EVENT0("GrContext::createTexture");
-
- GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, cacheID);
+ GrResourceKey resourceKey = GrTextureImpl::ComputeKey(fGpu, params, desc, cacheID);
GrTexture* texture;
- if (GrTexture::NeedsResizing(resourceKey)) {
+ if (GrTextureImpl::NeedsResizing(resourceKey)) {
+ // We do not know how to resize compressed textures.
+ SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig));
+
texture = this->createResizedTexture(desc, cacheID,
srcData, rowBytes,
- GrTexture::NeedsBilerp(resourceKey));
+ GrTextureImpl::NeedsBilerp(resourceKey));
} else {
- texture= fGpu->createTexture(desc, srcData, rowBytes);
+ texture = fGpu->createTexture(desc, srcData, rowBytes);
}
if (NULL != texture) {
// Adding a resource could put us overbudget. Try to free up the
// necessary space before adding it.
- fTextureCache->purgeAsNeeded(1, texture->sizeInBytes());
- fTextureCache->addResource(resourceKey, texture);
+ fResourceCache->purgeAsNeeded(1, texture->gpuMemorySize());
+ fResourceCache->addResource(resourceKey, texture);
if (NULL != cacheKey) {
*cacheKey = resourceKey;
@@ -399,16 +417,16 @@ GrTexture* GrContext::createTexture(const GrTextureParams* params,
}
static GrTexture* create_scratch_texture(GrGpu* gpu,
- GrResourceCache* textureCache,
+ GrResourceCache* resourceCache,
const GrTextureDesc& desc) {
GrTexture* texture = gpu->createTexture(desc, NULL, 0);
if (NULL != texture) {
- GrResourceKey key = GrTexture::ComputeScratchKey(texture->desc());
+ GrResourceKey key = GrTextureImpl::ComputeScratchKey(texture->desc());
// Adding a resource could put us overbudget. Try to free up the
// necessary space before adding it.
- textureCache->purgeAsNeeded(1, texture->sizeInBytes());
+ resourceCache->purgeAsNeeded(1, texture->gpuMemorySize());
// Make the resource exclusive so future 'find' calls don't return it
- textureCache->addResource(key, texture, GrResourceCache::kHide_OwnershipFlag);
+ resourceCache->addResource(key, texture, GrResourceCache::kHide_OwnershipFlag);
}
return texture;
}
@@ -426,7 +444,7 @@ GrTexture* GrContext::lockAndRefScratchTexture(const GrTextureDesc& inDesc, Scra
if (!fGpu->caps()->reuseScratchTextures() &&
!(inDesc.fFlags & kRenderTarget_GrTextureFlagBit)) {
// If we're never recycling this texture we can always make it the right size
- return create_scratch_texture(fGpu, fTextureCache, inDesc);
+ return create_scratch_texture(fGpu, fResourceCache, inDesc);
}
GrTextureDesc desc = inDesc;
@@ -434,18 +452,18 @@ GrTexture* GrContext::lockAndRefScratchTexture(const GrTextureDesc& inDesc, Scra
if (kApprox_ScratchTexMatch == match) {
// bin by pow2 with a reasonable min
static const int MIN_SIZE = 16;
- desc.fWidth = GrMax(MIN_SIZE, GrNextPow2(desc.fWidth));
- desc.fHeight = GrMax(MIN_SIZE, GrNextPow2(desc.fHeight));
+ desc.fWidth = SkTMax(MIN_SIZE, GrNextPow2(desc.fWidth));
+ desc.fHeight = SkTMax(MIN_SIZE, GrNextPow2(desc.fHeight));
}
- GrResource* resource = NULL;
+ GrCacheable* resource = NULL;
int origWidth = desc.fWidth;
int origHeight = desc.fHeight;
do {
- GrResourceKey key = GrTexture::ComputeScratchKey(desc);
+ GrResourceKey key = GrTextureImpl::ComputeScratchKey(desc);
// Ensure we have exclusive access to the texture so future 'find' calls don't return it
- resource = fTextureCache->find(key, GrResourceCache::kHide_OwnershipFlag);
+ resource = fResourceCache->find(key, GrResourceCache::kHide_OwnershipFlag);
if (NULL != resource) {
resource->ref();
break;
@@ -470,7 +488,7 @@ GrTexture* GrContext::lockAndRefScratchTexture(const GrTextureDesc& inDesc, Scra
desc.fFlags = inDesc.fFlags;
desc.fWidth = origWidth;
desc.fHeight = origHeight;
- resource = create_scratch_texture(fGpu, fTextureCache, desc);
+ resource = create_scratch_texture(fGpu, fResourceCache, desc);
}
return static_cast<GrTexture*>(resource);
@@ -493,13 +511,13 @@ void GrContext::addExistingTextureToCache(GrTexture* texture) {
if (fGpu->caps()->reuseScratchTextures() || NULL != texture->asRenderTarget()) {
// Since this texture came from an AutoScratchTexture it should
// still be in the exclusive pile. Recycle it.
- fTextureCache->makeNonExclusive(texture->getCacheEntry());
+ fResourceCache->makeNonExclusive(texture->getCacheEntry());
this->purgeCache();
} else if (texture->getDeferredRefCount() <= 0) {
// When we aren't reusing textures we know this scratch texture
// will never be reused and would be just wasting time in the cache
- fTextureCache->makeNonExclusive(texture->getCacheEntry());
- fTextureCache->deleteResource(texture->getCacheEntry());
+ fResourceCache->makeNonExclusive(texture->getCacheEntry());
+ fResourceCache->deleteResource(texture->getCacheEntry());
} else {
// In this case (fDeferredRefCount > 0) but the cache is the only
// one holding a real ref. Mark the object so when the deferred
@@ -519,21 +537,21 @@ void GrContext::unlockScratchTexture(GrTexture* texture) {
// the same texture).
if (texture->getCacheEntry()->key().isScratch()) {
if (fGpu->caps()->reuseScratchTextures() || NULL != texture->asRenderTarget()) {
- fTextureCache->makeNonExclusive(texture->getCacheEntry());
+ fResourceCache->makeNonExclusive(texture->getCacheEntry());
this->purgeCache();
} else if (texture->unique() && texture->getDeferredRefCount() <= 0) {
// Only the cache now knows about this texture. Since we're never
// reusing scratch textures (in this code path) it would just be
// wasting time sitting in the cache.
- fTextureCache->makeNonExclusive(texture->getCacheEntry());
- fTextureCache->deleteResource(texture->getCacheEntry());
+ fResourceCache->makeNonExclusive(texture->getCacheEntry());
+ fResourceCache->deleteResource(texture->getCacheEntry());
} else {
// In this case (fRefCnt > 1 || defRefCnt > 0) but we don't really
// want to readd it to the cache (since it will never be reused).
// Instead, give up the cache's ref and leave the decision up to
// addExistingTextureToCache once its ref count reaches 0. For
// this to work we need to leave it in the exclusive list.
- texture->setFlag((GrTextureFlags) GrTexture::kReturnToCache_FlagBit);
+ texture->impl()->setFlag((GrTextureFlags) GrTextureImpl::kReturnToCache_FlagBit);
// Give up the cache's ref to the texture
texture->unref();
}
@@ -541,8 +559,8 @@ void GrContext::unlockScratchTexture(GrTexture* texture) {
}
void GrContext::purgeCache() {
- if (NULL != fTextureCache) {
- fTextureCache->purgeAsNeeded();
+ if (NULL != fResourceCache) {
+ fResourceCache->purgeAsNeeded();
}
}
@@ -565,17 +583,16 @@ GrTexture* GrContext::createUncachedTexture(const GrTextureDesc& descIn,
return fGpu->createTexture(descCopy, srcData, rowBytes);
}
-void GrContext::getTextureCacheLimits(int* maxTextures,
- size_t* maxTextureBytes) const {
- fTextureCache->getLimits(maxTextures, maxTextureBytes);
+void GrContext::getResourceCacheLimits(int* maxTextures, size_t* maxTextureBytes) const {
+ fResourceCache->getLimits(maxTextures, maxTextureBytes);
}
-void GrContext::setTextureCacheLimits(int maxTextures, size_t maxTextureBytes) {
- fTextureCache->setLimits(maxTextures, maxTextureBytes);
+void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes) {
+ fResourceCache->setLimits(maxTextures, maxTextureBytes);
}
int GrContext::getMaxTextureSize() const {
- return GrMin(fGpu->caps()->maxTextureSize(), fMaxTextureSizeOverride);
+ return SkTMin(fGpu->caps()->maxTextureSize(), fMaxTextureSizeOverride);
}
int GrContext::getMaxRenderTargetSize() const {
@@ -601,11 +618,11 @@ GrRenderTarget* GrContext::wrapBackendRenderTarget(const GrBackendRenderTargetDe
bool GrContext::supportsIndex8PixelConfig(const GrTextureParams* params,
int width, int height) const {
const GrDrawTargetCaps* caps = fGpu->caps();
- if (!caps->eightBitPaletteSupport()) {
+ if (!caps->isConfigTexturable(kIndex_8_GrPixelConfig)) {
return false;
}
- bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
+ bool isPow2 = SkIsPow2(width) && SkIsPow2(height);
if (!isPow2) {
bool tiled = NULL != params && params->isTiled();
@@ -675,7 +692,7 @@ void GrContext::dumpFontCache() const {
could use an indices array, and then only send 8 verts, but not sure that
would be faster.
*/
-static void setStrokeRectStrip(GrPoint verts[10], SkRect rect,
+static void setStrokeRectStrip(SkPoint verts[10], SkRect rect,
SkScalar width) {
const SkScalar rad = SkScalarHalf(width);
rect.sort();
@@ -762,15 +779,22 @@ static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& po
void GrContext::drawRect(const GrPaint& paint,
const SkRect& rect,
- const SkStrokeRec* stroke,
+ const GrStrokeInfo* strokeInfo,
const SkMatrix* matrix) {
- SK_TRACE_EVENT0("GrContext::drawRect");
+ if (NULL != strokeInfo && strokeInfo->isDashed()) {
+ SkPath path;
+ path.addRect(rect);
+ this->drawPath(paint, path, *strokeInfo);
+ return;
+ }
AutoRestoreEffects are;
AutoCheckFlush acf(this);
GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
- SkScalar width = stroke == NULL ? -1 : stroke->getWidth();
+ GR_CREATE_TRACE_MARKER("GrContext::drawRect", target);
+
+ SkScalar width = NULL == strokeInfo ? -1 : strokeInfo->getStrokeRec().getWidth();
SkMatrix combinedMatrix = target->drawState()->getViewMatrix();
if (NULL != matrix) {
combinedMatrix.preConcat(*matrix);
@@ -817,6 +841,9 @@ void GrContext::drawRect(const GrPaint& paint,
!target->getDrawState().getRenderTarget()->isMultisampled();
bool doAA = needAA && apply_aa_to_rect(target, rect, width, combinedMatrix, &devBoundRect,
&useVertexCoverage);
+
+ const SkStrokeRec& strokeRec = strokeInfo->getStrokeRec();
+
if (doAA) {
GrDrawState::AutoViewMatrixRestore avmr;
if (!avmr.setIdentity(target->drawState())) {
@@ -825,7 +852,7 @@ void GrContext::drawRect(const GrPaint& paint,
if (width >= 0) {
fAARectRenderer->strokeAARect(this->getGpu(), target, rect,
combinedMatrix, devBoundRect,
- stroke, useVertexCoverage);
+ strokeRec, useVertexCoverage);
} else {
// filled AA rect
fAARectRenderer->fillAARect(this->getGpu(), target,
@@ -851,7 +878,7 @@ void GrContext::drawRect(const GrPaint& paint,
GrPrimitiveType primType;
int vertCount;
- GrPoint* vertex = geo.positions();
+ SkPoint* vertex = geo.positions();
if (width > 0) {
vertCount = 10;
@@ -886,11 +913,12 @@ void GrContext::drawRectToRect(const GrPaint& paint,
const SkRect& localRect,
const SkMatrix* dstMatrix,
const SkMatrix* localMatrix) {
- SK_TRACE_EVENT0("GrContext::drawRectToRect");
AutoRestoreEffects are;
AutoCheckFlush acf(this);
GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
+ GR_CREATE_TRACE_MARKER("GrContext::drawRectToRect", target);
+
target->drawRect(dstRect, dstMatrix, &localRect, localMatrix);
}
@@ -898,17 +926,17 @@ namespace {
extern const GrVertexAttrib gPosUVColorAttribs[] = {
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding },
- {kVec2f_GrVertexAttribType, sizeof(GrPoint), kLocalCoord_GrVertexAttribBinding },
- {kVec4ub_GrVertexAttribType, 2*sizeof(GrPoint), kColor_GrVertexAttribBinding}
+ {kVec2f_GrVertexAttribType, sizeof(SkPoint), kLocalCoord_GrVertexAttribBinding },
+ {kVec4ub_GrVertexAttribType, 2*sizeof(SkPoint), kColor_GrVertexAttribBinding}
};
extern const GrVertexAttrib gPosColorAttribs[] = {
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
- {kVec4ub_GrVertexAttribType, sizeof(GrPoint), kColor_GrVertexAttribBinding},
+ {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding},
};
static void set_vertex_attributes(GrDrawState* drawState,
- const GrPoint* texCoords,
+ const SkPoint* texCoords,
const GrColor* colors,
int* colorOffset,
int* texOffset) {
@@ -916,14 +944,14 @@ static void set_vertex_attributes(GrDrawState* drawState,
*colorOffset = -1;
if (NULL != texCoords && NULL != colors) {
- *texOffset = sizeof(GrPoint);
- *colorOffset = 2*sizeof(GrPoint);
+ *texOffset = sizeof(SkPoint);
+ *colorOffset = 2*sizeof(SkPoint);
drawState->setVertexAttribs<gPosUVColorAttribs>(3);
} else if (NULL != texCoords) {
- *texOffset = sizeof(GrPoint);
+ *texOffset = sizeof(SkPoint);
drawState->setVertexAttribs<gPosUVColorAttribs>(2);
} else if (NULL != colors) {
- *colorOffset = sizeof(GrPoint);
+ *colorOffset = sizeof(SkPoint);
drawState->setVertexAttribs<gPosColorAttribs>(2);
} else {
drawState->setVertexAttribs<gPosColorAttribs>(1);
@@ -935,26 +963,25 @@ static void set_vertex_attributes(GrDrawState* drawState,
void GrContext::drawVertices(const GrPaint& paint,
GrPrimitiveType primitiveType,
int vertexCount,
- const GrPoint positions[],
- const GrPoint texCoords[],
+ const SkPoint positions[],
+ const SkPoint texCoords[],
const GrColor colors[],
const uint16_t indices[],
int indexCount) {
- SK_TRACE_EVENT0("GrContext::drawVertices");
-
- GrDrawTarget::AutoReleaseGeometry geo;
-
AutoRestoreEffects are;
AutoCheckFlush acf(this);
- GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
+ GrDrawTarget::AutoReleaseGeometry geo; // must be inside AutoCheckFlush scope
+ GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
GrDrawState* drawState = target->drawState();
+ GR_CREATE_TRACE_MARKER("GrContext::drawVertices", target);
+
int colorOffset = -1, texOffset = -1;
set_vertex_attributes(drawState, texCoords, colors, &colorOffset, &texOffset);
size_t vertexSize = drawState->getVertexSize();
- if (sizeof(GrPoint) != vertexSize) {
+ if (sizeof(SkPoint) != vertexSize) {
if (!geo.set(target, vertexCount, 0)) {
GrPrintf("Failed to get space for vertices!\n");
return;
@@ -962,10 +989,10 @@ void GrContext::drawVertices(const GrPaint& paint,
void* curVertex = geo.vertices();
for (int i = 0; i < vertexCount; ++i) {
- *((GrPoint*)curVertex) = positions[i];
+ *((SkPoint*)curVertex) = positions[i];
if (texOffset >= 0) {
- *(GrPoint*)((intptr_t)curVertex + texOffset) = texCoords[i];
+ *(SkPoint*)((intptr_t)curVertex + texOffset) = texCoords[i];
}
if (colorOffset >= 0) {
*(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i];
@@ -991,9 +1018,40 @@ void GrContext::drawVertices(const GrPaint& paint,
///////////////////////////////////////////////////////////////////////////////
void GrContext::drawRRect(const GrPaint& paint,
- const SkRRect& rect,
- const SkStrokeRec& stroke) {
- if (rect.isEmpty()) {
+ const SkRRect& rrect,
+ const GrStrokeInfo& strokeInfo) {
+ if (rrect.isEmpty()) {
+ return;
+ }
+
+ if (strokeInfo.isDashed()) {
+ SkPath path;
+ path.addRRect(rrect);
+ this->drawPath(paint, path, strokeInfo);
+ return;
+ }
+
+ AutoRestoreEffects are;
+ AutoCheckFlush acf(this);
+ GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
+
+ GR_CREATE_TRACE_MARKER("GrContext::drawRRect", target);
+
+ const SkStrokeRec& strokeRec = strokeInfo.getStrokeRec();
+
+ if (!fOvalRenderer->drawRRect(target, this, paint.isAntiAlias(), rrect, strokeRec)) {
+ SkPath path;
+ path.addRRect(rrect);
+ this->internalDrawPath(target, paint.isAntiAlias(), path, strokeInfo);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void GrContext::drawDRRect(const GrPaint& paint,
+ const SkRRect& outer,
+ const SkRRect& inner) {
+ if (outer.isEmpty()) {
return;
}
@@ -1001,10 +1059,16 @@ void GrContext::drawRRect(const GrPaint& paint,
AutoCheckFlush acf(this);
GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
- if (!fOvalRenderer->drawSimpleRRect(target, this, paint.isAntiAlias(), rect, stroke)) {
+ GR_CREATE_TRACE_MARKER("GrContext::drawDRRect", target);
+
+ if (!fOvalRenderer->drawDRRect(target, this, paint.isAntiAlias(), outer, inner)) {
SkPath path;
- path.addRRect(rect);
- this->internalDrawPath(target, paint.isAntiAlias(), path, stroke);
+ path.addRRect(inner);
+ path.addRRect(outer);
+ path.setFillType(SkPath::kEvenOdd_FillType);
+
+ GrStrokeInfo fillRec(SkStrokeRec::kFill_InitStyle);
+ this->internalDrawPath(target, paint.isAntiAlias(), path, fillRec);
}
}
@@ -1012,19 +1076,31 @@ void GrContext::drawRRect(const GrPaint& paint,
void GrContext::drawOval(const GrPaint& paint,
const SkRect& oval,
- const SkStrokeRec& stroke) {
+ const GrStrokeInfo& strokeInfo) {
if (oval.isEmpty()) {
return;
}
+ if (strokeInfo.isDashed()) {
+ SkPath path;
+ path.addOval(oval);
+ this->drawPath(paint, path, strokeInfo);
+ return;
+ }
+
AutoRestoreEffects are;
AutoCheckFlush acf(this);
GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
- if (!fOvalRenderer->drawOval(target, this, paint.isAntiAlias(), oval, stroke)) {
+ GR_CREATE_TRACE_MARKER("GrContext::drawOval", target);
+
+ const SkStrokeRec& strokeRec = strokeInfo.getStrokeRec();
+
+
+ if (!fOvalRenderer->drawOval(target, this, paint.isAntiAlias(), oval, strokeRec)) {
SkPath path;
path.addOval(oval);
- this->internalDrawPath(target, paint.isAntiAlias(), path, stroke);
+ this->internalDrawPath(target, paint.isAntiAlias(), path, strokeInfo);
}
}
@@ -1083,7 +1159,7 @@ static bool is_nested_rects(GrDrawTarget* target,
return true;
}
-void GrContext::drawPath(const GrPaint& paint, const SkPath& path, const SkStrokeRec& stroke) {
+void GrContext::drawPath(const GrPaint& paint, const SkPath& path, const GrStrokeInfo& strokeInfo) {
if (path.isEmpty()) {
if (path.isInverseFillType()) {
@@ -1092,6 +1168,38 @@ void GrContext::drawPath(const GrPaint& paint, const SkPath& path, const SkStrok
return;
}
+ if (strokeInfo.isDashed()) {
+ SkPoint pts[2];
+ if (path.isLine(pts)) {
+ AutoRestoreEffects are;
+ AutoCheckFlush acf(this);
+ GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
+ GrDrawState* drawState = target->drawState();
+
+ SkMatrix origViewMatrix = drawState->getViewMatrix();
+ GrDrawState::AutoViewMatrixRestore avmr;
+ if (avmr.setIdentity(target->drawState())) {
+ if (GrDashingEffect::DrawDashLine(pts, paint, strokeInfo, fGpu, target,
+ origViewMatrix)) {
+ return;
+ }
+ }
+ }
+
+ // Filter dashed path into new path with the dashing applied
+ const SkPathEffect::DashInfo& info = strokeInfo.getDashInfo();
+ SkTLazy<SkPath> effectPath;
+ GrStrokeInfo newStrokeInfo(strokeInfo, false);
+ SkStrokeRec* stroke = newStrokeInfo.getStrokeRecPtr();
+ if (SkDashPath::FilterDashPath(effectPath.init(), path, stroke, NULL, info)) {
+ this->drawPath(paint, *effectPath.get(), newStrokeInfo);
+ return;
+ }
+
+ this->drawPath(paint, path, newStrokeInfo);
+ return;
+ }
+
// Note that internalDrawPath may sw-rasterize the path into a scratch texture.
// Scratch textures can be recycled after they are returned to the texture
// cache. This presents a potential hazard for buffered drawing. However,
@@ -1102,14 +1210,18 @@ void GrContext::drawPath(const GrPaint& paint, const SkPath& path, const SkStrok
GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
GrDrawState* drawState = target->drawState();
+ GR_CREATE_TRACE_MARKER("GrContext::drawPath", target);
+
+ const SkStrokeRec& strokeRec = strokeInfo.getStrokeRec();
+
bool useCoverageAA = paint.isAntiAlias() && !drawState->getRenderTarget()->isMultisampled();
- if (useCoverageAA && stroke.getWidth() < 0 && !path.isConvex()) {
+ if (useCoverageAA && strokeRec.getWidth() < 0 && !path.isConvex()) {
// Concave AA paths are expensive - try to avoid them for special cases
bool useVertexCoverage;
SkRect rects[2];
- if (is_nested_rects(target, path, stroke, rects, &useVertexCoverage)) {
+ if (is_nested_rects(target, path, strokeRec, rects, &useVertexCoverage)) {
SkMatrix origViewMatrix = drawState->getViewMatrix();
GrDrawState::AutoViewMatrixRestore avmr;
if (!avmr.setIdentity(target->drawState())) {
@@ -1128,15 +1240,18 @@ void GrContext::drawPath(const GrPaint& paint, const SkPath& path, const SkStrok
bool isOval = path.isOval(&ovalRect);
if (!isOval || path.isInverseFillType()
- || !fOvalRenderer->drawOval(target, this, paint.isAntiAlias(), ovalRect, stroke)) {
- this->internalDrawPath(target, paint.isAntiAlias(), path, stroke);
+ || !fOvalRenderer->drawOval(target, this, paint.isAntiAlias(), ovalRect, strokeRec)) {
+ this->internalDrawPath(target, paint.isAntiAlias(), path, strokeInfo);
}
}
void GrContext::internalDrawPath(GrDrawTarget* target, bool useAA, const SkPath& path,
- const SkStrokeRec& stroke) {
+ const GrStrokeInfo& strokeInfo) {
SkASSERT(!path.isEmpty());
+ GR_CREATE_TRACE_MARKER("GrContext::internalDrawPath", target);
+
+
// An Assumption here is that path renderer would use some form of tweaking
// the src color (either the input alpha or in the frag shader) to implement
// aa. If we have some future driver-mojo path AA that can do the right
@@ -1151,18 +1266,18 @@ void GrContext::internalDrawPath(GrDrawTarget* target, bool useAA, const SkPath&
GrPathRendererChain::kColor_DrawType;
const SkPath* pathPtr = &path;
- SkPath tmpPath;
- SkStrokeRec strokeRec(stroke);
+ SkTLazy<SkPath> tmpPath;
+ SkTCopyOnFirstWrite<SkStrokeRec> stroke(strokeInfo.getStrokeRec());
// Try a 1st time without stroking the path and without allowing the SW renderer
- GrPathRenderer* pr = this->getPathRenderer(*pathPtr, strokeRec, target, false, type);
+ GrPathRenderer* pr = this->getPathRenderer(*pathPtr, *stroke, target, false, type);
if (NULL == pr) {
- if (!GrPathRenderer::IsStrokeHairlineOrEquivalent(strokeRec, this->getMatrix(), NULL)) {
+ if (!GrPathRenderer::IsStrokeHairlineOrEquivalent(*stroke, this->getMatrix(), NULL)) {
// It didn't work the 1st time, so try again with the stroked path
- if (strokeRec.applyToPath(&tmpPath, *pathPtr)) {
- pathPtr = &tmpPath;
- strokeRec.setFillStyle();
+ if (stroke->applyToPath(tmpPath.init(), *pathPtr)) {
+ pathPtr = tmpPath.get();
+ stroke.writable()->setFillStyle();
if (pathPtr->isEmpty()) {
return;
}
@@ -1170,7 +1285,7 @@ void GrContext::internalDrawPath(GrDrawTarget* target, bool useAA, const SkPath&
}
// This time, allow SW renderer
- pr = this->getPathRenderer(*pathPtr, strokeRec, target, true, type);
+ pr = this->getPathRenderer(*pathPtr, *stroke, target, true, type);
}
if (NULL == pr) {
@@ -1180,7 +1295,7 @@ void GrContext::internalDrawPath(GrDrawTarget* target, bool useAA, const SkPath&
return;
}
- pr->drawPath(*pathPtr, strokeRec, target, useCoverageAA);
+ pr->drawPath(*pathPtr, *stroke, target, useCoverageAA);
}
////////////////////////////////////////////////////////////////////////////////
@@ -1202,7 +1317,6 @@ bool GrContext::writeTexturePixels(GrTexture* texture,
int left, int top, int width, int height,
GrPixelConfig config, const void* buffer, size_t rowBytes,
uint32_t flags) {
- SK_TRACE_EVENT0("GrContext::writeTexturePixels");
ASSERT_OWNED_RESOURCE(texture);
if ((kUnpremul_PixelOpsFlag & flags) || !fGpu->canWriteTexturePixels(texture, config)) {
@@ -1227,7 +1341,6 @@ bool GrContext::readTexturePixels(GrTexture* texture,
int left, int top, int width, int height,
GrPixelConfig config, void* buffer, size_t rowBytes,
uint32_t flags) {
- SK_TRACE_EVENT0("GrContext::readTexturePixels");
ASSERT_OWNED_RESOURCE(texture);
GrRenderTarget* target = texture->asRenderTarget();
@@ -1264,60 +1377,20 @@ bool GrContext::readTexturePixels(GrTexture* texture,
#include "SkConfig8888.h"
-namespace {
-/**
- * Converts a GrPixelConfig to a SkCanvas::Config8888. Only byte-per-channel
- * formats are representable as Config8888 and so the function returns false
- * if the GrPixelConfig has no equivalent Config8888.
- */
-bool grconfig_to_config8888(GrPixelConfig config,
- bool unpremul,
- SkCanvas::Config8888* config8888) {
- switch (config) {
- case kRGBA_8888_GrPixelConfig:
- if (unpremul) {
- *config8888 = SkCanvas::kRGBA_Unpremul_Config8888;
- } else {
- *config8888 = SkCanvas::kRGBA_Premul_Config8888;
- }
- return true;
- case kBGRA_8888_GrPixelConfig:
- if (unpremul) {
- *config8888 = SkCanvas::kBGRA_Unpremul_Config8888;
- } else {
- *config8888 = SkCanvas::kBGRA_Premul_Config8888;
- }
- return true;
- default:
- return false;
- }
-}
-
-// It returns a configuration with where the byte position of the R & B components are swapped in
-// relation to the input config. This should only be called with the result of
-// grconfig_to_config8888 as it will fail for other configs.
-SkCanvas::Config8888 swap_config8888_red_and_blue(SkCanvas::Config8888 config8888) {
- switch (config8888) {
- case SkCanvas::kBGRA_Premul_Config8888:
- return SkCanvas::kRGBA_Premul_Config8888;
- case SkCanvas::kBGRA_Unpremul_Config8888:
- return SkCanvas::kRGBA_Unpremul_Config8888;
- case SkCanvas::kRGBA_Premul_Config8888:
- return SkCanvas::kBGRA_Premul_Config8888;
- case SkCanvas::kRGBA_Unpremul_Config8888:
- return SkCanvas::kBGRA_Unpremul_Config8888;
- default:
- GrCrash("Unexpected input");
- return SkCanvas::kBGRA_Unpremul_Config8888;;
+// toggles between RGBA and BGRA
+static SkColorType toggle_colortype32(SkColorType ct) {
+ if (kRGBA_8888_SkColorType == ct) {
+ return kBGRA_8888_SkColorType;
+ } else {
+ SkASSERT(kBGRA_8888_SkColorType == ct);
+ return kRGBA_8888_SkColorType;
}
}
-}
bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
int left, int top, int width, int height,
GrPixelConfig dstConfig, void* buffer, size_t rowBytes,
uint32_t flags) {
- SK_TRACE_EVENT0("GrContext::readRenderTargetPixels");
ASSERT_OWNED_RESOURCE(target);
if (NULL == target) {
@@ -1438,22 +1511,21 @@ bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
}
// Perform any conversions we weren't able to perform using a scratch texture.
if (unpremul || swapRAndB) {
- // These are initialized to suppress a warning
- SkCanvas::Config8888 srcC8888 = SkCanvas::kNative_Premul_Config8888;
- SkCanvas::Config8888 dstC8888 = SkCanvas::kNative_Premul_Config8888;
+ SkDstPixelInfo dstPI;
+ if (!GrPixelConfig2ColorType(dstConfig, &dstPI.fColorType)) {
+ return false;
+ }
+ dstPI.fAlphaType = kUnpremul_SkAlphaType;
+ dstPI.fPixels = buffer;
+ dstPI.fRowBytes = rowBytes;
- SkDEBUGCODE(bool c8888IsValid =) grconfig_to_config8888(dstConfig, false, &srcC8888);
- grconfig_to_config8888(dstConfig, unpremul, &dstC8888);
+ SkSrcPixelInfo srcPI;
+ srcPI.fColorType = swapRAndB ? toggle_colortype32(dstPI.fColorType) : dstPI.fColorType;
+ srcPI.fAlphaType = kPremul_SkAlphaType;
+ srcPI.fPixels = buffer;
+ srcPI.fRowBytes = rowBytes;
- if (swapRAndB) {
- SkASSERT(c8888IsValid); // we should only do r/b swap on 8888 configs
- srcC8888 = swap_config8888_red_and_blue(srcC8888);
- }
- SkASSERT(c8888IsValid);
- uint32_t* b32 = reinterpret_cast<uint32_t*>(buffer);
- SkConvertConfig8888Pixels(b32, rowBytes, dstC8888,
- b32, rowBytes, srcC8888,
- width, height);
+ return srcPI.convertPixelsTo(&dstPI, width, height);
}
return true;
}
@@ -1468,6 +1540,14 @@ void GrContext::resolveRenderTarget(GrRenderTarget* target) {
fGpu->resolveRenderTarget(target);
}
+void GrContext::discardRenderTarget(GrRenderTarget* target) {
+ SkASSERT(target);
+ ASSERT_OWNED_RESOURCE(target);
+ AutoRestoreEffects are;
+ AutoCheckFlush acf(this);
+ this->prepareToDraw(NULL, BUFFERED_DRAW, &are, &acf)->discard(target);
+}
+
void GrContext::copyTexture(GrTexture* src, GrRenderTarget* dst, const SkIPoint* topLeft) {
if (NULL == src || NULL == dst) {
return;
@@ -1505,7 +1585,6 @@ bool GrContext::writeRenderTargetPixels(GrRenderTarget* target,
const void* buffer,
size_t rowBytes,
uint32_t flags) {
- SK_TRACE_EVENT0("GrContext::writeRenderTargetPixels");
ASSERT_OWNED_RESOURCE(target);
if (NULL == target) {
@@ -1574,18 +1653,26 @@ bool GrContext::writeRenderTargetPixels(GrRenderTarget* target,
effect.reset(this->createUPMToPMEffect(texture, swapRAndB, textureMatrix));
// handle the unpremul step on the CPU if we couldn't create an effect to do it.
if (NULL == effect) {
- SkCanvas::Config8888 srcConfig8888, dstConfig8888;
- SkDEBUGCODE(bool success = )
- grconfig_to_config8888(srcConfig, true, &srcConfig8888);
- SkASSERT(success);
- SkDEBUGCODE(success = )
- grconfig_to_config8888(srcConfig, false, &dstConfig8888);
- SkASSERT(success);
- const uint32_t* src = reinterpret_cast<const uint32_t*>(buffer);
+ SkSrcPixelInfo srcPI;
+ if (!GrPixelConfig2ColorType(srcConfig, &srcPI.fColorType)) {
+ return false;
+ }
+ srcPI.fAlphaType = kUnpremul_SkAlphaType;
+ srcPI.fPixels = buffer;
+ srcPI.fRowBytes = rowBytes;
+
tmpPixels.reset(width * height);
- SkConvertConfig8888Pixels(tmpPixels.get(), 4 * width, dstConfig8888,
- src, rowBytes, srcConfig8888,
- width, height);
+
+ SkDstPixelInfo dstPI;
+ dstPI.fColorType = srcPI.fColorType;
+ dstPI.fAlphaType = kPremul_SkAlphaType;
+ dstPI.fPixels = tmpPixels.get();
+ dstPI.fRowBytes = 4 * width;
+
+ if (!srcPI.convertPixelsTo(&dstPI, width, height)) {
+ return false;
+ }
+
buffer = tmpPixels.get();
rowBytes = 4 * width;
}
@@ -1703,6 +1790,23 @@ bool GrContext::isConfigRenderable(GrPixelConfig config, bool withMSAA) const {
return fGpu->caps()->isConfigRenderable(config, withMSAA);
}
+int GrContext::getRecommendedSampleCount(GrPixelConfig config,
+ SkScalar dpi) const {
+ if (!this->isConfigRenderable(config, true)) {
+ return 0;
+ }
+ int chosenSampleCount = 0;
+ if (fGpu->caps()->pathRenderingSupport()) {
+ if (dpi >= 250.0f) {
+ chosenSampleCount = 4;
+ } else {
+ chosenSampleCount = 16;
+ }
+ }
+ return chosenSampleCount <= fGpu->caps()->maxSampleCount() ?
+ chosenSampleCount : 0;
+}
+
void GrContext::setupDrawBuffer() {
SkASSERT(NULL == fDrawBuffer);
SkASSERT(NULL == fDrawBufferVBAllocPool);
@@ -1777,22 +1881,47 @@ const GrEffectRef* GrContext::createUPMToPMEffect(GrTexture* texture,
GrPath* GrContext::createPath(const SkPath& inPath, const SkStrokeRec& stroke) {
SkASSERT(fGpu->caps()->pathRenderingSupport());
- // TODO: now we add to fTextureCache. This should change to fResourceCache.
+ // TODO: now we add to fResourceCache. This should change to fResourceCache.
GrResourceKey resourceKey = GrPath::ComputeKey(inPath, stroke);
- GrPath* path = static_cast<GrPath*>(fTextureCache->find(resourceKey));
+ GrPath* path = static_cast<GrPath*>(fResourceCache->find(resourceKey));
if (NULL != path && path->isEqualTo(inPath, stroke)) {
path->ref();
} else {
path = fGpu->createPath(inPath, stroke);
- fTextureCache->purgeAsNeeded(1, path->sizeInBytes());
- fTextureCache->addResource(resourceKey, path);
+ fResourceCache->purgeAsNeeded(1, path->gpuMemorySize());
+ fResourceCache->addResource(resourceKey, path);
}
return path;
}
+void GrContext::addResourceToCache(const GrResourceKey& resourceKey, GrCacheable* resource) {
+ fResourceCache->purgeAsNeeded(1, resource->gpuMemorySize());
+ fResourceCache->addResource(resourceKey, resource);
+}
+
+GrCacheable* GrContext::findAndRefCachedResource(const GrResourceKey& resourceKey) {
+ GrCacheable* resource = fResourceCache->find(resourceKey);
+ SkSafeRef(resource);
+ return resource;
+}
+
+void GrContext::addGpuTraceMarker(const GrGpuTraceMarker* marker) {
+ fGpu->addGpuTraceMarker(marker);
+ if (NULL != fDrawBuffer) {
+ fDrawBuffer->addGpuTraceMarker(marker);
+ }
+}
+
+void GrContext::removeGpuTraceMarker(const GrGpuTraceMarker* marker) {
+ fGpu->removeGpuTraceMarker(marker);
+ if (NULL != fDrawBuffer) {
+ fDrawBuffer->removeGpuTraceMarker(marker);
+ }
+}
+
///////////////////////////////////////////////////////////////////////////////
#if GR_CACHE_STATS
void GrContext::printCacheStats() const {
- fTextureCache->printStats();
+ fResourceCache->printStats();
}
#endif
diff --git a/chromium/third_party/skia/src/gpu/GrDefaultPathRenderer.cpp b/chromium/third_party/skia/src/gpu/GrDefaultPathRenderer.cpp
index 1f20ac2724f..01e1a94adc8 100644
--- a/chromium/third_party/skia/src/gpu/GrDefaultPathRenderer.cpp
+++ b/chromium/third_party/skia/src/gpu/GrDefaultPathRenderer.cpp
@@ -13,7 +13,7 @@
#include "SkString.h"
#include "SkStrokeRec.h"
#include "SkTLazy.h"
-#include "SkTrace.h"
+#include "SkTraceEvent.h"
GrDefaultPathRenderer::GrDefaultPathRenderer(bool separateStencilSupport,
@@ -196,8 +196,6 @@ bool GrDefaultPathRenderer::createGeom(const SkPath& path,
int* indexCnt,
GrDrawTarget::AutoReleaseGeometry* arg) {
{
- SK_TRACE_EVENT0("GrDefaultPathRenderer::createGeom");
-
SkScalar srcSpaceTolSqd = SkScalarMul(srcSpaceTol, srcSpaceTol);
int contourCnt;
int maxPts = GrPathUtils::worstCasePointCount(path, &contourCnt,
@@ -241,11 +239,11 @@ bool GrDefaultPathRenderer::createGeom(const SkPath& path,
uint16_t* idx = idxBase;
uint16_t subpathIdxStart = 0;
- GrPoint* base = reinterpret_cast<GrPoint*>(arg->vertices());
+ SkPoint* base = reinterpret_cast<SkPoint*>(arg->vertices());
SkASSERT(NULL != base);
- GrPoint* vert = base;
+ SkPoint* vert = base;
- GrPoint pts[4];
+ SkPoint pts[4];
bool first = true;
int subpath = 0;
diff --git a/chromium/third_party/skia/src/gpu/GrDistanceFieldTextContext.cpp b/chromium/third_party/skia/src/gpu/GrDistanceFieldTextContext.cpp
index 2f67c4915a5..fe6e50fbde0 100755
--- a/chromium/third_party/skia/src/gpu/GrDistanceFieldTextContext.cpp
+++ b/chromium/third_party/skia/src/gpu/GrDistanceFieldTextContext.cpp
@@ -7,11 +7,19 @@
#include "GrDistanceFieldTextContext.h"
#include "GrAtlas.h"
+#include "SkColorFilter.h"
#include "GrDrawTarget.h"
+#include "GrDrawTargetCaps.h"
#include "GrFontScaler.h"
+#include "SkGlyphCache.h"
+#include "GrGpu.h"
#include "GrIndexBuffer.h"
+#include "GrStrokeInfo.h"
#include "GrTextStrike.h"
#include "GrTextStrike_impl.h"
+#include "SkDistanceFieldGen.h"
+#include "SkDraw.h"
+#include "SkGpuDevice.h"
#include "SkPath.h"
#include "SkRTConf.h"
#include "SkStrokeRec.h"
@@ -19,19 +27,26 @@
static const int kGlyphCoordsAttributeIndex = 1;
+static const int kSmallDFFontSize = 32;
+static const int kSmallDFFontLimit = 32;
+static const int kMediumDFFontSize = 64;
+static const int kMediumDFFontLimit = 64;
+static const int kLargeDFFontSize = 128;
+
SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false,
"Dump the contents of the font cache before every purge.");
-
GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context,
- const GrPaint& paint,
- SkColor color,
- SkScalar textRatio)
- : GrTextContext(context, paint)
- , fTextRatio(textRatio) {
- fSkPaintColor = color;
-
+ const SkDeviceProperties& properties,
+ bool enable)
+ : GrTextContext(context, properties) {
+#if SK_FORCE_DISTANCEFIELD_FONTS
+ fEnableDFRendering = true;
+#else
+ fEnableDFRendering = enable;
+#endif
fStrike = NULL;
+ fGammaTexture = NULL;
fCurrTexture = NULL;
fCurrVertex = 0;
@@ -42,6 +57,36 @@ GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context,
GrDistanceFieldTextContext::~GrDistanceFieldTextContext() {
this->flushGlyphs();
+ SkSafeSetNull(fGammaTexture);
+}
+
+bool GrDistanceFieldTextContext::canDraw(const SkPaint& paint) {
+ if (!fEnableDFRendering && !paint.isDistanceFieldTextTEMP()) {
+ return false;
+ }
+
+ // rasterizers and mask filters modify alpha, which doesn't
+ // translate well to distance
+ if (paint.getRasterizer() || paint.getMaskFilter() ||
+ !fContext->getTextTarget()->caps()->shaderDerivativeSupport()) {
+ return false;
+ }
+
+ // TODO: add some stroking support
+ if (paint.getStyle() != SkPaint::kFill_Style) {
+ return false;
+ }
+
+ // TODO: choose an appropriate maximum scale for distance fields and
+ // enable perspective
+ if (SkDraw::ShouldDrawTextAsPaths(paint, fContext->getMatrix())) {
+ return false;
+ }
+
+ // distance fields cannot represent color fonts
+ SkScalerContext::Rec rec;
+ SkScalerContext::MakeRec(paint, &fDeviceProperties, NULL, &rec);
+ return rec.getFormat() != SkMask::kARGB32_Format;
}
static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) {
@@ -62,16 +107,34 @@ void GrDistanceFieldTextContext::flushGlyphs() {
if (fCurrVertex > 0) {
// setup our sampler state for our text texture/atlas
- SkASSERT(GrIsALIGN4(fCurrVertex));
+ SkASSERT(SkIsAlign4(fCurrVertex));
SkASSERT(fCurrTexture);
GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBilerp_FilterMode);
+ GrTextureParams gammaParams(SkShader::kClamp_TileMode, GrTextureParams::kNone_FilterMode);
- // This effect could be stored with one of the cache objects (atlas?)
- drawState->addCoverageEffect(
- GrDistanceFieldTextureEffect::Create(fCurrTexture, params),
- kGlyphCoordsAttributeIndex)->unref();
+ // Effects could be stored with one of the cache objects (atlas?)
+ SkColor filteredColor;
+ SkColorFilter* colorFilter = fSkPaint.getColorFilter();
+ if (NULL != colorFilter) {
+ filteredColor = colorFilter->filterColor(fSkPaint.getColor());
+ } else {
+ filteredColor = fSkPaint.getColor();
+ }
+ if (fUseLCDText) {
+ GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor);
+ bool useBGR = SkDeviceProperties::Geometry::kBGR_Layout ==
+ fDeviceProperties.fGeometry.getLayout();
+ drawState->addCoverageEffect(GrDistanceFieldLCDTextureEffect::Create(
+ fCurrTexture,
+ params,
+ fGammaTexture,
+ gammaParams,
+ colorNoPreMul,
+ fContext->getMatrix().rectStaysRect() &&
+ fContext->getMatrix().isSimilarity(),
+ useBGR),
+ kGlyphCoordsAttributeIndex)->unref();
- if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) {
if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() ||
kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() ||
fPaint.numColorStages()) {
@@ -81,13 +144,28 @@ void GrDistanceFieldTextContext::flushGlyphs() {
// alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by
// the mask texture color. The end result is that we get
// mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor
- int a = SkColorGetA(fSkPaintColor);
+ int a = SkColorGetA(fSkPaint.getColor());
// paintAlpha
drawState->setColor(SkColorSetARGB(a, a, a, a));
// paintColor
- drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaintColor));
+ drawState->setBlendConstant(colorNoPreMul);
drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
} else {
+#ifdef SK_GAMMA_APPLY_TO_A8
+ U8CPU lum = SkColorSpaceLuminance::computeLuminance(fDeviceProperties.fGamma,
+ filteredColor);
+ drawState->addCoverageEffect(GrDistanceFieldTextureEffect::Create(
+ fCurrTexture, params,
+ fGammaTexture, gammaParams,
+ lum/255.f,
+ fContext->getMatrix().isSimilarity()),
+ kGlyphCoordsAttributeIndex)->unref();
+#else
+ drawState->addCoverageEffect(GrDistanceFieldTextureEffect::Create(
+ fCurrTexture, params,
+ fContext->getMatrix().isSimilarity()),
+ kGlyphCoordsAttributeIndex)->unref();
+#endif
// set back to normal in case we took LCD path previously.
drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
drawState->setColor(fPaint.getColor());
@@ -111,13 +189,13 @@ namespace {
// position + texture coord
extern const GrVertexAttrib gTextVertexAttribs[] = {
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
- {kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}
+ {kVec2f_GrVertexAttribType, sizeof(SkPoint), kEffect_GrVertexAttribBinding}
};
};
void GrDistanceFieldTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
- GrFixed vx, GrFixed vy,
+ SkFixed vx, SkFixed vy,
GrFontScaler* scaler) {
if (NULL == fDrawTarget) {
return;
@@ -153,13 +231,13 @@ void GrDistanceFieldTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
}
*/
if (NULL == glyph->fPlot) {
- if (fStrike->getGlyphAtlas(glyph, scaler)) {
+ if (fStrike->addGlyphToAtlas(glyph, scaler)) {
goto HAS_ATLAS;
}
// try to clear out an unused plot before we flush
- fContext->getFontCache()->freePlotExceptFor(fStrike);
- if (fStrike->getGlyphAtlas(glyph, scaler)) {
+ if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
+ fStrike->addGlyphToAtlas(glyph, scaler)) {
goto HAS_ATLAS;
}
@@ -173,10 +251,9 @@ void GrDistanceFieldTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
this->flushGlyphs();
fContext->flush();
- // try to purge
- fContext->getFontCache()->purgeExceptFor(fStrike);
- // need to use new flush count here
- if (fStrike->getGlyphAtlas(glyph, scaler)) {
+ // we should have an unused plot now
+ if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
+ fStrike->addGlyphToAtlas(glyph, scaler)) {
goto HAS_ATLAS;
}
@@ -191,12 +268,13 @@ void GrDistanceFieldTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
}
GrContext::AutoMatrix am;
- SkMatrix translate;
- translate.setTranslate(sx, sy);
+ SkMatrix ctm;
+ ctm.setScale(fTextRatio, fTextRatio);
+ ctm.postTranslate(sx, sy);
GrPaint tmpPaint(fPaint);
- am.setPreConcat(fContext, translate, &tmpPaint);
- SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
- fContext->drawPath(tmpPaint, *glyph->fPath, stroke);
+ am.setPreConcat(fContext, ctm, &tmpPaint);
+ GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle);
+ fContext->drawPath(tmpPaint, *glyph->fPath, strokeInfo);
return;
}
@@ -243,13 +321,13 @@ HAS_ATLAS:
GrTCast<void**>(&fVertices),
NULL);
GrAlwaysAssert(success);
- SkASSERT(2*sizeof(GrPoint) == fDrawTarget->getDrawState().getVertexSize());
+ SkASSERT(2*sizeof(SkPoint) == fDrawTarget->getDrawState().getVertexSize());
}
- SkScalar dx = SkIntToScalar(glyph->fBounds.fLeft);
- SkScalar dy = SkIntToScalar(glyph->fBounds.fTop);
- SkScalar width = SkIntToScalar(glyph->fBounds.width());
- SkScalar height = SkIntToScalar(glyph->fBounds.height());
+ SkScalar dx = SkIntToScalar(glyph->fBounds.fLeft + SK_DistanceFieldInset);
+ SkScalar dy = SkIntToScalar(glyph->fBounds.fTop + SK_DistanceFieldInset);
+ SkScalar width = SkIntToScalar(glyph->fBounds.width() - 2*SK_DistanceFieldInset);
+ SkScalar height = SkIntToScalar(glyph->fBounds.height() - 2*SK_DistanceFieldInset);
SkScalar scale = fTextRatio;
dx *= scale;
@@ -259,20 +337,240 @@ HAS_ATLAS:
width *= scale;
height *= scale;
- GrFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX);
- GrFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY);
- GrFixed tw = SkIntToFixed(glyph->fBounds.width());
- GrFixed th = SkIntToFixed(glyph->fBounds.height());
+ SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX + SK_DistanceFieldInset);
+ SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY + SK_DistanceFieldInset);
+ SkFixed tw = SkIntToFixed(glyph->fBounds.width() - 2*SK_DistanceFieldInset);
+ SkFixed th = SkIntToFixed(glyph->fBounds.height() - 2*SK_DistanceFieldInset);
+ static const size_t kVertexSize = 2 * sizeof(SkPoint);
fVertices[2*fCurrVertex].setRectFan(sx,
sy,
sx + width,
sy + height,
- 2 * sizeof(SkPoint));
+ kVertexSize);
fVertices[2*fCurrVertex+1].setRectFan(SkFixedToFloat(texture->normalizeFixedX(tx)),
SkFixedToFloat(texture->normalizeFixedY(ty)),
SkFixedToFloat(texture->normalizeFixedX(tx + tw)),
SkFixedToFloat(texture->normalizeFixedY(ty + th)),
- 2 * sizeof(SkPoint));
+ kVertexSize);
fCurrVertex += 4;
}
+
+inline void GrDistanceFieldTextContext::init(const GrPaint& paint, const SkPaint& skPaint) {
+ GrTextContext::init(paint, skPaint);
+
+ fStrike = NULL;
+
+ fCurrTexture = NULL;
+ fCurrVertex = 0;
+
+ fVertices = NULL;
+ fMaxVertices = 0;
+
+ if (fSkPaint.getTextSize() <= kSmallDFFontLimit) {
+ fTextRatio = fSkPaint.getTextSize()/kSmallDFFontSize;
+ fSkPaint.setTextSize(SkIntToScalar(kSmallDFFontSize));
+ } else if (fSkPaint.getTextSize() <= kMediumDFFontLimit) {
+ fTextRatio = fSkPaint.getTextSize()/kMediumDFFontSize;
+ fSkPaint.setTextSize(SkIntToScalar(kMediumDFFontSize));
+ } else {
+ fTextRatio = fSkPaint.getTextSize()/kLargeDFFontSize;
+ fSkPaint.setTextSize(SkIntToScalar(kLargeDFFontSize));
+ }
+
+ fUseLCDText = fSkPaint.isLCDRenderText();
+
+ fSkPaint.setLCDRenderText(false);
+ fSkPaint.setAutohinted(false);
+ fSkPaint.setHinting(SkPaint::kNormal_Hinting);
+ fSkPaint.setSubpixelText(true);
+
+}
+
+inline void GrDistanceFieldTextContext::finish() {
+ flushGlyphs();
+
+ GrTextContext::finish();
+}
+
+static void setup_gamma_texture(GrContext* context, const SkGlyphCache* cache,
+ const SkDeviceProperties& deviceProperties,
+ GrTexture** gammaTexture) {
+ if (NULL == *gammaTexture) {
+ int width, height;
+ size_t size;
+
+#ifdef SK_GAMMA_CONTRAST
+ SkScalar contrast = SK_GAMMA_CONTRAST;
+#else
+ SkScalar contrast = 0.5f;
+#endif
+ SkScalar paintGamma = deviceProperties.fGamma;
+ SkScalar deviceGamma = deviceProperties.fGamma;
+
+ size = SkScalerContext::GetGammaLUTSize(contrast, paintGamma, deviceGamma,
+ &width, &height);
+
+ SkAutoTArray<uint8_t> data((int)size);
+ SkScalerContext::GetGammaLUTData(contrast, paintGamma, deviceGamma, data.get());
+
+ // TODO: Update this to use the cache rather than directly creating a texture.
+ GrTextureDesc desc;
+ desc.fFlags = kDynamicUpdate_GrTextureFlagBit;
+ desc.fWidth = width;
+ desc.fHeight = height;
+ desc.fConfig = kAlpha_8_GrPixelConfig;
+
+ *gammaTexture = context->getGpu()->createTexture(desc, NULL, 0);
+ if (NULL == *gammaTexture) {
+ return;
+ }
+
+ context->writeTexturePixels(*gammaTexture,
+ 0, 0, width, height,
+ (*gammaTexture)->config(), data.get(), 0,
+ GrContext::kDontFlush_PixelOpsFlag);
+ }
+}
+
+void GrDistanceFieldTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint,
+ const char text[], size_t byteLength,
+ SkScalar x, SkScalar y) {
+ SkASSERT(byteLength == 0 || text != NULL);
+
+ // nothing to draw or can't draw
+ if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/
+ || fSkPaint.getRasterizer()) {
+ return;
+ }
+
+ this->init(paint, skPaint);
+
+ SkScalar sizeRatio = fTextRatio;
+
+ SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
+
+ SkAutoGlyphCacheNoGamma autoCache(fSkPaint, &fDeviceProperties, NULL);
+ SkGlyphCache* cache = autoCache.getCache();
+ GrFontScaler* fontScaler = GetGrFontScaler(cache);
+
+ setup_gamma_texture(fContext, cache, fDeviceProperties, &fGammaTexture);
+
+ // need to measure first
+ // TODO - generate positions and pre-load cache as well?
+ const char* stop = text + byteLength;
+ if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
+ SkFixed stopX = 0;
+ SkFixed stopY = 0;
+
+ const char* textPtr = text;
+ while (textPtr < stop) {
+ // don't need x, y here, since all subpixel variants will have the
+ // same advance
+ const SkGlyph& glyph = glyphCacheProc(cache, &textPtr, 0, 0);
+
+ stopX += glyph.fAdvanceX;
+ stopY += glyph.fAdvanceY;
+ }
+ SkASSERT(textPtr == stop);
+
+ SkScalar alignX = SkFixedToScalar(stopX)*sizeRatio;
+ SkScalar alignY = SkFixedToScalar(stopY)*sizeRatio;
+
+ if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
+ alignX = SkScalarHalf(alignX);
+ alignY = SkScalarHalf(alignY);
+ }
+
+ x -= alignX;
+ y -= alignY;
+ }
+
+ SkFixed fx = SkScalarToFixed(x);
+ SkFixed fy = SkScalarToFixed(y);
+ SkFixed fixedScale = SkScalarToFixed(sizeRatio);
+ while (text < stop) {
+ const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
+
+ if (glyph.fWidth) {
+ this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+ glyph.getSubXFixed(),
+ glyph.getSubYFixed()),
+ fx,
+ fy,
+ fontScaler);
+ }
+
+ fx += SkFixedMul_portable(glyph.fAdvanceX, fixedScale);
+ fy += SkFixedMul_portable(glyph.fAdvanceY, fixedScale);
+ }
+
+ this->finish();
+}
+
+void GrDistanceFieldTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPaint,
+ const char text[], size_t byteLength,
+ const SkScalar pos[], SkScalar constY,
+ int scalarsPerPosition) {
+
+ SkASSERT(byteLength == 0 || text != NULL);
+ SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
+
+ // nothing to draw
+ if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/) {
+ return;
+ }
+
+ this->init(paint, skPaint);
+
+ SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
+
+ SkAutoGlyphCacheNoGamma autoCache(fSkPaint, &fDeviceProperties, NULL);
+ SkGlyphCache* cache = autoCache.getCache();
+ GrFontScaler* fontScaler = GetGrFontScaler(cache);
+
+ setup_gamma_texture(fContext, cache, fDeviceProperties, &fGammaTexture);
+
+ const char* stop = text + byteLength;
+
+ if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
+ while (text < stop) {
+ // the last 2 parameters are ignored
+ const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
+
+ if (glyph.fWidth) {
+ SkScalar x = pos[0];
+ SkScalar y = scalarsPerPosition == 1 ? constY : pos[1];
+
+ this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+ glyph.getSubXFixed(),
+ glyph.getSubYFixed()),
+ SkScalarToFixed(x),
+ SkScalarToFixed(y),
+ fontScaler);
+ }
+ pos += scalarsPerPosition;
+ }
+ } else {
+ int alignShift = SkPaint::kCenter_Align == fSkPaint.getTextAlign() ? 1 : 0;
+ while (text < stop) {
+ // the last 2 parameters are ignored
+ const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
+
+ if (glyph.fWidth) {
+ SkScalar x = pos[0];
+ SkScalar y = scalarsPerPosition == 1 ? constY : pos[1];
+
+ this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+ glyph.getSubXFixed(),
+ glyph.getSubYFixed()),
+ SkScalarToFixed(x) - (glyph.fAdvanceX >> alignShift),
+ SkScalarToFixed(y) - (glyph.fAdvanceY >> alignShift),
+ fontScaler);
+ }
+ pos += scalarsPerPosition;
+ }
+ }
+
+ this->finish();
+}
diff --git a/chromium/third_party/skia/src/gpu/GrDistanceFieldTextContext.h b/chromium/third_party/skia/src/gpu/GrDistanceFieldTextContext.h
new file mode 100644
index 00000000000..3a602f050b3
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/GrDistanceFieldTextContext.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrDistanceFieldTextContext_DEFINED
+#define GrDistanceFieldTextContext_DEFINED
+
+#include "GrTextContext.h"
+
+class GrTextStrike;
+
+/*
+ * This class implements GrTextContext using distance field fonts
+ */
+class GrDistanceFieldTextContext : public GrTextContext {
+public:
+ GrDistanceFieldTextContext(GrContext*, const SkDeviceProperties&, bool enable);
+ virtual ~GrDistanceFieldTextContext();
+
+ virtual void drawText(const GrPaint&, const SkPaint&, const char text[], size_t byteLength,
+ SkScalar x, SkScalar y) SK_OVERRIDE;
+ virtual void drawPosText(const GrPaint&, const SkPaint&,
+ const char text[], size_t byteLength,
+ const SkScalar pos[], SkScalar constY,
+ int scalarsPerPosition) SK_OVERRIDE;
+
+ virtual bool canDraw(const SkPaint& paint) SK_OVERRIDE;
+
+private:
+ GrTextStrike* fStrike;
+ SkScalar fTextRatio;
+ bool fUseLCDText;
+ bool fEnableDFRendering;
+ GrTexture* fGammaTexture;
+
+ void init(const GrPaint&, const SkPaint&);
+ void drawPackedGlyph(GrGlyph::PackedID, SkFixed left, SkFixed top, GrFontScaler*);
+ void flushGlyphs(); // automatically called by destructor
+ void finish();
+
+ enum {
+ kMinRequestedGlyphs = 1,
+ kDefaultRequestedGlyphs = 64,
+ kMinRequestedVerts = kMinRequestedGlyphs * 4,
+ kDefaultRequestedVerts = kDefaultRequestedGlyphs * 4,
+ };
+
+ SkPoint* fVertices;
+ int32_t fMaxVertices;
+ GrTexture* fCurrTexture;
+ int fCurrVertex;
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/GrDrawState.h b/chromium/third_party/skia/src/gpu/GrDrawState.h
index 3de0b12e859..6cefd977613 100644
--- a/chromium/third_party/skia/src/gpu/GrDrawState.h
+++ b/chromium/third_party/skia/src/gpu/GrDrawState.h
@@ -13,7 +13,6 @@
#include "GrColor.h"
#include "GrEffectStage.h"
#include "GrPaint.h"
-#include "GrPoint.h"
#include "GrRenderTarget.h"
#include "GrStencil.h"
#include "GrTemplates.h"
@@ -185,20 +184,20 @@ public:
* Defaults to zero (corresponding to vertex position)
* @return pointer to the vertex component as a GrPoint
*/
- static GrPoint* GetVertexPoint(void* vertices,
+ static SkPoint* GetVertexPoint(void* vertices,
int vertexIndex,
int vertexSize,
int offset = 0) {
intptr_t start = GrTCast<intptr_t>(vertices);
- return GrTCast<GrPoint*>(start + offset +
+ return GrTCast<SkPoint*>(start + offset +
vertexIndex * vertexSize);
}
- static const GrPoint* GetVertexPoint(const void* vertices,
+ static const SkPoint* GetVertexPoint(const void* vertices,
int vertexIndex,
int vertexSize,
int offset = 0) {
intptr_t start = GrTCast<intptr_t>(vertices);
- return GrTCast<const GrPoint*>(start + offset +
+ return GrTCast<const SkPoint*>(start + offset +
vertexIndex * vertexSize);
}
@@ -412,6 +411,8 @@ public:
}
}
+ bool isSet() const { return NULL != fDrawState; }
+
private:
GrDrawState* fDrawState;
int fColorEffectCnt;
diff --git a/chromium/third_party/skia/src/gpu/GrDrawTarget.cpp b/chromium/third_party/skia/src/gpu/GrDrawTarget.cpp
index 0b4d96af84d..7cdb743a491 100644
--- a/chromium/third_party/skia/src/gpu/GrDrawTarget.cpp
+++ b/chromium/third_party/skia/src/gpu/GrDrawTarget.cpp
@@ -88,7 +88,8 @@ void GrDrawTarget::DrawInfo::adjustStartIndex(int indexOffset) {
GrDrawTarget::GrDrawTarget(GrContext* context)
: fClip(NULL)
- , fContext(context) {
+ , fContext(context)
+ , fGpuTraceMarkerCount(0) {
SkASSERT(NULL != context);
fDrawState = &fDefaultDrawState;
@@ -243,7 +244,7 @@ void GrDrawTarget::releasePreviousVertexSource() {
#endif
break;
default:
- GrCrash("Unknown Vertex Source Type.");
+ SkFAIL("Unknown Vertex Source Type.");
break;
}
}
@@ -266,7 +267,7 @@ void GrDrawTarget::releasePreviousIndexSource() {
#endif
break;
default:
- GrCrash("Unknown Index Source Type.");
+ SkFAIL("Unknown Index Source Type.");
break;
}
}
@@ -354,34 +355,34 @@ bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
int maxValidVertex;
switch (geoSrc.fVertexSrc) {
case kNone_GeometrySrcType:
- GrCrash("Attempting to draw without vertex src.");
+ SkFAIL("Attempting to draw without vertex src.");
case kReserved_GeometrySrcType: // fallthrough
case kArray_GeometrySrcType:
maxValidVertex = geoSrc.fVertexCount;
break;
case kBuffer_GeometrySrcType:
- maxValidVertex = static_cast<int>(geoSrc.fVertexBuffer->sizeInBytes() / geoSrc.fVertexSize);
+ maxValidVertex = static_cast<int>(geoSrc.fVertexBuffer->gpuMemorySize() / geoSrc.fVertexSize);
break;
}
if (maxVertex > maxValidVertex) {
- GrCrash("Drawing outside valid vertex range.");
+ SkFAIL("Drawing outside valid vertex range.");
}
if (indexCount > 0) {
int maxIndex = startIndex + indexCount;
int maxValidIndex;
switch (geoSrc.fIndexSrc) {
case kNone_GeometrySrcType:
- GrCrash("Attempting to draw indexed geom without index src.");
+ SkFAIL("Attempting to draw indexed geom without index src.");
case kReserved_GeometrySrcType: // fallthrough
case kArray_GeometrySrcType:
maxValidIndex = geoSrc.fIndexCount;
break;
case kBuffer_GeometrySrcType:
- maxValidIndex = static_cast<int>(geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t));
+ maxValidIndex = static_cast<int>(geoSrc.fIndexBuffer->gpuMemorySize() / sizeof(uint16_t));
break;
}
if (maxIndex > maxValidIndex) {
- GrCrash("Index reads outside valid index range.");
+ SkFAIL("Index reads outside valid index range.");
}
}
@@ -547,6 +548,77 @@ void GrDrawTarget::drawPath(const GrPath* path, SkPath::FillType fill) {
this->onDrawPath(path, fill, dstCopy.texture() ? &dstCopy : NULL);
}
+void GrDrawTarget::drawPaths(int pathCount, const GrPath** paths,
+ const SkMatrix* transforms,
+ SkPath::FillType fill, SkStrokeRec::Style stroke) {
+ SkASSERT(pathCount > 0);
+ SkASSERT(NULL != paths);
+ SkASSERT(NULL != paths[0]);
+ SkASSERT(this->caps()->pathRenderingSupport());
+ SkASSERT(!SkPath::IsInverseFillType(fill));
+
+ const GrDrawState* drawState = &getDrawState();
+
+ SkRect devBounds;
+ for (int i = 0; i < pathCount; ++i) {
+ SkRect mappedPathBounds;
+ transforms[i].mapRect(&mappedPathBounds, paths[i]->getBounds());
+ devBounds.join(mappedPathBounds);
+ }
+
+ SkMatrix viewM = drawState->getViewMatrix();
+ viewM.mapRect(&devBounds);
+
+ GrDeviceCoordTexture dstCopy;
+ if (!this->setupDstReadIfNecessary(&dstCopy, &devBounds)) {
+ return;
+ }
+
+ this->onDrawPaths(pathCount, paths, transforms, fill, stroke,
+ dstCopy.texture() ? &dstCopy : NULL);
+}
+
+typedef GrTraceMarkerSet::Iter TMIter;
+void GrDrawTarget::saveActiveTraceMarkers() {
+ if (this->caps()->gpuTracingSupport()) {
+ SkASSERT(0 == fStoredTraceMarkers.count());
+ fStoredTraceMarkers.addSet(fActiveTraceMarkers);
+ for (TMIter iter = fStoredTraceMarkers.begin(); iter != fStoredTraceMarkers.end(); ++iter) {
+ this->removeGpuTraceMarker(&(*iter));
+ }
+ }
+}
+
+void GrDrawTarget::restoreActiveTraceMarkers() {
+ if (this->caps()->gpuTracingSupport()) {
+ SkASSERT(0 == fActiveTraceMarkers.count());
+ for (TMIter iter = fStoredTraceMarkers.begin(); iter != fStoredTraceMarkers.end(); ++iter) {
+ this->addGpuTraceMarker(&(*iter));
+ }
+ for (TMIter iter = fActiveTraceMarkers.begin(); iter != fActiveTraceMarkers.end(); ++iter) {
+ this->fStoredTraceMarkers.remove(*iter);
+ }
+ }
+}
+
+void GrDrawTarget::addGpuTraceMarker(const GrGpuTraceMarker* marker) {
+ if (this->caps()->gpuTracingSupport()) {
+ SkASSERT(fGpuTraceMarkerCount >= 0);
+ this->fActiveTraceMarkers.add(*marker);
+ this->didAddGpuTraceMarker();
+ ++fGpuTraceMarkerCount;
+ }
+}
+
+void GrDrawTarget::removeGpuTraceMarker(const GrGpuTraceMarker* marker) {
+ if (this->caps()->gpuTracingSupport()) {
+ SkASSERT(fGpuTraceMarkerCount >= 1);
+ this->fActiveTraceMarkers.remove(*marker);
+ this->didRemoveGpuTraceMarker();
+ --fGpuTraceMarkerCount;
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
bool GrDrawTarget::willUseHWAALines() const {
@@ -602,7 +674,7 @@ void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
}
while (instanceCount) {
- info.fInstanceCount = GrMin(instanceCount, maxInstancesPerDraw);
+ info.fInstanceCount = SkTMin(instanceCount, maxInstancesPerDraw);
info.fVertexCount = info.fInstanceCount * verticesPerInstance;
info.fIndexCount = info.fInstanceCount * indicesPerInstance;
@@ -625,7 +697,7 @@ namespace {
// position + (optional) texture coord
extern const GrVertexAttrib gBWRectPosUVAttribs[] = {
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
- {kVec2f_GrVertexAttribType, sizeof(GrPoint), kLocalCoord_GrVertexAttribBinding}
+ {kVec2f_GrVertexAttribType, sizeof(SkPoint), kLocalCoord_GrVertexAttribBinding}
};
void set_vertex_attributes(GrDrawState* drawState, bool hasUVs) {
@@ -659,8 +731,8 @@ void GrDrawTarget::onDrawRect(const SkRect& rect,
size_t vsize = this->drawState()->getVertexSize();
geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize);
if (NULL != localRect) {
- GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) +
- sizeof(GrPoint));
+ SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) +
+ sizeof(SkPoint));
coords->setRectFan(localRect->fLeft, localRect->fTop,
localRect->fRight, localRect->fBottom,
vsize);
@@ -668,13 +740,10 @@ void GrDrawTarget::onDrawRect(const SkRect& rect,
localMatrix->mapPointsWithStride(coords, vsize, 4);
}
}
- SkTLazy<SkRect> bounds;
- if (this->getDrawState().willEffectReadDstColor()) {
- bounds.init();
- this->getDrawState().getViewMatrix().mapRect(bounds.get(), rect);
- }
+ SkRect bounds;
+ this->getDrawState().getViewMatrix().mapRect(&bounds, rect);
- this->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4, bounds.getMaybeNull());
+ this->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4, &bounds);
}
void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) {
@@ -961,7 +1030,7 @@ void GrDrawTarget::initCopySurfaceDstDesc(const GrSurface* src, GrTextureDesc* d
///////////////////////////////////////////////////////////////////////////////
void GrDrawTargetCaps::reset() {
- f8BitPaletteSupport = false;
+ fMipMapSupport = false;
fNPOTTextureTileSupport = false;
fTwoSidedStencilSupport = false;
fStencilWrapOpsSupport = false;
@@ -969,20 +1038,24 @@ void GrDrawTargetCaps::reset() {
fShaderDerivativeSupport = false;
fGeometryShaderSupport = false;
fDualSourceBlendingSupport = false;
- fBufferLockSupport = false;
fPathRenderingSupport = false;
fDstReadInShaderSupport = false;
+ fDiscardRenderTargetSupport = false;
fReuseScratchTextures = true;
+ fGpuTracingSupport = false;
+
+ fMapBufferFlags = kNone_MapFlags;
fMaxRenderTargetSize = 0;
fMaxTextureSize = 0;
fMaxSampleCount = 0;
memset(fConfigRenderSupport, 0, sizeof(fConfigRenderSupport));
+ memset(fConfigTextureSupport, 0, sizeof(fConfigTextureSupport));
}
GrDrawTargetCaps& GrDrawTargetCaps::operator=(const GrDrawTargetCaps& other) {
- f8BitPaletteSupport = other.f8BitPaletteSupport;
+ fMipMapSupport = other.fMipMapSupport;
fNPOTTextureTileSupport = other.fNPOTTextureTileSupport;
fTwoSidedStencilSupport = other.fTwoSidedStencilSupport;
fStencilWrapOpsSupport = other.fStencilWrapOpsSupport;
@@ -990,38 +1063,65 @@ GrDrawTargetCaps& GrDrawTargetCaps::operator=(const GrDrawTargetCaps& other) {
fShaderDerivativeSupport = other.fShaderDerivativeSupport;
fGeometryShaderSupport = other.fGeometryShaderSupport;
fDualSourceBlendingSupport = other.fDualSourceBlendingSupport;
- fBufferLockSupport = other.fBufferLockSupport;
fPathRenderingSupport = other.fPathRenderingSupport;
fDstReadInShaderSupport = other.fDstReadInShaderSupport;
+ fDiscardRenderTargetSupport = other.fDiscardRenderTargetSupport;
fReuseScratchTextures = other.fReuseScratchTextures;
+ fGpuTracingSupport = other.fGpuTracingSupport;
+
+ fMapBufferFlags = other.fMapBufferFlags;
fMaxRenderTargetSize = other.fMaxRenderTargetSize;
fMaxTextureSize = other.fMaxTextureSize;
fMaxSampleCount = other.fMaxSampleCount;
memcpy(fConfigRenderSupport, other.fConfigRenderSupport, sizeof(fConfigRenderSupport));
+ memcpy(fConfigTextureSupport, other.fConfigTextureSupport, sizeof(fConfigTextureSupport));
return *this;
}
+static SkString map_flags_to_string(uint32_t flags) {
+ SkString str;
+ if (GrDrawTargetCaps::kNone_MapFlags == flags) {
+ str = "none";
+ } else {
+ SkASSERT(GrDrawTargetCaps::kCanMap_MapFlag & flags);
+ SkDEBUGCODE(flags &= ~GrDrawTargetCaps::kCanMap_MapFlag);
+ str = "can_map";
+
+ if (GrDrawTargetCaps::kSubset_MapFlag & flags) {
+ str.append(" partial");
+ } else {
+ str.append(" full");
+ }
+ SkDEBUGCODE(flags &= ~GrDrawTargetCaps::kSubset_MapFlag);
+ }
+ SkASSERT(0 == flags); // Make sure we handled all the flags.
+ return str;
+}
+
SkString GrDrawTargetCaps::dump() const {
SkString r;
static const char* gNY[] = {"NO", "YES"};
- r.appendf("8 Bit Palette Support : %s\n", gNY[f8BitPaletteSupport]);
- r.appendf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]);
- r.appendf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]);
- r.appendf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]);
- r.appendf("HW AA Lines Support : %s\n", gNY[fHWAALineSupport]);
- r.appendf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]);
- r.appendf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]);
- r.appendf("Dual Source Blending Support: %s\n", gNY[fDualSourceBlendingSupport]);
- r.appendf("Buffer Lock Support : %s\n", gNY[fBufferLockSupport]);
- r.appendf("Path Rendering Support : %s\n", gNY[fPathRenderingSupport]);
- r.appendf("Dst Read In Shader Support : %s\n", gNY[fDstReadInShaderSupport]);
- r.appendf("Reuse Scratch Textures : %s\n", gNY[fReuseScratchTextures]);
- r.appendf("Max Texture Size : %d\n", fMaxTextureSize);
- r.appendf("Max Render Target Size : %d\n", fMaxRenderTargetSize);
- r.appendf("Max Sample Count : %d\n", fMaxSampleCount);
+ r.appendf("MIP Map Support : %s\n", gNY[fMipMapSupport]);
+ r.appendf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]);
+ r.appendf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]);
+ r.appendf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]);
+ r.appendf("HW AA Lines Support : %s\n", gNY[fHWAALineSupport]);
+ r.appendf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]);
+ r.appendf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]);
+ r.appendf("Dual Source Blending Support : %s\n", gNY[fDualSourceBlendingSupport]);
+ r.appendf("Path Rendering Support : %s\n", gNY[fPathRenderingSupport]);
+ r.appendf("Dst Read In Shader Support : %s\n", gNY[fDstReadInShaderSupport]);
+ r.appendf("Discard Render Target Support: %s\n", gNY[fDiscardRenderTargetSupport]);
+ r.appendf("Reuse Scratch Textures : %s\n", gNY[fReuseScratchTextures]);
+ r.appendf("Gpu Tracing Support : %s\n", gNY[fGpuTracingSupport]);
+ r.appendf("Max Texture Size : %d\n", fMaxTextureSize);
+ r.appendf("Max Render Target Size : %d\n", fMaxRenderTargetSize);
+ r.appendf("Max Sample Count : %d\n", fMaxSampleCount);
+
+ r.appendf("Map Buffer Support : %s\n", map_flags_to_string(fMapBufferFlags).c_str());
static const char* kConfigNames[] = {
"Unknown", // kUnknown_GrPixelConfig
@@ -1031,6 +1131,8 @@ SkString GrDrawTargetCaps::dump() const {
"RGBA444", // kRGBA_4444_GrPixelConfig,
"RGBA8888", // kRGBA_8888_GrPixelConfig,
"BGRA8888", // kBGRA_8888_GrPixelConfig,
+ "ETC1", // kETC1_GrPixelConfig,
+ "LATC", // kLATC_GrPixelConfig,
};
GR_STATIC_ASSERT(0 == kUnknown_GrPixelConfig);
GR_STATIC_ASSERT(1 == kAlpha_8_GrPixelConfig);
@@ -1039,17 +1141,27 @@ SkString GrDrawTargetCaps::dump() const {
GR_STATIC_ASSERT(4 == kRGBA_4444_GrPixelConfig);
GR_STATIC_ASSERT(5 == kRGBA_8888_GrPixelConfig);
GR_STATIC_ASSERT(6 == kBGRA_8888_GrPixelConfig);
+ GR_STATIC_ASSERT(7 == kETC1_GrPixelConfig);
+ GR_STATIC_ASSERT(8 == kLATC_GrPixelConfig);
GR_STATIC_ASSERT(SK_ARRAY_COUNT(kConfigNames) == kGrPixelConfigCnt);
SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][0]);
SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][1]);
- for (size_t i = 0; i < SK_ARRAY_COUNT(kConfigNames); ++i) {
- if (i != kUnknown_GrPixelConfig) {
- r.appendf("%s is renderable: %s, with MSAA: %s\n",
- kConfigNames[i],
- gNY[fConfigRenderSupport[i][0]],
- gNY[fConfigRenderSupport[i][1]]);
- }
+
+ for (size_t i = 1; i < SK_ARRAY_COUNT(kConfigNames); ++i) {
+ r.appendf("%s is renderable: %s, with MSAA: %s\n",
+ kConfigNames[i],
+ gNY[fConfigRenderSupport[i][0]],
+ gNY[fConfigRenderSupport[i][1]]);
+ }
+
+ SkASSERT(!fConfigTextureSupport[kUnknown_GrPixelConfig]);
+
+ for (size_t i = 1; i < SK_ARRAY_COUNT(kConfigNames); ++i) {
+ r.appendf("%s is uploadable to a texture: %s\n",
+ kConfigNames[i],
+ gNY[fConfigTextureSupport[i]]);
}
+
return r;
}
diff --git a/chromium/third_party/skia/src/gpu/GrDrawTarget.h b/chromium/third_party/skia/src/gpu/GrDrawTarget.h
index c5058699b5e..7898dfdcab6 100644
--- a/chromium/third_party/skia/src/gpu/GrDrawTarget.h
+++ b/chromium/third_party/skia/src/gpu/GrDrawTarget.h
@@ -9,12 +9,15 @@
#define GrDrawTarget_DEFINED
#include "GrClipData.h"
+#include "GrContext.h"
#include "GrDrawState.h"
#include "GrIndexBuffer.h"
+#include "GrTraceMarker.h"
#include "SkClipStack.h"
#include "SkMatrix.h"
#include "SkPath.h"
+#include "SkStrokeRec.h"
#include "SkTArray.h"
#include "SkTLazy.h"
#include "SkTypes.h"
@@ -24,7 +27,6 @@ class GrClipData;
class GrDrawTargetCaps;
class GrPath;
class GrVertexBuffer;
-class SkStrokeRec;
class GrDrawTarget : public SkRefCnt {
protected:
@@ -344,6 +346,19 @@ public:
void drawPath(const GrPath*, SkPath::FillType fill);
/**
+ * Draws many paths. It will respect the HW
+ * antialias flag on the draw state (if possible in the 3D API).
+ *
+ * @param transforms array of 2d affine transformations, one for each path.
+ * @param fill the fill type for drawing all the paths. Fill must not be a
+ * hairline.
+ * @param stroke the stroke for drawing all the paths.
+ */
+ void drawPaths(int pathCount, const GrPath** paths,
+ const SkMatrix* transforms, SkPath::FillType fill,
+ SkStrokeRec::Style stroke);
+
+ /**
* Helper function for drawing rects. It performs a geometry src push and pop
* and thus will finalize any reserved geometry.
*
@@ -423,6 +438,31 @@ public:
GrRenderTarget* renderTarget = NULL) = 0;
/**
+ * Discards the contents render target. NULL indicates that the current render target should
+ * be discarded.
+ **/
+ virtual void discard(GrRenderTarget* = NULL) = 0;
+
+ /**
+ * Called at start and end of gpu trace marking
+ * GR_CREATE_GPU_TRACE_MARKER(marker_str, target) will automatically call these at the start
+ * and end of a code block respectively
+ */
+ void addGpuTraceMarker(const GrGpuTraceMarker* marker);
+ void removeGpuTraceMarker(const GrGpuTraceMarker* marker);
+
+ /**
+ * Takes the current active set of markers and stores them for later use. Any current marker
+ * in the active set is removed from the active set and the targets remove function is called.
+ * These functions do not work as a stack so you cannot call save a second time before calling
+ * restore. Also, it is assumed that when restore is called the current active set of markers
+ * is empty. When the stored markers are added back into the active set, the targets add marker
+ * is called.
+ */
+ void saveActiveTraceMarkers();
+ void restoreActiveTraceMarkers();
+
+ /**
* Copies a pixel rectangle from one surface to another. This call may finalize
* reserved vertex/index data (as though a draw call was made). The src pixels
* copied are specified by srcRect. They are copied to a rect of the same
@@ -473,6 +513,20 @@ public:
this->onDrawPath(path, fill, dstCopy);
}
+ /**
+ * For subclass internal use to invoke a call to onDrawPaths().
+ */
+ void executeDrawPaths(int pathCount, const GrPath** paths,
+ const SkMatrix* transforms, SkPath::FillType fill,
+ SkStrokeRec::Style stroke,
+ const GrDeviceCoordTexture* dstCopy) {
+ this->onDrawPaths(pathCount, paths, transforms, fill, stroke, dstCopy);
+ }
+
+ inline bool isGpuTracingEnabled() const {
+ return this->getContext()->isGpuTracingEnabled();
+ }
+
////////////////////////////////////////////////////////////////////////////
/**
@@ -564,8 +618,8 @@ public:
bool succeeded() const { return NULL != fTarget; }
void* vertices() const { SkASSERT(this->succeeded()); return fVertices; }
void* indices() const { SkASSERT(this->succeeded()); return fIndices; }
- GrPoint* positions() const {
- return static_cast<GrPoint*>(this->vertices());
+ SkPoint* positions() const {
+ return static_cast<SkPoint*>(this->vertices());
}
private:
@@ -699,9 +753,9 @@ protected:
case kArray_GeometrySrcType:
return src.fIndexCount;
case kBuffer_GeometrySrcType:
- return static_cast<int>(src.fIndexBuffer->sizeInBytes() / sizeof(uint16_t));
+ return static_cast<int>(src.fIndexBuffer->gpuMemorySize() / sizeof(uint16_t));
default:
- GrCrash("Unexpected Index Source.");
+ SkFAIL("Unexpected Index Source.");
return 0;
}
}
@@ -749,6 +803,8 @@ protected:
// Subclass must initialize this in its constructor.
SkAutoTUnref<const GrDrawTargetCaps> fCaps;
+ const GrTraceMarkerSet& getActiveTraceMarkers() { return fActiveTraceMarkers; }
+
/**
* Used to communicate draws to subclass's onDraw function.
*/
@@ -853,6 +909,12 @@ private:
virtual void onStencilPath(const GrPath*, SkPath::FillType) = 0;
virtual void onDrawPath(const GrPath*, SkPath::FillType,
const GrDeviceCoordTexture* dstCopy) = 0;
+ virtual void onDrawPaths(int, const GrPath**, const SkMatrix*,
+ SkPath::FillType, SkStrokeRec::Style,
+ const GrDeviceCoordTexture* dstCopy) = 0;
+
+ virtual void didAddGpuTraceMarker() = 0;
+ virtual void didRemoveGpuTraceMarker() = 0;
// helpers for reserving vertex and index space.
bool reserveVertexSpace(size_t vertexSize,
@@ -888,6 +950,10 @@ private:
GrDrawState fDefaultDrawState;
// The context owns us, not vice-versa, so this ptr is not ref'ed by DrawTarget.
GrContext* fContext;
+ // To keep track that we always have at least as many debug marker adds as removes
+ int fGpuTraceMarkerCount;
+ GrTraceMarkerSet fActiveTraceMarkers;
+ GrTraceMarkerSet fStoredTraceMarkers;
typedef SkRefCnt INHERITED;
};
diff --git a/chromium/third_party/skia/src/gpu/GrDrawTargetCaps.h b/chromium/third_party/skia/src/gpu/GrDrawTargetCaps.h
index e597e099c94..dcea79e0915 100644
--- a/chromium/third_party/skia/src/gpu/GrDrawTargetCaps.h
+++ b/chromium/third_party/skia/src/gpu/GrDrawTargetCaps.h
@@ -26,17 +26,34 @@ public:
virtual void reset();
virtual SkString dump() const;
- bool eightBitPaletteSupport() const { return f8BitPaletteSupport; }
bool npotTextureTileSupport() const { return fNPOTTextureTileSupport; }
+ /** To avoid as-yet-unnecessary complexity we don't allow any partial support of MIP Maps (e.g.
+ only for POT textures) */
+ bool mipMapSupport() const { return fMipMapSupport; }
bool twoSidedStencilSupport() const { return fTwoSidedStencilSupport; }
bool stencilWrapOpsSupport() const { return fStencilWrapOpsSupport; }
bool hwAALineSupport() const { return fHWAALineSupport; }
bool shaderDerivativeSupport() const { return fShaderDerivativeSupport; }
bool geometryShaderSupport() const { return fGeometryShaderSupport; }
bool dualSourceBlendingSupport() const { return fDualSourceBlendingSupport; }
- bool bufferLockSupport() const { return fBufferLockSupport; }
bool pathRenderingSupport() const { return fPathRenderingSupport; }
bool dstReadInShaderSupport() const { return fDstReadInShaderSupport; }
+ bool discardRenderTargetSupport() const { return fDiscardRenderTargetSupport; }
+ bool gpuTracingSupport() const { return fGpuTracingSupport; }
+
+ /**
+ * Indicates whether GPU->CPU memory mapping for GPU resources such as vertex buffers and
+ * textures allows partial mappings or full mappings.
+ */
+ enum MapFlags {
+ kNone_MapFlags = 0x0, //<! Cannot map the resource.
+
+ kCanMap_MapFlag = 0x1, //<! The resource can be mapped. Must be set for any of
+ // the other flags to have meaning.k
+ kSubset_MapFlag = 0x2, //<! The resource can be partially mapped.
+ };
+
+ uint32_t mapBufferFlags() const { return fMapBufferFlags; }
// Scratch textures not being reused means that those scratch textures
// that we upload to (i.e., don't have a render target) will not be
@@ -54,19 +71,27 @@ public:
return fConfigRenderSupport[config][withMSAA];
}
+ bool isConfigTexturable(GrPixelConfig config) const {
+ SkASSERT(kGrPixelConfigCnt > config);
+ return fConfigTextureSupport[config];
+ }
+
protected:
- bool f8BitPaletteSupport : 1;
bool fNPOTTextureTileSupport : 1;
+ bool fMipMapSupport : 1;
bool fTwoSidedStencilSupport : 1;
bool fStencilWrapOpsSupport : 1;
bool fHWAALineSupport : 1;
bool fShaderDerivativeSupport : 1;
bool fGeometryShaderSupport : 1;
bool fDualSourceBlendingSupport : 1;
- bool fBufferLockSupport : 1;
bool fPathRenderingSupport : 1;
bool fDstReadInShaderSupport : 1;
+ bool fDiscardRenderTargetSupport: 1;
bool fReuseScratchTextures : 1;
+ bool fGpuTracingSupport : 1;
+
+ uint32_t fMapBufferFlags;
int fMaxRenderTargetSize;
int fMaxTextureSize;
@@ -74,6 +99,7 @@ protected:
// The first entry for each config is without msaa and the second is with.
bool fConfigRenderSupport[kGrPixelConfigCnt][2];
+ bool fConfigTextureSupport[kGrPixelConfigCnt];
typedef SkRefCnt INHERITED;
};
diff --git a/chromium/third_party/skia/src/gpu/GrGeometryBuffer.h b/chromium/third_party/skia/src/gpu/GrGeometryBuffer.h
index 3bb7118fafc..67e91cc4d90 100644
--- a/chromium/third_party/skia/src/gpu/GrGeometryBuffer.h
+++ b/chromium/third_party/skia/src/gpu/GrGeometryBuffer.h
@@ -10,14 +10,14 @@
#ifndef GrGeometryBuffer_DEFINED
#define GrGeometryBuffer_DEFINED
-#include "GrResource.h"
+#include "GrGpuObject.h"
class GrGpu;
/**
* Parent class for vertex and index buffers
*/
-class GrGeometryBuffer : public GrResource {
+class GrGeometryBuffer : public GrGpuObject {
public:
SK_DECLARE_INST_COUNT(GrGeometryBuffer);
@@ -30,74 +30,96 @@ public:
/**
* Returns true if the buffer is a wrapper around a CPU array. If true it
- * indicates that lock will always succeed and will be free.
+ * indicates that map will always succeed and will be free.
*/
bool isCPUBacked() const { return fCPUBacked; }
/**
- * Locks the buffer to be written by the CPU.
+ * Maps the buffer to be written by the CPU.
*
* The previous content of the buffer is invalidated. It is an error
- * to draw from the buffer while it is locked. It is an error to call lock
- * on an already locked buffer. It may fail if the backend doesn't support
- * locking the buffer. If the buffer is CPU backed then it will always
- * succeed and is a free operation. Must be matched by an unlock() call.
- * Currently only one lock at a time is supported (no nesting of
- * lock/unlock).
+ * to draw from the buffer while it is mapped. It is an error to call map
+ * on an already mapped buffer. It may fail if the backend doesn't support
+ * mapping the buffer. If the buffer is CPU backed then it will always
+ * succeed and is a free operation. Must be matched by an unmap() call.
+ * Currently only one map at a time is supported (no nesting of
+ * map/unmap).
*
- * @return a pointer to the data or NULL if the lock fails.
+ * Note that buffer mapping does not go through GrContext and therefore is
+ * not serialized with other operations.
+ *
+ * @return a pointer to the data or NULL if the map fails.
*/
- virtual void* lock() = 0;
+ void* map() { return (fMapPtr = this->onMap()); }
/**
- * Returns the same ptr that lock() returned at time of lock or NULL if the
- * is not locked.
+ * Unmaps the buffer.
*
- * @return ptr to locked buffer data or undefined if buffer is not locked.
+ * The pointer returned by the previous map call will no longer be valid.
*/
- virtual void* lockPtr() const = 0;
+ void unmap() {
+ SkASSERT(NULL != fMapPtr);
+ this->onUnmap();
+ fMapPtr = NULL;
+ }
/**
- * Unlocks the buffer.
+ * Returns the same ptr that map() returned at time of map or NULL if the
+ * is not mapped.
*
- * The pointer returned by the previous lock call will no longer be valid.
+ * @return ptr to mapped buffer data or NULL if buffer is not mapped.
*/
- virtual void unlock() = 0;
+ void* mapPtr() const { return fMapPtr; }
/**
- Queries whether the buffer has been locked.
+ Queries whether the buffer has been mapped.
- @return true if the buffer is locked, false otherwise.
+ @return true if the buffer is mapped, false otherwise.
*/
- virtual bool isLocked() const = 0;
+ bool isMapped() const { return NULL != fMapPtr; }
/**
* Updates the buffer data.
*
* The size of the buffer will be preserved. The src data will be
* placed at the beginning of the buffer and any remaining contents will
- * be undefined.
+ * be undefined. srcSizeInBytes must be <= to the buffer size.
+ *
+ * The buffer must not be mapped.
+ *
+ * Note that buffer updates do not go through GrContext and therefore are
+ * not serialized with other operations.
*
* @return returns true if the update succeeds, false otherwise.
*/
- virtual bool updateData(const void* src, size_t srcSizeInBytes) = 0;
+ bool updateData(const void* src, size_t srcSizeInBytes) {
+ SkASSERT(!this->isMapped());
+ SkASSERT(srcSizeInBytes <= fGpuMemorySize);
+ return this->onUpdateData(src, srcSizeInBytes);
+ }
- // GrResource overrides
- virtual size_t sizeInBytes() const { return fSizeInBytes; }
+ // GrGpuObject overrides
+ virtual size_t gpuMemorySize() const { return fGpuMemorySize; }
protected:
- GrGeometryBuffer(GrGpu* gpu, bool isWrapped, size_t sizeInBytes, bool dynamic, bool cpuBacked)
+ GrGeometryBuffer(GrGpu* gpu, bool isWrapped, size_t gpuMemorySize, bool dynamic, bool cpuBacked)
: INHERITED(gpu, isWrapped)
- , fSizeInBytes(sizeInBytes)
+ , fMapPtr(NULL)
+ , fGpuMemorySize(gpuMemorySize)
, fDynamic(dynamic)
, fCPUBacked(cpuBacked) {}
private:
- size_t fSizeInBytes;
+ virtual void* onMap() = 0;
+ virtual void onUnmap() = 0;
+ virtual bool onUpdateData(const void* src, size_t srcSizeInBytes) = 0;
+
+ void* fMapPtr;
+ size_t fGpuMemorySize;
bool fDynamic;
bool fCPUBacked;
- typedef GrResource INHERITED;
+ typedef GrGpuObject INHERITED;
};
#endif
diff --git a/chromium/third_party/skia/src/gpu/GrGpu.cpp b/chromium/third_party/skia/src/gpu/GrGpu.cpp
index af7037a7c23..fd249deb7b0 100644
--- a/chromium/third_party/skia/src/gpu/GrGpu.cpp
+++ b/chromium/third_party/skia/src/gpu/GrGpu.cpp
@@ -57,11 +57,11 @@ void GrGpu::abandonResources() {
fClipMaskManager.releaseResources();
- while (NULL != fResourceList.head()) {
- fResourceList.head()->abandon();
+ while (NULL != fObjectList.head()) {
+ fObjectList.head()->abandon();
}
- SkASSERT(NULL == fQuadIndexBuffer || !fQuadIndexBuffer->isValid());
+ SkASSERT(NULL == fQuadIndexBuffer || fQuadIndexBuffer->wasDestroyed());
SkSafeSetNull(fQuadIndexBuffer);
delete fVertexPool;
fVertexPool = NULL;
@@ -73,11 +73,11 @@ void GrGpu::releaseResources() {
fClipMaskManager.releaseResources();
- while (NULL != fResourceList.head()) {
- fResourceList.head()->release();
+ while (NULL != fObjectList.head()) {
+ fObjectList.head()->release();
}
- SkASSERT(NULL == fQuadIndexBuffer || !fQuadIndexBuffer->isValid());
+ SkASSERT(NULL == fQuadIndexBuffer || fQuadIndexBuffer->wasDestroyed());
SkSafeSetNull(fQuadIndexBuffer);
delete fVertexPool;
fVertexPool = NULL;
@@ -85,18 +85,18 @@ void GrGpu::releaseResources() {
fIndexPool = NULL;
}
-void GrGpu::insertResource(GrResource* resource) {
- SkASSERT(NULL != resource);
- SkASSERT(this == resource->getGpu());
+void GrGpu::insertObject(GrGpuObject* object) {
+ SkASSERT(NULL != object);
+ SkASSERT(this == object->getGpu());
- fResourceList.addToHead(resource);
+ fObjectList.addToHead(object);
}
-void GrGpu::removeResource(GrResource* resource) {
- SkASSERT(NULL != resource);
- SkASSERT(this == resource->getGpu());
+void GrGpu::removeObject(GrGpuObject* object) {
+ SkASSERT(NULL != object);
+ SkASSERT(this == object->getGpu());
- fResourceList.remove(resource);
+ fObjectList.remove(object);
}
@@ -110,25 +110,40 @@ void GrGpu::unimpl(const char msg[]) {
GrTexture* GrGpu::createTexture(const GrTextureDesc& desc,
const void* srcData, size_t rowBytes) {
- if (kUnknown_GrPixelConfig == desc.fConfig) {
+ if (!this->caps()->isConfigTexturable(desc.fConfig)) {
return NULL;
}
+
if ((desc.fFlags & kRenderTarget_GrTextureFlagBit) &&
!this->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
return NULL;
}
- this->handleDirtyContext();
- GrTexture* tex = this->onCreateTexture(desc, srcData, rowBytes);
- if (NULL != tex &&
- (kRenderTarget_GrTextureFlagBit & desc.fFlags) &&
- !(kNoStencil_GrTextureFlagBit & desc.fFlags)) {
- SkASSERT(NULL != tex->asRenderTarget());
- // TODO: defer this and attach dynamically
- if (!this->attachStencilBufferToRenderTarget(tex->asRenderTarget())) {
- tex->unref();
+ GrTexture *tex = NULL;
+ if (GrPixelConfigIsCompressed(desc.fConfig)) {
+ // We shouldn't be rendering into this
+ SkASSERT((desc.fFlags & kRenderTarget_GrTextureFlagBit) == 0);
+
+ if (!this->caps()->npotTextureTileSupport() &&
+ (!SkIsPow2(desc.fWidth) || !SkIsPow2(desc.fHeight))) {
return NULL;
}
+
+ this->handleDirtyContext();
+ tex = this->onCreateCompressedTexture(desc, srcData);
+ } else {
+ this->handleDirtyContext();
+ tex = this->onCreateTexture(desc, srcData, rowBytes);
+ if (NULL != tex &&
+ (kRenderTarget_GrTextureFlagBit & desc.fFlags) &&
+ !(kNoStencil_GrTextureFlagBit & desc.fFlags)) {
+ SkASSERT(NULL != tex->asRenderTarget());
+ // TODO: defer this and attach dynamically
+ if (!this->attachStencilBufferToRenderTarget(tex->asRenderTarget())) {
+ tex->unref();
+ return NULL;
+ }
+ }
}
return tex;
}
@@ -219,11 +234,6 @@ void GrGpu::clear(const SkIRect* rect,
this->onClear(rect, color, canIgnoreRect);
}
-void GrGpu::forceRenderTargetFlush() {
- this->handleDirtyContext();
- this->onForceRenderTargetFlush();
-}
-
bool GrGpu::readPixels(GrRenderTarget* target,
int left, int top, int width, int height,
GrPixelConfig config, void* buffer,
@@ -270,7 +280,7 @@ void GrGpu::getPathStencilSettingsForFillType(SkPath::FillType fill, GrStencilSe
switch (fill) {
default:
- GrCrash("Unexpected path fill.");
+ SkFAIL("Unexpected path fill.");
/* fallthrough */;
case SkPath::kWinding_FillType:
case SkPath::kInverseWinding_FillType:
@@ -308,17 +318,17 @@ const GrIndexBuffer* GrGpu::getQuadIndexBuffer() const {
GrGpu* me = const_cast<GrGpu*>(this);
fQuadIndexBuffer = me->createIndexBuffer(SIZE, false);
if (NULL != fQuadIndexBuffer) {
- uint16_t* indices = (uint16_t*)fQuadIndexBuffer->lock();
+ uint16_t* indices = (uint16_t*)fQuadIndexBuffer->map();
if (NULL != indices) {
fill_indices(indices, MAX_QUADS);
- fQuadIndexBuffer->unlock();
+ fQuadIndexBuffer->unmap();
} else {
indices = (uint16_t*)sk_malloc_throw(SIZE);
fill_indices(indices, MAX_QUADS);
if (!fQuadIndexBuffer->updateData(indices, SIZE)) {
fQuadIndexBuffer->unref();
fQuadIndexBuffer = NULL;
- GrCrash("Can't get indices into buffer!");
+ SkFAIL("Can't get indices into buffer!");
}
sk_free(indices);
}
@@ -331,8 +341,9 @@ const GrIndexBuffer* GrGpu::getQuadIndexBuffer() const {
////////////////////////////////////////////////////////////////////////////////
bool GrGpu::setupClipAndFlushState(DrawType type, const GrDeviceCoordTexture* dstCopy,
- GrDrawState::AutoRestoreEffects* are) {
- if (!fClipMaskManager.setupClipping(this->getClip(), are)) {
+ GrDrawState::AutoRestoreEffects* are,
+ const SkRect* devBounds) {
+ if (!fClipMaskManager.setupClipping(this->getClip(), are, devBounds)) {
return false;
}
@@ -376,8 +387,7 @@ void GrGpu::onDraw(const DrawInfo& info) {
this->handleDirtyContext();
GrDrawState::AutoRestoreEffects are;
if (!this->setupClipAndFlushState(PrimTypeToDrawType(info.primitiveType()),
- info.getDstCopy(),
- &are)) {
+ info.getDstCopy(), &are, info.getDevBounds())) {
return;
}
this->onGpuDraw(info);
@@ -387,7 +397,7 @@ void GrGpu::onStencilPath(const GrPath* path, SkPath::FillType fill) {
this->handleDirtyContext();
GrDrawState::AutoRestoreEffects are;
- if (!this->setupClipAndFlushState(kStencilPath_DrawType, NULL, &are)) {
+ if (!this->setupClipAndFlushState(kStencilPath_DrawType, NULL, &are, NULL)) {
return;
}
@@ -402,21 +412,37 @@ void GrGpu::onDrawPath(const GrPath* path, SkPath::FillType fill,
drawState()->setDefaultVertexAttribs();
GrDrawState::AutoRestoreEffects are;
- if (!this->setupClipAndFlushState(kDrawPath_DrawType, dstCopy, &are)) {
+ if (!this->setupClipAndFlushState(kDrawPath_DrawType, dstCopy, &are, NULL)) {
return;
}
this->onGpuDrawPath(path, fill);
}
+void GrGpu::onDrawPaths(int pathCount, const GrPath** paths,
+ const SkMatrix* transforms, SkPath::FillType fill,
+ SkStrokeRec::Style style,
+ const GrDeviceCoordTexture* dstCopy) {
+ this->handleDirtyContext();
+
+ drawState()->setDefaultVertexAttribs();
+
+ GrDrawState::AutoRestoreEffects are;
+ if (!this->setupClipAndFlushState(kDrawPaths_DrawType, dstCopy, &are, NULL)) {
+ return;
+ }
+
+ this->onGpuDrawPaths(pathCount, paths, transforms, fill, style);
+}
+
void GrGpu::finalizeReservedVertices() {
SkASSERT(NULL != fVertexPool);
- fVertexPool->unlock();
+ fVertexPool->unmap();
}
void GrGpu::finalizeReservedIndices() {
SkASSERT(NULL != fIndexPool);
- fIndexPool->unlock();
+ fIndexPool->unmap();
}
void GrGpu::prepareVertexPool() {
diff --git a/chromium/third_party/skia/src/gpu/GrGpu.h b/chromium/third_party/skia/src/gpu/GrGpu.h
index f9028b95fb6..cd7502e18ac 100644
--- a/chromium/third_party/skia/src/gpu/GrGpu.h
+++ b/chromium/third_party/skia/src/gpu/GrGpu.h
@@ -13,11 +13,11 @@
#include "SkPath.h"
class GrContext;
+class GrGpuObject;
class GrIndexBufferAllocPool;
class GrPath;
class GrPathRenderer;
class GrPathRendererChain;
-class GrResource;
class GrStencilBuffer;
class GrVertexBufferAllocPool;
@@ -71,15 +71,26 @@ public:
* two but underlying API requires a power of two texture then srcData
* will be embedded in a power of two texture. The extra width and height
* is filled as though srcData were rendered clamped into the texture.
+ * The exception is when using compressed data formats. In this case, the
+ * desc width and height must be a multiple of the compressed format block
+ * size otherwise this function returns NULL. Similarly, if the underlying
+ * API requires a power of two texture and the source width and height are not
+ * a power of two, then this function returns NULL.
*
* If kRenderTarget_TextureFlag is specified the GrRenderTarget is
* accessible via GrTexture::asRenderTarget(). The texture will hold a ref
- * on the render target until the texture is destroyed.
+ * on the render target until the texture is destroyed. Compressed textures
+ * cannot have the kRenderTarget_TextureFlag set.
*
* @param desc describes the texture to be created.
* @param srcData texel data to load texture. Begins with full-size
- * palette data for paletted textures. Contains width*
- * height texels. If NULL texture data is uninitialized.
+ * palette data for paletted textures. For compressed
+ * formats it contains the compressed pixel data. Otherwise,
+ * it contains width*height texels. If NULL texture data
+ * is uninitialized.
+ * @param rowBytes the number of bytes between consecutive rows. Zero
+ * means rows are tightly packed. This field is ignored
+ * for compressed formats.
*
* @return The texture object if successful, otherwise NULL.
*/
@@ -101,8 +112,8 @@ public:
*
* @param size size in bytes of the vertex buffer
* @param dynamic hints whether the data will be frequently changed
- * by either GrVertexBuffer::lock or
- * GrVertexBuffer::updateData.
+ * by either GrVertexBuffer::map() or
+ * GrVertexBuffer::updateData().
*
* @return The vertex buffer if successful, otherwise NULL.
*/
@@ -113,8 +124,8 @@ public:
*
* @param size size in bytes of the index buffer
* @param dynamic hints whether the data will be frequently changed
- * by either GrIndexBuffer::lock or
- * GrIndexBuffer::updateData.
+ * by either GrIndexBuffer::map() or
+ * GrIndexBuffer::updateData().
*
* @return The index buffer if successful, otherwise NULL.
*/
@@ -141,13 +152,6 @@ public:
void resolveRenderTarget(GrRenderTarget* target);
/**
- * Ensures that the current render target is actually set in the
- * underlying 3D API. Used when client wants to use 3D API to directly
- * render to the RT.
- */
- void forceRenderTargetFlush();
-
- /**
* Gets a preferred 8888 config to use for writing/reading pixel data to/from a surface with
* config surfaceConfig. The returned config must have at least as many bits per channel as the
* readConfig or writeConfig param.
@@ -238,29 +242,28 @@ public:
size_t rowBytes);
/**
- * Called to tell Gpu object that all GrResources have been lost and should
+ * Called to tell GrGpu that all GrGpuObjects have been lost and should
* be abandoned. Overrides must call INHERITED::abandonResources().
*/
virtual void abandonResources();
/**
- * Called to tell Gpu object to release all GrResources. Overrides must call
+ * Called to tell GrGpu to release all GrGpuObjects. Overrides must call
* INHERITED::releaseResources().
*/
void releaseResources();
/**
- * Add resource to list of resources. Should only be called by GrResource.
+ * Add object to list of objects. Should only be called by GrGpuObject.
* @param resource the resource to add.
*/
- void insertResource(GrResource* resource);
+ void insertObject(GrGpuObject* object);
/**
- * Remove resource from list of resources. Should only be called by
- * GrResource.
+ * Remove object from list of objects. Should only be called by GrGpuObject.
* @param resource the resource to remove.
*/
- void removeResource(GrResource* resource);
+ void removeObject(GrGpuObject* object);
// GrDrawTarget overrides
virtual void clear(const SkIRect* rect,
@@ -330,15 +333,16 @@ public:
void getPathStencilSettingsForFillType(SkPath::FillType fill, GrStencilSettings* outStencilSettings);
-protected:
enum DrawType {
kDrawPoints_DrawType,
kDrawLines_DrawType,
kDrawTriangles_DrawType,
kStencilPath_DrawType,
kDrawPath_DrawType,
+ kDrawPaths_DrawType,
};
+protected:
DrawType PrimTypeToDrawType(GrPrimitiveType type) {
switch (type) {
case kTriangles_GrPrimitiveType:
@@ -351,7 +355,7 @@ protected:
case kLineStrip_GrPrimitiveType:
return kDrawLines_DrawType;
default:
- GrCrash("Unexpected primitive type");
+ SkFAIL("Unexpected primitive type");
return kDrawTriangles_DrawType;
}
}
@@ -359,7 +363,8 @@ protected:
// prepares clip flushes gpu state before a draw
bool setupClipAndFlushState(DrawType,
const GrDeviceCoordTexture* dstCopy,
- GrDrawState::AutoRestoreEffects* are);
+ GrDrawState::AutoRestoreEffects* are,
+ const SkRect* devBounds);
// Functions used to map clip-respecting stencil tests into normal
// stencil funcs supported by GPUs.
@@ -420,6 +425,8 @@ private:
virtual GrTexture* onCreateTexture(const GrTextureDesc& desc,
const void* srcData,
size_t rowBytes) = 0;
+ virtual GrTexture* onCreateCompressedTexture(const GrTextureDesc& desc,
+ const void* srcData) = 0;
virtual GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&) = 0;
virtual GrRenderTarget* onWrapBackendRenderTarget(const GrBackendRenderTargetDesc&) = 0;
virtual GrVertexBuffer* onCreateVertexBuffer(size_t size, bool dynamic) = 0;
@@ -437,9 +444,8 @@ private:
// overridden by backend-specific derived class to perform the path stenciling.
virtual void onGpuStencilPath(const GrPath*, SkPath::FillType) = 0;
virtual void onGpuDrawPath(const GrPath*, SkPath::FillType) = 0;
-
- // overridden by backend-specific derived class to perform flush
- virtual void onForceRenderTargetFlush() = 0;
+ virtual void onGpuDrawPaths(int, const GrPath**, const SkMatrix*,
+ SkPath::FillType, SkStrokeRec::Style) = 0;
// overridden by backend-specific derived class to perform the read pixels.
virtual bool onReadPixels(GrRenderTarget* target,
@@ -482,6 +488,9 @@ private:
virtual void onStencilPath(const GrPath*, SkPath::FillType) SK_OVERRIDE;
virtual void onDrawPath(const GrPath*, SkPath::FillType,
const GrDeviceCoordTexture* dstCopy) SK_OVERRIDE;
+ virtual void onDrawPaths(int, const GrPath**, const SkMatrix*,
+ SkPath::FillType, SkStrokeRec::Style,
+ const GrDeviceCoordTexture* dstCopy) SK_OVERRIDE;
// readies the pools to provide vertex/index data.
void prepareVertexPool();
@@ -506,7 +515,7 @@ private:
enum {
kPreallocGeomPoolStateStackCnt = 4,
};
- typedef SkTInternalLList<GrResource> ResourceList;
+ typedef SkTInternalLList<GrGpuObject> ObjectList;
SkSTArray<kPreallocGeomPoolStateStackCnt, GeometryPoolState, true> fGeomPoolStateStack;
ResetTimestamp fResetTimestamp;
uint32_t fResetBits;
@@ -519,7 +528,7 @@ private:
mutable GrIndexBuffer* fQuadIndexBuffer;
// Used to abandon/release all resources created by this GrGpu. TODO: Move this
// functionality to GrResourceCache.
- ResourceList fResourceList;
+ ObjectList fObjectList;
typedef GrDrawTarget INHERITED;
};
diff --git a/chromium/third_party/skia/src/gpu/GrResource.cpp b/chromium/third_party/skia/src/gpu/GrGpuObject.cpp
index e20a30ffd39..43a86f2d51b 100644
--- a/chromium/third_party/skia/src/gpu/GrResource.cpp
+++ b/chromium/third_party/skia/src/gpu/GrGpuObject.cpp
@@ -7,44 +7,43 @@
*/
-#include "GrResource.h"
+#include "GrGpuObject.h"
#include "GrGpu.h"
-GrResource::GrResource(GrGpu* gpu, bool isWrapped) {
+GrGpuObject::GrGpuObject(GrGpu* gpu, bool isWrapped) {
fGpu = gpu;
- fCacheEntry = NULL;
fDeferredRefCount = 0;
if (isWrapped) {
fFlags = kWrapped_FlagBit;
} else {
fFlags = 0;
}
- fGpu->insertResource(this);
+ fGpu->insertObject(this);
}
-GrResource::~GrResource() {
+GrGpuObject::~GrGpuObject() {
// subclass should have released this.
SkASSERT(0 == fDeferredRefCount);
- SkASSERT(!this->isValid());
+ SkASSERT(this->wasDestroyed());
}
-void GrResource::release() {
+void GrGpuObject::release() {
if (NULL != fGpu) {
this->onRelease();
- fGpu->removeResource(this);
+ fGpu->removeObject(this);
fGpu = NULL;
}
}
-void GrResource::abandon() {
+void GrGpuObject::abandon() {
if (NULL != fGpu) {
this->onAbandon();
- fGpu->removeResource(this);
+ fGpu->removeObject(this);
fGpu = NULL;
}
}
-const GrContext* GrResource::getContext() const {
+const GrContext* GrGpuObject::getContext() const {
if (NULL != fGpu) {
return fGpu->getContext();
} else {
@@ -52,7 +51,7 @@ const GrContext* GrResource::getContext() const {
}
}
-GrContext* GrResource::getContext() {
+GrContext* GrGpuObject::getContext() {
if (NULL != fGpu) {
return fGpu->getContext();
} else {
diff --git a/chromium/third_party/skia/src/gpu/GrInOrderDrawBuffer.cpp b/chromium/third_party/skia/src/gpu/GrInOrderDrawBuffer.cpp
index 669167c419b..deea72b90d9 100644
--- a/chromium/third_party/skia/src/gpu/GrInOrderDrawBuffer.cpp
+++ b/chromium/third_party/skia/src/gpu/GrInOrderDrawBuffer.cpp
@@ -9,10 +9,10 @@
#include "GrBufferAllocPool.h"
#include "GrDrawTargetCaps.h"
+#include "GrTextStrike.h"
#include "GrGpu.h"
#include "GrIndexBuffer.h"
#include "GrPath.h"
-#include "GrPoint.h"
#include "GrRenderTarget.h"
#include "GrTemplates.h"
#include "GrTexture.h"
@@ -62,13 +62,13 @@ void get_vertex_bounds(const void* vertices,
size_t vertexSize,
int vertexCount,
SkRect* bounds) {
- SkASSERT(vertexSize >= sizeof(GrPoint));
+ SkASSERT(vertexSize >= sizeof(SkPoint));
SkASSERT(vertexCount > 0);
- const GrPoint* point = static_cast<const GrPoint*>(vertices);
+ const SkPoint* point = static_cast<const SkPoint*>(vertices);
bounds->fLeft = bounds->fRight = point->fX;
bounds->fTop = bounds->fBottom = point->fY;
for (int i = 1; i < vertexCount; ++i) {
- point = reinterpret_cast<GrPoint*>(reinterpret_cast<intptr_t>(point) + vertexSize);
+ point = reinterpret_cast<SkPoint*>(reinterpret_cast<intptr_t>(point) + vertexSize);
bounds->growToInclude(point->fX, point->fY);
}
}
@@ -79,14 +79,14 @@ namespace {
extern const GrVertexAttrib kRectPosColorUVAttribs[] = {
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
- {kVec4ub_GrVertexAttribType, sizeof(GrPoint), kColor_GrVertexAttribBinding},
- {kVec2f_GrVertexAttribType, sizeof(GrPoint)+sizeof(GrColor),
+ {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding},
+ {kVec2f_GrVertexAttribType, sizeof(SkPoint)+sizeof(GrColor),
kLocalCoord_GrVertexAttribBinding},
};
extern const GrVertexAttrib kRectPosUVAttribs[] = {
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
- {kVec2f_GrVertexAttribType, sizeof(GrPoint), kLocalCoord_GrVertexAttribBinding},
+ {kVec2f_GrVertexAttribType, sizeof(SkPoint), kLocalCoord_GrVertexAttribBinding},
};
static void set_vertex_attributes(GrDrawState* drawState,
@@ -102,14 +102,14 @@ static void set_vertex_attributes(GrDrawState* drawState,
// dual-source blending isn't available. This comes into play when there is coverage. If colors
// were a stage it could take a hint that every vertex's color will be opaque.
if (hasColor && hasUVs) {
- *colorOffset = sizeof(GrPoint);
- *localOffset = sizeof(GrPoint) + sizeof(GrColor);
+ *colorOffset = sizeof(SkPoint);
+ *localOffset = sizeof(SkPoint) + sizeof(GrColor);
drawState->setVertexAttribs<kRectPosColorUVAttribs>(3);
} else if (hasColor) {
- *colorOffset = sizeof(GrPoint);
+ *colorOffset = sizeof(SkPoint);
drawState->setVertexAttribs<kRectPosColorUVAttribs>(2);
} else if (hasUVs) {
- *localOffset = sizeof(GrPoint);
+ *localOffset = sizeof(SkPoint);
drawState->setVertexAttribs<kRectPosUVAttribs>(2);
} else {
drawState->setVertexAttribs<kRectPosUVAttribs>(1);
@@ -118,6 +118,23 @@ static void set_vertex_attributes(GrDrawState* drawState,
};
+enum {
+ kTraceCmdBit = 0x80,
+ kCmdMask = 0x7f,
+};
+
+static uint8_t add_trace_bit(uint8_t cmd) {
+ return cmd | kTraceCmdBit;
+}
+
+static uint8_t strip_trace_bit(uint8_t cmd) {
+ return cmd & kCmdMask;
+}
+
+static bool cmd_has_trace_marker(uint8_t cmd) {
+ return SkToBool(cmd & kTraceCmdBit);
+}
+
void GrInOrderDrawBuffer::onDrawRect(const SkRect& rect,
const SkMatrix* matrix,
const SkRect* localRect,
@@ -175,7 +192,7 @@ void GrInOrderDrawBuffer::onDrawRect(const SkRect& rect,
get_vertex_bounds(geo.vertices(), vsize, 4, &devBounds);
if (localOffset >= 0) {
- GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) + localOffset);
+ SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) + localOffset);
coords->setRectFan(localRect->fLeft, localRect->fTop,
localRect->fRight, localRect->fBottom,
vsize);
@@ -256,7 +273,7 @@ int GrInOrderDrawBuffer::concatInstancedDraw(const DrawInfo& info) {
}
// Check if there is a draw info that is compatible that uses the same VB from the pool and
// the same IB
- if (kDraw_Cmd != fCmds.back()) {
+ if (kDraw_Cmd != strip_trace_bit(fCmds.back())) {
return 0;
}
@@ -283,14 +300,25 @@ int GrInOrderDrawBuffer::concatInstancedDraw(const DrawInfo& info) {
// how many instances can be concat'ed onto draw given the size of the index buffer
int instancesToConcat = this->indexCountInCurrentSource() / info.indicesPerInstance();
instancesToConcat -= draw->instanceCount();
- instancesToConcat = GrMin(instancesToConcat, info.instanceCount());
+ instancesToConcat = SkTMin(instancesToConcat, info.instanceCount());
// update the amount of reserved vertex data actually referenced in draws
size_t vertexBytes = instancesToConcat * info.verticesPerInstance() *
drawState.getVertexSize();
- poolState.fUsedPoolVertexBytes = GrMax(poolState.fUsedPoolVertexBytes, vertexBytes);
+ poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, vertexBytes);
draw->adjustInstanceCount(instancesToConcat);
+
+ // update last fGpuCmdMarkers to include any additional trace markers that have been added
+ if (this->getActiveTraceMarkers().count() > 0) {
+ if (cmd_has_trace_marker(fCmds.back())) {
+ fGpuCmdMarkers.back().addSet(this->getActiveTraceMarkers());
+ } else {
+ fGpuCmdMarkers.push_back(this->getActiveTraceMarkers());
+ fCmds.back() = add_trace_bit(fCmds.back());
+ }
+ }
+
return instancesToConcat;
}
@@ -352,13 +380,13 @@ void GrInOrderDrawBuffer::onDraw(const DrawInfo& info) {
case kArray_GeometrySrcType: {
size_t vertexBytes = (info.vertexCount() + info.startVertex()) *
drawState.getVertexSize();
- poolState.fUsedPoolVertexBytes = GrMax(poolState.fUsedPoolVertexBytes, vertexBytes);
+ poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, vertexBytes);
draw->fVertexBuffer = poolState.fPoolVertexBuffer;
draw->adjustStartVertex(poolState.fPoolStartVertex);
break;
}
default:
- GrCrash("unknown geom src type");
+ SkFAIL("unknown geom src type");
}
draw->fVertexBuffer->ref();
@@ -370,13 +398,13 @@ void GrInOrderDrawBuffer::onDraw(const DrawInfo& info) {
case kReserved_GeometrySrcType: // fallthrough
case kArray_GeometrySrcType: {
size_t indexBytes = (info.indexCount() + info.startIndex()) * sizeof(uint16_t);
- poolState.fUsedPoolIndexBytes = GrMax(poolState.fUsedPoolIndexBytes, indexBytes);
+ poolState.fUsedPoolIndexBytes = SkTMax(poolState.fUsedPoolIndexBytes, indexBytes);
draw->fIndexBuffer = poolState.fPoolIndexBuffer;
draw->adjustStartIndex(poolState.fPoolStartIndex);
break;
}
default:
- GrCrash("unknown geom src type");
+ SkFAIL("unknown geom src type");
}
draw->fIndexBuffer->ref();
} else {
@@ -386,6 +414,16 @@ void GrInOrderDrawBuffer::onDraw(const DrawInfo& info) {
GrInOrderDrawBuffer::StencilPath::StencilPath() {}
GrInOrderDrawBuffer::DrawPath::DrawPath() {}
+GrInOrderDrawBuffer::DrawPaths::DrawPaths() {}
+GrInOrderDrawBuffer::DrawPaths::~DrawPaths() {
+ if (fTransforms) {
+ SkDELETE_ARRAY(fTransforms);
+ }
+ for (int i = 0; i < fPathCount; ++i) {
+ fPaths[i]->unref();
+ }
+ SkDELETE_ARRAY(fPaths);
+}
void GrInOrderDrawBuffer::onStencilPath(const GrPath* path, SkPath::FillType fill) {
if (this->needsNewClip()) {
@@ -419,6 +457,38 @@ void GrInOrderDrawBuffer::onDrawPath(const GrPath* path,
}
}
+void GrInOrderDrawBuffer::onDrawPaths(int pathCount, const GrPath** paths,
+ const SkMatrix* transforms,
+ SkPath::FillType fill,
+ SkStrokeRec::Style stroke,
+ const GrDeviceCoordTexture* dstCopy) {
+ SkASSERT(pathCount);
+
+ if (this->needsNewClip()) {
+ this->recordClip();
+ }
+ if (this->needsNewState()) {
+ this->recordState();
+ }
+ DrawPaths* dp = this->recordDrawPaths();
+ dp->fPathCount = pathCount;
+ dp->fPaths = SkNEW_ARRAY(const GrPath*, pathCount);
+ memcpy(dp->fPaths, paths, sizeof(GrPath*) * pathCount);
+ for (int i = 0; i < pathCount; ++i) {
+ dp->fPaths[i]->ref();
+ }
+
+ dp->fTransforms = SkNEW_ARRAY(SkMatrix, pathCount);
+ memcpy(dp->fTransforms, transforms, sizeof(SkMatrix) * pathCount);
+
+ dp->fFill = fill;
+ dp->fStroke = stroke;
+
+ if (NULL != dstCopy) {
+ dp->fDstCopy = *dstCopy;
+ }
+}
+
void GrInOrderDrawBuffer::clear(const SkIRect* rect, GrColor color,
bool canIgnoreRect, GrRenderTarget* renderTarget) {
SkIRect r;
@@ -434,6 +504,7 @@ void GrInOrderDrawBuffer::clear(const SkIRect* rect, GrColor color,
rect = &r;
}
Clear* clr = this->recordClear();
+ GrColorIsPMAssert(color);
clr->fColor = color;
clr->fRect = *rect;
clr->fCanIgnoreRect = canIgnoreRect;
@@ -441,6 +512,20 @@ void GrInOrderDrawBuffer::clear(const SkIRect* rect, GrColor color,
renderTarget->ref();
}
+void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
+ if (!this->caps()->discardRenderTargetSupport()) {
+ return;
+ }
+ if (NULL == renderTarget) {
+ renderTarget = this->drawState()->getRenderTarget();
+ SkASSERT(NULL != renderTarget);
+ }
+ Clear* clr = this->recordClear();
+ clr->fColor = GrColor_ILLEGAL;
+ clr->fRenderTarget = renderTarget;
+ renderTarget->ref();
+}
+
void GrInOrderDrawBuffer::reset() {
SkASSERT(1 == fGeoPoolStateStack.count());
this->resetVertexSource();
@@ -455,6 +540,7 @@ void GrInOrderDrawBuffer::reset() {
fCmds.reset();
fDraws.reset();
fStencilPaths.reset();
+ fDrawPath.reset();
fDrawPaths.reset();
fStates.reset();
fClears.reset();
@@ -463,6 +549,7 @@ void GrInOrderDrawBuffer::reset() {
fClips.reset();
fClipOrigins.reset();
fCopySurfaces.reset();
+ fGpuCmdMarkers.reset();
fClipSet = true;
}
@@ -471,6 +558,8 @@ void GrInOrderDrawBuffer::flush() {
return;
}
+ this->getContext()->getFontCache()->updateTextures();
+
SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fVertexSrc);
SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fIndexSrc);
@@ -482,8 +571,8 @@ void GrInOrderDrawBuffer::flush() {
GrAutoTRestore<bool> flushRestore(&fFlushing);
fFlushing = true;
- fVertexPool.unlock();
- fIndexPool.unlock();
+ fVertexPool.unmap();
+ fIndexPool.unmap();
GrDrawTarget::AutoClipRestore acr(fDstGpu);
AutoGeometryAndStatePush agasp(fDstGpu, kPreserve_ASRInit);
@@ -501,10 +590,20 @@ void GrInOrderDrawBuffer::flush() {
int currDraw = 0;
int currStencilPath = 0;
int currDrawPath = 0;
+ int currDrawPaths = 0;
int currCopySurface = 0;
+ int currCmdMarker = 0;
+ fDstGpu->saveActiveTraceMarkers();
for (int c = 0; c < numCmds; ++c) {
- switch (fCmds[c]) {
+ GrGpuTraceMarker newMarker("", -1);
+ if (cmd_has_trace_marker(fCmds[c])) {
+ SkString traceString = fGpuCmdMarkers[currCmdMarker].toString();
+ newMarker.fMarker = traceString.c_str();
+ fDstGpu->addGpuTraceMarker(&newMarker);
+ ++currCmdMarker;
+ }
+ switch (strip_trace_bit(fCmds[c])) {
case kDraw_Cmd: {
const DrawRecord& draw = fDraws[currDraw];
fDstGpu->setVertexSourceToBuffer(draw.fVertexBuffer);
@@ -512,7 +611,6 @@ void GrInOrderDrawBuffer::flush() {
fDstGpu->setIndexSourceToBuffer(draw.fIndexBuffer);
}
fDstGpu->executeDraw(draw);
-
++currDraw;
break;
}
@@ -523,12 +621,22 @@ void GrInOrderDrawBuffer::flush() {
break;
}
case kDrawPath_Cmd: {
- const DrawPath& cp = fDrawPaths[currDrawPath];
+ const DrawPath& cp = fDrawPath[currDrawPath];
fDstGpu->executeDrawPath(cp.fPath.get(), cp.fFill,
NULL != cp.fDstCopy.texture() ? &cp.fDstCopy : NULL);
++currDrawPath;
break;
}
+ case kDrawPaths_Cmd: {
+ DrawPaths& dp = fDrawPaths[currDrawPaths];
+ const GrDeviceCoordTexture* dstCopy =
+ NULL != dp.fDstCopy.texture() ? &dp.fDstCopy : NULL;
+ fDstGpu->executeDrawPaths(dp.fPathCount, dp.fPaths,
+ dp.fTransforms, dp.fFill, dp.fStroke,
+ dstCopy);
+ ++currDrawPaths;
+ break;
+ }
case kSetState_Cmd:
fStates[currState].restoreTo(&playbackState);
++currState;
@@ -540,10 +648,14 @@ void GrInOrderDrawBuffer::flush() {
++currClip;
break;
case kClear_Cmd:
- fDstGpu->clear(&fClears[currClear].fRect,
- fClears[currClear].fColor,
- fClears[currClear].fCanIgnoreRect,
- fClears[currClear].fRenderTarget);
+ if (GrColor_ILLEGAL == fClears[currClear].fColor) {
+ fDstGpu->discard(fClears[currClear].fRenderTarget);
+ } else {
+ fDstGpu->clear(&fClears[currClear].fRect,
+ fClears[currClear].fColor,
+ fClears[currClear].fCanIgnoreRect,
+ fClears[currClear].fRenderTarget);
+ }
++currClear;
break;
case kCopySurface_Cmd:
@@ -554,7 +666,11 @@ void GrInOrderDrawBuffer::flush() {
++currCopySurface;
break;
}
+ if (cmd_has_trace_marker(fCmds[c])) {
+ fDstGpu->removeGpuTraceMarker(&newMarker);
+ }
}
+ fDstGpu->restoreActiveTraceMarkers();
// we should have consumed all the states, clips, etc.
SkASSERT(fStates.count() == currState);
SkASSERT(fClips.count() == currClip);
@@ -562,6 +678,7 @@ void GrInOrderDrawBuffer::flush() {
SkASSERT(fClears.count() == currClear);
SkASSERT(fDraws.count() == currDraw);
SkASSERT(fCopySurfaces.count() == currCopySurface);
+ SkASSERT(fGpuCmdMarkers.count() == currCmdMarker);
fDstGpu->setDrawState(prevDrawState);
prevDrawState->unref();
@@ -817,40 +934,56 @@ bool GrInOrderDrawBuffer::needsNewClip() const {
return false;
}
+void GrInOrderDrawBuffer::addToCmdBuffer(uint8_t cmd) {
+ SkASSERT(!cmd_has_trace_marker(cmd));
+ const GrTraceMarkerSet& activeTraceMarkers = this->getActiveTraceMarkers();
+ if (activeTraceMarkers.count() > 0) {
+ fCmds.push_back(add_trace_bit(cmd));
+ fGpuCmdMarkers.push_back(activeTraceMarkers);
+ } else {
+ fCmds.push_back(cmd);
+ }
+}
+
void GrInOrderDrawBuffer::recordClip() {
- fClips.push_back() = *this->getClip()->fClipStack;
+ fClips.push_back(*this->getClip()->fClipStack);
fClipOrigins.push_back() = this->getClip()->fOrigin;
fClipSet = false;
- fCmds.push_back(kSetClip_Cmd);
+ this->addToCmdBuffer(kSetClip_Cmd);
}
void GrInOrderDrawBuffer::recordState() {
fStates.push_back().saveFrom(this->getDrawState());
- fCmds.push_back(kSetState_Cmd);
+ this->addToCmdBuffer(kSetState_Cmd);
}
GrInOrderDrawBuffer::DrawRecord* GrInOrderDrawBuffer::recordDraw(const DrawInfo& info) {
- fCmds.push_back(kDraw_Cmd);
+ this->addToCmdBuffer(kDraw_Cmd);
return &fDraws.push_back(info);
}
GrInOrderDrawBuffer::StencilPath* GrInOrderDrawBuffer::recordStencilPath() {
- fCmds.push_back(kStencilPath_Cmd);
+ this->addToCmdBuffer(kStencilPath_Cmd);
return &fStencilPaths.push_back();
}
GrInOrderDrawBuffer::DrawPath* GrInOrderDrawBuffer::recordDrawPath() {
- fCmds.push_back(kDrawPath_Cmd);
+ this->addToCmdBuffer(kDrawPath_Cmd);
+ return &fDrawPath.push_back();
+}
+
+GrInOrderDrawBuffer::DrawPaths* GrInOrderDrawBuffer::recordDrawPaths() {
+ this->addToCmdBuffer(kDrawPaths_Cmd);
return &fDrawPaths.push_back();
}
GrInOrderDrawBuffer::Clear* GrInOrderDrawBuffer::recordClear() {
- fCmds.push_back(kClear_Cmd);
+ this->addToCmdBuffer(kClear_Cmd);
return &fClears.push_back();
}
GrInOrderDrawBuffer::CopySurface* GrInOrderDrawBuffer::recordCopySurface() {
- fCmds.push_back(kCopySurface_Cmd);
+ this->addToCmdBuffer(kCopySurface_Cmd);
return &fCopySurfaces.push_back();
}
diff --git a/chromium/third_party/skia/src/gpu/GrInOrderDrawBuffer.h b/chromium/third_party/skia/src/gpu/GrInOrderDrawBuffer.h
index 6b680b2d555..34fb0a7cff5 100644
--- a/chromium/third_party/skia/src/gpu/GrInOrderDrawBuffer.h
+++ b/chromium/third_party/skia/src/gpu/GrInOrderDrawBuffer.h
@@ -72,7 +72,9 @@ public:
virtual void clear(const SkIRect* rect,
GrColor color,
bool canIgnoreRect,
- GrRenderTarget* renderTarget = NULL) SK_OVERRIDE;
+ GrRenderTarget* renderTarget) SK_OVERRIDE;
+
+ virtual void discard(GrRenderTarget*) SK_OVERRIDE;
virtual void initCopySurfaceDstDesc(const GrSurface* src, GrTextureDesc* desc) SK_OVERRIDE;
@@ -88,6 +90,7 @@ private:
kClear_Cmd = 5,
kCopySurface_Cmd = 6,
kDrawPath_Cmd = 7,
+ kDrawPaths_Cmd = 8,
};
class DrawRecord : public DrawInfo {
@@ -112,6 +115,19 @@ private:
GrDeviceCoordTexture fDstCopy;
};
+ struct DrawPaths : public ::SkNoncopyable {
+ DrawPaths();
+ ~DrawPaths();
+
+ int fPathCount;
+ const GrPath** fPaths;
+ SkMatrix* fTransforms;
+ SkPath::FillType fFill;
+ SkStrokeRec::Style fStroke;
+ GrDeviceCoordTexture fDstCopy;
+ };
+
+ // This is also used to record a discard by setting the color to GrColor_ILLEGAL
struct Clear : public ::SkNoncopyable {
Clear() : fRenderTarget(NULL) {}
~Clear() { SkSafeUnref(fRenderTarget); }
@@ -139,6 +155,9 @@ private:
virtual void onStencilPath(const GrPath*, SkPath::FillType) SK_OVERRIDE;
virtual void onDrawPath(const GrPath*, SkPath::FillType,
const GrDeviceCoordTexture* dstCopy) SK_OVERRIDE;
+ virtual void onDrawPaths(int, const GrPath**, const SkMatrix*,
+ SkPath::FillType, SkStrokeRec::Style,
+ const GrDeviceCoordTexture* dstCopy) SK_OVERRIDE;
virtual bool onReserveVertexSpace(size_t vertexSize,
int vertexCount,
@@ -168,6 +187,9 @@ private:
bool quickInsideClip(const SkRect& devBounds);
+ virtual void didAddGpuTraceMarker() SK_OVERRIDE {}
+ virtual void didRemoveGpuTraceMarker() SK_OVERRIDE {}
+
// Attempts to concat instances from info onto the previous draw. info must represent an
// instanced draw. The caller must have already recorded a new draw state and clip if necessary.
int concatInstancedDraw(const DrawInfo& info);
@@ -183,6 +205,7 @@ private:
DrawRecord* recordDraw(const DrawInfo&);
StencilPath* recordStencilPath();
DrawPath* recordDrawPath();
+ DrawPaths* recordDrawPaths();
Clear* recordClear();
CopySurface* recordCopySurface();
@@ -192,6 +215,7 @@ private:
kDrawPreallocCnt = 8,
kStencilPathPreallocCnt = 8,
kDrawPathPreallocCnt = 8,
+ kDrawPathsPreallocCnt = 8,
kStatePreallocCnt = 8,
kClipPreallocCnt = 8,
kClearPreallocCnt = 4,
@@ -201,13 +225,15 @@ private:
SkSTArray<kCmdPreallocCnt, uint8_t, true> fCmds;
GrSTAllocator<kDrawPreallocCnt, DrawRecord> fDraws;
- GrSTAllocator<kStatePreallocCnt, StencilPath> fStencilPaths;
- GrSTAllocator<kStatePreallocCnt, DrawPath> fDrawPaths;
+ GrSTAllocator<kStencilPathPreallocCnt, StencilPath> fStencilPaths;
+ GrSTAllocator<kDrawPathPreallocCnt, DrawPath> fDrawPath;
+ GrSTAllocator<kDrawPathsPreallocCnt, DrawPaths> fDrawPaths;
GrSTAllocator<kStatePreallocCnt, GrDrawState::DeferredState> fStates;
GrSTAllocator<kClearPreallocCnt, Clear> fClears;
GrSTAllocator<kCopySurfacePreallocCnt, CopySurface> fCopySurfaces;
GrSTAllocator<kClipPreallocCnt, SkClipStack> fClips;
GrSTAllocator<kClipPreallocCnt, SkIPoint> fClipOrigins;
+ SkTArray<GrTraceMarkerSet, false> fGpuCmdMarkers;
GrDrawTarget* fDstGpu;
@@ -240,6 +266,8 @@ private:
virtual bool isIssued(uint32_t drawID) { return drawID != fDrawID; }
+ void addToCmdBuffer(uint8_t cmd);
+
bool fFlushing;
uint32_t fDrawID;
diff --git a/chromium/third_party/skia/src/gpu/GrIndexBuffer.h b/chromium/third_party/skia/src/gpu/GrIndexBuffer.h
index e23bc9b19ac..113b89d3070 100644
--- a/chromium/third_party/skia/src/gpu/GrIndexBuffer.h
+++ b/chromium/third_party/skia/src/gpu/GrIndexBuffer.h
@@ -21,11 +21,11 @@ public:
* @return the maximum number of quads using full size of index buffer.
*/
int maxQuads() const {
- return static_cast<int>(this->sizeInBytes() / (sizeof(uint16_t) * 6));
+ return static_cast<int>(this->gpuMemorySize() / (sizeof(uint16_t) * 6));
}
protected:
- GrIndexBuffer(GrGpu* gpu, bool isWrapped, size_t sizeInBytes, bool dynamic, bool cpuBacked)
- : INHERITED(gpu, isWrapped, sizeInBytes, dynamic, cpuBacked) {}
+ GrIndexBuffer(GrGpu* gpu, bool isWrapped, size_t gpuMemorySize, bool dynamic, bool cpuBacked)
+ : INHERITED(gpu, isWrapped, gpuMemorySize, dynamic, cpuBacked) {}
private:
typedef GrGeometryBuffer INHERITED;
};
diff --git a/chromium/third_party/skia/src/gpu/GrLayerCache.cpp b/chromium/third_party/skia/src/gpu/GrLayerCache.cpp
new file mode 100644
index 00000000000..f6377bf7e92
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/GrLayerCache.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrAtlas.h"
+#include "GrGpu.h"
+#include "GrLayerCache.h"
+
+/**
+ * PictureLayerKey just wraps a saveLayer's id in the picture for GrTHashTable.
+ */
+class GrLayerCache::PictureLayerKey {
+public:
+ PictureLayerKey(uint32_t pictureID, int layerID)
+ : fPictureID(pictureID)
+ , fLayerID(layerID) {
+ }
+
+ uint32_t pictureID() const { return fPictureID; }
+ int layerID() const { return fLayerID; }
+
+ uint32_t getHash() const { return (fPictureID << 16) | fLayerID; }
+
+ static bool LessThan(const GrCachedLayer& layer, const PictureLayerKey& key) {
+ if (layer.pictureID() == key.pictureID()) {
+ return layer.layerID() < key.layerID();
+ }
+
+ return layer.pictureID() < key.pictureID();
+ }
+
+ static bool Equals(const GrCachedLayer& layer, const PictureLayerKey& key) {
+ return layer.pictureID() == key.pictureID() && layer.layerID() == key.layerID();
+ }
+
+private:
+ uint32_t fPictureID;
+ int fLayerID;
+};
+
+GrLayerCache::GrLayerCache(GrGpu* gpu)
+ : fGpu(SkRef(gpu))
+ , fLayerPool(16) { // TODO: may need to increase this later
+}
+
+GrLayerCache::~GrLayerCache() {
+}
+
+void GrLayerCache::init() {
+ static const int kAtlasTextureWidth = 1024;
+ static const int kAtlasTextureHeight = 1024;
+
+ SkASSERT(NULL == fAtlasMgr.get());
+
+ // The layer cache only gets 1 plot
+ SkISize textureSize = SkISize::Make(kAtlasTextureWidth, kAtlasTextureHeight);
+ fAtlasMgr.reset(SkNEW_ARGS(GrAtlasMgr, (fGpu, kSkia8888_GrPixelConfig,
+ textureSize, 1, 1, false)));
+}
+
+void GrLayerCache::freeAll() {
+ fLayerHash.deleteAll();
+ fAtlasMgr.free();
+}
+
+GrCachedLayer* GrLayerCache::createLayer(const SkPicture* picture, int layerID) {
+ GrCachedLayer* layer = fLayerPool.alloc();
+
+ SkASSERT(picture->uniqueID() != SK_InvalidGenID);
+ layer->init(picture->uniqueID(), layerID);
+ fLayerHash.insert(PictureLayerKey(picture->uniqueID(), layerID), layer);
+ return layer;
+}
+
+
+GrCachedLayer* GrLayerCache::findLayerOrCreate(const SkPicture* picture, int layerID) {
+ SkASSERT(picture->uniqueID() != SK_InvalidGenID);
+ GrCachedLayer* layer = fLayerHash.find(PictureLayerKey(picture->uniqueID(), layerID));
+ if (NULL == layer) {
+ layer = this->createLayer(picture, layerID);
+ }
+ return layer;
+}
diff --git a/chromium/third_party/skia/src/gpu/GrLayerCache.h b/chromium/third_party/skia/src/gpu/GrLayerCache.h
new file mode 100644
index 00000000000..a957e78013e
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/GrLayerCache.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrLayerCache_DEFINED
+#define GrLayerCache_DEFINED
+
+#include "GrAllocPool.h"
+#include "GrTHashTable.h"
+#include "GrPictureUtils.h"
+#include "GrRect.h"
+
+class GrAtlasMgr;
+class GrGpu;
+class GrPlot;
+class SkPicture;
+
+// GrAtlasLocation captures an atlased item's position in the atlas. This
+// means the plot in which it resides and its bounds inside the plot.
+// TODO: Make GrGlyph use one of these?
+class GrAtlasLocation {
+public:
+ GrAtlasLocation() : fPlot(NULL) {}
+
+ void set(GrPlot* plot, const GrIRect16& bounds) {
+ fPlot = plot;
+ fBounds = bounds;
+ }
+
+ const GrPlot* plot() const {
+ return fPlot;
+ }
+
+ const GrIRect16& bounds() const {
+ return fBounds;
+ }
+
+private:
+ GrPlot* fPlot;
+ GrIRect16 fBounds; // only valid is fPlot != NULL
+};
+
+// GrCachedLayer encapsulates the caching information for a single saveLayer.
+//
+// Atlased layers get a ref to their atlas GrTexture and their GrAtlasLocation
+// is filled in.
+// In this case GrCachedLayer is roughly equivalent to a GrGlyph in the font
+// caching system.
+//
+// Non-atlased layers get a ref to the GrTexture in which they reside.
+// TODO: can we easily reuse the empty space in the non-atlased GrTexture's?
+struct GrCachedLayer {
+public:
+ uint32_t pictureID() const { return fPictureID; }
+ int layerID() const { return fLayerID; }
+
+ void init(uint32_t pictureID, int layerID) {
+ fPictureID = pictureID;
+ fLayerID = layerID;
+ fTexture = NULL;
+ fLocation.set(NULL, GrIRect16::MakeEmpty());
+ }
+
+ // This call takes over the caller's ref
+ void setTexture(GrTexture* texture) {
+ if (NULL != fTexture) {
+ fTexture->unref();
+ }
+
+ fTexture = texture; // just take over caller's ref
+ }
+ GrTexture* getTexture() { return fTexture; }
+
+private:
+ uint32_t fPictureID;
+ // fLayerID is only valid when fPicture != kInvalidGenID in which case it
+ // is the index of this layer in the picture (one of 0 .. #layers).
+ int fLayerID;
+
+ // fTexture is a ref on the atlasing texture for atlased layers and a
+ // ref on a GrTexture for non-atlased textures. In both cases, if this is
+ // non-NULL, that means that the texture is locked in the texture cache.
+ GrTexture* fTexture;
+
+ GrAtlasLocation fLocation; // only valid if the layer is atlased
+};
+
+// The GrLayerCache caches pre-computed saveLayers for later rendering.
+// Non-atlased layers are stored in their own GrTexture while the atlased
+// layers share a single GrTexture.
+// Unlike the GrFontCache, the GrTexture atlas only has one GrAtlasMgr (for 8888)
+// and one GrPlot (for the entire atlas). As such, the GrLayerCache
+// roughly combines the functionality of the GrFontCache and GrTextStrike
+// classes.
+class GrLayerCache {
+public:
+ GrLayerCache(GrGpu*);
+ ~GrLayerCache();
+
+ void freeAll();
+
+ GrCachedLayer* findLayerOrCreate(const SkPicture* picture, int id);
+
+private:
+ SkAutoTUnref<GrGpu> fGpu;
+ SkAutoTDelete<GrAtlasMgr> fAtlasMgr; // TODO: could lazily allocate
+
+ class PictureLayerKey;
+ GrTHashTable<GrCachedLayer, PictureLayerKey, 7> fLayerHash;
+ GrTAllocPool<GrCachedLayer> fLayerPool;
+
+ void init();
+ GrCachedLayer* createLayer(const SkPicture* picture, int id);
+
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/GrMemory.cpp b/chromium/third_party/skia/src/gpu/GrMemory.cpp
deleted file mode 100644
index bf96b0bc310..00000000000
--- a/chromium/third_party/skia/src/gpu/GrMemory.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-
-/*
- * Copyright 2010 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-
-#include <stdlib.h>
-#include "GrTypes.h"
-
-void* GrMalloc(size_t bytes) {
- void* ptr = ::malloc(bytes);
- if (NULL == ptr) {
- ::exit(-1);
- }
- return ptr;
-}
-
-void GrFree(void* ptr) {
- if (ptr) {
- ::free(ptr);
- }
-}
diff --git a/chromium/third_party/skia/src/gpu/GrMemoryPool.cpp b/chromium/third_party/skia/src/gpu/GrMemoryPool.cpp
index 75a3c9a3b9c..8839c66d07c 100644
--- a/chromium/third_party/skia/src/gpu/GrMemoryPool.cpp
+++ b/chromium/third_party/skia/src/gpu/GrMemoryPool.cpp
@@ -16,10 +16,10 @@
GrMemoryPool::GrMemoryPool(size_t preallocSize, size_t minAllocSize) {
SkDEBUGCODE(fAllocationCnt = 0);
- minAllocSize = GrMax<size_t>(minAllocSize, 1 << 10);
+ minAllocSize = SkTMax<size_t>(minAllocSize, 1 << 10);
fMinAllocSize = GrSizeAlignUp(minAllocSize + kPerAllocPad, kAlignment),
fPreallocSize = GrSizeAlignUp(preallocSize + kPerAllocPad, kAlignment);
- fPreallocSize = GrMax(fPreallocSize, fMinAllocSize);
+ fPreallocSize = SkTMax(fPreallocSize, fMinAllocSize);
fHead = CreateBlock(fPreallocSize);
fTail = fHead;
@@ -42,7 +42,7 @@ void* GrMemoryPool::allocate(size_t size) {
size += kPerAllocPad;
if (fTail->fFreeSize < size) {
size_t blockSize = size;
- blockSize = GrMax<size_t>(blockSize, fMinAllocSize);
+ blockSize = SkTMax<size_t>(blockSize, fMinAllocSize);
BlockHeader* block = CreateBlock(blockSize);
block->fPrev = fTail;
diff --git a/chromium/third_party/skia/src/gpu/GrOrderedSet.h b/chromium/third_party/skia/src/gpu/GrOrderedSet.h
new file mode 100644
index 00000000000..23b9353a516
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/GrOrderedSet.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrOrderedSet_DEFINED
+#define GrOrderedSet_DEFINED
+
+#include "GrRedBlackTree.h"
+
+template <typename T, typename C = GrLess<T> >
+class GrOrderedSet : SkNoncopyable {
+public:
+ /**
+ * Creates an empty set
+ */
+ GrOrderedSet() : fComp() {}
+ ~GrOrderedSet() {}
+
+ class Iter;
+
+ /**
+ * @return true if there are no items in the set, false otherwise.
+ */
+ bool empty() const { return fRBTree.empty(); }
+
+ /**
+ * @return the number of items in the set.
+ */
+ int count() const { return fRBTree.count(); }
+
+ /**
+ * Removes all items in the set
+ */
+ void reset() { fRBTree.reset(); }
+
+ /**
+ * Adds an element to set if it does not already exists in the set.
+ * @param t the item to add
+ * @return an iterator to added element or matching element already in set
+ */
+ Iter insert(const T& t);
+
+ /**
+ * Removes the item indicated by an iterator. The iterator will not be valid
+ * afterwards.
+ * @param iter iterator of item to remove. Must be valid (not end()).
+ */
+ void remove(const Iter& iter);
+
+ /**
+ * @return an iterator to the first item in sorted order, or end() if empty
+ */
+ Iter begin();
+
+ /**
+ * Gets the last valid iterator. This is always valid, even on an empty.
+ * However, it can never be dereferenced. Useful as a loop terminator.
+ * @return an iterator that is just beyond the last item in sorted order.
+ */
+ Iter end();
+
+ /**
+ * @return an iterator that to the last item in sorted order, or end() if
+ * empty.
+ */
+ Iter last();
+
+ /**
+ * Finds an occurrence of an item.
+ * @param t the item to find.
+ * @return an iterator to a set element equal to t or end() if none exists.
+ */
+ Iter find(const T& t);
+
+private:
+ GrRedBlackTree<T, C> fRBTree;
+
+ const C fComp;
+};
+
+template <typename T, typename C>
+class GrOrderedSet<T,C>::Iter {
+public:
+ Iter() {}
+ Iter(const Iter& i) { fTreeIter = i.fTreeIter; }
+ Iter& operator =(const Iter& i) {
+ fTreeIter = i.fTreeIter;
+ return *this;
+ }
+ const T& operator *() const { return *fTreeIter; }
+ bool operator ==(const Iter& i) const {
+ return fTreeIter == i.fTreeIter;
+ }
+ bool operator !=(const Iter& i) const { return !(*this == i); }
+ Iter& operator ++() {
+ ++fTreeIter;
+ return *this;
+ }
+ Iter& operator --() {
+ --fTreeIter;
+ return *this;
+ }
+ const typename GrRedBlackTree<T,C>::Iter& getTreeIter() const {
+ return fTreeIter;
+ }
+
+private:
+ friend class GrOrderedSet;
+ explicit Iter(typename GrRedBlackTree<T, C>::Iter iter) {
+ fTreeIter = iter;
+ }
+ typename GrRedBlackTree<T,C>::Iter fTreeIter;
+};
+
+template <typename T, typename C>
+typename GrOrderedSet<T,C>::Iter GrOrderedSet<T,C>::begin() {
+ return Iter(fRBTree.begin());
+}
+
+template <typename T, typename C>
+typename GrOrderedSet<T,C>::Iter GrOrderedSet<T,C>::end() {
+ return Iter(fRBTree.end());
+}
+
+template <typename T, typename C>
+typename GrOrderedSet<T,C>::Iter GrOrderedSet<T,C>::last() {
+ return Iter(fRBTree.last());
+}
+
+template <typename T, typename C>
+typename GrOrderedSet<T,C>::Iter GrOrderedSet<T,C>::find(const T& t) {
+ return Iter(fRBTree.find(t));
+}
+
+template <typename T, typename C>
+typename GrOrderedSet<T,C>::Iter GrOrderedSet<T,C>::insert(const T& t) {
+ if (fRBTree.find(t) == fRBTree.end()) {
+ return Iter(fRBTree.insert(t));
+ } else {
+ return Iter(fRBTree.find(t));
+ }
+}
+
+template <typename T, typename C>
+void GrOrderedSet<T,C>::remove(const typename GrOrderedSet<T,C>::Iter& iter) {
+ if (this->end() != iter) {
+ fRBTree.remove(iter.getTreeIter());
+ }
+}
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/GrOvalRenderer.cpp b/chromium/third_party/skia/src/gpu/GrOvalRenderer.cpp
index ac33a5cc5d9..8a76646b5b1 100644
--- a/chromium/third_party/skia/src/gpu/GrOvalRenderer.cpp
+++ b/chromium/third_party/skia/src/gpu/GrOvalRenderer.cpp
@@ -19,29 +19,31 @@
#include "SkRRect.h"
#include "SkStrokeRec.h"
+#include "SkTLazy.h"
#include "effects/GrVertexEffect.h"
+#include "effects/GrRRectEffect.h"
namespace {
struct CircleVertex {
- GrPoint fPos;
- GrPoint fOffset;
+ SkPoint fPos;
+ SkPoint fOffset;
SkScalar fOuterRadius;
SkScalar fInnerRadius;
};
struct EllipseVertex {
- GrPoint fPos;
- GrPoint fOffset;
- GrPoint fOuterRadii;
- GrPoint fInnerRadii;
+ SkPoint fPos;
+ SkPoint fOffset;
+ SkPoint fOuterRadii;
+ SkPoint fInnerRadii;
};
struct DIEllipseVertex {
- GrPoint fPos;
- GrPoint fOuterOffset;
- GrPoint fInnerOffset;
+ SkPoint fPos;
+ SkPoint fOuterOffset;
+ SkPoint fInnerOffset;
};
inline bool circle_stays_circle(const SkMatrix& m) {
@@ -230,9 +232,7 @@ public:
builder->fsCodeAppend("\tfloat test = dot(scaledOffset, scaledOffset) - 1.0;\n");
builder->fsCodeAppendf("\tvec2 grad = 2.0*scaledOffset*%s.xy;\n", fsRadiiName);
builder->fsCodeAppend("\tfloat grad_dot = dot(grad, grad);\n");
- // we need to clamp the length^2 of the gradiant vector to a non-zero value, because
- // on the Nexus 4 the undefined result of inversesqrt(0) drops out an entire tile
- // TODO: restrict this to Adreno-only
+ // avoid calling inversesqrt on zero.
builder->fsCodeAppend("\tgrad_dot = max(grad_dot, 1.0e-4);\n");
builder->fsCodeAppend("\tfloat invlen = inversesqrt(grad_dot);\n");
builder->fsCodeAppend("\tfloat edgeAlpha = clamp(0.5-test*invlen, 0.0, 1.0);\n");
@@ -378,9 +378,7 @@ public:
fsOffsetName0, fsOffsetName0, fsOffsetName0, fsOffsetName0);
builder->fsCodeAppend("\tfloat grad_dot = dot(grad, grad);\n");
- // we need to clamp the length^2 of the gradiant vector to a non-zero value, because
- // on the Nexus 4 the undefined result of inversesqrt(0) drops out an entire tile
- // TODO: restrict this to Adreno-only
+ // avoid calling inversesqrt on zero.
builder->fsCodeAppend("\tgrad_dot = max(grad_dot, 1.0e-4);\n");
builder->fsCodeAppend("\tfloat invlen = inversesqrt(grad_dot);\n");
if (kHairline == ellipseEffect.getMode()) {
@@ -490,7 +488,7 @@ bool GrOvalRenderer::drawOval(GrDrawTarget* target, const GrContext* context, bo
// position + edge
extern const GrVertexAttrib gCircleVertexAttribs[] = {
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
- {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}
+ {kVec4f_GrVertexAttribType, sizeof(SkPoint), kEffect_GrVertexAttribBinding}
};
void GrOvalRenderer::drawCircle(GrDrawTarget* target,
@@ -501,7 +499,7 @@ void GrOvalRenderer::drawCircle(GrDrawTarget* target,
GrDrawState* drawState = target->drawState();
const SkMatrix& vm = drawState->getViewMatrix();
- GrPoint center = GrPoint::Make(circle.centerX(), circle.centerY());
+ SkPoint center = SkPoint::Make(circle.centerX(), circle.centerY());
vm.mapPoints(&center, 1);
SkScalar radius = vm.mapRadius(SkScalarHalf(circle.width()));
SkScalar strokeWidth = vm.mapRadius(stroke.getWidth());
@@ -523,12 +521,14 @@ void GrOvalRenderer::drawCircle(GrDrawTarget* target,
CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices());
SkStrokeRec::Style style = stroke.getStyle();
- bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style);
+ bool isStrokeOnly = SkStrokeRec::kStroke_Style == style ||
+ SkStrokeRec::kHairline_Style == style;
+ bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style;
SkScalar innerRadius = 0.0f;
SkScalar outerRadius = radius;
SkScalar halfWidth = 0;
- if (style != SkStrokeRec::kFill_Style) {
+ if (hasStroke) {
if (SkScalarNearlyZero(strokeWidth)) {
halfWidth = SK_ScalarHalf;
} else {
@@ -536,12 +536,12 @@ void GrOvalRenderer::drawCircle(GrDrawTarget* target,
}
outerRadius += halfWidth;
- if (isStroked) {
+ if (isStrokeOnly) {
innerRadius = radius - halfWidth;
}
}
- GrEffectRef* effect = CircleEdgeEffect::Create(isStroked && innerRadius > 0);
+ GrEffectRef* effect = CircleEdgeEffect::Create(isStrokeOnly && innerRadius > 0);
static const int kCircleEdgeAttrIndex = 1;
drawState->addCoverageEffect(effect, kCircleEdgeAttrIndex)->unref();
@@ -587,15 +587,15 @@ void GrOvalRenderer::drawCircle(GrDrawTarget* target,
// position + offset + 1/radii
extern const GrVertexAttrib gEllipseVertexAttribs[] = {
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
- {kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding},
- {kVec4f_GrVertexAttribType, 2*sizeof(GrPoint), kEffect_GrVertexAttribBinding}
+ {kVec2f_GrVertexAttribType, sizeof(SkPoint), kEffect_GrVertexAttribBinding},
+ {kVec4f_GrVertexAttribType, 2*sizeof(SkPoint), kEffect_GrVertexAttribBinding}
};
// position + offsets
extern const GrVertexAttrib gDIEllipseVertexAttribs[] = {
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
- {kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding},
- {kVec2f_GrVertexAttribType, 2*sizeof(GrPoint), kEffect_GrVertexAttribBinding},
+ {kVec2f_GrVertexAttribType, sizeof(SkPoint), kEffect_GrVertexAttribBinding},
+ {kVec2f_GrVertexAttribType, 2*sizeof(SkPoint), kEffect_GrVertexAttribBinding},
};
bool GrOvalRenderer::drawEllipse(GrDrawTarget* target,
@@ -614,7 +614,7 @@ bool GrOvalRenderer::drawEllipse(GrDrawTarget* target,
// do any matrix crunching before we reset the draw state for device coords
const SkMatrix& vm = drawState->getViewMatrix();
- GrPoint center = GrPoint::Make(ellipse.centerX(), ellipse.centerY());
+ SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY());
vm.mapPoints(&center, 1);
SkScalar ellipseXRadius = SkScalarHalf(ellipse.width());
SkScalar ellipseYRadius = SkScalarHalf(ellipse.height());
@@ -630,11 +630,13 @@ bool GrOvalRenderer::drawEllipse(GrDrawTarget* target,
scaledStroke.fY = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMSkewX] + vm[SkMatrix::kMScaleY]));
SkStrokeRec::Style style = stroke.getStyle();
- bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style);
+ bool isStrokeOnly = SkStrokeRec::kStroke_Style == style ||
+ SkStrokeRec::kHairline_Style == style;
+ bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style;
SkScalar innerXRadius = 0;
SkScalar innerYRadius = 0;
- if (SkStrokeRec::kFill_Style != style) {
+ if (hasStroke) {
if (SkScalarNearlyZero(scaledStroke.length())) {
scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf);
} else {
@@ -654,7 +656,7 @@ bool GrOvalRenderer::drawEllipse(GrDrawTarget* target,
}
// this is legit only if scale & translation (which should be the case at the moment)
- if (isStroked) {
+ if (isStrokeOnly) {
innerXRadius = xRadius - scaledStroke.fX;
innerYRadius = yRadius - scaledStroke.fY;
}
@@ -679,7 +681,7 @@ bool GrOvalRenderer::drawEllipse(GrDrawTarget* target,
EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices());
- GrEffectRef* effect = EllipseEdgeEffect::Create(isStroked &&
+ GrEffectRef* effect = EllipseEdgeEffect::Create(isStrokeOnly &&
innerXRadius > 0 && innerYRadius > 0);
static const int kEllipseCenterAttrIndex = 1;
@@ -738,7 +740,7 @@ bool GrOvalRenderer::drawDIEllipse(GrDrawTarget* target,
GrDrawState* drawState = target->drawState();
const SkMatrix& vm = drawState->getViewMatrix();
- GrPoint center = GrPoint::Make(ellipse.centerX(), ellipse.centerY());
+ SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY());
SkScalar xRadius = SkScalarHalf(ellipse.width());
SkScalar yRadius = SkScalarHalf(ellipse.height());
@@ -881,9 +883,69 @@ GrIndexBuffer* GrOvalRenderer::rRectIndexBuffer(GrGpu* gpu) {
return fRRectIndexBuffer;
}
-bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, bool useAA,
- const SkRRect& rrect, const SkStrokeRec& stroke)
-{
+bool GrOvalRenderer::drawDRRect(GrDrawTarget* target, GrContext* context, bool useAA,
+ const SkRRect& origOuter, const SkRRect& origInner) {
+ bool applyAA = useAA &&
+ !target->getDrawState().getRenderTarget()->isMultisampled() &&
+ !target->shouldDisableCoverageAAForBlend();
+ GrDrawState::AutoRestoreEffects are;
+ if (!origInner.isEmpty()) {
+ SkTCopyOnFirstWrite<SkRRect> inner(origInner);
+ if (!context->getMatrix().isIdentity()) {
+ if (!origInner.transform(context->getMatrix(), inner.writable())) {
+ return false;
+ }
+ }
+ GrEffectEdgeType edgeType = applyAA ? kInverseFillAA_GrEffectEdgeType :
+ kInverseFillBW_GrEffectEdgeType;
+ GrEffectRef* effect = GrRRectEffect::Create(edgeType, *inner);
+ if (NULL == effect) {
+ return false;
+ }
+ are.set(target->drawState());
+ target->drawState()->addCoverageEffect(effect)->unref();
+ }
+
+ SkStrokeRec fillRec(SkStrokeRec::kFill_InitStyle);
+ if (this->drawRRect(target, context, useAA, origOuter, fillRec)) {
+ return true;
+ }
+
+ SkASSERT(!origOuter.isEmpty());
+ SkTCopyOnFirstWrite<SkRRect> outer(origOuter);
+ if (!context->getMatrix().isIdentity()) {
+ if (!origOuter.transform(context->getMatrix(), outer.writable())) {
+ return false;
+ }
+ }
+ GrEffectEdgeType edgeType = applyAA ? kFillAA_GrEffectEdgeType :
+ kFillBW_GrEffectEdgeType;
+ GrEffectRef* effect = GrRRectEffect::Create(edgeType, *outer);
+ if (NULL == effect) {
+ return false;
+ }
+ if (!are.isSet()) {
+ are.set(target->drawState());
+ }
+ GrDrawState::AutoViewMatrixRestore avmr;
+ if (!avmr.setIdentity(target->drawState())) {
+ return false;
+ }
+ target->drawState()->addCoverageEffect(effect)->unref();
+ SkRect bounds = outer->getBounds();
+ if (applyAA) {
+ bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
+ }
+ target->drawRect(bounds, NULL, NULL, NULL);
+ return true;
+}
+
+bool GrOvalRenderer::drawRRect(GrDrawTarget* target, GrContext* context, bool useAA,
+ const SkRRect& rrect, const SkStrokeRec& stroke) {
+ if (rrect.isOval()) {
+ return this->drawOval(target, context, useAA, rrect.getBounds(), stroke);
+ }
+
bool useCoverageAA = useAA &&
!target->getDrawState().getRenderTarget()->isMultisampled() &&
!target->shouldDisableCoverageAAForBlend();
@@ -894,12 +956,10 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b
}
const SkMatrix& vm = context->getMatrix();
-#ifdef SK_DEBUG
- {
- // we should have checked for this previously
- SkASSERT(useCoverageAA && vm.rectStaysRect() && rrect.isSimple());
+
+ if (!vm.rectStaysRect() || !rrect.isSimple()) {
+ return false;
}
-#endif
// do any matrix crunching before we reset the draw state for device coords
const SkRect& rrectBounds = rrect.getBounds();
@@ -912,21 +972,38 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b
SkScalar yRadius = SkScalarAbs(vm[SkMatrix::kMSkewX]*radii.fX +
vm[SkMatrix::kMScaleY]*radii.fY);
- // if hairline stroke is greater than radius, we don't handle that right now
SkStrokeRec::Style style = stroke.getStyle();
- if (SkStrokeRec::kHairline_Style == style &&
- (SK_ScalarHalf > xRadius || SK_ScalarHalf > yRadius)) {
- return false;
- }
// do (potentially) anisotropic mapping of stroke
SkVector scaledStroke;
SkScalar strokeWidth = stroke.getWidth();
- scaledStroke.fX = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMScaleX] + vm[SkMatrix::kMSkewY]));
- scaledStroke.fY = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMSkewX] + vm[SkMatrix::kMScaleY]));
- // if half of strokewidth is greater than radius, we don't handle that right now
- if (SK_ScalarHalf*scaledStroke.fX > xRadius || SK_ScalarHalf*scaledStroke.fY > yRadius) {
+ bool isStrokeOnly = SkStrokeRec::kStroke_Style == style ||
+ SkStrokeRec::kHairline_Style == style;
+ bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style;
+
+ if (hasStroke) {
+ if (SkStrokeRec::kHairline_Style == style) {
+ scaledStroke.set(1, 1);
+ } else {
+ scaledStroke.fX = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMScaleX] +
+ vm[SkMatrix::kMSkewY]));
+ scaledStroke.fY = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMSkewX] +
+ vm[SkMatrix::kMScaleY]));
+ }
+
+ // if half of strokewidth is greater than radius, we don't handle that right now
+ if (SK_ScalarHalf*scaledStroke.fX > xRadius || SK_ScalarHalf*scaledStroke.fY > yRadius) {
+ return false;
+ }
+ }
+
+ // The way the effect interpolates the offset-to-ellipse/circle-center attribute only works on
+ // the interior of the rrect if the radii are >= 0.5. Otherwise, the inner rect of the nine-
+ // patch will have fractional coverage. This only matters when the interior is actually filled.
+ // We could consider falling back to rect rendering here, since a tiny radius is
+ // indistinguishable from a square corner.
+ if (!isStrokeOnly && (SK_ScalarHalf > xRadius || SK_ScalarHalf > yRadius)) {
return false;
}
@@ -937,8 +1014,6 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b
return false;
}
- bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style);
-
GrIndexBuffer* indexBuffer = this->rRectIndexBuffer(context->getGpu());
if (NULL == indexBuffer) {
GrPrintf("Failed to create index buffer!\n");
@@ -946,7 +1021,7 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b
}
// if the corners are circles, use the circle renderer
- if ((!isStroked || scaledStroke.fX == scaledStroke.fY) && xRadius == yRadius) {
+ if ((!hasStroke || scaledStroke.fX == scaledStroke.fY) && xRadius == yRadius) {
drawState->setVertexAttribs<gCircleVertexAttribs>(SK_ARRAY_COUNT(gCircleVertexAttribs));
SkASSERT(sizeof(CircleVertex) == drawState->getVertexSize());
@@ -960,23 +1035,23 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b
SkScalar innerRadius = 0.0f;
SkScalar outerRadius = xRadius;
SkScalar halfWidth = 0;
- if (style != SkStrokeRec::kFill_Style) {
+ if (hasStroke) {
if (SkScalarNearlyZero(scaledStroke.fX)) {
halfWidth = SK_ScalarHalf;
} else {
halfWidth = SkScalarHalf(scaledStroke.fX);
}
- if (isStroked) {
+ if (isStrokeOnly) {
innerRadius = xRadius - halfWidth;
}
outerRadius += halfWidth;
bounds.outset(halfWidth, halfWidth);
}
- isStroked = (isStroked && innerRadius >= 0);
+ isStrokeOnly = (isStrokeOnly && innerRadius >= 0);
- GrEffectRef* effect = CircleEdgeEffect::Create(isStroked);
+ GrEffectRef* effect = CircleEdgeEffect::Create(isStrokeOnly);
static const int kCircleEdgeAttrIndex = 1;
drawState->addCoverageEffect(effect, kCircleEdgeAttrIndex)->unref();
@@ -1029,7 +1104,8 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b
}
// drop out the middle quad if we're stroked
- int indexCnt = isStroked ? GR_ARRAY_COUNT(gRRectIndices)-6 : GR_ARRAY_COUNT(gRRectIndices);
+ int indexCnt = isStrokeOnly ? SK_ARRAY_COUNT(gRRectIndices) - 6 :
+ SK_ARRAY_COUNT(gRRectIndices);
target->setIndexSourceToBuffer(indexBuffer);
target->drawIndexed(kTriangles_GrPrimitiveType, 0, 0, 16, indexCnt, &bounds);
@@ -1040,7 +1116,7 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b
SkScalar innerXRadius = 0.0f;
SkScalar innerYRadius = 0.0f;
- if (SkStrokeRec::kFill_Style != style) {
+ if (hasStroke) {
if (SkScalarNearlyZero(scaledStroke.length())) {
scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf);
} else {
@@ -1060,7 +1136,7 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b
}
// this is legit only if scale & translation (which should be the case at the moment)
- if (isStroked) {
+ if (isStrokeOnly) {
innerXRadius = xRadius - scaledStroke.fX;
innerYRadius = yRadius - scaledStroke.fY;
}
@@ -1070,7 +1146,7 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b
bounds.outset(scaledStroke.fX, scaledStroke.fY);
}
- isStroked = (isStroked && innerXRadius >= 0 && innerYRadius >= 0);
+ isStrokeOnly = (isStrokeOnly && innerXRadius >= 0 && innerYRadius >= 0);
GrDrawTarget::AutoReleaseGeometry geo(target, 16, 0);
if (!geo.succeeded()) {
@@ -1079,7 +1155,7 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b
}
EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices());
- GrEffectRef* effect = EllipseEdgeEffect::Create(isStroked);
+ GrEffectRef* effect = EllipseEdgeEffect::Create(isStrokeOnly);
static const int kEllipseOffsetAttrIndex = 1;
static const int kEllipseRadiiAttrIndex = 2;
drawState->addCoverageEffect(effect,
@@ -1138,7 +1214,8 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b
}
// drop out the middle quad if we're stroked
- int indexCnt = isStroked ? GR_ARRAY_COUNT(gRRectIndices)-6 : GR_ARRAY_COUNT(gRRectIndices);
+ int indexCnt = isStrokeOnly ? SK_ARRAY_COUNT(gRRectIndices) - 6 :
+ SK_ARRAY_COUNT(gRRectIndices);
target->setIndexSourceToBuffer(indexBuffer);
target->drawIndexed(kTriangles_GrPrimitiveType, 0, 0, 16, indexCnt, &bounds);
}
diff --git a/chromium/third_party/skia/src/gpu/GrOvalRenderer.h b/chromium/third_party/skia/src/gpu/GrOvalRenderer.h
index 9653fccd722..92f6ff0cdf2 100644
--- a/chromium/third_party/skia/src/gpu/GrOvalRenderer.h
+++ b/chromium/third_party/skia/src/gpu/GrOvalRenderer.h
@@ -33,8 +33,10 @@ public:
bool drawOval(GrDrawTarget* target, const GrContext* context, bool useAA,
const SkRect& oval, const SkStrokeRec& stroke);
- bool drawSimpleRRect(GrDrawTarget* target, GrContext* context, bool useAA,
- const SkRRect& rrect, const SkStrokeRec& stroke);
+ bool drawRRect(GrDrawTarget* target, GrContext* context, bool useAA,
+ const SkRRect& rrect, const SkStrokeRec& stroke);
+ bool drawDRRect(GrDrawTarget* target, GrContext* context, bool useAA,
+ const SkRRect& outer, const SkRRect& inner);
private:
bool drawEllipse(GrDrawTarget* target, bool useCoverageAA,
diff --git a/chromium/third_party/skia/src/gpu/GrPaint.cpp b/chromium/third_party/skia/src/gpu/GrPaint.cpp
index 7499cd0ea24..35912a94bd5 100644
--- a/chromium/third_party/skia/src/gpu/GrPaint.cpp
+++ b/chromium/third_party/skia/src/gpu/GrPaint.cpp
@@ -104,7 +104,7 @@ bool GrPaint::getOpaqueAndKnownColor(GrColor* solidColor,
case kDA_GrBlendCoeff:
case kIDA_GrBlendCoeff:
default:
- GrCrash("srcCoeff should not refer to src or dst.");
+ SkFAIL("srcCoeff should not refer to src or dst.");
break;
// TODO: update this once GrPaint actually has a const color.
diff --git a/chromium/third_party/skia/src/gpu/GrPath.h b/chromium/third_party/skia/src/gpu/GrPath.h
index f481ea42864..d324e6a7455 100644
--- a/chromium/third_party/skia/src/gpu/GrPath.h
+++ b/chromium/third_party/skia/src/gpu/GrPath.h
@@ -8,13 +8,13 @@
#ifndef GrPath_DEFINED
#define GrPath_DEFINED
-#include "GrResource.h"
+#include "GrGpuObject.h"
#include "GrResourceCache.h"
#include "SkPath.h"
#include "SkRect.h"
#include "SkStrokeRec.h"
-class GrPath : public GrResource {
+class GrPath : public GrGpuObject {
public:
SK_DECLARE_INST_COUNT(GrPath);
@@ -41,7 +41,7 @@ protected:
SkRect fBounds;
private:
- typedef GrResource INHERITED;
+ typedef GrGpuObject INHERITED;
};
#endif
diff --git a/chromium/third_party/skia/src/gpu/GrPathUtils.cpp b/chromium/third_party/skia/src/gpu/GrPathUtils.cpp
index e2b1ac76343..464231a8dc3 100644
--- a/chromium/third_party/skia/src/gpu/GrPathUtils.cpp
+++ b/chromium/third_party/skia/src/gpu/GrPathUtils.cpp
@@ -7,15 +7,15 @@
#include "GrPathUtils.h"
-#include "GrPoint.h"
+#include "GrTypes.h"
#include "SkGeometry.h"
SkScalar GrPathUtils::scaleToleranceToSrc(SkScalar devTol,
const SkMatrix& viewM,
const SkRect& pathBounds) {
// In order to tesselate the path we get a bound on how much the matrix can
- // stretch when mapping to screen coordinates.
- SkScalar stretch = viewM.getMaxStretch();
+ // scale when mapping to screen coordinates.
+ SkScalar stretch = viewM.getMaxScale();
SkScalar srcTol = devTol;
if (stretch < 0) {
@@ -36,7 +36,7 @@ SkScalar GrPathUtils::scaleToleranceToSrc(SkScalar devTol,
static const int MAX_POINTS_PER_CURVE = 1 << 10;
static const SkScalar gMinCurveTol = 0.0001f;
-uint32_t GrPathUtils::quadraticPointCount(const GrPoint points[],
+uint32_t GrPathUtils::quadraticPointCount(const SkPoint points[],
SkScalar tol) {
if (tol < gMinCurveTol) {
tol = gMinCurveTol;
@@ -51,7 +51,7 @@ uint32_t GrPathUtils::quadraticPointCount(const GrPoint points[],
// subdivide x = log4(d/tol) times. x subdivisions creates 2^(x)
// points.
// 2^(log4(x)) = sqrt(x);
- int temp = SkScalarCeil(SkScalarSqrt(SkScalarDiv(d, tol)));
+ int temp = SkScalarCeilToInt(SkScalarSqrt(SkScalarDiv(d, tol)));
int pow2 = GrNextPow2(temp);
// Because of NaNs & INFs we can wind up with a degenerate temp
// such that pow2 comes out negative. Also, our point generator
@@ -59,15 +59,15 @@ uint32_t GrPathUtils::quadraticPointCount(const GrPoint points[],
if (pow2 < 1) {
pow2 = 1;
}
- return GrMin(pow2, MAX_POINTS_PER_CURVE);
+ return SkTMin(pow2, MAX_POINTS_PER_CURVE);
}
}
-uint32_t GrPathUtils::generateQuadraticPoints(const GrPoint& p0,
- const GrPoint& p1,
- const GrPoint& p2,
+uint32_t GrPathUtils::generateQuadraticPoints(const SkPoint& p0,
+ const SkPoint& p1,
+ const SkPoint& p2,
SkScalar tolSqd,
- GrPoint** points,
+ SkPoint** points,
uint32_t pointsLeft) {
if (pointsLeft < 2 ||
(p1.distanceToLineSegmentBetweenSqd(p0, p2)) < tolSqd) {
@@ -76,11 +76,11 @@ uint32_t GrPathUtils::generateQuadraticPoints(const GrPoint& p0,
return 1;
}
- GrPoint q[] = {
+ SkPoint q[] = {
{ SkScalarAve(p0.fX, p1.fX), SkScalarAve(p0.fY, p1.fY) },
{ SkScalarAve(p1.fX, p2.fX), SkScalarAve(p1.fY, p2.fY) },
};
- GrPoint r = { SkScalarAve(q[0].fX, q[1].fX), SkScalarAve(q[0].fY, q[1].fY) };
+ SkPoint r = { SkScalarAve(q[0].fX, q[1].fX), SkScalarAve(q[0].fY, q[1].fY) };
pointsLeft >>= 1;
uint32_t a = generateQuadraticPoints(p0, q[0], r, tolSqd, points, pointsLeft);
@@ -88,21 +88,21 @@ uint32_t GrPathUtils::generateQuadraticPoints(const GrPoint& p0,
return a + b;
}
-uint32_t GrPathUtils::cubicPointCount(const GrPoint points[],
+uint32_t GrPathUtils::cubicPointCount(const SkPoint points[],
SkScalar tol) {
if (tol < gMinCurveTol) {
tol = gMinCurveTol;
}
SkASSERT(tol > 0);
- SkScalar d = GrMax(
+ SkScalar d = SkTMax(
points[1].distanceToLineSegmentBetweenSqd(points[0], points[3]),
points[2].distanceToLineSegmentBetweenSqd(points[0], points[3]));
d = SkScalarSqrt(d);
if (d <= tol) {
return 1;
} else {
- int temp = SkScalarCeil(SkScalarSqrt(SkScalarDiv(d, tol)));
+ int temp = SkScalarCeilToInt(SkScalarSqrt(SkScalarDiv(d, tol)));
int pow2 = GrNextPow2(temp);
// Because of NaNs & INFs we can wind up with a degenerate temp
// such that pow2 comes out negative. Also, our point generator
@@ -110,16 +110,16 @@ uint32_t GrPathUtils::cubicPointCount(const GrPoint points[],
if (pow2 < 1) {
pow2 = 1;
}
- return GrMin(pow2, MAX_POINTS_PER_CURVE);
+ return SkTMin(pow2, MAX_POINTS_PER_CURVE);
}
}
-uint32_t GrPathUtils::generateCubicPoints(const GrPoint& p0,
- const GrPoint& p1,
- const GrPoint& p2,
- const GrPoint& p3,
+uint32_t GrPathUtils::generateCubicPoints(const SkPoint& p0,
+ const SkPoint& p1,
+ const SkPoint& p2,
+ const SkPoint& p3,
SkScalar tolSqd,
- GrPoint** points,
+ SkPoint** points,
uint32_t pointsLeft) {
if (pointsLeft < 2 ||
(p1.distanceToLineSegmentBetweenSqd(p0, p3) < tolSqd &&
@@ -128,16 +128,16 @@ uint32_t GrPathUtils::generateCubicPoints(const GrPoint& p0,
*points += 1;
return 1;
}
- GrPoint q[] = {
+ SkPoint q[] = {
{ SkScalarAve(p0.fX, p1.fX), SkScalarAve(p0.fY, p1.fY) },
{ SkScalarAve(p1.fX, p2.fX), SkScalarAve(p1.fY, p2.fY) },
{ SkScalarAve(p2.fX, p3.fX), SkScalarAve(p2.fY, p3.fY) }
};
- GrPoint r[] = {
+ SkPoint r[] = {
{ SkScalarAve(q[0].fX, q[1].fX), SkScalarAve(q[0].fY, q[1].fY) },
{ SkScalarAve(q[1].fX, q[2].fX), SkScalarAve(q[1].fY, q[2].fY) }
};
- GrPoint s = { SkScalarAve(r[0].fX, r[1].fX), SkScalarAve(r[0].fY, r[1].fY) };
+ SkPoint s = { SkScalarAve(r[0].fX, r[1].fX), SkScalarAve(r[0].fY, r[1].fY) };
pointsLeft >>= 1;
uint32_t a = generateCubicPoints(p0, q[0], r[0], s, tolSqd, points, pointsLeft);
uint32_t b = generateCubicPoints(s, r[1], q[2], p3, tolSqd, points, pointsLeft);
@@ -159,7 +159,7 @@ int GrPathUtils::worstCasePointCount(const SkPath& path, int* subpaths,
SkPath::Iter iter(path, false);
SkPath::Verb verb;
- GrPoint pts[4];
+ SkPoint pts[4];
while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
switch (verb) {
@@ -186,10 +186,7 @@ int GrPathUtils::worstCasePointCount(const SkPath& path, int* subpaths,
return pointCount;
}
-void GrPathUtils::QuadUVMatrix::set(const GrPoint qPts[3]) {
-#ifndef SK_SCALAR_IS_FLOAT
- GrCrash("Expected scalar is float.");
-#endif
+void GrPathUtils::QuadUVMatrix::set(const SkPoint qPts[3]) {
SkMatrix m;
// We want M such that M * xy_pt = uv_pt
// We know M * control_pts = [0 1/2 1]
@@ -229,11 +226,11 @@ void GrPathUtils::QuadUVMatrix::set(const GrPoint qPts[3]) {
// We could have a tolerance here, not sure if it would improve anything
if (maxD > 0) {
// Set the matrix to give (u = 0, v = distance_to_line)
- GrVec lineVec = qPts[(maxEdge + 1)%3] - qPts[maxEdge];
+ SkVector lineVec = qPts[(maxEdge + 1)%3] - qPts[maxEdge];
// when looking from the point 0 down the line we want positive
// distances to be to the left. This matches the non-degenerate
// case.
- lineVec.setOrthog(lineVec, GrPoint::kLeft_Side);
+ lineVec.setOrthog(lineVec, SkPoint::kLeft_Side);
lineVec.dot(qPts[0]);
// first row
fM[0] = 0;
@@ -408,49 +405,56 @@ void convert_noninflect_cubic_to_quads(const SkPoint p[4],
dc = p[1] - p[3];
}
- // When the ab and cd tangents are nearly parallel with vector from d to a the constraint that
- // the quad point falls between the tangents becomes hard to enforce and we are likely to hit
- // the max subdivision count. However, in this case the cubic is approaching a line and the
- // accuracy of the quad point isn't so important. We check if the two middle cubic control
- // points are very close to the baseline vector. If so then we just pick quadratic points on the
- // control polygon.
+ // When the ab and cd tangents are degenerate or nearly parallel with vector from d to a the
+ // constraint that the quad point falls between the tangents becomes hard to enforce and we are
+ // likely to hit the max subdivision count. However, in this case the cubic is approaching a
+ // line and the accuracy of the quad point isn't so important. We check if the two middle cubic
+ // control points are very close to the baseline vector. If so then we just pick quadratic
+ // points on the control polygon.
if (constrainWithinTangents) {
SkVector da = p[0] - p[3];
- SkScalar invDALengthSqd = da.lengthSqd();
- if (invDALengthSqd > SK_ScalarNearlyZero) {
- invDALengthSqd = SkScalarInvert(invDALengthSqd);
- // cross(ab, da)^2/length(da)^2 == sqd distance from b to line from d to a.
- // same goed for point c using vector cd.
- SkScalar detABSqd = ab.cross(da);
- detABSqd = SkScalarSquare(detABSqd);
- SkScalar detDCSqd = dc.cross(da);
- detDCSqd = SkScalarSquare(detDCSqd);
- if (SkScalarMul(detABSqd, invDALengthSqd) < toleranceSqd &&
- SkScalarMul(detDCSqd, invDALengthSqd) < toleranceSqd) {
- SkPoint b = p[0] + ab;
- SkPoint c = p[3] + dc;
- SkPoint mid = b + c;
- mid.scale(SK_ScalarHalf);
- // Insert two quadratics to cover the case when ab points away from d and/or dc
- // points away from a.
- if (SkVector::DotProduct(da, dc) < 0 || SkVector::DotProduct(ab,da) > 0) {
- SkPoint* qpts = quads->push_back_n(6);
- qpts[0] = p[0];
- qpts[1] = b;
- qpts[2] = mid;
- qpts[3] = mid;
- qpts[4] = c;
- qpts[5] = p[3];
- } else {
- SkPoint* qpts = quads->push_back_n(3);
- qpts[0] = p[0];
- qpts[1] = mid;
- qpts[2] = p[3];
+ bool doQuads = dc.lengthSqd() < SK_ScalarNearlyZero ||
+ ab.lengthSqd() < SK_ScalarNearlyZero;
+ if (!doQuads) {
+ SkScalar invDALengthSqd = da.lengthSqd();
+ if (invDALengthSqd > SK_ScalarNearlyZero) {
+ invDALengthSqd = SkScalarInvert(invDALengthSqd);
+ // cross(ab, da)^2/length(da)^2 == sqd distance from b to line from d to a.
+ // same goes for point c using vector cd.
+ SkScalar detABSqd = ab.cross(da);
+ detABSqd = SkScalarSquare(detABSqd);
+ SkScalar detDCSqd = dc.cross(da);
+ detDCSqd = SkScalarSquare(detDCSqd);
+ if (SkScalarMul(detABSqd, invDALengthSqd) < toleranceSqd &&
+ SkScalarMul(detDCSqd, invDALengthSqd) < toleranceSqd) {
+ doQuads = true;
}
- return;
}
}
+ if (doQuads) {
+ SkPoint b = p[0] + ab;
+ SkPoint c = p[3] + dc;
+ SkPoint mid = b + c;
+ mid.scale(SK_ScalarHalf);
+ // Insert two quadratics to cover the case when ab points away from d and/or dc
+ // points away from a.
+ if (SkVector::DotProduct(da, dc) < 0 || SkVector::DotProduct(ab,da) > 0) {
+ SkPoint* qpts = quads->push_back_n(6);
+ qpts[0] = p[0];
+ qpts[1] = b;
+ qpts[2] = mid;
+ qpts[3] = mid;
+ qpts[4] = c;
+ qpts[5] = p[3];
+ } else {
+ SkPoint* qpts = quads->push_back_n(3);
+ qpts[0] = p[0];
+ qpts[1] = mid;
+ qpts[2] = p[3];
+ }
+ return;
+ }
}
static const SkScalar kLengthScale = 3 * SK_Scalar1 / 2;
@@ -522,7 +526,7 @@ void convert_noninflect_cubic_to_quads(const SkPoint p[4],
}
}
-void GrPathUtils::convertCubicToQuads(const GrPoint p[4],
+void GrPathUtils::convertCubicToQuads(const SkPoint p[4],
SkScalar tolScale,
bool constrainWithinTangents,
SkPath::Direction dir,
diff --git a/chromium/third_party/skia/src/gpu/GrPathUtils.h b/chromium/third_party/skia/src/gpu/GrPathUtils.h
index 71f6e0b9c1e..c15fd7ae103 100644
--- a/chromium/third_party/skia/src/gpu/GrPathUtils.h
+++ b/chromium/third_party/skia/src/gpu/GrPathUtils.h
@@ -8,7 +8,6 @@
#ifndef GrPathUtils_DEFINED
#define GrPathUtils_DEFINED
-#include "GrPoint.h"
#include "SkRect.h"
#include "SkPath.h"
#include "SkTArray.h"
@@ -31,25 +30,25 @@ namespace GrPathUtils {
/// Since we divide by tol if we're computing exact worst-case bounds,
/// very small tolerances will be increased to gMinCurveTol.
- uint32_t quadraticPointCount(const GrPoint points[], SkScalar tol);
+ uint32_t quadraticPointCount(const SkPoint points[], SkScalar tol);
- uint32_t generateQuadraticPoints(const GrPoint& p0,
- const GrPoint& p1,
- const GrPoint& p2,
+ uint32_t generateQuadraticPoints(const SkPoint& p0,
+ const SkPoint& p1,
+ const SkPoint& p2,
SkScalar tolSqd,
- GrPoint** points,
+ SkPoint** points,
uint32_t pointsLeft);
/// Since we divide by tol if we're computing exact worst-case bounds,
/// very small tolerances will be increased to gMinCurveTol.
- uint32_t cubicPointCount(const GrPoint points[], SkScalar tol);
+ uint32_t cubicPointCount(const SkPoint points[], SkScalar tol);
- uint32_t generateCubicPoints(const GrPoint& p0,
- const GrPoint& p1,
- const GrPoint& p2,
- const GrPoint& p3,
+ uint32_t generateCubicPoints(const SkPoint& p0,
+ const SkPoint& p1,
+ const SkPoint& p2,
+ const SkPoint& p3,
SkScalar tolSqd,
- GrPoint** points,
+ SkPoint** points,
uint32_t pointsLeft);
// A 2x3 matrix that goes from the 2d space coordinates to UV space where
@@ -59,8 +58,8 @@ namespace GrPathUtils {
public:
QuadUVMatrix() {};
// Initialize the matrix from the control pts
- QuadUVMatrix(const GrPoint controlPts[3]) { this->set(controlPts); }
- void set(const GrPoint controlPts[3]);
+ QuadUVMatrix(const SkPoint controlPts[3]) { this->set(controlPts); }
+ void set(const SkPoint controlPts[3]);
/**
* Applies the matrix to vertex positions to compute UV coords. This
@@ -85,8 +84,8 @@ namespace GrPathUtils {
float sy = fM[4];
float ty = fM[5];
for (int i = 0; i < N; ++i) {
- const GrPoint* xy = reinterpret_cast<const GrPoint*>(xyPtr);
- GrPoint* uv = reinterpret_cast<GrPoint*>(uvPtr);
+ const SkPoint* xy = reinterpret_cast<const SkPoint*>(xyPtr);
+ SkPoint* uv = reinterpret_cast<SkPoint*>(uvPtr);
uv->fX = sx * xy->fX + kx * xy->fY + tx;
uv->fY = ky * xy->fX + sy * xy->fY + ty;
xyPtr += STRIDE;
@@ -119,7 +118,7 @@ namespace GrPathUtils {
// Setting constrainWithinTangents to true enforces this property. When this
// is true the cubic must be simple and dir must specify the orientation of
// the cubic. Otherwise, dir is ignored.
- void convertCubicToQuads(const GrPoint p[4],
+ void convertCubicToQuads(const SkPoint p[4],
SkScalar tolScale,
bool constrainWithinTangents,
SkPath::Direction dir,
diff --git a/chromium/third_party/skia/src/gpu/GrPictureUtils.cpp b/chromium/third_party/skia/src/gpu/GrPictureUtils.cpp
new file mode 100644
index 00000000000..6fed2f6d9ff
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/GrPictureUtils.cpp
@@ -0,0 +1,279 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrPictureUtils.h"
+#include "SkDevice.h"
+#include "SkDraw.h"
+#include "SkPaintPriv.h"
+#include "SkPicturePlayback.h"
+
+SkPicture::AccelData::Key GPUAccelData::ComputeAccelDataKey() {
+ static const SkPicture::AccelData::Key gGPUID = SkPicture::AccelData::GenerateDomain();
+
+ return gGPUID;
+}
+
+// The GrGather device performs GPU-backend-specific preprocessing on
+// a picture. The results are stored in a GPUAccelData.
+//
+// Currently the only interesting work is done in drawDevice (i.e., when a
+// saveLayer is collapsed back into its parent) and, maybe, in onCreateDevice.
+// All the current work could be done much more efficiently by just traversing the
+// raw op codes in the SkPicture (although we would still need to replay all the
+// clip calls).
+class GrGatherDevice : public SkBaseDevice {
+public:
+ SK_DECLARE_INST_COUNT(GrGatherDevice)
+
+ GrGatherDevice(int width, int height, const SkPicture* picture, GPUAccelData* accelData,
+ int saveLayerDepth) {
+ fPicture = picture;
+ fSaveLayerDepth = saveLayerDepth;
+ fInfo.fValid = true;
+ fInfo.fSize.set(width, height);
+ fInfo.fPaint = NULL;
+ fInfo.fSaveLayerOpID = fPicture->EXPERIMENTAL_curOpID();
+ fInfo.fRestoreOpID = 0;
+ fInfo.fHasNestedLayers = false;
+ fInfo.fIsNested = (2 == fSaveLayerDepth);
+
+ fEmptyBitmap.setInfo(SkImageInfo::MakeUnknown(fInfo.fSize.fWidth, fInfo.fSize.fHeight));
+ fAccelData = accelData;
+ fAlreadyDrawn = false;
+ }
+
+ virtual ~GrGatherDevice() { }
+
+ virtual SkImageInfo imageInfo() const SK_OVERRIDE {
+ return fEmptyBitmap.info();
+ }
+
+#ifdef SK_SUPPORT_LEGACY_WRITEPIXELSCONFIG
+ virtual void writePixels(const SkBitmap& bitmap, int x, int y,
+ SkCanvas::Config8888 config8888) SK_OVERRIDE {
+ NotSupported();
+ }
+#endif
+ virtual GrRenderTarget* accessRenderTarget() SK_OVERRIDE { return NULL; }
+
+protected:
+ virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) SK_OVERRIDE {
+ return false;
+ }
+ virtual void clear(SkColor color) SK_OVERRIDE {
+ NothingToDo();
+ }
+ virtual void drawPaint(const SkDraw& draw, const SkPaint& paint) SK_OVERRIDE {
+ }
+ virtual void drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count,
+ const SkPoint points[], const SkPaint& paint) SK_OVERRIDE {
+ }
+ virtual void drawRect(const SkDraw& draw, const SkRect& rect,
+ const SkPaint& paint) SK_OVERRIDE {
+ }
+ virtual void drawOval(const SkDraw& draw, const SkRect& rect,
+ const SkPaint& paint) SK_OVERRIDE {
+ }
+ virtual void drawRRect(const SkDraw& draw, const SkRRect& rrect,
+ const SkPaint& paint) SK_OVERRIDE {
+ }
+ virtual void drawPath(const SkDraw& draw, const SkPath& path,
+ const SkPaint& paint, const SkMatrix* prePathMatrix,
+ bool pathIsMutable) SK_OVERRIDE {
+ }
+ virtual void drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
+ const SkMatrix& matrix, const SkPaint& paint) SK_OVERRIDE {
+ }
+ virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
+ int x, int y, const SkPaint& paint) SK_OVERRIDE {
+ }
+ virtual void drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
+ const SkRect* srcOrNull, const SkRect& dst,
+ const SkPaint& paint,
+ SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE {
+ }
+ virtual void drawText(const SkDraw& draw, const void* text, size_t len,
+ SkScalar x, SkScalar y,
+ const SkPaint& paint) SK_OVERRIDE {
+ }
+ virtual void drawPosText(const SkDraw& draw, const void* text, size_t len,
+ const SkScalar pos[], SkScalar constY,
+ int scalarsPerPos, const SkPaint& paint) SK_OVERRIDE {
+ }
+ virtual void drawTextOnPath(const SkDraw& draw, const void* text, size_t len,
+ const SkPath& path, const SkMatrix* matrix,
+ const SkPaint& paint) SK_OVERRIDE {
+ }
+ virtual void drawVertices(const SkDraw& draw, SkCanvas::VertexMode, int vertexCount,
+ const SkPoint verts[], const SkPoint texs[],
+ const SkColor colors[], SkXfermode* xmode,
+ const uint16_t indices[], int indexCount,
+ const SkPaint& paint) SK_OVERRIDE {
+ }
+ virtual void drawDevice(const SkDraw& draw, SkBaseDevice* deviceIn, int x, int y,
+ const SkPaint& paint) SK_OVERRIDE {
+ // deviceIn is the one that is being "restored" back to its parent
+ GrGatherDevice* device = static_cast<GrGatherDevice*>(deviceIn);
+
+ if (device->fAlreadyDrawn) {
+ return;
+ }
+
+ device->fInfo.fRestoreOpID = fPicture->EXPERIMENTAL_curOpID();
+ device->fInfo.fCTM = *draw.fMatrix;
+ device->fInfo.fCTM.postTranslate(SkIntToScalar(-device->getOrigin().fX),
+ SkIntToScalar(-device->getOrigin().fY));
+
+ device->fInfo.fOffset = device->getOrigin();
+
+ if (NeedsDeepCopy(paint)) {
+ // This NULL acts as a signal that the paint was uncopyable (for now)
+ device->fInfo.fPaint = NULL;
+ device->fInfo.fValid = false;
+ } else {
+ device->fInfo.fPaint = SkNEW_ARGS(SkPaint, (paint));
+ }
+
+ fAccelData->addSaveLayerInfo(device->fInfo);
+ device->fAlreadyDrawn = true;
+ }
+ // TODO: allow this call to return failure, or move to SkBitmapDevice only.
+ virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE {
+ return fEmptyBitmap;
+ }
+#ifdef SK_SUPPORT_LEGACY_READPIXELSCONFIG
+ virtual bool onReadPixels(const SkBitmap& bitmap,
+ int x, int y,
+ SkCanvas::Config8888 config8888) SK_OVERRIDE {
+ NotSupported();
+ return false;
+ }
+#endif
+ virtual void lockPixels() SK_OVERRIDE { NothingToDo(); }
+ virtual void unlockPixels() SK_OVERRIDE { NothingToDo(); }
+ virtual bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
+ virtual bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
+ virtual bool filterImage(const SkImageFilter*, const SkBitmap&, const SkImageFilter::Context&,
+ SkBitmap* result, SkIPoint* offset) SK_OVERRIDE {
+ return false;
+ }
+
+private:
+ // The picture being processed
+ const SkPicture *fPicture;
+
+ SkBitmap fEmptyBitmap; // legacy -- need to remove
+
+ // All information gathered during the gather process is stored here
+ GPUAccelData* fAccelData;
+
+ // true if this device has already been drawn back to its parent(s) at least
+ // once.
+ bool fAlreadyDrawn;
+
+ // The information regarding the saveLayer call this device represents.
+ GPUAccelData::SaveLayerInfo fInfo;
+
+ // The depth of this device in the saveLayer stack
+ int fSaveLayerDepth;
+
+ virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE {
+ NotSupported();
+ }
+
+ virtual SkBaseDevice* onCreateDevice(const SkImageInfo& info, Usage usage) SK_OVERRIDE {
+ // we expect to only get called via savelayer, in which case it is fine.
+ SkASSERT(kSaveLayer_Usage == usage);
+
+ fInfo.fHasNestedLayers = true;
+ return SkNEW_ARGS(GrGatherDevice, (info.width(), info.height(), fPicture,
+ fAccelData, fSaveLayerDepth+1));
+ }
+
+ virtual void flush() SK_OVERRIDE {}
+
+ static void NotSupported() {
+ SkDEBUGFAIL("this method should never be called");
+ }
+
+ static void NothingToDo() {}
+
+ typedef SkBaseDevice INHERITED;
+};
+
+// The GrGatherCanvas allows saveLayers but simplifies clipping. It is really
+// only intended to be used as:
+//
+// GrGatherDevice dev(w, h, picture, accelData);
+// GrGatherCanvas canvas(..., picture);
+// canvas.gather();
+//
+// which is all just to fill in 'accelData'
+class SK_API GrGatherCanvas : public SkCanvas {
+public:
+ GrGatherCanvas(GrGatherDevice* device, const SkPicture* pict)
+ : INHERITED(device)
+ , fPicture(pict) {
+ }
+
+ void gather() {
+ if (NULL == fPicture || 0 == fPicture->width() || 0 == fPicture->height()) {
+ return;
+ }
+
+ this->clipRect(SkRect::MakeWH(SkIntToScalar(fPicture->width()),
+ SkIntToScalar(fPicture->height())),
+ SkRegion::kIntersect_Op, false);
+ this->drawPicture(fPicture);
+ }
+
+protected:
+ // disable aa for speed
+ virtual void onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle) SK_OVERRIDE {
+ this->INHERITED::onClipRect(rect, op, kHard_ClipEdgeStyle);
+ }
+
+ // for speed, just respect the bounds, and disable AA. May give us a few
+ // false positives and negatives.
+ virtual void onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle) SK_OVERRIDE {
+ this->updateClipConservativelyUsingBounds(path.getBounds(), op,
+ path.isInverseFillType());
+ }
+ virtual void onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle) SK_OVERRIDE {
+ this->updateClipConservativelyUsingBounds(rrect.getBounds(), op, false);
+ }
+
+ virtual void onDrawPicture(const SkPicture* picture) SK_OVERRIDE {
+ // BBH-based rendering doesn't re-issue many of the operations the gather
+ // process cares about (e.g., saves and restores) so it must be disabled.
+ if (NULL != picture->fPlayback) {
+ picture->fPlayback->setUseBBH(false);
+ }
+ picture->draw(this);
+ if (NULL != picture->fPlayback) {
+ picture->fPlayback->setUseBBH(true);
+ }
+ }
+
+private:
+ const SkPicture* fPicture;
+
+ typedef SkCanvas INHERITED;
+};
+
+// GatherGPUInfo is only intended to be called within the context of SkGpuDevice's
+// EXPERIMENTAL_optimize method.
+void GatherGPUInfo(const SkPicture* pict, GPUAccelData* accelData) {
+ if (0 == pict->width() || 0 == pict->height()) {
+ return ;
+ }
+
+ GrGatherDevice device(pict->width(), pict->height(), pict, accelData, 0);
+ GrGatherCanvas canvas(&device, pict);
+
+ canvas.gather();
+}
diff --git a/chromium/third_party/skia/src/gpu/GrPictureUtils.h b/chromium/third_party/skia/src/gpu/GrPictureUtils.h
new file mode 100644
index 00000000000..a730697d62d
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/GrPictureUtils.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrPictureUtils_DEFINED
+#define GrPictureUtils_DEFINED
+
+#include "SkPicture.h"
+#include "SkTDArray.h"
+
+// This class encapsulates the GPU-backend-specific acceleration data
+// for a single SkPicture
+class GPUAccelData : public SkPicture::AccelData {
+public:
+ // Information about a given saveLayer in an SkPicture
+ struct SaveLayerInfo {
+ // True if the SaveLayerInfo is valid. False if either 'fOffset' is
+ // invalid (due to a non-invertible CTM) or 'fPaint' is NULL (due
+ // to a non-copyable paint).
+ bool fValid;
+ // The size of the saveLayer
+ SkISize fSize;
+ // The CTM in which this layer's draws must occur. It already incorporates
+ // the translation needed to map the layer's top-left point to the origin.
+ SkMatrix fCTM;
+ // The offset that needs to be passed to drawBitmap to correctly
+ // position the pre-rendered layer. It is in device space.
+ SkIPoint fOffset;
+ // The paint to use on restore. NULL if the paint was not copyable (and
+ // thus that this layer should not be pulled forward).
+ const SkPaint* fPaint;
+ // The ID of this saveLayer in the picture. 0 is an invalid ID.
+ size_t fSaveLayerOpID;
+ // The ID of the matching restore in the picture. 0 is an invalid ID.
+ size_t fRestoreOpID;
+ // True if this saveLayer has at least one other saveLayer nested within it.
+ // False otherwise.
+ bool fHasNestedLayers;
+ // True if this saveLayer is nested within another. False otherwise.
+ bool fIsNested;
+ };
+
+ GPUAccelData(Key key) : INHERITED(key) { }
+
+ virtual ~GPUAccelData() {
+ for (int i = 0; i < fSaveLayerInfo.count(); ++i) {
+ SkDELETE(fSaveLayerInfo[i].fPaint);
+ }
+ }
+
+ void addSaveLayerInfo(const SaveLayerInfo& info) {
+ SkASSERT(info.fSaveLayerOpID < info.fRestoreOpID);
+ *fSaveLayerInfo.push() = info;
+ }
+
+ int numSaveLayers() const { return fSaveLayerInfo.count(); }
+
+ const SaveLayerInfo& saveLayerInfo(int index) const {
+ SkASSERT(index < fSaveLayerInfo.count());
+
+ return fSaveLayerInfo[index];
+ }
+
+ // We may, in the future, need to pass in the GPUDevice in order to
+ // incorporate the clip and matrix state into the key
+ static SkPicture::AccelData::Key ComputeAccelDataKey();
+
+private:
+ SkTDArray<SaveLayerInfo> fSaveLayerInfo;
+
+ typedef SkPicture::AccelData INHERITED;
+};
+
+void GatherGPUInfo(const SkPicture* pict, GPUAccelData* accelData);
+
+#endif // GrPictureUtils_DEFINED
diff --git a/chromium/third_party/skia/src/gpu/GrPlotMgr.h b/chromium/third_party/skia/src/gpu/GrPlotMgr.h
index 6ea6086b06c..14416113274 100644
--- a/chromium/third_party/skia/src/gpu/GrPlotMgr.h
+++ b/chromium/third_party/skia/src/gpu/GrPlotMgr.h
@@ -9,10 +9,9 @@
#define GrPlotMgr_DEFINED
#include "GrTypes.h"
-#include "GrPoint.h"
#include "SkTypes.h"
-class GrPlotMgr : public SkNoncopyable {
+class GrPlotMgr : SkNoncopyable {
public:
GrPlotMgr(int width, int height) {
fDim.set(width, height);
@@ -35,7 +34,7 @@ public:
sk_bzero(fBusy, fDim.fX * fDim.fY);
}
- bool newPlot(GrIPoint16* loc) {
+ bool newPlot(SkIPoint16* loc) {
char* busy = fBusy;
for (int y = 0; y < fDim.fY; y++) {
for (int x = 0; x < fDim.fX; x++) {
@@ -68,7 +67,7 @@ private:
};
char fStorage[STORAGE];
char* fBusy;
- GrIPoint16 fDim;
+ SkIPoint16 fDim;
};
#endif
diff --git a/chromium/third_party/skia/src/gpu/GrRectanizer.cpp b/chromium/third_party/skia/src/gpu/GrRectanizer.cpp
deleted file mode 100644
index 9f0d846e6c9..00000000000
--- a/chromium/third_party/skia/src/gpu/GrRectanizer.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-
-/*
- * Copyright 2010 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-
-#include "GrRectanizer.h"
-#include "GrTBSearch.h"
-
-#define MIN_HEIGHT_POW2 2
-
-class GrRectanizerPow2 : public GrRectanizer {
-public:
- GrRectanizerPow2(int w, int h) : GrRectanizer(w, h) {
- fNextStripY = 0;
- fAreaSoFar = 0;
- sk_bzero(fRows, sizeof(fRows));
- }
-
- virtual ~GrRectanizerPow2() {
- }
-
- virtual void reset() {
- fNextStripY = 0;
- fAreaSoFar = 0;
- sk_bzero(fRows, sizeof(fRows));
- }
-
- virtual bool addRect(int w, int h, GrIPoint16* loc);
-
- virtual float percentFull() const {
- return fAreaSoFar / ((float)this->width() * this->height());
- }
-
- virtual int stripToPurge(int height) const { return -1; }
- virtual void purgeStripAtY(int yCoord) { }
-
- ///////////////////////////////////////////////////////////////////////////
-
- struct Row {
- GrIPoint16 fLoc;
- int fRowHeight;
-
- bool canAddWidth(int width, int containerWidth) const {
- return fLoc.fX + width <= containerWidth;
- }
- };
-
- Row fRows[16];
-
- static int HeightToRowIndex(int height) {
- SkASSERT(height >= MIN_HEIGHT_POW2);
- return 32 - SkCLZ(height - 1);
- }
-
- int fNextStripY;
- int32_t fAreaSoFar;
-
- bool canAddStrip(int height) const {
- return fNextStripY + height <= this->height();
- }
-
- void initRow(Row* row, int rowHeight) {
- row->fLoc.set(0, fNextStripY);
- row->fRowHeight = rowHeight;
- fNextStripY += rowHeight;
- }
-};
-
-bool GrRectanizerPow2::addRect(int width, int height, GrIPoint16* loc) {
- if ((unsigned)width > (unsigned)this->width() ||
- (unsigned)height > (unsigned)this->height()) {
- return false;
- }
-
- int32_t area = width * height;
-
- /*
- We use bsearch, but there may be more than one row with the same height,
- so we actually search for height-1, which can only be a pow2 itself if
- height == 2. Thus we set a minimum height.
- */
- height = GrNextPow2(height);
- if (height < MIN_HEIGHT_POW2) {
- height = MIN_HEIGHT_POW2;
- }
-
- Row* row = &fRows[HeightToRowIndex(height)];
- SkASSERT(row->fRowHeight == 0 || row->fRowHeight == height);
-
- if (0 == row->fRowHeight) {
- if (!this->canAddStrip(height)) {
- return false;
- }
- this->initRow(row, height);
- } else {
- if (!row->canAddWidth(width, this->width())) {
- if (!this->canAddStrip(height)) {
- return false;
- }
- // that row is now "full", so retarget our Row record for
- // another one
- this->initRow(row, height);
- }
- }
-
- SkASSERT(row->fRowHeight == height);
- SkASSERT(row->canAddWidth(width, this->width()));
- *loc = row->fLoc;
- row->fLoc.fX += width;
-
- SkASSERT(row->fLoc.fX <= this->width());
- SkASSERT(row->fLoc.fY <= this->height());
- SkASSERT(fNextStripY <= this->height());
- fAreaSoFar += area;
- return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-// factory is now in GrRectanizer_skyline.cpp
-//GrRectanizer* GrRectanizer::Factory(int width, int height) {
-// return SkNEW_ARGS(GrRectanizerPow2, (width, height));
-//}
diff --git a/chromium/third_party/skia/src/gpu/GrRectanizer.h b/chromium/third_party/skia/src/gpu/GrRectanizer.h
index c1ac2c129ec..dc697c41d7d 100644
--- a/chromium/third_party/skia/src/gpu/GrRectanizer.h
+++ b/chromium/third_party/skia/src/gpu/GrRectanizer.h
@@ -8,14 +8,9 @@
#ifndef GrRectanizer_DEFINED
#define GrRectanizer_DEFINED
-#include "GrPoint.h"
+#include "GrTypes.h"
-class GrRectanizerPurgeListener {
-public:
- virtual ~GrRectanizerPurgeListener() {}
-
- virtual void notifyPurgeStrip(void*, int yCoord) = 0;
-};
+struct SkIPoint16;
class GrRectanizer {
public:
@@ -31,15 +26,11 @@ public:
int width() const { return fWidth; }
int height() const { return fHeight; }
- virtual bool addRect(int width, int height, GrIPoint16* loc) = 0;
+ // Attempt to add a rect. Return true on success; false on failure. If
+ // successful the position in the atlas is returned in 'loc'.
+ virtual bool addRect(int width, int height, SkIPoint16* loc) = 0;
virtual float percentFull() const = 0;
- // return the Y-coordinate of a strip that should be purged, given height
- // i.e. return the oldest such strip, or some other criteria. Return -1
- // if there is no candidate
- virtual int stripToPurge(int height) const = 0;
- virtual void purgeStripAtY(int yCoord) = 0;
-
/**
* Our factory, which returns the subclass du jour
*/
diff --git a/chromium/third_party/skia/src/gpu/GrRectanizer_fifo.cpp b/chromium/third_party/skia/src/gpu/GrRectanizer_fifo.cpp
deleted file mode 100644
index 9dd808618b1..00000000000
--- a/chromium/third_party/skia/src/gpu/GrRectanizer_fifo.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-
-/*
- * Copyright 2010 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-
-#include "GrRectanizer.h"
-#include "GrTBSearch.h"
-
-#define MIN_HEIGHT_POW2 2
-
-class GrRectanizerFIFO : public GrRectanizer {
-public:
- GrRectanizerFIFO(int w, int h) : GrRectanizer(w, h) {
- fNextStripY = 0;
- fAreaSoFar = 0;
- sk_bzero(fRows, sizeof(fRows));
- }
-
- virtual ~GrRectanizerFIFO() {
- }
-
- virtual bool addRect(int w, int h, GrIPoint16* loc);
-
- virtual float percentFull() const {
- return fAreaSoFar / ((float)this->width() * this->height());
- }
-
- virtual int stripToPurge(int height) const { return -1; }
- virtual void purgeStripAtY(int yCoord) { }
-
- ///////////////////////////////////////////////////////////////////////////
-
- struct Row {
- GrIPoint16 fLoc;
- int fRowHeight;
-
- bool canAddWidth(int width, int containerWidth) const {
- return fLoc.fX + width <= containerWidth;
- }
- };
-
- Row fRows[16];
-
- static int HeightToRowIndex(int height) {
- SkASSERT(height >= MIN_HEIGHT_POW2);
- return 32 - Gr_clz(height - 1);
- }
-
- int fNextStripY;
- int32_t fAreaSoFar;
-
- bool canAddStrip(int height) const {
- return fNextStripY + height <= this->height();
- }
-
- void initRow(Row* row, int rowHeight) {
- row->fLoc.set(0, fNextStripY);
- row->fRowHeight = rowHeight;
- fNextStripY += rowHeight;
- }
-};
-
-bool GrRectanizerFIFO::addRect(int width, int height, GrIPoint16* loc) {
- if ((unsigned)width > (unsigned)this->width() ||
- (unsigned)height > (unsigned)this->height()) {
- return false;
- }
-
- int32_t area = width * height;
-
- /*
- We use bsearch, but there may be more than one row with the same height,
- so we actually search for height-1, which can only be a pow2 itself if
- height == 2. Thus we set a minimum height.
- */
- height = GrNextPow2(height);
- if (height < MIN_HEIGHT_POW2) {
- height = MIN_HEIGHT_POW2;
- }
-
- Row* row = &fRows[HeightToRowIndex(height)];
- SkASSERT(row->fRowHeight == 0 || row->fRowHeight == height);
-
- if (0 == row->fRowHeight) {
- if (!this->canAddStrip(height)) {
- return false;
- }
- this->initRow(row, height);
- } else {
- if (!row->canAddWidth(width, this->width())) {
- if (!this->canAddStrip(height)) {
- return false;
- }
- // that row is now "full", so retarget our Row record for
- // another one
- this->initRow(row, height);
- }
- }
-
- SkASSERT(row->fRowHeight == height);
- SkASSERT(row->canAddWidth(width, this->width()));
- *loc = row->fLoc;
- row->fLoc.fX += width;
-
- SkASSERT(row->fLoc.fX <= this->width());
- SkASSERT(row->fLoc.fY <= this->height());
- SkASSERT(fNextStripY <= this->height());
- fAreaSoFar += area;
- return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-GrRectanizer* GrRectanizer::Factory(int width, int height) {
- return SkNEW_ARGS(GrRectanizerFIFO, (width, height));
-}
diff --git a/chromium/third_party/skia/src/gpu/GrRectanizer_pow2.cpp b/chromium/third_party/skia/src/gpu/GrRectanizer_pow2.cpp
new file mode 100644
index 00000000000..2d443cab8c6
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/GrRectanizer_pow2.cpp
@@ -0,0 +1,60 @@
+
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrRectanizer_pow2.h"
+
+bool GrRectanizerPow2::addRect(int width, int height, SkIPoint16* loc) {
+ if ((unsigned)width > (unsigned)this->width() ||
+ (unsigned)height > (unsigned)this->height()) {
+ return false;
+ }
+
+ int32_t area = width * height; // computed here since height will be modified
+
+ height = GrNextPow2(height);
+ if (height < kMIN_HEIGHT_POW2) {
+ height = kMIN_HEIGHT_POW2;
+ }
+
+ Row* row = &fRows[HeightToRowIndex(height)];
+ SkASSERT(row->fRowHeight == 0 || row->fRowHeight == height);
+
+ if (0 == row->fRowHeight) {
+ if (!this->canAddStrip(height)) {
+ return false;
+ }
+ this->initRow(row, height);
+ } else {
+ if (!row->canAddWidth(width, this->width())) {
+ if (!this->canAddStrip(height)) {
+ return false;
+ }
+ // that row is now "full", so retarget our Row record for
+ // another one
+ this->initRow(row, height);
+ }
+ }
+
+ SkASSERT(row->fRowHeight == height);
+ SkASSERT(row->canAddWidth(width, this->width()));
+ *loc = row->fLoc;
+ row->fLoc.fX += width;
+
+ SkASSERT(row->fLoc.fX <= this->width());
+ SkASSERT(row->fLoc.fY <= this->height());
+ SkASSERT(fNextStripY <= this->height());
+ fAreaSoFar += area;
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+// factory is now in GrRectanizer_skyline.cpp
+//GrRectanizer* GrRectanizer::Factory(int width, int height) {
+// return SkNEW_ARGS(GrRectanizerPow2, (width, height));
+//}
diff --git a/chromium/third_party/skia/src/gpu/GrRectanizer_pow2.h b/chromium/third_party/skia/src/gpu/GrRectanizer_pow2.h
new file mode 100644
index 00000000000..7bf2b868c05
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/GrRectanizer_pow2.h
@@ -0,0 +1,79 @@
+/*
+* Copyright 2014 Google Inc.
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+
+#ifndef GrRectanizer_pow2_DEFINED
+#define GrRectanizer_pow2_DEFINED
+
+#include "GrRectanizer.h"
+#include "SkPoint.h"
+
+// This Rectanizer quantizes the incoming rects to powers of 2. Each power
+// of two can have, at most, one active row/shelf. Once a row/shelf for
+// a particular power of two gets full its fRows entry is recycled to point
+// to a new row.
+// The skyline algorithm almost always provides a better packing.
+class GrRectanizerPow2 : public GrRectanizer {
+public:
+ GrRectanizerPow2(int w, int h) : INHERITED(w, h) {
+ this->reset();
+ }
+
+ virtual ~GrRectanizerPow2() { }
+
+ virtual void reset() SK_OVERRIDE {
+ fNextStripY = 0;
+ fAreaSoFar = 0;
+ sk_bzero(fRows, sizeof(fRows));
+ }
+
+ virtual bool addRect(int w, int h, SkIPoint16* loc) SK_OVERRIDE;
+
+ virtual float percentFull() const SK_OVERRIDE {
+ return fAreaSoFar / ((float)this->width() * this->height());
+ }
+
+private:
+ static const int kMIN_HEIGHT_POW2 = 2;
+ static const int kMaxExponent = 16;
+
+ struct Row {
+ SkIPoint16 fLoc;
+ // fRowHeight is actually known by this struct's position in fRows
+ // but it is used to signal if there exists an open row of this height
+ int fRowHeight;
+
+ bool canAddWidth(int width, int containerWidth) const {
+ return fLoc.fX + width <= containerWidth;
+ }
+ };
+
+ Row fRows[kMaxExponent]; // 0-th entry will be unused
+
+ int fNextStripY;
+ int32_t fAreaSoFar;
+
+ static int HeightToRowIndex(int height) {
+ SkASSERT(height >= kMIN_HEIGHT_POW2);
+ int index = 32 - SkCLZ(height - 1);
+ SkASSERT(index < kMaxExponent);
+ return index;
+ }
+
+ bool canAddStrip(int height) const {
+ return fNextStripY + height <= this->height();
+ }
+
+ void initRow(Row* row, int rowHeight) {
+ row->fLoc.set(0, fNextStripY);
+ row->fRowHeight = rowHeight;
+ fNextStripY += rowHeight;
+ }
+
+ typedef GrRectanizer INHERITED;
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/GrRectanizer_skyline.cpp b/chromium/third_party/skia/src/gpu/GrRectanizer_skyline.cpp
index a55451a896b..44da1c326a1 100755
--- a/chromium/third_party/skia/src/gpu/GrRectanizer_skyline.cpp
+++ b/chromium/third_party/skia/src/gpu/GrRectanizer_skyline.cpp
@@ -6,56 +6,10 @@
* found in the LICENSE file.
*/
-#include "GrRectanizer.h"
-#include "SkTDArray.h"
+#include "GrRectanizer_skyline.h"
+#include "SkPoint.h"
-// Pack rectangles and track the current silhouette
-// Based in part on Jukka Jylänki's work at http://clb.demon.fi
-
-class GrRectanizerSkyline : public GrRectanizer {
-public:
- GrRectanizerSkyline(int w, int h) : GrRectanizer(w, h) {
- reset();
- }
-
- virtual ~GrRectanizerSkyline() {
- }
-
- virtual void reset() {
- fAreaSoFar = 0;
- fSkyline.reset();
- SkylineSegment* seg = fSkyline.append(1);
- seg->fX = 0;
- seg->fY = 0;
- seg->fWidth = width();
- }
-
- virtual bool addRect(int w, int h, GrIPoint16* loc);
-
- virtual float percentFull() const {
- return fAreaSoFar / ((float)this->width() * this->height());
- }
-
- virtual int stripToPurge(int height) const { return -1; }
- virtual void purgeStripAtY(int yCoord) { }
-
- ///////////////////////////////////////////////////////////////////////////
-
- struct SkylineSegment {
- int fX;
- int fY;
- int fWidth;
- };
-
- SkTDArray<SkylineSegment> fSkyline;
-
- int32_t fAreaSoFar;
-
- bool rectangleFits(int skylineIndex, int width, int height, int* y) const;
- void addSkylineLevel(int skylineIndex, int x, int y, int width, int height);
-};
-
-bool GrRectanizerSkyline::addRect(int width, int height, GrIPoint16* loc) {
+bool GrRectanizerSkyline::addRect(int width, int height, SkIPoint16* loc) {
if ((unsigned)width > (unsigned)this->width() ||
(unsigned)height > (unsigned)this->height()) {
return false;
@@ -104,13 +58,13 @@ bool GrRectanizerSkyline::rectangleFits(int skylineIndex, int width, int height,
int i = skylineIndex;
int y = fSkyline[skylineIndex].fY;
while (widthLeft > 0) {
- y = SkMax32(y, fSkyline[i].fY);
+ y = SkMax32(y, fSkyline[i].fY);
if (y + height > this->height()) {
return false;
}
- widthLeft -= fSkyline[i].fWidth;
- ++i;
- SkASSERT(i < fSkyline.count() || widthLeft <= 0);
+ widthLeft -= fSkyline[i].fWidth;
+ ++i;
+ SkASSERT(i < fSkyline.count() || widthLeft <= 0);
}
*ypos = y;
@@ -127,8 +81,9 @@ void GrRectanizerSkyline::addSkylineLevel(int skylineIndex, int x, int y, int wi
SkASSERT(newSegment.fX + newSegment.fWidth <= this->width());
SkASSERT(newSegment.fY <= this->height());
- // delete width of this skyline segment from following ones
+ // delete width of the new skyline segment from following ones
for (int i = skylineIndex+1; i < fSkyline.count(); ++i) {
+ // The new segment subsumes all or part of fSkyline[i]
SkASSERT(fSkyline[i-1].fX <= fSkyline[i].fX);
if (fSkyline[i].fX < fSkyline[i-1].fX + fSkyline[i-1].fWidth) {
@@ -138,14 +93,16 @@ void GrRectanizerSkyline::addSkylineLevel(int skylineIndex, int x, int y, int wi
fSkyline[i].fWidth -= shrink;
if (fSkyline[i].fWidth <= 0) {
+ // fully consumed
fSkyline.remove(i);
--i;
- }
- else
+ } else {
+ // only partially consumed
break;
- }
- else
+ }
+ } else {
break;
+ }
}
// merge fSkylines
diff --git a/chromium/third_party/skia/src/gpu/GrRectanizer_skyline.h b/chromium/third_party/skia/src/gpu/GrRectanizer_skyline.h
new file mode 100644
index 00000000000..21043c0b6d1
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/GrRectanizer_skyline.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrRectanizer_skyline_DEFINED
+#define GrRectanizer_skyline_DEFINED
+
+#include "GrRectanizer.h"
+#include "SkTDArray.h"
+
+// Pack rectangles and track the current silhouette
+// Based, in part, on Jukka Jylanki's work at http://clb.demon.fi
+class GrRectanizerSkyline : public GrRectanizer {
+public:
+ GrRectanizerSkyline(int w, int h) : INHERITED(w, h) {
+ this->reset();
+ }
+
+ virtual ~GrRectanizerSkyline() { }
+
+ virtual void reset() SK_OVERRIDE{
+ fAreaSoFar = 0;
+ fSkyline.reset();
+ SkylineSegment* seg = fSkyline.append(1);
+ seg->fX = 0;
+ seg->fY = 0;
+ seg->fWidth = this->width();
+ }
+
+ virtual bool addRect(int w, int h, SkIPoint16* loc) SK_OVERRIDE;
+
+ virtual float percentFull() const SK_OVERRIDE {
+ return fAreaSoFar / ((float)this->width() * this->height());
+ }
+
+private:
+ struct SkylineSegment {
+ int fX;
+ int fY;
+ int fWidth;
+ };
+
+ SkTDArray<SkylineSegment> fSkyline;
+
+ int32_t fAreaSoFar;
+
+ // Can a width x height rectangle fit in the free space represented by
+ // the skyline segments >= 'skylineIndex'? If so, return true and fill in
+ // 'y' with the y-location at which it fits (the x location is pulled from
+ // 'skylineIndex's segment.
+ bool rectangleFits(int skylineIndex, int width, int height, int* y) const;
+ // Update the skyline structure to include a width x height rect located
+ // at x,y.
+ void addSkylineLevel(int skylineIndex, int x, int y, int width, int height);
+
+ typedef GrRectanizer INHERITED;
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/GrRedBlackTree.h b/chromium/third_party/skia/src/gpu/GrRedBlackTree.h
index 1b2195c4f7e..d9b1a049bd8 100644
--- a/chromium/third_party/skia/src/gpu/GrRedBlackTree.h
+++ b/chromium/third_party/skia/src/gpu/GrRedBlackTree.h
@@ -8,6 +8,7 @@
#ifndef GrRedBlackTree_DEFINED
#define GrRedBlackTree_DEFINED
+#include "GrConfig.h"
#include "SkTypes.h"
template <typename T>
@@ -22,6 +23,11 @@ public:
bool operator()(const T* a, const T* b) const { return *a < *b; }
};
+class GrStrLess {
+public:
+ bool operator()(const char* a, const char* b) const { return strcmp(a,b) < 0; }
+};
+
/**
* In debug build this will cause full traversals of the tree when the validate
* is called on insert and remove. Useful for debugging but very slow.
@@ -34,7 +40,7 @@ public:
* will be created and used for all comparisons.
*/
template <typename T, typename C = GrLess<T> >
-class GrRedBlackTree : public SkNoncopyable {
+class GrRedBlackTree : SkNoncopyable {
public:
/**
* Creates an empty tree.
@@ -124,8 +130,6 @@ public:
*/
void remove(const Iter& iter) { deleteAtNode(iter.fN); }
- static void UnitTest();
-
private:
enum Color {
kRed_Color,
@@ -941,175 +945,4 @@ bool GrRedBlackTree<T,C>::validateChildRelations(const Node* n,
}
#endif
-#include "SkRandom.h"
-
-template <typename T, typename C>
-void GrRedBlackTree<T,C>::UnitTest() {
- GrRedBlackTree<int> tree;
-
- SkRandom r;
-
- int count[100] = {0};
- // add 10K ints
- for (int i = 0; i < 10000; ++i) {
- int x = r.nextU()%100;
- SkDEBUGCODE(Iter xi = ) tree.insert(x);
- SkASSERT(*xi == x);
- ++count[x];
- }
-
- tree.insert(0);
- ++count[0];
- tree.insert(99);
- ++count[99];
- SkASSERT(*tree.begin() == 0);
- SkASSERT(*tree.last() == 99);
- SkASSERT(--(++tree.begin()) == tree.begin());
- SkASSERT(--tree.end() == tree.last());
- SkASSERT(tree.count() == 10002);
-
- int c = 0;
- // check that we iterate through the correct number of
- // elements and they are properly sorted.
- for (Iter a = tree.begin(); tree.end() != a; ++a) {
- Iter b = a;
- ++b;
- ++c;
- SkASSERT(b == tree.end() || *a <= *b);
- }
- SkASSERT(c == tree.count());
-
- // check that the tree reports the correct number of each int
- // and that we can iterate through them correctly both forward
- // and backward.
- for (int i = 0; i < 100; ++i) {
- int c;
- c = tree.countOf(i);
- SkASSERT(c == count[i]);
- c = 0;
- Iter iter = tree.findFirst(i);
- while (iter != tree.end() && *iter == i) {
- ++c;
- ++iter;
- }
- SkASSERT(count[i] == c);
- c = 0;
- iter = tree.findLast(i);
- if (iter != tree.end()) {
- do {
- if (*iter == i) {
- ++c;
- } else {
- break;
- }
- if (iter != tree.begin()) {
- --iter;
- } else {
- break;
- }
- } while (true);
- }
- SkASSERT(c == count[i]);
- }
- // remove all the ints between 25 and 74. Randomly chose to remove
- // the first, last, or any entry for each.
- for (int i = 25; i < 75; ++i) {
- while (0 != tree.countOf(i)) {
- --count[i];
- int x = r.nextU() % 3;
- Iter iter;
- switch (x) {
- case 0:
- iter = tree.findFirst(i);
- break;
- case 1:
- iter = tree.findLast(i);
- break;
- case 2:
- default:
- iter = tree.find(i);
- break;
- }
- tree.remove(iter);
- }
- SkASSERT(0 == count[i]);
- SkASSERT(tree.findFirst(i) == tree.end());
- SkASSERT(tree.findLast(i) == tree.end());
- SkASSERT(tree.find(i) == tree.end());
- }
- // remove all of the 0 entries. (tests removing begin())
- SkASSERT(*tree.begin() == 0);
- SkASSERT(*(--tree.end()) == 99);
- while (0 != tree.countOf(0)) {
- --count[0];
- tree.remove(tree.find(0));
- }
- SkASSERT(0 == count[0]);
- SkASSERT(tree.findFirst(0) == tree.end());
- SkASSERT(tree.findLast(0) == tree.end());
- SkASSERT(tree.find(0) == tree.end());
- SkASSERT(0 < *tree.begin());
-
- // remove all the 99 entries (tests removing last()).
- while (0 != tree.countOf(99)) {
- --count[99];
- tree.remove(tree.find(99));
- }
- SkASSERT(0 == count[99]);
- SkASSERT(tree.findFirst(99) == tree.end());
- SkASSERT(tree.findLast(99) == tree.end());
- SkASSERT(tree.find(99) == tree.end());
- SkASSERT(99 > *(--tree.end()));
- SkASSERT(tree.last() == --tree.end());
-
- // Make sure iteration still goes through correct number of entries
- // and is still sorted correctly.
- c = 0;
- for (Iter a = tree.begin(); tree.end() != a; ++a) {
- Iter b = a;
- ++b;
- ++c;
- SkASSERT(b == tree.end() || *a <= *b);
- }
- SkASSERT(c == tree.count());
-
- // repeat check that correct number of each entry is in the tree
- // and iterates correctly both forward and backward.
- for (int i = 0; i < 100; ++i) {
- SkASSERT(tree.countOf(i) == count[i]);
- int c = 0;
- Iter iter = tree.findFirst(i);
- while (iter != tree.end() && *iter == i) {
- ++c;
- ++iter;
- }
- SkASSERT(count[i] == c);
- c = 0;
- iter = tree.findLast(i);
- if (iter != tree.end()) {
- do {
- if (*iter == i) {
- ++c;
- } else {
- break;
- }
- if (iter != tree.begin()) {
- --iter;
- } else {
- break;
- }
- } while (true);
- }
- SkASSERT(count[i] == c);
- }
-
- // remove all entries
- while (!tree.empty()) {
- tree.remove(tree.begin());
- }
-
- // test reset on empty tree.
- tree.reset();
-}
-
#endif
diff --git a/chromium/third_party/skia/src/gpu/GrReducedClip.cpp b/chromium/third_party/skia/src/gpu/GrReducedClip.cpp
index 8480e041b8d..6ad9cc6d8b8 100644
--- a/chromium/third_party/skia/src/gpu/GrReducedClip.cpp
+++ b/chromium/third_party/skia/src/gpu/GrReducedClip.cpp
@@ -72,6 +72,8 @@ void ReduceClipStack(const SkClipStack& stack,
*requiresAA = false;
}
} else if (isectRect.intersect(stackBounds, scalarQueryBounds)) {
+ // If the caller asked for tighter integer bounds we may be able to
+ // return kAllIn and give the bounds with no elements
if (NULL != tighterBounds) {
isectRect.roundOut(tighterBounds);
SkRect scalarTighterBounds = SkRect::Make(*tighterBounds);
@@ -83,14 +85,14 @@ void ReduceClipStack(const SkClipStack& stack,
*initialState = kAllIn_InitialState;
return;
}
- *initialState = kAllOut_InitialState;
- // iior should only be true if aa/non-aa status matches among all elements.
- SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart);
- bool doAA = iter.prev()->isAA();
- SkNEW_INSERT_AT_LLIST_HEAD(result, Element, (isectRect, SkRegion::kReplace_Op, doAA));
- if (NULL != requiresAA) {
- *requiresAA = doAA;
- }
+ }
+ *initialState = kAllOut_InitialState;
+ // iior should only be true if aa/non-aa status matches among all elements.
+ SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart);
+ bool doAA = iter.prev()->isAA();
+ SkNEW_INSERT_AT_LLIST_HEAD(result, Element, (isectRect, SkRegion::kReplace_Op, doAA));
+ if (NULL != requiresAA) {
+ *requiresAA = doAA;
}
} else {
*initialState = kAllOut_InitialState;
diff --git a/chromium/third_party/skia/src/gpu/GrReducedClip.h b/chromium/third_party/skia/src/gpu/GrReducedClip.h
index 0b79f2c7f56..cbb03465fd0 100644
--- a/chromium/third_party/skia/src/gpu/GrReducedClip.h
+++ b/chromium/third_party/skia/src/gpu/GrReducedClip.h
@@ -30,13 +30,14 @@ enum InitialState {
* required to process any of the elements in the result.
*
* This may become a member function of SkClipStack when its interface is determined to be stable.
+ * Marked SK_API so that SkLua can call this in a shared library build.
*/
-void ReduceClipStack(const SkClipStack& stack,
- const SkIRect& queryBounds,
- ElementList* result,
- int32_t* resultGenID,
- InitialState* initialState,
- SkIRect* tighterBounds = NULL,
- bool* requiresAA = NULL);
+SK_API void ReduceClipStack(const SkClipStack& stack,
+ const SkIRect& queryBounds,
+ ElementList* result,
+ int32_t* resultGenID,
+ InitialState* initialState,
+ SkIRect* tighterBounds = NULL,
+ bool* requiresAA = NULL);
} // namespace GrReducedClip
diff --git a/chromium/third_party/skia/src/gpu/GrRenderTarget.cpp b/chromium/third_party/skia/src/gpu/GrRenderTarget.cpp
index f18df2cfa6d..13fc2290751 100644
--- a/chromium/third_party/skia/src/gpu/GrRenderTarget.cpp
+++ b/chromium/third_party/skia/src/gpu/GrRenderTarget.cpp
@@ -54,7 +54,16 @@ void GrRenderTarget::resolve() {
context->resolveRenderTarget(this);
}
-size_t GrRenderTarget::sizeInBytes() const {
+void GrRenderTarget::discard() {
+ // go through context so that all necessary flushing occurs
+ GrContext* context = this->getContext();
+ if (NULL == context) {
+ return;
+ }
+ context->discardRenderTarget(this);
+}
+
+size_t GrRenderTarget::gpuMemorySize() const {
size_t colorBits;
if (kUnknown_GrPixelConfig == fDesc.fConfig) {
colorBits = 32; // don't know, make a guess
@@ -64,7 +73,7 @@ size_t GrRenderTarget::sizeInBytes() const {
uint64_t size = fDesc.fWidth;
size *= fDesc.fHeight;
size *= colorBits;
- size *= GrMax(1, fDesc.fSampleCnt);
+ size *= SkTMax(1, fDesc.fSampleCnt);
return (size_t)(size / 8);
}
diff --git a/chromium/third_party/skia/src/gpu/GrResourceCache.cpp b/chromium/third_party/skia/src/gpu/GrResourceCache.cpp
index 5cf3f82c7d7..529c3a5d1db 100644
--- a/chromium/third_party/skia/src/gpu/GrResourceCache.cpp
+++ b/chromium/third_party/skia/src/gpu/GrResourceCache.cpp
@@ -9,15 +9,26 @@
#include "GrResourceCache.h"
-#include "GrResource.h"
+#include "GrCacheable.h"
+DECLARE_SKMESSAGEBUS_MESSAGE(GrResourceInvalidatedMessage);
+
+///////////////////////////////////////////////////////////////////////////////
+
+void GrCacheable::didChangeGpuMemorySize() const {
+ if (this->isInCache()) {
+ fCacheEntry->didChangeResourceSize();
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
GrResourceKey::ResourceType GrResourceKey::GenerateResourceType() {
static int32_t gNextType = 0;
int32_t type = sk_atomic_inc(&gNextType);
if (type >= (1 << 8 * sizeof(ResourceType))) {
- GrCrash("Too many Resource Types");
+ SkFAIL("Too many Resource Types");
}
return static_cast<ResourceType>(type);
@@ -25,26 +36,44 @@ GrResourceKey::ResourceType GrResourceKey::GenerateResourceType() {
///////////////////////////////////////////////////////////////////////////////
-GrResourceEntry::GrResourceEntry(const GrResourceKey& key, GrResource* resource)
- : fKey(key), fResource(resource) {
+GrResourceCacheEntry::GrResourceCacheEntry(GrResourceCache* resourceCache,
+ const GrResourceKey& key,
+ GrCacheable* resource)
+ : fResourceCache(resourceCache),
+ fKey(key),
+ fResource(resource),
+ fCachedSize(resource->gpuMemorySize()),
+ fIsExclusive(false) {
// we assume ownership of the resource, and will unref it when we die
SkASSERT(resource);
resource->ref();
}
-GrResourceEntry::~GrResourceEntry() {
+GrResourceCacheEntry::~GrResourceCacheEntry() {
fResource->setCacheEntry(NULL);
fResource->unref();
}
#ifdef SK_DEBUG
-void GrResourceEntry::validate() const {
+void GrResourceCacheEntry::validate() const {
+ SkASSERT(fResourceCache);
SkASSERT(fResource);
SkASSERT(fResource->getCacheEntry() == this);
+ SkASSERT(fResource->gpuMemorySize() == fCachedSize);
fResource->validate();
}
#endif
+void GrResourceCacheEntry::didChangeResourceSize() {
+ size_t oldSize = fCachedSize;
+ fCachedSize = fResource->gpuMemorySize();
+ if (fCachedSize > oldSize) {
+ fResourceCache->didIncreaseResourceSize(this, fCachedSize - oldSize);
+ } else if (fCachedSize < oldSize) {
+ fResourceCache->didDecreaseResourceSize(this, oldSize - fCachedSize);
+ }
+}
+
///////////////////////////////////////////////////////////////////////////////
GrResourceCache::GrResourceCache(int maxCount, size_t maxBytes) :
@@ -74,7 +103,7 @@ GrResourceCache::~GrResourceCache() {
EntryList::Iter iter;
// Unlike the removeAll, here we really remove everything, including locked resources.
- while (GrResourceEntry* entry = fList.head()) {
+ while (GrResourceCacheEntry* entry = fList.head()) {
GrAutoResourceCacheValidate atcv(this);
// remove from our cache
@@ -107,14 +136,14 @@ void GrResourceCache::setLimits(int maxResources, size_t maxResourceBytes) {
}
}
-void GrResourceCache::internalDetach(GrResourceEntry* entry,
+void GrResourceCache::internalDetach(GrResourceCacheEntry* entry,
BudgetBehaviors behavior) {
fList.remove(entry);
// update our stats
if (kIgnore_BudgetBehavior == behavior) {
fClientDetachedCount += 1;
- fClientDetachedBytes += entry->resource()->sizeInBytes();
+ fClientDetachedBytes += entry->fCachedSize;
#if GR_CACHE_STATS
if (fHighWaterClientDetachedCount < fClientDetachedCount) {
@@ -129,23 +158,23 @@ void GrResourceCache::internalDetach(GrResourceEntry* entry,
SkASSERT(kAccountFor_BudgetBehavior == behavior);
fEntryCount -= 1;
- fEntryBytes -= entry->resource()->sizeInBytes();
+ fEntryBytes -= entry->fCachedSize;
}
}
-void GrResourceCache::attachToHead(GrResourceEntry* entry,
+void GrResourceCache::attachToHead(GrResourceCacheEntry* entry,
BudgetBehaviors behavior) {
fList.addToHead(entry);
// update our stats
if (kIgnore_BudgetBehavior == behavior) {
fClientDetachedCount -= 1;
- fClientDetachedBytes -= entry->resource()->sizeInBytes();
+ fClientDetachedBytes -= entry->fCachedSize;
} else {
SkASSERT(kAccountFor_BudgetBehavior == behavior);
fEntryCount += 1;
- fEntryBytes += entry->resource()->sizeInBytes();
+ fEntryBytes += entry->fCachedSize;
#if GR_CACHE_STATS
if (fHighWaterEntryCount < fEntryCount) {
@@ -163,15 +192,15 @@ void GrResourceCache::attachToHead(GrResourceEntry* entry,
// is relying on the texture.
class GrTFindUnreffedFunctor {
public:
- bool operator()(const GrResourceEntry* entry) const {
+ bool operator()(const GrResourceCacheEntry* entry) const {
return entry->resource()->unique();
}
};
-GrResource* GrResourceCache::find(const GrResourceKey& key, uint32_t ownershipFlags) {
+GrCacheable* GrResourceCache::find(const GrResourceKey& key, uint32_t ownershipFlags) {
GrAutoResourceCacheValidate atcv(this);
- GrResourceEntry* entry = NULL;
+ GrResourceCacheEntry* entry = NULL;
if (ownershipFlags & kNoOtherOwners_OwnershipFlag) {
GrTFindUnreffedFunctor functor;
@@ -197,7 +226,7 @@ GrResource* GrResourceCache::find(const GrResourceKey& key, uint32_t ownershipFl
}
void GrResourceCache::addResource(const GrResourceKey& key,
- GrResource* resource,
+ GrCacheable* resource,
uint32_t ownershipFlags) {
SkASSERT(NULL == resource->getCacheEntry());
// we don't expect to create new resources during a purge. In theory
@@ -207,7 +236,7 @@ void GrResourceCache::addResource(const GrResourceKey& key,
SkASSERT(!fPurging);
GrAutoResourceCacheValidate atcv(this);
- GrResourceEntry* entry = SkNEW_ARGS(GrResourceEntry, (key, resource));
+ GrResourceCacheEntry* entry = SkNEW_ARGS(GrResourceCacheEntry, (this, key, resource));
resource->setCacheEntry(entry);
this->attachToHead(entry);
@@ -219,9 +248,12 @@ void GrResourceCache::addResource(const GrResourceKey& key,
}
-void GrResourceCache::makeExclusive(GrResourceEntry* entry) {
+void GrResourceCache::makeExclusive(GrResourceCacheEntry* entry) {
GrAutoResourceCacheValidate atcv(this);
+ SkASSERT(!entry->fIsExclusive);
+ entry->fIsExclusive = true;
+
// When scratch textures are detached (to hide them from future finds) they
// still count against the resource budget
this->internalDetach(entry, kIgnore_BudgetBehavior);
@@ -232,37 +264,59 @@ void GrResourceCache::makeExclusive(GrResourceEntry* entry) {
#endif
}
-void GrResourceCache::removeInvalidResource(GrResourceEntry* entry) {
+void GrResourceCache::removeInvalidResource(GrResourceCacheEntry* entry) {
// If the resource went invalid while it was detached then purge it
// This can happen when a 3D context was lost,
// the client called GrContext::contextDestroyed() to notify Gr,
// and then later an SkGpuDevice's destructor releases its backing
// texture (which was invalidated at contextDestroyed time).
+ // TODO: Safely delete the GrResourceCacheEntry as well.
fClientDetachedCount -= 1;
fEntryCount -= 1;
- size_t size = entry->resource()->sizeInBytes();
- fClientDetachedBytes -= size;
- fEntryBytes -= size;
+ fClientDetachedBytes -= entry->fCachedSize;
+ fEntryBytes -= entry->fCachedSize;
+ entry->fCachedSize = 0;
}
-void GrResourceCache::makeNonExclusive(GrResourceEntry* entry) {
+void GrResourceCache::makeNonExclusive(GrResourceCacheEntry* entry) {
GrAutoResourceCacheValidate atcv(this);
#ifdef SK_DEBUG
fExclusiveList.remove(entry);
#endif
- if (entry->resource()->isValid()) {
+ if (entry->resource()->isValidOnGpu()) {
// Since scratch textures still count against the cache budget even
// when they have been removed from the cache, re-adding them doesn't
// alter the budget information.
attachToHead(entry, kIgnore_BudgetBehavior);
fCache.insert(entry->key(), entry);
+
+ SkASSERT(entry->fIsExclusive);
+ entry->fIsExclusive = false;
} else {
this->removeInvalidResource(entry);
}
}
+void GrResourceCache::didIncreaseResourceSize(const GrResourceCacheEntry* entry, size_t amountInc) {
+ fEntryBytes += amountInc;
+ if (entry->fIsExclusive) {
+ fClientDetachedBytes += amountInc;
+ }
+ this->purgeAsNeeded();
+}
+
+void GrResourceCache::didDecreaseResourceSize(const GrResourceCacheEntry* entry, size_t amountDec) {
+ fEntryBytes -= amountDec;
+ if (entry->fIsExclusive) {
+ fClientDetachedBytes -= amountDec;
+ }
+#ifdef SK_DEBUG
+ this->validate();
+#endif
+}
+
/**
* Destroying a resource may potentially trigger the unlock of additional
* resources which in turn will trigger a nested purge. We block the nested
@@ -312,14 +366,13 @@ void GrResourceCache::purgeInvalidated() {
//
// This is complicated and confusing. May try this in the future. For
// now, these resources are just LRU'd as if we never got the message.
- GrResourceEntry* entry = fCache.find(invalidated[i].key, GrTFindUnreffedFunctor());
- if (entry) {
+ while (GrResourceCacheEntry* entry = fCache.find(invalidated[i].key, GrTFindUnreffedFunctor())) {
this->deleteResource(entry);
}
}
}
-void GrResourceCache::deleteResource(GrResourceEntry* entry) {
+void GrResourceCache::deleteResource(GrResourceCacheEntry* entry) {
SkASSERT(1 == entry->fResource->getRefCnt());
// remove from our cache
@@ -347,7 +400,7 @@ void GrResourceCache::internalPurge(int extraCount, size_t extraBytes) {
// doubly linked list doesn't invalidate its data/pointers
// outside of the specific area where a deletion occurs (e.g.,
// in internalDetach)
- GrResourceEntry* entry = iter.init(fList, EntryList::Iter::kTail_IterStart);
+ GrResourceCacheEntry* entry = iter.init(fList, EntryList::Iter::kTail_IterStart);
while (NULL != entry) {
GrAutoResourceCacheValidate atcv(this);
@@ -358,7 +411,7 @@ void GrResourceCache::internalPurge(int extraCount, size_t extraBytes) {
break;
}
- GrResourceEntry* prev = iter.prev();
+ GrResourceCacheEntry* prev = iter.prev();
if (entry->fResource->unique()) {
changed = true;
this->deleteResource(entry);
@@ -371,7 +424,7 @@ void GrResourceCache::internalPurge(int extraCount, size_t extraBytes) {
void GrResourceCache::purgeAllUnlocked() {
GrAutoResourceCacheValidate atcv(this);
- // we can have one GrResource holding a lock on another
+ // we can have one GrCacheable holding a lock on another
// so we don't want to just do a simple loop kicking each
// entry out. Instead change the budget and purge.
@@ -406,11 +459,11 @@ size_t GrResourceCache::countBytes(const EntryList& list) {
EntryList::Iter iter;
- const GrResourceEntry* entry = iter.init(const_cast<EntryList&>(list),
- EntryList::Iter::kTail_IterStart);
+ const GrResourceCacheEntry* entry = iter.init(const_cast<EntryList&>(list),
+ EntryList::Iter::kTail_IterStart);
for ( ; NULL != entry; entry = iter.prev()) {
- bytes += entry->resource()->sizeInBytes();
+ bytes += entry->resource()->gpuMemorySize();
}
return bytes;
}
@@ -428,14 +481,11 @@ void GrResourceCache::validate() const {
SkASSERT(fClientDetachedCount <= fEntryCount);
SkASSERT((fEntryCount - fClientDetachedCount) == fCache.count());
- fCache.validate();
-
-
EntryList::Iter iter;
// check that the exclusively held entries are okay
- const GrResourceEntry* entry = iter.init(const_cast<EntryList&>(fExclusiveList),
- EntryList::Iter::kHead_IterStart);
+ const GrResourceCacheEntry* entry = iter.init(const_cast<EntryList&>(fExclusiveList),
+ EntryList::Iter::kHead_IterStart);
for ( ; NULL != entry; entry = iter.next()) {
entry->validate();
@@ -471,7 +521,7 @@ void GrResourceCache::printStats() {
EntryList::Iter iter;
- GrResourceEntry* entry = iter.init(fList, EntryList::Iter::kTail_IterStart);
+ GrResourceCacheEntry* entry = iter.init(fList, EntryList::Iter::kTail_IterStart);
for ( ; NULL != entry; entry = iter.prev()) {
if (entry->fResource->getRefCnt() > 1) {
diff --git a/chromium/third_party/skia/src/gpu/GrResourceCache.h b/chromium/third_party/skia/src/gpu/GrResourceCache.h
index ca30732bbc1..1a81fe61d12 100644
--- a/chromium/third_party/skia/src/gpu/GrResourceCache.h
+++ b/chromium/third_party/skia/src/gpu/GrResourceCache.h
@@ -13,32 +13,27 @@
#include "GrConfig.h"
#include "GrTypes.h"
-#include "GrTHashTable.h"
+#include "GrTMultiMap.h"
#include "GrBinHashKey.h"
#include "SkMessageBus.h"
#include "SkTInternalLList.h"
-class GrResource;
-class GrResourceEntry;
+class GrCacheable;
+class GrResourceCache;
+class GrResourceCacheEntry;
class GrResourceKey {
public:
- enum {
- kHashBits = 7,
- kHashCount = 1 << kHashBits,
- kHashMask = kHashCount - 1
- };
-
static GrCacheID::Domain ScratchDomain() {
static const GrCacheID::Domain gDomain = GrCacheID::GenerateDomain();
return gDomain;
}
- /** Uniquely identifies the GrResource subclass in the key to avoid collisions
+ /** Uniquely identifies the GrCacheable subclass in the key to avoid collisions
across resource types. */
typedef uint8_t ResourceType;
- /** Flags set by the GrResource subclass. */
+ /** Flags set by the GrCacheable subclass. */
typedef uint8_t ResourceFlags;
/** Generate a unique ResourceType */
@@ -61,9 +56,8 @@ public:
this->init(id.getDomain(), id.getKey(), type, flags);
}
- //!< returns hash value [0..kHashMask] for the key
- int getHash() const {
- return fKey.getHash() & kHashMask;
+ uint32_t getHash() const {
+ return fKey.getHash();
}
bool isScratch() const {
@@ -83,14 +77,6 @@ public:
}
bool operator==(const GrResourceKey& other) const { return fKey == other.fKey; }
- bool operator<(const GrResourceKey& other) const { return fKey < other.fKey; }
-
- static bool LessThan(const GrResourceEntry& entry, const GrResourceKey& key);
- static bool Equals(const GrResourceEntry& entry, const GrResourceKey& key);
-#ifdef SK_DEBUG
- static bool LessThan(const GrResourceEntry& a, const GrResourceEntry& b);
- static bool Equals(const GrResourceEntry& a, const GrResourceEntry& b);
-#endif
private:
enum {
@@ -130,72 +116,61 @@ struct GrResourceInvalidatedMessage {
///////////////////////////////////////////////////////////////////////////////
-class GrResourceEntry {
+class GrResourceCacheEntry {
public:
- GrResource* resource() const { return fResource; }
+ GrCacheable* resource() const { return fResource; }
const GrResourceKey& key() const { return fKey; }
+ static const GrResourceKey& GetKey(const GrResourceCacheEntry& e) { return e.key(); }
+ static uint32_t Hash(const GrResourceKey& key) { return key.getHash(); }
#ifdef SK_DEBUG
void validate() const;
#else
void validate() const {}
#endif
+ /**
+ * Update the cached size for this entry and inform the resource cache that
+ * it has changed. Usually invoked from GrCacheable::didChangeGpuMemorySize,
+ * not directly from here.
+ */
+ void didChangeResourceSize();
+
private:
- GrResourceEntry(const GrResourceKey& key, GrResource* resource);
- ~GrResourceEntry();
+ GrResourceCacheEntry(GrResourceCache* resourceCache,
+ const GrResourceKey& key,
+ GrCacheable* resource);
+ ~GrResourceCacheEntry();
+ GrResourceCache* fResourceCache;
GrResourceKey fKey;
- GrResource* fResource;
+ GrCacheable* fResource;
+ size_t fCachedSize;
+ bool fIsExclusive;
- // we're a linked list
- SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrResourceEntry);
+ // Linked list for the LRU ordering.
+ SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrResourceCacheEntry);
friend class GrResourceCache;
- friend class GrDLinkedList;
};
-inline bool GrResourceKey::LessThan(const GrResourceEntry& entry, const GrResourceKey& key) {
- return entry.key() < key;
-}
-
-inline bool GrResourceKey::Equals(const GrResourceEntry& entry, const GrResourceKey& key) {
- return entry.key() == key;
-}
-
-#ifdef SK_DEBUG
-inline bool GrResourceKey::LessThan(const GrResourceEntry& a, const GrResourceEntry& b) {
- return a.key() < b.key();
-}
-
-inline bool GrResourceKey::Equals(const GrResourceEntry& a, const GrResourceEntry& b) {
- return a.key() == b.key();
-}
-#endif
-
///////////////////////////////////////////////////////////////////////////////
/**
- * Cache of GrResource objects.
+ * Cache of GrCacheable objects.
*
* These have a corresponding GrResourceKey, built from 128bits identifying the
- * resource.
+ * resource. Multiple resources can map to same GrResourceKey.
*
* The cache stores the entries in a double-linked list, which is its LRU.
* When an entry is "locked" (i.e. given to the caller), it is moved to the
* head of the list. If/when we must purge some of the entries, we walk the
* list backwards from the tail, since those are the least recently used.
*
- * For fast searches, we maintain a sorted array (based on the GrResourceKey)
- * which we can bsearch. When a new entry is added, it is inserted into this
- * array.
- *
- * For even faster searches, a hash is computed from the Key. If there is
- * a collision between two keys with the same hash, we fall back on the
- * bsearch, and update the hash to reflect the most recent Key requested.
+ * For fast searches, we maintain a hash map based on the GrResourceKey.
*
* It is a goal to make the GrResourceCache the central repository and bookkeeper
- * of all resources. It should replace the linked list of GrResources that
+ * of all resources. It should replace the linked list of GrGpuObjects that
* GrGpu uses to call abandon/release.
*/
class GrResourceCache {
@@ -248,6 +223,11 @@ public:
*/
size_t getCachedResourceBytes() const { return fEntryBytes; }
+ /**
+ * Returns the number of cached resources.
+ */
+ int getCachedResourceCount() const { return fEntryCount; }
+
// For a found or added resource to be completely exclusive to the caller
// both the kNoOtherOwners and kHide flags need to be specified
enum OwnershipFlags {
@@ -266,8 +246,8 @@ public:
* For a resource to be completely exclusive to a caller both kNoOtherOwners
* and kHide must be specified.
*/
- GrResource* find(const GrResourceKey& key,
- uint32_t ownershipFlags = 0);
+ GrCacheable* find(const GrResourceKey& key,
+ uint32_t ownershipFlags = 0);
/**
* Add the new resource to the cache (by creating a new cache entry based
@@ -281,7 +261,7 @@ public:
* is called.
*/
void addResource(const GrResourceKey& key,
- GrResource* resource,
+ GrCacheable* resource,
uint32_t ownershipFlags = 0);
/**
@@ -296,18 +276,24 @@ public:
* the cache's budget and should be made non-exclusive when exclusive access
* is no longer needed.
*/
- void makeExclusive(GrResourceEntry* entry);
+ void makeExclusive(GrResourceCacheEntry* entry);
/**
* Restore 'entry' so that it can be found by future searches. 'entry'
* will also be purgeable (provided its lock count is now 0.)
*/
- void makeNonExclusive(GrResourceEntry* entry);
+ void makeNonExclusive(GrResourceCacheEntry* entry);
+
+ /**
+ * Notify the cache that the size of a resource has changed.
+ */
+ void didIncreaseResourceSize(const GrResourceCacheEntry*, size_t amountInc);
+ void didDecreaseResourceSize(const GrResourceCacheEntry*, size_t amountDec);
/**
* Remove a resource from the cache and delete it!
*/
- void deleteResource(GrResourceEntry* entry);
+ void deleteResource(GrResourceCacheEntry* entry);
/**
* Removes every resource in the cache that isn't locked.
@@ -343,15 +329,15 @@ private:
kIgnore_BudgetBehavior
};
- void internalDetach(GrResourceEntry*, BudgetBehaviors behavior = kAccountFor_BudgetBehavior);
- void attachToHead(GrResourceEntry*, BudgetBehaviors behavior = kAccountFor_BudgetBehavior);
+ void internalDetach(GrResourceCacheEntry*, BudgetBehaviors behavior = kAccountFor_BudgetBehavior);
+ void attachToHead(GrResourceCacheEntry*, BudgetBehaviors behavior = kAccountFor_BudgetBehavior);
- void removeInvalidResource(GrResourceEntry* entry);
+ void removeInvalidResource(GrResourceCacheEntry* entry);
- GrTHashTable<GrResourceEntry, GrResourceKey, 8> fCache;
+ GrTMultiMap<GrResourceCacheEntry, GrResourceKey> fCache;
// We're an internal doubly linked list
- typedef SkTInternalLList<GrResourceEntry> EntryList;
+ typedef SkTInternalLList<GrResourceCacheEntry> EntryList;
EntryList fList;
#ifdef SK_DEBUG
@@ -389,7 +375,7 @@ private:
void purgeInvalidated();
#ifdef SK_DEBUG
- static size_t countBytes(const SkTInternalLList<GrResourceEntry>& list);
+ static size_t countBytes(const SkTInternalLList<GrResourceCacheEntry>& list);
#endif
};
diff --git a/chromium/third_party/skia/src/gpu/GrSWMaskHelper.cpp b/chromium/third_party/skia/src/gpu/GrSWMaskHelper.cpp
index eefc951e7e4..15b5457cccc 100644
--- a/chromium/third_party/skia/src/gpu/GrSWMaskHelper.cpp
+++ b/chromium/third_party/skia/src/gpu/GrSWMaskHelper.cpp
@@ -6,16 +6,20 @@
*/
#include "GrSWMaskHelper.h"
+
#include "GrDrawState.h"
#include "GrDrawTargetCaps.h"
#include "GrGpu.h"
+#include "SkData.h"
#include "SkStrokeRec.h"
+#include "SkTextureCompressor.h"
// TODO: try to remove this #include
#include "GrContext.h"
namespace {
+
/*
* Convert a boolean operation into a transfer mode code
*/
@@ -99,8 +103,7 @@ bool GrSWMaskHelper::init(const SkIRect& resultBounds,
SkIRect bounds = SkIRect::MakeWH(resultBounds.width(),
resultBounds.height());
- fBM.setConfig(SkBitmap::kA8_Config, bounds.fRight, bounds.fBottom);
- if (!fBM.allocPixels()) {
+ if (!fBM.allocPixels(SkImageInfo::MakeA8(bounds.fRight, bounds.fBottom))) {
return false;
}
sk_bzero(fBM.getPixels(), fBM.getSafeSize());
@@ -122,31 +125,61 @@ bool GrSWMaskHelper::getTexture(GrAutoScratchTexture* texture) {
GrTextureDesc desc;
desc.fWidth = fBM.width();
desc.fHeight = fBM.height();
- desc.fConfig = kAlpha_8_GrPixelConfig;
+
+#if GR_COMPRESS_ALPHA_MASK
+ static const int kLATCBlockSize = 4;
+ if (desc.fWidth % kLATCBlockSize == 0 && desc.fHeight % kLATCBlockSize == 0) {
+ desc.fConfig = kLATC_GrPixelConfig;
+ } else {
+#endif
+ desc.fConfig = kAlpha_8_GrPixelConfig;
+#if GR_COMPRESS_ALPHA_MASK
+ }
+#endif
texture->set(fContext, desc);
return NULL != texture->texture();
}
-/**
- * Move the result of the software mask generation back to the gpu
- */
-void GrSWMaskHelper::toTexture(GrTexture *texture) {
- SkAutoLockPixels alp(fBM);
-
+void GrSWMaskHelper::sendTextureData(GrTexture *texture, const GrTextureDesc& desc,
+ const void *data, int rowbytes) {
// If we aren't reusing scratch textures we don't need to flush before
// writing since no one else will be using 'texture'
bool reuseScratch = fContext->getGpu()->caps()->reuseScratchTextures();
- // Since we're uploading to it, 'texture' shouldn't have a render target.
+ // Since we're uploading to it, and it's compressed, 'texture' shouldn't
+ // have a render target.
SkASSERT(NULL == texture->asRenderTarget());
- texture->writePixels(0, 0, fBM.width(), fBM.height(),
- kAlpha_8_GrPixelConfig,
- fBM.getPixels(), fBM.rowBytes(),
+ texture->writePixels(0, 0, desc.fWidth, desc.fHeight,
+ desc.fConfig, data, rowbytes,
reuseScratch ? 0 : GrContext::kDontFlush_PixelOpsFlag);
}
+/**
+ * Move the result of the software mask generation back to the gpu
+ */
+void GrSWMaskHelper::toTexture(GrTexture *texture) {
+ SkAutoLockPixels alp(fBM);
+
+ GrTextureDesc desc;
+ desc.fWidth = fBM.width();
+ desc.fHeight = fBM.height();
+ desc.fConfig = texture->config();
+
+ // First see if we should compress this texture before uploading.
+ if (texture->config() == kLATC_GrPixelConfig) {
+ SkTextureCompressor::Format format = SkTextureCompressor::kLATC_Format;
+ SkAutoDataUnref latcData(SkTextureCompressor::CompressBitmapToFormat(fBM, format));
+ SkASSERT(NULL != latcData);
+
+ this->sendTextureData(texture, desc, latcData->data(), 0);
+ } else {
+ // Looks like we have to send a full A8 texture.
+ this->sendTextureData(texture, desc, fBM.getPixels(), fBM.rowBytes());
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
/**
* Software rasterizes path to A8 mask (possibly using the context's matrix)
@@ -159,8 +192,6 @@ GrTexture* GrSWMaskHelper::DrawPathMaskToTexture(GrContext* context,
const SkIRect& resultBounds,
bool antiAlias,
SkMatrix* matrix) {
- GrAutoScratchTexture ast;
-
GrSWMaskHelper helper(context);
if (!helper.init(resultBounds, matrix)) {
@@ -169,6 +200,7 @@ GrTexture* GrSWMaskHelper::DrawPathMaskToTexture(GrContext* context,
helper.draw(path, stroke, SkRegion::kReplace_Op, antiAlias, 0xFF);
+ GrAutoScratchTexture ast;
if (!helper.getTexture(&ast)) {
return NULL;
}
diff --git a/chromium/third_party/skia/src/gpu/GrSWMaskHelper.h b/chromium/third_party/skia/src/gpu/GrSWMaskHelper.h
index b274e84c66d..0ffaa649822 100644
--- a/chromium/third_party/skia/src/gpu/GrSWMaskHelper.h
+++ b/chromium/third_party/skia/src/gpu/GrSWMaskHelper.h
@@ -38,7 +38,7 @@ class GrDrawTarget;
* The result of this process will be the final mask (on the GPU) in the
* upper left hand corner of the texture.
*/
-class GrSWMaskHelper : public SkNoncopyable {
+class GrSWMaskHelper : SkNoncopyable {
public:
GrSWMaskHelper(GrContext* context)
: fContext(context) {
@@ -101,6 +101,11 @@ private:
SkDraw fDraw;
SkRasterClip fRasterClip;
+ // Actually sends the texture data to the GPU. This is called from
+ // toTexture with the data filled in depending on the texture config.
+ void sendTextureData(GrTexture *texture, const GrTextureDesc& desc,
+ const void *data, int rowbytes);
+
typedef SkNoncopyable INHERITED;
};
diff --git a/chromium/third_party/skia/src/gpu/GrStencil.cpp b/chromium/third_party/skia/src/gpu/GrStencil.cpp
index 767726084cf..f37aa317ec3 100644
--- a/chromium/third_party/skia/src/gpu/GrStencil.cpp
+++ b/chromium/third_party/skia/src/gpu/GrStencil.cpp
@@ -389,7 +389,7 @@ bool GrStencilSettings::GetClipPasses(
}
break;
default:
- GrCrash("Unknown set op");
+ SkFAIL("Unknown set op");
}
return false;
}
diff --git a/chromium/third_party/skia/src/gpu/GrStencilBuffer.h b/chromium/third_party/skia/src/gpu/GrStencilBuffer.h
index 37d40f16ba7..696ba839129 100644
--- a/chromium/third_party/skia/src/gpu/GrStencilBuffer.h
+++ b/chromium/third_party/skia/src/gpu/GrStencilBuffer.h
@@ -11,13 +11,12 @@
#define GrStencilBuffer_DEFINED
#include "GrClipData.h"
-#include "GrResource.h"
+#include "GrGpuObject.h"
class GrRenderTarget;
-class GrResourceEntry;
class GrResourceKey;
-class GrStencilBuffer : public GrResource {
+class GrStencilBuffer : public GrGpuObject {
public:
SK_DECLARE_INST_COUNT(GrStencilBuffer);
@@ -55,7 +54,7 @@ public:
protected:
GrStencilBuffer(GrGpu* gpu, bool isWrapped, int width, int height, int bits, int sampleCnt)
- : GrResource(gpu, isWrapped)
+ : GrGpuObject(gpu, isWrapped)
, fWidth(width)
, fHeight(height)
, fBits(bits)
@@ -75,7 +74,7 @@ private:
SkIRect fLastClipStackRect;
SkIPoint fLastClipSpaceOffset;
- typedef GrResource INHERITED;
+ typedef GrGpuObject INHERITED;
};
#endif
diff --git a/chromium/third_party/skia/src/gpu/GrStrokeInfo.h b/chromium/third_party/skia/src/gpu/GrStrokeInfo.h
new file mode 100644
index 00000000000..b9ba5eada1a
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/GrStrokeInfo.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrStrokeInfo_DEFINED
+#define GrStrokeInfo_DEFINED
+
+#include "SkStrokeRec.h"
+#include "SkPathEffect.h"
+
+/*
+ * GrStrokeInfo encapsulates the data objects that hold all the pertinent infomation
+ * regarding the stroke. The two objects are SkStrokeRec which holds information on fill style,
+ * width, miter, cap, and join. The second object is DashInfo. This holds information about the
+ * dash like intervals, count, and phase.
+ */
+class GrStrokeInfo {
+public:
+ GrStrokeInfo(SkStrokeRec::InitStyle style) :
+ fStroke(style), fDashType(SkPathEffect::kNone_DashType) {}
+
+ GrStrokeInfo(const GrStrokeInfo& src, bool includeDash = true) : fStroke(src.fStroke) {
+ if (includeDash) {
+ fDashInfo = src.fDashInfo;
+ fDashType = src.fDashType;
+ fIntervals.reset(src.dashCount());
+ memcpy(fIntervals.get(), src.fIntervals.get(), src.dashCount() * sizeof(SkScalar));
+ } else {
+ fDashType = SkPathEffect::kNone_DashType;
+ }
+ }
+
+ GrStrokeInfo(const SkPaint& paint, SkPaint::Style styleOverride) :
+ fStroke(paint, styleOverride), fDashType(SkPathEffect::kNone_DashType) {
+ this->init(paint);
+ }
+
+
+ explicit GrStrokeInfo(const SkPaint& paint) :
+ fStroke(paint), fDashType(SkPathEffect::kNone_DashType) {
+ this->init(paint);
+ }
+
+ const SkStrokeRec& getStrokeRec() const { return fStroke; }
+
+ SkStrokeRec* getStrokeRecPtr() { return &fStroke; }
+
+ void setFillStyle() { fStroke.setFillStyle(); }
+
+ /*
+ * This functions takes in a patheffect and fills in fDashInfo with the various dashing
+ * information if the path effect is a Dash type. Returns true if the path effect is a
+ * dashed effect and we are stroking, otherwise it retruns false.
+ */
+ bool setDashInfo(const SkPathEffect* pe) {
+ if (NULL != pe && !fStroke.isFillStyle()) {
+ fDashInfo.fIntervals = NULL;
+ fDashType = pe->asADash(&fDashInfo);
+ if (SkPathEffect::kDash_DashType == fDashType) {
+ fIntervals.reset(fDashInfo.fCount);
+ fDashInfo.fIntervals = fIntervals.get();
+ pe->asADash(&fDashInfo);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool isDashed() const {
+ return (!fStroke.isFillStyle() && SkPathEffect::kDash_DashType == fDashType);
+ }
+
+ int32_t dashCount() const {
+ return fDashInfo.fCount;
+ }
+
+ void removeDash() {
+ fDashType = SkPathEffect::kNone_DashType;
+ }
+
+ const SkPathEffect::DashInfo& getDashInfo() const { return fDashInfo; }
+
+private:
+
+ void init(const SkPaint& paint) {
+ const SkPathEffect* pe = paint.getPathEffect();
+ this->setDashInfo(pe);
+ }
+
+ SkStrokeRec fStroke;
+ SkPathEffect::DashType fDashType;
+ SkPathEffect::DashInfo fDashInfo;
+ SkAutoSTArray<2, SkScalar> fIntervals;
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/GrSurface.cpp b/chromium/third_party/skia/src/gpu/GrSurface.cpp
index 1fcc4ff18be..a07fe67ae45 100644
--- a/chromium/third_party/skia/src/gpu/GrSurface.cpp
+++ b/chromium/third_party/skia/src/gpu/GrSurface.cpp
@@ -12,19 +12,23 @@
#include "SkImageEncoder.h"
#include <stdio.h>
-void GrSurface::asImageInfo(SkImageInfo* info) const {
- if (!GrPixelConfig2ColorType(this->config(), &info->fColorType)) {
+SkImageInfo GrSurface::info() const {
+ SkImageInfo info;
+ if (!GrPixelConfig2ColorType(this->config(), &info.fColorType)) {
sk_throw();
}
- info->fWidth = this->width();
- info->fHeight = this->height();
- info->fAlphaType = kPremul_SkAlphaType;
+ info.fWidth = this->width();
+ info.fHeight = this->height();
+ info.fAlphaType = kPremul_SkAlphaType;
+ return info;
}
bool GrSurface::savePixels(const char* filename) {
SkBitmap bm;
- bm.setConfig(SkBitmap::kARGB_8888_Config, this->width(), this->height());
- bm.allocPixels();
+ if (!bm.allocPixels(SkImageInfo::MakeN32Premul(this->width(),
+ this->height()))) {
+ return false;
+ }
bool result = readPixels(0, 0, this->width(), this->height(), kSkia8888_GrPixelConfig,
bm.getPixels());
diff --git a/chromium/third_party/skia/src/gpu/GrTBSearch.h b/chromium/third_party/skia/src/gpu/GrTBSearch.h
index 08b0b85f357..01e97440a65 100644
--- a/chromium/third_party/skia/src/gpu/GrTBSearch.h
+++ b/chromium/third_party/skia/src/gpu/GrTBSearch.h
@@ -1,4 +1,3 @@
-
/*
* Copyright 2010 Google Inc.
*
@@ -6,11 +5,11 @@
* found in the LICENSE file.
*/
-
-
#ifndef GrTBSearch_DEFINED
#define GrTBSearch_DEFINED
+#include "SkTypes.h"
+
template <typename ELEM, typename KEY>
int GrTBSearch(const ELEM array[], int count, KEY target) {
SkASSERT(count >= 0);
diff --git a/chromium/third_party/skia/src/gpu/GrTHashTable.h b/chromium/third_party/skia/src/gpu/GrTHashTable.h
index 83462c70c9e..9da4b06debe 100644
--- a/chromium/third_party/skia/src/gpu/GrTHashTable.h
+++ b/chromium/third_party/skia/src/gpu/GrTHashTable.h
@@ -61,7 +61,12 @@ private:
kHashCount = 1 << kHashBits,
kHashMask = kHashCount - 1
};
- static unsigned hash2Index(uint32_t hash) {
+ static unsigned hash2Index(intptr_t hash) {
+#if 0
+ if (sizeof(hash) == 8) {
+ hash ^= hash >> 32;
+ }
+#endif
hash ^= hash >> 16;
if (kHashBits <= 8) {
hash ^= hash >> 8;
diff --git a/chromium/third_party/skia/src/gpu/GrTMultiMap.h b/chromium/third_party/skia/src/gpu/GrTMultiMap.h
new file mode 100644
index 00000000000..0007a04a2ad
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/GrTMultiMap.h
@@ -0,0 +1,110 @@
+
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrTMultiMap_DEFINED
+#define GrTMultiMap_DEFINED
+
+#include "GrTypes.h"
+#include "SkTDynamicHash.h"
+
+/** A set that contains pointers to instances of T. Instances can be looked up with key Key.
+ * Multiple (possibly same) values can have the same key.
+ */
+template <typename T,
+ typename Key,
+ typename HashTraits=T>
+class GrTMultiMap {
+ struct ValueList {
+ explicit ValueList(T* value) : fValue(value), fNext(NULL) {}
+
+ static const Key& GetKey(const ValueList& e) { return HashTraits::GetKey(*e.fValue); }
+ static uint32_t Hash(const Key& key) { return HashTraits::Hash(key); }
+ T* fValue;
+ ValueList* fNext;
+ };
+public:
+ GrTMultiMap() : fCount(0) {}
+
+ ~GrTMultiMap() {
+ SkASSERT(fCount == 0);
+ SkASSERT(fHash.count() == 0);
+ }
+
+ void insert(const Key& key, T* value) {
+ ValueList* list = fHash.find(key);
+ if (NULL != list) {
+ // The new ValueList entry is inserted as the second element in the
+ // linked list, and it will contain the value of the first element.
+ ValueList* newEntry = SkNEW_ARGS(ValueList, (list->fValue));
+ newEntry->fNext = list->fNext;
+ // The existing first ValueList entry is updated to contain the
+ // inserted value.
+ list->fNext = newEntry;
+ list->fValue = value;
+ } else {
+ fHash.add(SkNEW_ARGS(ValueList, (value)));
+ }
+
+ ++fCount;
+ }
+
+ void remove(const Key& key, const T* value) {
+ ValueList* list = fHash.find(key);
+ // Since we expect the caller to be fully aware of what is stored, just
+ // assert that the caller removes an existing value.
+ SkASSERT(NULL != list);
+ ValueList* prev = NULL;
+ while (list->fValue != value) {
+ prev = list;
+ list = list->fNext;
+ }
+
+ if (NULL != list->fNext) {
+ ValueList* next = list->fNext;
+ list->fValue = next->fValue;
+ list->fNext = next->fNext;
+ SkDELETE(next);
+ } else if (NULL != prev) {
+ prev->fNext = NULL;
+ SkDELETE(list);
+ } else {
+ fHash.remove(key);
+ SkDELETE(list);
+ }
+
+ --fCount;
+ }
+
+ T* find(const Key& key) const {
+ ValueList* list = fHash.find(key);
+ if (NULL != list) {
+ return list->fValue;
+ }
+ return NULL;
+ }
+
+ template<class FindPredicate>
+ T* find(const Key& key, const FindPredicate f) {
+ ValueList* list = fHash.find(key);
+ while (NULL != list) {
+ if (f(list->fValue)){
+ return list->fValue;
+ }
+ list = list->fNext;
+ }
+ return NULL;
+ }
+
+ int count() const { return fCount; }
+
+private:
+ SkTDynamicHash<ValueList, Key> fHash;
+ int fCount;
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/GrTemplates.h b/chromium/third_party/skia/src/gpu/GrTemplates.h
index 5a009dfdf10..2cab1327831 100644
--- a/chromium/third_party/skia/src/gpu/GrTemplates.h
+++ b/chromium/third_party/skia/src/gpu/GrTemplates.h
@@ -35,7 +35,7 @@ template <typename Dst, typename Src> Dst GrTCast(Src src) {
* ...
* } // fCount is restored
*/
-template <typename T> class GrAutoTRestore : public SkNoncopyable {
+template <typename T> class GrAutoTRestore : SkNoncopyable {
public:
GrAutoTRestore() : fPtr(NULL), fVal() {}
diff --git a/chromium/third_party/skia/src/gpu/GrTest.cpp b/chromium/third_party/skia/src/gpu/GrTest.cpp
index 934f089f3d6..10dc0346576 100644
--- a/chromium/third_party/skia/src/gpu/GrTest.cpp
+++ b/chromium/third_party/skia/src/gpu/GrTest.cpp
@@ -9,6 +9,7 @@
#include "GrTest.h"
#include "GrGpu.h"
+#include "GrResourceCache.h"
void GrTestTarget::init(GrContext* ctx, GrDrawTarget* target) {
SkASSERT(!fContext);
@@ -35,3 +36,7 @@ void GrContext::getTestTarget(GrTestTarget* tar) {
void GrContext::setMaxTextureSizeOverride(int maxTextureSizeOverride) {
fMaxTextureSizeOverride = maxTextureSizeOverride;
}
+
+void GrContext::purgeAllUnlockedResources() {
+ fResourceCache->purgeAllUnlocked();
+}
diff --git a/chromium/third_party/skia/src/gpu/GrTextContext.cpp b/chromium/third_party/skia/src/gpu/GrTextContext.cpp
index 9e9162878df..bc116714dad 100644
--- a/chromium/third_party/skia/src/gpu/GrTextContext.cpp
+++ b/chromium/third_party/skia/src/gpu/GrTextContext.cpp
@@ -5,23 +5,73 @@
* found in the LICENSE file.
*/
-
#include "GrTextContext.h"
+#include "GrContext.h"
+
+#include "SkAutoKern.h"
+#include "SkGlyphCache.h"
+#include "SkGr.h"
-GrTextContext::GrTextContext(GrContext* context, const GrPaint& paint) : fPaint(paint) {
- fContext = context;
+GrTextContext::GrTextContext(GrContext* context, const SkDeviceProperties& properties) :
+ fContext(context), fDeviceProperties(properties), fDrawTarget(NULL) {
+}
- const GrClipData* clipData = context->getClip();
+void GrTextContext::init(const GrPaint& grPaint, const SkPaint& skPaint) {
+ const GrClipData* clipData = fContext->getClip();
SkRect devConservativeBound;
clipData->fClipStack->getConservativeBounds(
-clipData->fOrigin.fX,
-clipData->fOrigin.fY,
- context->getRenderTarget()->width(),
- context->getRenderTarget()->height(),
+ fContext->getRenderTarget()->width(),
+ fContext->getRenderTarget()->height(),
&devConservativeBound);
devConservativeBound.roundOut(&fClipRect);
fDrawTarget = fContext->getTextTarget();
+
+ fPaint = grPaint;
+ fSkPaint = skPaint;
+}
+
+//*** change to output positions?
+void GrTextContext::MeasureText(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
+ const char text[], size_t byteLength, SkVector* stopVector) {
+ SkFixed x = 0, y = 0;
+ const char* stop = text + byteLength;
+
+ SkAutoKern autokern;
+
+ while (text < stop) {
+ // don't need x, y here, since all subpixel variants will have the
+ // same advance
+ const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
+
+ x += autokern.adjust(glyph) + glyph.fAdvanceX;
+ y += glyph.fAdvanceY;
+ }
+ stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y));
+
+ SkASSERT(text == stop);
+}
+
+static void GlyphCacheAuxProc(void* data) {
+ GrFontScaler* scaler = (GrFontScaler*)data;
+ SkSafeUnref(scaler);
+}
+
+GrFontScaler* GrTextContext::GetGrFontScaler(SkGlyphCache* cache) {
+ void* auxData;
+ GrFontScaler* scaler = NULL;
+
+ if (cache->getAuxProcData(GlyphCacheAuxProc, &auxData)) {
+ scaler = (GrFontScaler*)auxData;
+ }
+ if (NULL == scaler) {
+ scaler = SkNEW_ARGS(SkGrFontScaler, (cache));
+ cache->setAuxProc(GlyphCacheAuxProc, scaler);
+ }
+
+ return scaler;
}
diff --git a/chromium/third_party/skia/src/gpu/GrTextContext.h b/chromium/third_party/skia/src/gpu/GrTextContext.h
new file mode 100644
index 00000000000..c139e222959
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/GrTextContext.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrTextContext_DEFINED
+#define GrTextContext_DEFINED
+
+#include "GrGlyph.h"
+#include "GrPaint.h"
+#include "SkDeviceProperties.h"
+
+#include "SkPostConfig.h"
+
+class GrContext;
+class GrDrawTarget;
+class GrFontScaler;
+
+/*
+ * This class wraps the state for a single text render
+ */
+class GrTextContext {
+public:
+ virtual ~GrTextContext() {}
+ virtual void drawText(const GrPaint&, const SkPaint&, const char text[], size_t byteLength,
+ SkScalar x, SkScalar y) = 0;
+ virtual void drawPosText(const GrPaint&, const SkPaint&,
+ const char text[], size_t byteLength,
+ const SkScalar pos[], SkScalar constY,
+ int scalarsPerPosition) = 0;
+
+ virtual bool canDraw(const SkPaint& paint) = 0;
+
+protected:
+ GrTextContext(GrContext*, const SkDeviceProperties&);
+
+ static GrFontScaler* GetGrFontScaler(SkGlyphCache* cache);
+ static void MeasureText(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
+ const char text[], size_t byteLength, SkVector* stopVector);
+
+ void init(const GrPaint&, const SkPaint&);
+ void finish() { fDrawTarget = NULL; }
+
+ GrContext* fContext;
+ SkDeviceProperties fDeviceProperties;
+
+ GrDrawTarget* fDrawTarget;
+ SkIRect fClipRect;
+ GrPaint fPaint;
+ SkPaint fSkPaint;
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/GrTextStrike.cpp b/chromium/third_party/skia/src/gpu/GrTextStrike.cpp
index c70e822cd9b..b03d14f96fd 100644
--- a/chromium/third_party/skia/src/gpu/GrTextStrike.cpp
+++ b/chromium/third_party/skia/src/gpu/GrTextStrike.cpp
@@ -5,19 +5,25 @@
* found in the LICENSE file.
*/
-#include "GrAtlas.h"
#include "GrGpu.h"
#include "GrRectanizer.h"
#include "GrTextStrike.h"
#include "GrTextStrike_impl.h"
#include "SkString.h"
-#if SK_DISTANCEFIELD_FONTS
-#include "edtaa3.h"
-#endif
+#include "SkDistanceFieldGen.h"
///////////////////////////////////////////////////////////////////////////////
+#define GR_ATLAS_TEXTURE_WIDTH 1024
+#define GR_ATLAS_TEXTURE_HEIGHT 2048
+
+#define GR_PLOT_WIDTH 256
+#define GR_PLOT_HEIGHT 256
+
+#define GR_NUM_PLOTS_X (GR_ATLAS_TEXTURE_WIDTH / GR_PLOT_WIDTH)
+#define GR_NUM_PLOTS_Y (GR_ATLAS_TEXTURE_HEIGHT / GR_PLOT_HEIGHT)
+
#define FONT_CACHE_STATS 0
#if FONT_CACHE_STATS
static int g_PurgeCount = 0;
@@ -74,7 +80,13 @@ GrTextStrike* GrFontCache::generateStrike(GrFontScaler* scaler,
GrPixelConfig config = mask_format_to_pixel_config(format);
int atlasIndex = mask_format_to_atlas_index(format);
if (NULL == fAtlasMgr[atlasIndex]) {
- fAtlasMgr[atlasIndex] = SkNEW_ARGS(GrAtlasMgr, (fGpu, config));
+ SkISize textureSize = SkISize::Make(GR_ATLAS_TEXTURE_WIDTH,
+ GR_ATLAS_TEXTURE_HEIGHT);
+ fAtlasMgr[atlasIndex] = SkNEW_ARGS(GrAtlasMgr, (fGpu, config,
+ textureSize,
+ GR_NUM_PLOTS_X,
+ GR_NUM_PLOTS_Y,
+ true));
}
GrTextStrike* strike = SkNEW_ARGS(GrTextStrike,
(this, scaler->getKey(), format, fAtlasMgr[atlasIndex]));
@@ -110,47 +122,39 @@ void GrFontCache::purgeStrike(GrTextStrike* strike) {
delete strike;
}
-void GrFontCache::purgeExceptFor(GrTextStrike* preserveStrike) {
+bool GrFontCache::freeUnusedPlot(GrTextStrike* preserveStrike) {
SkASSERT(NULL != preserveStrike);
- GrTextStrike* strike = fTail;
- bool purge = true;
+
+ GrAtlasMgr* atlasMgr = preserveStrike->fAtlasMgr;
+ GrPlot* plot = atlasMgr->getUnusedPlot();
+ if (NULL == plot) {
+ return false;
+ }
+ plot->resetRects();
+
+ GrTextStrike* strike = fHead;
GrMaskFormat maskFormat = preserveStrike->fMaskFormat;
while (strike) {
- if (strike == preserveStrike || maskFormat != strike->fMaskFormat) {
- strike = strike->fPrev;
+ if (maskFormat != strike->fMaskFormat) {
+ strike = strike->fNext;
continue;
}
+
GrTextStrike* strikeToPurge = strike;
- strike = strikeToPurge->fPrev;
- if (purge) {
- // keep purging if we won't free up any atlases with this strike.
- purge = strikeToPurge->fAtlas.isEmpty();
+ strike = strikeToPurge->fNext;
+ strikeToPurge->removePlot(plot);
+
+ // clear out any empty strikes (except this one)
+ if (strikeToPurge != preserveStrike && strikeToPurge->fAtlas.isEmpty()) {
this->purgeStrike(strikeToPurge);
}
}
+
#if FONT_CACHE_STATS
++g_PurgeCount;
#endif
-}
-void GrFontCache::freePlotExceptFor(GrTextStrike* preserveStrike) {
- SkASSERT(NULL != preserveStrike);
- GrTextStrike* strike = fTail;
- GrMaskFormat maskFormat = preserveStrike->fMaskFormat;
- while (strike) {
- if (strike == preserveStrike || maskFormat != strike->fMaskFormat) {
- strike = strike->fPrev;
- continue;
- }
- GrTextStrike* strikeToPurge = strike;
- strike = strikeToPurge->fPrev;
- if (strikeToPurge->removeUnusedPlots()) {
- if (strikeToPurge->fAtlas.isEmpty()) {
- this->purgeStrike(strikeToPurge);
- }
- break;
- }
- }
+ return true;
}
#ifdef SK_DEBUG
@@ -183,7 +187,6 @@ void GrFontCache::validate() const {
}
#endif
-#ifdef SK_DEVELOPER
void GrFontCache::dump() const {
static int gDumpCount = 0;
for (int i = 0; i < kAtlasCount; ++i) {
@@ -191,14 +194,17 @@ void GrFontCache::dump() const {
GrTexture* texture = fAtlasMgr[i]->getTexture();
if (NULL != texture) {
SkString filename;
+#ifdef SK_BUILD_FOR_ANDROID
+ filename.printf("/sdcard/fontcache_%d%d.png", gDumpCount, i);
+#else
filename.printf("fontcache_%d%d.png", gDumpCount, i);
+#endif
texture->savePixels(filename.c_str());
}
}
}
++gDumpCount;
}
-#endif
///////////////////////////////////////////////////////////////////////////////
@@ -206,11 +212,6 @@ void GrFontCache::dump() const {
static int gCounter;
#endif
-#if SK_DISTANCEFIELD_FONTS
-#define DISTANCE_FIELD_PAD 4
-#define DISTANCE_FIELD_RANGE (4.0)
-#endif
-
/*
The text strike is specific to a given font/style/matrix setup, which is
represented by the GrHostFontScaler object we are given in getGlyph().
@@ -221,7 +222,7 @@ void GrFontCache::dump() const {
GrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key,
GrMaskFormat format,
- GrAtlasMgr* atlasMgr) : fPool(64), fAtlas(atlasMgr) {
+ GrAtlasMgr* atlasMgr) : fPool(64) {
fFontScalerKey = key;
fFontScalerKey->ref();
@@ -236,16 +237,10 @@ GrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key,
#endif
}
-// these signatures are needed because they're used with
-// SkTDArray::visitAll() (see destructor & removeUnusedAtlases())
+// this signature is needed because it's used with
+// SkTDArray::visitAll() (see destructor)
static void free_glyph(GrGlyph*& glyph) { glyph->free(); }
-static void invalidate_glyph(GrGlyph*& glyph) {
- if (glyph->fPlot && glyph->fPlot->drawToken().isIssued()) {
- glyph->fPlot = NULL;
- }
-}
-
GrTextStrike::~GrTextStrike() {
fFontScalerKey->unref();
fCache.getArray().visitAll(free_glyph);
@@ -259,32 +254,35 @@ GrTextStrike::~GrTextStrike() {
GrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed,
GrFontScaler* scaler) {
SkIRect bounds;
- if (!scaler->getPackedGlyphBounds(packed, &bounds)) {
- return NULL;
+ if (fUseDistanceField) {
+ if (!scaler->getPackedGlyphDFBounds(packed, &bounds)) {
+ return NULL;
+ }
+ } else {
+ if (!scaler->getPackedGlyphBounds(packed, &bounds)) {
+ return NULL;
+ }
}
GrGlyph* glyph = fPool.alloc();
-#if SK_DISTANCEFIELD_FONTS
- // expand bounds to hold full distance field data
- if (fUseDistanceField) {
- bounds.fLeft -= DISTANCE_FIELD_PAD;
- bounds.fRight += DISTANCE_FIELD_PAD;
- bounds.fTop -= DISTANCE_FIELD_PAD;
- bounds.fBottom += DISTANCE_FIELD_PAD;
- }
-#endif
glyph->init(packed, bounds);
fCache.insert(packed, glyph);
return glyph;
}
-bool GrTextStrike::removeUnusedPlots() {
- fCache.getArray().visitAll(invalidate_glyph);
- return fAtlasMgr->removeUnusedPlots(&fAtlas);
+void GrTextStrike::removePlot(const GrPlot* plot) {
+ SkTDArray<GrGlyph*>& glyphArray = fCache.getArray();
+ for (int i = 0; i < glyphArray.count(); ++i) {
+ if (plot == glyphArray[i]->fPlot) {
+ glyphArray[i]->fPlot = NULL;
+ }
+ }
+
+ fAtlasMgr->removePlot(&fAtlas, plot);
}
-bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) {
+bool GrTextStrike::addGlyphToAtlas(GrGlyph* glyph, GrFontScaler* scaler) {
#if 0 // testing hack to force us to flush our cache often
static int gCounter;
if ((++gCounter % 10) == 0) return false;
@@ -299,116 +297,26 @@ bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) {
int bytesPerPixel = GrMaskFormatBytesPerPixel(fMaskFormat);
- GrPlot* plot;
-#if SK_DISTANCEFIELD_FONTS
+ size_t size = glyph->fBounds.area() * bytesPerPixel;
+ SkAutoSMalloc<1024> storage(size);
if (fUseDistanceField) {
- SkASSERT(1 == bytesPerPixel);
-
- // we've already expanded the glyph dimensions to match the final size
- // but must shrink back down to get the packed glyph data
- int dfWidth = glyph->width();
- int dfHeight = glyph->height();
- int width = dfWidth - 2*DISTANCE_FIELD_PAD;
- int height = dfHeight - 2*DISTANCE_FIELD_PAD;
- size_t stride = width*bytesPerPixel;
-
- size_t size = width * height * bytesPerPixel;
- SkAutoSMalloc<1024> storage(size);
- if (!scaler->getPackedGlyphImage(glyph->fPackedID, width, height, stride, storage.get())) {
+ if (!scaler->getPackedGlyphDFImage(glyph->fPackedID, glyph->width(),
+ glyph->height(),
+ storage.get())) {
return false;
}
-
- // alloc storage for distance field glyph
- size_t dfSize = dfWidth * dfHeight * bytesPerPixel;
- SkAutoSMalloc<1024> dfStorage(dfSize);
-
- // copy glyph into distance field storage
- sk_bzero(dfStorage.get(), dfSize);
-
- unsigned char* ptr = (unsigned char*) storage.get();
- unsigned char* dfPtr = (unsigned char*) dfStorage.get();
- size_t dfStride = dfWidth*bytesPerPixel;
- dfPtr += DISTANCE_FIELD_PAD*dfStride;
- dfPtr += DISTANCE_FIELD_PAD*bytesPerPixel;
-
- for (int i = 0; i < height; ++i) {
- memcpy(dfPtr, ptr, stride);
-
- dfPtr += dfStride;
- ptr += stride;
- }
-
- // generate distance field data
- SkAutoSMalloc<1024> distXStorage(dfWidth*dfHeight*sizeof(short));
- SkAutoSMalloc<1024> distYStorage(dfWidth*dfHeight*sizeof(short));
- SkAutoSMalloc<1024> outerDistStorage(dfWidth*dfHeight*sizeof(double));
- SkAutoSMalloc<1024> innerDistStorage(dfWidth*dfHeight*sizeof(double));
- SkAutoSMalloc<1024> gxStorage(dfWidth*dfHeight*sizeof(double));
- SkAutoSMalloc<1024> gyStorage(dfWidth*dfHeight*sizeof(double));
-
- short* distX = (short*) distXStorage.get();
- short* distY = (short*) distYStorage.get();
- double* outerDist = (double*) outerDistStorage.get();
- double* innerDist = (double*) innerDistStorage.get();
- double* gx = (double*) gxStorage.get();
- double* gy = (double*) gyStorage.get();
-
- dfPtr = (unsigned char*) dfStorage.get();
- EDTAA::computegradient(dfPtr, dfWidth, dfHeight, gx, gy);
- EDTAA::edtaa3(dfPtr, gx, gy, dfWidth, dfHeight, distX, distY, outerDist);
-
- for (int i = 0; i < dfWidth*dfHeight; ++i) {
- *dfPtr = 255 - *dfPtr;
- dfPtr++;
- }
- dfPtr = (unsigned char*) dfStorage.get();
- sk_bzero(gx, sizeof(double)*dfWidth*dfHeight);
- sk_bzero(gy, sizeof(double)*dfWidth*dfHeight);
- EDTAA::computegradient(dfPtr, dfWidth, dfHeight, gx, gy);
- EDTAA::edtaa3(dfPtr, gx, gy, dfWidth, dfHeight, distX, distY, innerDist);
-
- for (int i = 0; i < dfWidth*dfHeight; ++i) {
- unsigned char val;
- double outerval = outerDist[i];
- if (outerval < 0.0) {
- outerval = 0.0;
- }
- double innerval = innerDist[i];
- if (innerval < 0.0) {
- innerval = 0.0;
- }
- double dist = outerval - innerval;
- if (dist <= -DISTANCE_FIELD_RANGE) {
- val = 255;
- } else if (dist > DISTANCE_FIELD_RANGE) {
- val = 0;
- } else {
- val = (unsigned char)((DISTANCE_FIELD_RANGE-dist)*128.0/DISTANCE_FIELD_RANGE);
- }
- *dfPtr++ = val;
- }
-
- // copy to atlas
- plot = fAtlasMgr->addToAtlas(&fAtlas, dfWidth, dfHeight, dfStorage.get(),
- &glyph->fAtlasLocation);
-
} else {
-#endif
- size_t size = glyph->fBounds.area() * bytesPerPixel;
- SkAutoSMalloc<1024> storage(size);
if (!scaler->getPackedGlyphImage(glyph->fPackedID, glyph->width(),
glyph->height(),
glyph->width() * bytesPerPixel,
storage.get())) {
return false;
}
-
- plot = fAtlasMgr->addToAtlas(&fAtlas, glyph->width(),
- glyph->height(), storage.get(),
- &glyph->fAtlasLocation);
-#if SK_DISTANCEFIELD_FONTS
}
-#endif
+
+ GrPlot* plot = fAtlasMgr->addToAtlas(&fAtlas, glyph->width(),
+ glyph->height(), storage.get(),
+ &glyph->fAtlasLocation);
if (NULL == plot) {
return false;
diff --git a/chromium/third_party/skia/src/gpu/GrTextStrike.h b/chromium/third_party/skia/src/gpu/GrTextStrike.h
index c5a3f656251..955eb7fd003 100644
--- a/chromium/third_party/skia/src/gpu/GrTextStrike.h
+++ b/chromium/third_party/skia/src/gpu/GrTextStrike.h
@@ -14,7 +14,6 @@
#include "GrAllocPool.h"
#include "GrFontScaler.h"
#include "GrTHashTable.h"
-#include "GrPoint.h"
#include "GrGlyph.h"
#include "GrDrawTarget.h"
#include "GrAtlas.h"
@@ -37,7 +36,7 @@ public:
GrMaskFormat getMaskFormat() const { return fMaskFormat; }
inline GrGlyph* getGlyph(GrGlyph::PackedID, GrFontScaler*);
- bool getGlyphAtlas(GrGlyph*, GrFontScaler*);
+ bool addGlyphToAtlas(GrGlyph*, GrFontScaler*);
// testing
int countGlyphs() const { return fCache.getArray().count(); }
@@ -45,11 +44,11 @@ public:
return fCache.getArray()[index];
}
- // returns true if a plot was removed
- bool removeUnusedPlots();
+ // remove any references to this plot
+ void removePlot(const GrPlot* plot);
public:
- // for LRU
+ // for easy removal from list
GrTextStrike* fPrev;
GrTextStrike* fNext;
@@ -62,9 +61,7 @@ private:
GrFontCache* fFontCache;
GrAtlasMgr* fAtlasMgr;
GrMaskFormat fMaskFormat;
-#if SK_DISTANCEFIELD_FONTS
bool fUseDistanceField;
-#endif
GrAtlas fAtlas;
@@ -78,18 +75,12 @@ public:
GrFontCache(GrGpu*);
~GrFontCache();
-#if SK_DISTANCEFIELD_FONTS
inline GrTextStrike* getStrike(GrFontScaler*, bool useDistanceField);
-#else
- inline GrTextStrike* getStrike(GrFontScaler*);
-#endif
void freeAll();
- void purgeExceptFor(GrTextStrike*);
-
- // remove an unused plot and its strike (if necessary)
- void freePlotExceptFor(GrTextStrike*);
+ // make an unused plot available
+ bool freeUnusedPlot(GrTextStrike* preserveStrike);
// testing
int countStrikes() const { return fCache.getArray().count(); }
@@ -98,15 +89,21 @@ public:
}
GrTextStrike* getHeadStrike() const { return fHead; }
+ void updateTextures() {
+ for (int i = 0; i < kAtlasCount; ++i) {
+ if (fAtlasMgr[i]) {
+ fAtlasMgr[i]->uploadPlotsToTexture();
+ }
+ }
+ }
+
#ifdef SK_DEBUG
void validate() const;
#else
void validate() const {}
#endif
-#ifdef SK_DEVELOPER
void dump() const;
-#endif
enum AtlasType {
kA8_AtlasType, //!< 1-byte per pixel
diff --git a/chromium/third_party/skia/src/gpu/GrTextStrike_impl.h b/chromium/third_party/skia/src/gpu/GrTextStrike_impl.h
index 0691eaa6432..dcfc04aaae3 100644
--- a/chromium/third_party/skia/src/gpu/GrTextStrike_impl.h
+++ b/chromium/third_party/skia/src/gpu/GrTextStrike_impl.h
@@ -48,11 +48,7 @@ void GrFontCache::detachStrikeFromList(GrTextStrike* strike) {
}
}
-#if SK_DISTANCEFIELD_FONTS
GrTextStrike* GrFontCache::getStrike(GrFontScaler* scaler, bool useDistanceField) {
-#else
-GrTextStrike* GrFontCache::getStrike(GrFontScaler* scaler) {
-#endif
this->validate();
const Key key(scaler->getKey());
@@ -61,7 +57,7 @@ GrTextStrike* GrFontCache::getStrike(GrFontScaler* scaler) {
strike = this->generateStrike(scaler, key);
} else if (strike->fPrev) {
// Need to put the strike at the head of its dllist, since that is how
- // we age the strikes for purging (we purge from the back of the list
+ // we age the strikes for purging (we purge from the back of the list)
this->detachStrikeFromList(strike);
// attach at the head
fHead->fPrev = strike;
@@ -69,9 +65,7 @@ GrTextStrike* GrFontCache::getStrike(GrFontScaler* scaler) {
strike->fPrev = NULL;
fHead = strike;
}
-#if SK_DISTANCEFIELD_FONTS
strike->fUseDistanceField = useDistanceField;
-#endif
this->validate();
return strike;
}
diff --git a/chromium/third_party/skia/src/gpu/GrTexture.cpp b/chromium/third_party/skia/src/gpu/GrTexture.cpp
index f8515153710..4f95730b120 100644
--- a/chromium/third_party/skia/src/gpu/GrTexture.cpp
+++ b/chromium/third_party/skia/src/gpu/GrTexture.cpp
@@ -26,13 +26,12 @@ GrTexture::~GrTexture() {
* textures back in the texture cache when their ref count goes to zero.
*/
void GrTexture::internal_dispose() const {
-
- if (this->isSetFlag((GrTextureFlags) kReturnToCache_FlagBit) &&
+ if (this->impl()->isSetFlag((GrTextureFlags) GrTextureImpl::kReturnToCache_FlagBit) &&
NULL != this->INHERITED::getContext()) {
GrTexture* nonConstThis = const_cast<GrTexture *>(this);
this->fRefCnt = 1; // restore ref count to initial setting
- nonConstThis->resetFlag((GrTextureFlags) kReturnToCache_FlagBit);
+ nonConstThis->impl()->resetFlag((GrTextureFlags) GrTextureImpl::kReturnToCache_FlagBit);
nonConstThis->INHERITED::getContext()->addExistingTextureToCache(nonConstThis);
// Note: "this" texture might be freed inside addExistingTextureToCache
@@ -44,6 +43,52 @@ void GrTexture::internal_dispose() const {
this->INHERITED::internal_dispose();
}
+void GrTextureImpl::dirtyMipMaps(bool mipMapsDirty) {
+ if (mipMapsDirty) {
+ if (kValid_MipMapsStatus == fMipMapsStatus) {
+ fMipMapsStatus = kAllocated_MipMapsStatus;
+ }
+ } else {
+ const bool sizeChanged = kNotAllocated_MipMapsStatus == fMipMapsStatus;
+ fMipMapsStatus = kValid_MipMapsStatus;
+ if (sizeChanged) {
+ // This must not be called until after changing fMipMapsStatus.
+ this->didChangeGpuMemorySize();
+ }
+ }
+}
+
+size_t GrTexture::gpuMemorySize() const {
+ size_t textureSize = (size_t) fDesc.fWidth *
+ fDesc.fHeight *
+ GrBytesPerPixel(fDesc.fConfig);
+
+ if (GrPixelConfigIsCompressed(fDesc.fConfig)) {
+ // Figure out the width and height corresponding to the data...
+
+ // Both of the available formats (ETC1 and LATC) have 4x4
+ // blocks that compress down to 8 bytes.
+ switch(fDesc.fConfig) {
+ case kETC1_GrPixelConfig:
+ case kLATC_GrPixelConfig:
+ SkASSERT((fDesc.fWidth & 3) == 0);
+ SkASSERT((fDesc.fHeight & 3) == 0);
+ textureSize = (fDesc.fWidth >> 2) * (fDesc.fHeight >> 2) * 8;
+ break;
+
+ default:
+ SkFAIL("Unknown compressed config");
+ }
+ }
+
+ if (this->impl()->hasMipMaps()) {
+ // We don't have to worry about the mipmaps being a different size than
+ // we'd expect because we never change fDesc.fWidth/fHeight.
+ textureSize *= 2;
+ }
+ return textureSize;
+}
+
bool GrTexture::readPixels(int left, int top, int width, int height,
GrPixelConfig config, void* buffer,
size_t rowBytes, uint32_t pixelOpsFlags) {
@@ -73,7 +118,7 @@ void GrTexture::writePixels(int left, int top, int width, int height,
}
void GrTexture::onRelease() {
- SkASSERT(!this->isSetFlag((GrTextureFlags) kReturnToCache_FlagBit));
+ SkASSERT(!this->impl()->isSetFlag((GrTextureFlags) GrTextureImpl::kReturnToCache_FlagBit));
INHERITED::onRelease();
}
@@ -103,6 +148,8 @@ void GrTexture::validateDesc() const {
}
}
+//////////////////////////////////////////////////////////////////////////////
+
// These flags need to fit in a GrResourceKey::ResourceFlags so they can be folded into the texture
// key
enum TextureFlags {
@@ -125,7 +172,7 @@ GrResourceKey::ResourceFlags get_texture_flags(const GrGpu* gpu,
GrResourceKey::ResourceFlags flags = 0;
bool tiled = NULL != params && params->isTiled();
if (tiled && !gpu->caps()->npotTextureTileSupport()) {
- if (!GrIsPow2(desc.fWidth) || !GrIsPow2(desc.fHeight)) {
+ if (!SkIsPow2(desc.fWidth) || !SkIsPow2(desc.fHeight)) {
flags |= kStretchToPOT_TextureFlag;
switch(params->filterMode()) {
case GrTextureParams::kNone_FilterMode:
@@ -159,7 +206,9 @@ GrSurfaceOrigin resolve_origin(const GrTextureDesc& desc) {
}
}
-GrResourceKey GrTexture::ComputeKey(const GrGpu* gpu,
+//////////////////////////////////////////////////////////////////////////////
+
+GrResourceKey GrTextureImpl::ComputeKey(const GrGpu* gpu,
const GrTextureParams* params,
const GrTextureDesc& desc,
const GrCacheID& cacheID) {
@@ -167,7 +216,7 @@ GrResourceKey GrTexture::ComputeKey(const GrGpu* gpu,
return GrResourceKey(cacheID, texture_resource_type(), flags);
}
-GrResourceKey GrTexture::ComputeScratchKey(const GrTextureDesc& desc) {
+GrResourceKey GrTextureImpl::ComputeScratchKey(const GrTextureDesc& desc) {
GrCacheID::Key idKey;
// Instead of a client-provided key of the texture contents we create a key from the
// descriptor.
@@ -186,10 +235,10 @@ GrResourceKey GrTexture::ComputeScratchKey(const GrTextureDesc& desc) {
return GrResourceKey(cacheID, texture_resource_type(), 0);
}
-bool GrTexture::NeedsResizing(const GrResourceKey& key) {
+bool GrTextureImpl::NeedsResizing(const GrResourceKey& key) {
return SkToBool(key.getResourceFlags() & kStretchToPOT_TextureFlag);
}
-bool GrTexture::NeedsBilerp(const GrResourceKey& key) {
+bool GrTextureImpl::NeedsBilerp(const GrResourceKey& key) {
return SkToBool(key.getResourceFlags() & kBilerp_TextureFlag);
}
diff --git a/chromium/third_party/skia/src/gpu/GrTextureAccess.cpp b/chromium/third_party/skia/src/gpu/GrTextureAccess.cpp
index e4b078698de..91db08bea54 100644
--- a/chromium/third_party/skia/src/gpu/GrTextureAccess.cpp
+++ b/chromium/third_party/skia/src/gpu/GrTextureAccess.cpp
@@ -100,7 +100,7 @@ void GrTextureAccess::setSwizzle(const char* swizzle) {
fSwizzleMask |= kA_GrColorComponentFlag;
break;
default:
- GrCrash("Unexpected swizzle string character.");
+ SkFAIL("Unexpected swizzle string character.");
break;
}
}
diff --git a/chromium/third_party/skia/src/gpu/GrTraceMarker.cpp b/chromium/third_party/skia/src/gpu/GrTraceMarker.cpp
new file mode 100644
index 00000000000..11cdd5e2c25
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/GrTraceMarker.cpp
@@ -0,0 +1,87 @@
+
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrTraceMarker.h"
+#include "GrTracing.h"
+#include "SkString.h"
+#include "SkTSort.h"
+
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+
+GrTraceMarkerSet::GrTraceMarkerSet(const GrTraceMarkerSet& other) {
+ this->addSet(other);
+}
+
+void GrTraceMarkerSet::add(const GrGpuTraceMarker& marker) {
+ this->fMarkerArray.push(marker);
+}
+
+void GrTraceMarkerSet::addSet(const GrTraceMarkerSet& markerSet) {
+ for (Iter iter = markerSet.begin(); iter != markerSet.end(); ++iter) {
+ this->add(*iter);
+ }
+}
+
+void GrTraceMarkerSet::remove(const GrGpuTraceMarker& marker) {
+ SkASSERT(-1 != fMarkerArray.find(marker));
+ int index = this->fMarkerArray.find(marker);
+ this->fMarkerArray.remove(index);
+}
+
+int GrTraceMarkerSet::count() const {
+ return this->fMarkerArray.count();
+}
+
+SkString GrTraceMarkerSet::toString() const {
+ SkTQSort<GrGpuTraceMarker>(this->fMarkerArray.begin(), this->fMarkerArray.end() - 1);
+ SkString marker_string;
+ const char* prevMarkerName = "";
+ int prevMarkerID = -1;
+ int counter = 0;
+ const int numMarkers = this->fMarkerArray.count();
+
+ // check used for GrGpuGL device after we've already collapsed all markers
+ if (1 == numMarkers && -1 == this->fMarkerArray[0].fID) {
+ marker_string.append(this->fMarkerArray[0].fMarker);
+ return marker_string;
+ }
+
+ for (int i = 0; i < numMarkers; ++i ) {
+ GrGpuTraceMarker& currMarker = this->fMarkerArray[i];
+ const char* currCmd = currMarker.fMarker;
+ if (currCmd != prevMarkerName) {
+ if (counter != 0) {
+ marker_string.append(") ");
+ }
+ marker_string.append(currCmd);
+ marker_string.append("(");
+ marker_string.appendS32(currMarker.fID);
+ prevMarkerName = currCmd;
+ } else if (currMarker.fID != prevMarkerID) {
+ marker_string.append(", ");
+ marker_string.appendS32(currMarker.fID);
+ }
+ prevMarkerID = currMarker.fID;
+ ++counter;
+ }
+ if (counter > 0) {
+ marker_string.append(")");
+ }
+ return marker_string;
+}
+
+GrTraceMarkerSet::Iter GrTraceMarkerSet::begin() const {
+ return Iter(this, 0);
+}
+
+GrTraceMarkerSet::Iter GrTraceMarkerSet::end() const {
+ return Iter(this, this->fMarkerArray.count());
+}
+
diff --git a/chromium/third_party/skia/src/gpu/GrTraceMarker.h b/chromium/third_party/skia/src/gpu/GrTraceMarker.h
new file mode 100644
index 00000000000..fa4904e0c9c
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/GrTraceMarker.h
@@ -0,0 +1,98 @@
+
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkTDArray.h"
+
+#ifndef GrTraceMarkerSet_DEFINED
+#define GrTraceMarkerSet_DEFINED
+
+class GrGpuTraceMarker {
+public:
+ GrGpuTraceMarker() {};
+ GrGpuTraceMarker(const char* marker, int idCounter) : fMarker(marker), fID(idCounter) {}
+
+ bool operator<(const GrGpuTraceMarker& rhs) const {
+ return this->fMarker < rhs.fMarker || (this->fMarker == rhs.fMarker && this->fID < rhs.fID);
+ }
+
+ bool operator==(const GrGpuTraceMarker& rhs) const {
+ return (this->fID == rhs.fID && this->fMarker == rhs.fMarker);
+ }
+
+ const char* fMarker;
+ int fID;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class SkString;
+
+class GrTraceMarkerSet {
+public:
+ GrTraceMarkerSet() {}
+
+ GrTraceMarkerSet(const GrTraceMarkerSet& other);
+
+ // Adds marker to the set.
+ void add(const GrGpuTraceMarker& marker);
+ // Adds all markers from one set into this set.
+ void addSet(const GrTraceMarkerSet& markerSet);
+
+ void remove(const GrGpuTraceMarker& marker);
+
+ int count() const;
+
+ /**
+ * First sorts fMarkerArray and returns a string of the format
+ * MarkerName1(#,#,...)%MarkerName2(#,#,...):... where MarkerName is the
+ * marker string used in the TraceMarker and the (#,#,..) is a list of instance
+ * id's for the the given marker string
+ */
+ SkString toString() const;
+
+ class Iter;
+
+ Iter begin() const;
+
+ Iter end() const;
+
+private:
+ mutable SkTDArray<GrGpuTraceMarker> fMarkerArray;
+};
+
+class GrTraceMarkerSet::Iter {
+public:
+ Iter() {};
+ Iter& operator=(const Iter& i) {
+ fCurrentIndex = i.fCurrentIndex;
+ fMarkers = i.fMarkers;
+ return *this;
+ }
+ bool operator==(const Iter& i) const {
+ return fCurrentIndex == i.fCurrentIndex && fMarkers == i.fMarkers;
+ }
+ bool operator!=(const Iter& i) const { return !(*this == i); }
+ const GrGpuTraceMarker& operator*() const { return fMarkers->fMarkerArray[fCurrentIndex]; }
+ Iter& operator++() {
+ SkASSERT(*this != fMarkers->end());
+ ++fCurrentIndex;
+ return *this;
+ }
+
+private:
+ friend class GrTraceMarkerSet;
+ Iter(const GrTraceMarkerSet* markers, int index)
+ : fMarkers(markers), fCurrentIndex(index) {
+ SkASSERT(markers);
+ }
+
+ const GrTraceMarkerSet* fMarkers;
+ int fCurrentIndex;
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/GrTracing.h b/chromium/third_party/skia/src/gpu/GrTracing.h
new file mode 100644
index 00000000000..311042f27b5
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/GrTracing.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrTracing_DEFINED
+#define GrTracing_DEFINED
+
+#include "GrDrawTarget.h"
+#include "GrGpu.h"
+#include "GrInOrderDrawBuffer.h"
+#include "GrTraceMarker.h"
+#include "SkTraceEvent.h"
+
+/**
+ * Marker generation class used for adding and removing markers around code blocks
+ */
+class GrGpuTraceMarkerGenerator : public ::SkNoncopyable {
+public:
+ GrGpuTraceMarkerGenerator(GrDrawTarget* target) : fTarget(target) {}
+
+ ~GrGpuTraceMarkerGenerator() {
+ if (fTraceMarker.isValid()) {
+ fTarget->removeGpuTraceMarker(fTraceMarker.get());
+ }
+ }
+
+ void initialize(const char* marker_str, int* marker_counter) {
+ GrGpuTraceMarker* traceMarker = fTraceMarker.init();
+ traceMarker->fMarker = marker_str;
+ traceMarker->fID = *marker_counter;
+ fTarget->addGpuTraceMarker(traceMarker);
+ }
+
+private:
+ GrDrawTarget* fTarget;
+ SkTLazy<GrGpuTraceMarker> fTraceMarker;
+};
+
+class GrGpuTraceMarkerGeneratorContext : public ::SkNoncopyable {
+public:
+ GrGpuTraceMarkerGeneratorContext(GrContext* context) : fContext(context) {}
+
+ ~GrGpuTraceMarkerGeneratorContext() {
+ if (fTraceMarker.isValid()) {
+ fContext->removeGpuTraceMarker(fTraceMarker.get());
+ }
+ }
+
+ void initialize(const char* marker_str, int* marker_counter) {
+ GrGpuTraceMarker* traceMarker = fTraceMarker.init();
+ traceMarker->fMarker = marker_str;
+ traceMarker->fID = *marker_counter;
+ fContext->addGpuTraceMarker(traceMarker);
+ }
+
+private:
+ GrContext* fContext;
+ SkTLazy<GrGpuTraceMarker> fTraceMarker;
+};
+
+/**
+ * GR_CREATE_TRACE_MARKER will place begin and end trace markers for both
+ * cpu and gpu (if gpu tracing enabled) for the current scope.
+ * marker is of type const char* and target is of type GrDrawTarget*
+ */
+#define GR_CREATE_TRACE_MARKER(name, target) \
+ static const char* SK_MACRO_APPEND_LINE(static_name) = name; \
+ static int SK_MACRO_APPEND_LINE(name_counter) = 0; \
+ INTERNAL_GR_CREATE_TRACE_MARKER(SK_MACRO_APPEND_LINE(static_name), \
+ SK_MACRO_APPEND_LINE(name_counter), \
+ target) \
+ sk_atomic_inc(&SK_MACRO_APPEND_LINE(name_counter)); \
+
+#define INTERNAL_GR_CREATE_TRACE_MARKER(name, name_counter, target) \
+ GR_CREATE_GPU_TRACE_MARKER(name, name_counter, target) \
+ TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("skia.gpu"),name, \
+ "id", name_counter) \
+
+#define GR_CREATE_GPU_TRACE_MARKER(name, name_counter, target) \
+ GrGpuTraceMarkerGenerator SK_MACRO_APPEND_LINE(TMG)(target); \
+ if (target->isGpuTracingEnabled()) { \
+ SK_MACRO_APPEND_LINE(TMG).initialize(name, &name_counter); \
+ } \
+
+#define GR_CREATE_TRACE_MARKER_CONTEXT(name, context) \
+ static const char* SK_MACRO_APPEND_LINE(static_name) = name; \
+ static int SK_MACRO_APPEND_LINE(name_counter) = 0; \
+ INTERNAL_GR_CREATE_TRACE_MARKER_C(SK_MACRO_APPEND_LINE(static_name), \
+ SK_MACRO_APPEND_LINE(name_counter), \
+ context) \
+ sk_atomic_inc(&SK_MACRO_APPEND_LINE(name_counter)); \
+
+#define INTERNAL_GR_CREATE_TRACE_MARKER_C(name, name_counter, context) \
+ GR_CREATE_GPU_TRACE_MARKER_C(name, name_counter, context) \
+ TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("skia.gpu"),name, \
+ "id", name_counter) \
+
+#define GR_CREATE_GPU_TRACE_MARKER_C(name, name_counter, context) \
+ GrGpuTraceMarkerGeneratorContext SK_MACRO_APPEND_LINE(TMG)(context); \
+ if (context->isGpuTracingEnabled()) { \
+ SK_MACRO_APPEND_LINE(TMG).initialize(name, &name_counter); \
+ } \
+
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/GrVertexBuffer.h b/chromium/third_party/skia/src/gpu/GrVertexBuffer.h
index a2bd5a1b4d1..c3cf5348927 100644
--- a/chromium/third_party/skia/src/gpu/GrVertexBuffer.h
+++ b/chromium/third_party/skia/src/gpu/GrVertexBuffer.h
@@ -15,8 +15,8 @@
class GrVertexBuffer : public GrGeometryBuffer {
protected:
- GrVertexBuffer(GrGpu* gpu, bool isWrapped, size_t sizeInBytes, bool dynamic, bool cpuBacked)
- : INHERITED(gpu, isWrapped, sizeInBytes, dynamic, cpuBacked) {}
+ GrVertexBuffer(GrGpu* gpu, bool isWrapped, size_t gpuMemorySize, bool dynamic, bool cpuBacked)
+ : INHERITED(gpu, isWrapped, gpuMemorySize, dynamic, cpuBacked) {}
private:
typedef GrGeometryBuffer INHERITED;
};
diff --git a/chromium/third_party/skia/src/gpu/SkGpuDevice.cpp b/chromium/third_party/skia/src/gpu/SkGpuDevice.cpp
index a413d042046..d0c32eb77c6 100644
--- a/chromium/third_party/skia/src/gpu/SkGpuDevice.cpp
+++ b/chromium/third_party/skia/src/gpu/SkGpuDevice.cpp
@@ -8,26 +8,34 @@
#include "SkGpuDevice.h"
#include "effects/GrBicubicEffect.h"
+#include "effects/GrDashingEffect.h"
#include "effects/GrTextureDomain.h"
#include "effects/GrSimpleTextureEffect.h"
#include "GrContext.h"
#include "GrBitmapTextContext.h"
-#if SK_DISTANCEFIELD_FONTS
#include "GrDistanceFieldTextContext.h"
-#endif
+#include "GrLayerCache.h"
+#include "GrPictureUtils.h"
+#include "GrStrokeInfo.h"
+#include "GrTracing.h"
#include "SkGrTexturePixelRef.h"
-#include "SkColorFilter.h"
#include "SkDeviceImageFilterProxy.h"
#include "SkDrawProcs.h"
#include "SkGlyphCache.h"
#include "SkImageFilter.h"
+#include "SkMaskFilter.h"
#include "SkPathEffect.h"
+#include "SkPicture.h"
+#include "SkPicturePlayback.h"
#include "SkRRect.h"
#include "SkStroke.h"
+#include "SkSurface.h"
+#include "SkTLazy.h"
#include "SkUtils.h"
+#include "SkVertState.h"
#include "SkErrorInternals.h"
#define CACHE_COMPATIBLE_DEVICE_TEXTURES 1
@@ -119,88 +127,53 @@ public:
///////////////////////////////////////////////////////////////////////////////
-static SkBitmap::Config grConfig2skConfig(GrPixelConfig config, bool* isOpaque) {
- switch (config) {
- case kAlpha_8_GrPixelConfig:
- *isOpaque = false;
- return SkBitmap::kA8_Config;
- case kRGB_565_GrPixelConfig:
- *isOpaque = true;
- return SkBitmap::kRGB_565_Config;
- case kRGBA_4444_GrPixelConfig:
- *isOpaque = false;
- return SkBitmap::kARGB_4444_Config;
- case kSkia8888_GrPixelConfig:
- // we don't currently have a way of knowing whether
- // a 8888 is opaque based on the config.
- *isOpaque = false;
- return SkBitmap::kARGB_8888_Config;
- default:
- *isOpaque = false;
- return SkBitmap::kNo_Config;
- }
-}
-
/*
* GrRenderTarget does not know its opaqueness, only its config, so we have
* to make conservative guesses when we return an "equivalent" bitmap.
*/
static SkBitmap make_bitmap(GrContext* context, GrRenderTarget* renderTarget) {
- bool isOpaque;
- SkBitmap::Config config = grConfig2skConfig(renderTarget->config(), &isOpaque);
-
SkBitmap bitmap;
- bitmap.setConfig(config, renderTarget->width(), renderTarget->height(), 0,
- isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
+ bitmap.setInfo(renderTarget->info());
return bitmap;
}
-/*
- * Calling SkBitmapDevice with individual params asks it to allocate pixel memory.
- * We never want that, so we always need to call it with a bitmap argument
- * (which says take my allocate (or lack thereof)).
- *
- * This is a REALLY good reason to finish the clean-up of SkBaseDevice, and have
- * SkGpuDevice inherit from that instead of SkBitmapDevice.
- */
-static SkBitmap make_bitmap(SkBitmap::Config config, int width, int height, bool isOpaque) {
- SkBitmap bm;
- bm.setConfig(config, width, height, isOpaque);
- return bm;
-}
-
-SkGpuDevice* SkGpuDevice::Create(GrSurface* surface) {
+SkGpuDevice* SkGpuDevice::Create(GrSurface* surface, unsigned flags) {
SkASSERT(NULL != surface);
if (NULL == surface->asRenderTarget() || NULL == surface->getContext()) {
return NULL;
}
if (surface->asTexture()) {
- return SkNEW_ARGS(SkGpuDevice, (surface->getContext(), surface->asTexture()));
+ return SkNEW_ARGS(SkGpuDevice, (surface->getContext(), surface->asTexture(), flags));
} else {
- return SkNEW_ARGS(SkGpuDevice, (surface->getContext(), surface->asRenderTarget()));
+ return SkNEW_ARGS(SkGpuDevice, (surface->getContext(), surface->asRenderTarget(), flags));
}
}
-SkGpuDevice::SkGpuDevice(GrContext* context, GrTexture* texture)
+SkGpuDevice::SkGpuDevice(GrContext* context, GrTexture* texture, unsigned flags)
: SkBitmapDevice(make_bitmap(context, texture->asRenderTarget())) {
- this->initFromRenderTarget(context, texture->asRenderTarget(), false);
+ this->initFromRenderTarget(context, texture->asRenderTarget(), flags);
}
-SkGpuDevice::SkGpuDevice(GrContext* context, GrRenderTarget* renderTarget)
+SkGpuDevice::SkGpuDevice(GrContext* context, GrRenderTarget* renderTarget, unsigned flags)
: SkBitmapDevice(make_bitmap(context, renderTarget)) {
- this->initFromRenderTarget(context, renderTarget, false);
+ this->initFromRenderTarget(context, renderTarget, flags);
}
void SkGpuDevice::initFromRenderTarget(GrContext* context,
GrRenderTarget* renderTarget,
- bool cached) {
+ unsigned flags) {
fDrawProcs = NULL;
fContext = context;
fContext->ref();
+ bool useDFFonts = !!(flags & kDFFonts_Flag);
+ fMainTextContext = SkNEW_ARGS(GrDistanceFieldTextContext, (fContext, fLeakyProperties,
+ useDFFonts));
+ fFallbackTextContext = SkNEW_ARGS(GrBitmapTextContext, (fContext, fLeakyProperties));
+
fRenderTarget = NULL;
- fNeedClear = false;
+ fNeedClear = flags & kNeedClear_Flag;
SkASSERT(NULL != renderTarget);
fRenderTarget = renderTarget;
@@ -215,63 +188,44 @@ void SkGpuDevice::initFromRenderTarget(GrContext* context,
surface = fRenderTarget;
}
- SkImageInfo info;
- surface->asImageInfo(&info);
- SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (info, surface, cached));
+ SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef,
+ (surface->info(), surface, SkToBool(flags & kCached_Flag)));
- this->setPixelRef(pr, 0)->unref();
+ this->setPixelRef(pr)->unref();
}
-SkGpuDevice::SkGpuDevice(GrContext* context,
- SkBitmap::Config config,
- int width,
- int height,
- int sampleCount)
- : SkBitmapDevice(make_bitmap(config, width, height, false /*isOpaque*/))
-{
- fDrawProcs = NULL;
-
- fContext = context;
- fContext->ref();
-
- fRenderTarget = NULL;
- fNeedClear = false;
+SkGpuDevice* SkGpuDevice::Create(GrContext* context, const SkImageInfo& origInfo,
+ int sampleCount) {
+ if (kUnknown_SkColorType == origInfo.colorType() ||
+ origInfo.width() < 0 || origInfo.height() < 0) {
+ return NULL;
+ }
- if (config != SkBitmap::kRGB_565_Config) {
- config = SkBitmap::kARGB_8888_Config;
+ SkImageInfo info = origInfo;
+ // TODO: perhas we can loosen this check now that colortype is more detailed
+ // e.g. can we support both RGBA and BGRA here?
+ if (kRGB_565_SkColorType == info.colorType()) {
+ info.fAlphaType = kOpaque_SkAlphaType; // force this setting
+ } else {
+ info.fColorType = kN32_SkColorType;
+ if (kOpaque_SkAlphaType != info.alphaType()) {
+ info.fAlphaType = kPremul_SkAlphaType; // force this setting
+ }
}
GrTextureDesc desc;
desc.fFlags = kRenderTarget_GrTextureFlagBit;
- desc.fWidth = width;
- desc.fHeight = height;
- desc.fConfig = SkBitmapConfig2GrPixelConfig(config);
+ desc.fWidth = info.width();
+ desc.fHeight = info.height();
+ desc.fConfig = SkImageInfo2GrPixelConfig(info);
desc.fSampleCnt = sampleCount;
- SkImageInfo info;
- if (!GrPixelConfig2ColorType(desc.fConfig, &info.fColorType)) {
- sk_throw();
+ SkAutoTUnref<GrTexture> texture(context->createUncachedTexture(desc, NULL, 0));
+ if (!texture.get()) {
+ return NULL;
}
- info.fWidth = width;
- info.fHeight = height;
- info.fAlphaType = kPremul_SkAlphaType;
-
- SkAutoTUnref<GrTexture> texture(fContext->createUncachedTexture(desc, NULL, 0));
-
- if (NULL != texture) {
- fRenderTarget = texture->asRenderTarget();
- fRenderTarget->ref();
-
- SkASSERT(NULL != fRenderTarget);
- // wrap the bitmap with a pixelref to expose our texture
- SkGrPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (info, texture));
- this->setPixelRef(pr, 0)->unref();
- } else {
- GrPrintf("--- failed to create gpu-offscreen [%d %d]\n",
- width, height);
- SkASSERT(false);
- }
+ return SkNEW_ARGS(SkGpuDevice, (context, texture.get()));
}
SkGpuDevice::~SkGpuDevice() {
@@ -279,6 +233,9 @@ SkGpuDevice::~SkGpuDevice() {
delete fDrawProcs;
}
+ delete fMainTextContext;
+ delete fFallbackTextContext;
+
// The GrContext takes a ref on the target. We don't want to cause the render
// target to be unnecessarily kept alive.
if (fContext->getRenderTarget() == fRenderTarget) {
@@ -302,75 +259,46 @@ void SkGpuDevice::makeRenderTargetCurrent() {
///////////////////////////////////////////////////////////////////////////////
-namespace {
-GrPixelConfig config8888_to_grconfig_and_flags(SkCanvas::Config8888 config8888, uint32_t* flags) {
- switch (config8888) {
- case SkCanvas::kNative_Premul_Config8888:
- *flags = 0;
- return kSkia8888_GrPixelConfig;
- case SkCanvas::kNative_Unpremul_Config8888:
- *flags = GrContext::kUnpremul_PixelOpsFlag;
- return kSkia8888_GrPixelConfig;
- case SkCanvas::kBGRA_Premul_Config8888:
- *flags = 0;
- return kBGRA_8888_GrPixelConfig;
- case SkCanvas::kBGRA_Unpremul_Config8888:
- *flags = GrContext::kUnpremul_PixelOpsFlag;
- return kBGRA_8888_GrPixelConfig;
- case SkCanvas::kRGBA_Premul_Config8888:
- *flags = 0;
- return kRGBA_8888_GrPixelConfig;
- case SkCanvas::kRGBA_Unpremul_Config8888:
- *flags = GrContext::kUnpremul_PixelOpsFlag;
- return kRGBA_8888_GrPixelConfig;
- default:
- GrCrash("Unexpected Config8888.");
- *flags = 0; // suppress warning
- return kSkia8888_GrPixelConfig;
- }
-}
-}
-
-bool SkGpuDevice::onReadPixels(const SkBitmap& bitmap,
- int x, int y,
- SkCanvas::Config8888 config8888) {
+bool SkGpuDevice::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
+ int x, int y) {
DO_DEFERRED_CLEAR();
- SkASSERT(SkBitmap::kARGB_8888_Config == bitmap.config());
- SkASSERT(!bitmap.isNull());
- SkASSERT(SkIRect::MakeWH(this->width(), this->height()).contains(SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height())));
- SkAutoLockPixels alp(bitmap);
- GrPixelConfig config;
- uint32_t flags;
- config = config8888_to_grconfig_and_flags(config8888, &flags);
- return fContext->readRenderTargetPixels(fRenderTarget,
- x, y,
- bitmap.width(),
- bitmap.height(),
- config,
- bitmap.getPixels(),
- bitmap.rowBytes(),
- flags);
-}
+ // TODO: teach fRenderTarget to take ImageInfo directly to specify the src pixels
+ GrPixelConfig config = SkImageInfo2GrPixelConfig(dstInfo);
+ if (kUnknown_GrPixelConfig == config) {
+ return false;
+ }
-void SkGpuDevice::writePixels(const SkBitmap& bitmap, int x, int y,
- SkCanvas::Config8888 config8888) {
- SkAutoLockPixels alp(bitmap);
- if (!bitmap.readyToDraw()) {
- return;
+ uint32_t flags = 0;
+ if (kUnpremul_SkAlphaType == dstInfo.alphaType()) {
+ flags = GrContext::kUnpremul_PixelOpsFlag;
}
+ return fContext->readRenderTargetPixels(fRenderTarget, x, y, dstInfo.width(), dstInfo.height(),
+ config, dstPixels, dstRowBytes, flags);
+}
- GrPixelConfig config;
- uint32_t flags;
- if (SkBitmap::kARGB_8888_Config == bitmap.config()) {
- config = config8888_to_grconfig_and_flags(config8888, &flags);
- } else {
- flags = 0;
- config= SkBitmapConfig2GrPixelConfig(bitmap.config());
+bool SkGpuDevice::onWritePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes,
+ int x, int y) {
+ // TODO: teach fRenderTarget to take ImageInfo directly to specify the src pixels
+ GrPixelConfig config = SkImageInfo2GrPixelConfig(info);
+ if (kUnknown_GrPixelConfig == config) {
+ return false;
}
+ uint32_t flags = 0;
+ if (kUnpremul_SkAlphaType == info.alphaType()) {
+ flags = GrContext::kUnpremul_PixelOpsFlag;
+ }
+ fRenderTarget->writePixels(x, y, info.width(), info.height(), config, pixels, rowBytes, flags);
+
+ // need to bump our genID for compatibility with clients that "know" we have a bitmap
+ this->onAccessBitmap().notifyPixelsChanged();
- fRenderTarget->writePixels(x, y, bitmap.width(), bitmap.height(),
- config, bitmap.getPixels(), bitmap.rowBytes(), flags);
+ return true;
+}
+
+const SkBitmap& SkGpuDevice::onAccessBitmap() {
+ DO_DEFERRED_CLEAR();
+ return INHERITED::onAccessBitmap();
}
void SkGpuDevice::onAttachToCanvas(SkCanvas* canvas) {
@@ -424,131 +352,8 @@ SK_COMPILE_ASSERT(SkShader::kTwoPointConical_BitmapType == 5,
SK_COMPILE_ASSERT(SkShader::kLinear_BitmapType == 6, shader_type_mismatch);
SK_COMPILE_ASSERT(SkShader::kLast_BitmapType == 6, shader_type_mismatch);
-namespace {
-
-// converts a SkPaint to a GrPaint, ignoring the skPaint's shader
-// justAlpha indicates that skPaint's alpha should be used rather than the color
-// Callers may subsequently modify the GrPaint. Setting constantColor indicates
-// that the final paint will draw the same color at every pixel. This allows
-// an optimization where the the color filter can be applied to the skPaint's
-// color once while converting to GrPaint and then ignored.
-inline bool skPaint2GrPaintNoShader(SkGpuDevice* dev,
- const SkPaint& skPaint,
- bool justAlpha,
- bool constantColor,
- GrPaint* grPaint) {
-
- grPaint->setDither(skPaint.isDither());
- grPaint->setAntiAlias(skPaint.isAntiAlias());
-
- SkXfermode::Coeff sm;
- SkXfermode::Coeff dm;
-
- SkXfermode* mode = skPaint.getXfermode();
- GrEffectRef* xferEffect = NULL;
- if (SkXfermode::AsNewEffectOrCoeff(mode, &xferEffect, &sm, &dm)) {
- if (NULL != xferEffect) {
- grPaint->addColorEffect(xferEffect)->unref();
- sm = SkXfermode::kOne_Coeff;
- dm = SkXfermode::kZero_Coeff;
- }
- } else {
- //SkDEBUGCODE(SkDebugf("Unsupported xfer mode.\n");)
-#if 0
- return false;
-#else
- // Fall back to src-over
- sm = SkXfermode::kOne_Coeff;
- dm = SkXfermode::kISA_Coeff;
-#endif
- }
- grPaint->setBlendFunc(sk_blend_to_grblend(sm), sk_blend_to_grblend(dm));
-
- if (justAlpha) {
- uint8_t alpha = skPaint.getAlpha();
- grPaint->setColor(GrColorPackRGBA(alpha, alpha, alpha, alpha));
- // justAlpha is currently set to true only if there is a texture,
- // so constantColor should not also be true.
- SkASSERT(!constantColor);
- } else {
- grPaint->setColor(SkColor2GrColor(skPaint.getColor()));
- }
-
- SkColorFilter* colorFilter = skPaint.getColorFilter();
- if (NULL != colorFilter) {
- // if the source color is a constant then apply the filter here once rather than per pixel
- // in a shader.
- if (constantColor) {
- SkColor filtered = colorFilter->filterColor(skPaint.getColor());
- grPaint->setColor(SkColor2GrColor(filtered));
- } else {
- SkAutoTUnref<GrEffectRef> effect(colorFilter->asNewEffect(dev->context()));
- if (NULL != effect.get()) {
- grPaint->addColorEffect(effect);
- }
- }
- }
-
- return true;
-}
-
-// This function is similar to skPaint2GrPaintNoShader but also converts
-// skPaint's shader to a GrTexture/GrEffectStage if possible. The texture to
-// be used is set on grPaint and returned in param act. constantColor has the
-// same meaning as in skPaint2GrPaintNoShader.
-inline bool skPaint2GrPaintShader(SkGpuDevice* dev,
- const SkPaint& skPaint,
- bool constantColor,
- GrPaint* grPaint) {
- SkShader* shader = skPaint.getShader();
- if (NULL == shader) {
- return skPaint2GrPaintNoShader(dev, skPaint, false, constantColor, grPaint);
- }
-
- // SkShader::asNewEffect() may do offscreen rendering. Setup default drawing state
- // Also require shader to set the render target .
- GrContext::AutoWideOpenIdentityDraw awo(dev->context(), NULL);
- GrContext::AutoRenderTarget(dev->context(), NULL);
-
- // setup the shader as the first color effect on the paint
- SkAutoTUnref<GrEffectRef> effect(shader->asNewEffect(dev->context(), skPaint));
- if (NULL != effect.get()) {
- grPaint->addColorEffect(effect);
- // Now setup the rest of the paint.
- return skPaint2GrPaintNoShader(dev, skPaint, true, false, grPaint);
- } else {
- // We still don't have SkColorShader::asNewEffect() implemented.
- SkShader::GradientInfo info;
- SkColor color;
-
- info.fColors = &color;
- info.fColorOffsets = NULL;
- info.fColorCount = 1;
- if (SkShader::kColor_GradientType == shader->asAGradient(&info)) {
- SkPaint copy(skPaint);
- copy.setShader(NULL);
- // modulate the paint alpha by the shader's solid color alpha
- U8CPU newA = SkMulDiv255Round(SkColorGetA(color), copy.getAlpha());
- copy.setColor(SkColorSetA(color, newA));
- return skPaint2GrPaintNoShader(dev, copy, false, constantColor, grPaint);
- } else {
- return false;
- }
- }
-}
-}
-
///////////////////////////////////////////////////////////////////////////////
-SkBitmap::Config SkGpuDevice::config() const {
- if (NULL == fRenderTarget) {
- return SkBitmap::kNo_Config;
- }
-
- bool isOpaque;
- return grConfig2skConfig(fRenderTarget->config(), &isOpaque);
-}
-
void SkGpuDevice::clear(SkColor color) {
SkIRect rect = SkIRect::MakeWH(this->width(), this->height());
fContext->clear(&rect, SkColor2GrColor(color), true, fRenderTarget);
@@ -559,9 +364,7 @@ void SkGpuDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
CHECK_SHOULD_DRAW(draw, false);
GrPaint grPaint;
- if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
- return;
- }
+ SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
fContext->drawPaint(grPaint);
}
@@ -583,6 +386,17 @@ void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
return;
}
+ if (paint.getPathEffect() && 2 == count && SkCanvas::kLines_PointMode == mode) {
+ GrStrokeInfo strokeInfo(paint, SkPaint::kStroke_Style);
+ GrPaint grPaint;
+ SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
+ SkPath path;
+ path.moveTo(pts[0]);
+ path.lineTo(pts[1]);
+ fContext->drawPath(grPaint, path, strokeInfo);
+ return;
+ }
+
// we only handle hairlines and paints without path effects or mask filters,
// else we let the SkDraw call our drawPath()
if (width > 0 || paint.getPathEffect() || paint.getMaskFilter()) {
@@ -591,14 +405,12 @@ void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
}
GrPaint grPaint;
- if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
- return;
- }
+ SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
fContext->drawVertices(grPaint,
gPointMode2PrimtiveType[mode],
SkToS32(count),
- (GrPoint*)pts,
+ (SkPoint*)pts,
NULL,
NULL,
NULL,
@@ -609,6 +421,8 @@ void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect,
const SkPaint& paint) {
+ GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawRect", fContext);
+
CHECK_FOR_ANNOTATION(paint);
CHECK_SHOULD_DRAW(draw, false);
@@ -623,9 +437,11 @@ void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect,
(paint.getStrokeJoin() == SkPaint::kRound_Join ||
(paint.getStrokeJoin() == SkPaint::kBevel_Join && rect.isEmpty()));
// another two reasons we might need to call drawPath...
- if (paint.getMaskFilter() || paint.getPathEffect()) {
+
+ if (paint.getMaskFilter()) {
usePath = true;
}
+
if (!usePath && paint.isAntiAlias() && !fContext->getMatrix().rectStaysRect()) {
#if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT)
if (doStroke) {
@@ -642,6 +458,13 @@ void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect,
usePath = true;
}
+ GrStrokeInfo strokeInfo(paint);
+
+ const SkPathEffect* pe = paint.getPathEffect();
+ if (!usePath && NULL != pe && !strokeInfo.isDashed()) {
+ usePath = true;
+ }
+
if (usePath) {
SkPath path;
path.addRect(rect);
@@ -650,16 +473,9 @@ void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect,
}
GrPaint grPaint;
- if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
- return;
- }
-
- if (!doStroke) {
- fContext->drawRect(grPaint, rect);
- } else {
- SkStrokeRec stroke(paint);
- fContext->drawRect(grPaint, rect, &stroke);
- }
+ SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
+
+ fContext->drawRect(grPaint, rect, &strokeInfo);
}
///////////////////////////////////////////////////////////////////////////////
@@ -669,43 +485,105 @@ void SkGpuDevice::drawRRect(const SkDraw& draw, const SkRRect& rect,
CHECK_FOR_ANNOTATION(paint);
CHECK_SHOULD_DRAW(draw, false);
- bool usePath = !rect.isSimple();
- // another two reasons we might need to call drawPath...
- if (paint.getMaskFilter() || paint.getPathEffect()) {
- usePath = true;
+ GrPaint grPaint;
+ SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
+
+ GrStrokeInfo strokeInfo(paint);
+ if (paint.getMaskFilter()) {
+ // try to hit the fast path for drawing filtered round rects
+
+ SkRRect devRRect;
+ if (rect.transform(fContext->getMatrix(), &devRRect)) {
+ if (devRRect.allCornersCircular()) {
+ SkRect maskRect;
+ if (paint.getMaskFilter()->canFilterMaskGPU(devRRect.rect(),
+ draw.fClip->getBounds(),
+ fContext->getMatrix(),
+ &maskRect)) {
+ SkIRect finalIRect;
+ maskRect.roundOut(&finalIRect);
+ if (draw.fClip->quickReject(finalIRect)) {
+ // clipped out
+ return;
+ }
+ if (paint.getMaskFilter()->directFilterRRectMaskGPU(fContext, &grPaint,
+ strokeInfo.getStrokeRec(),
+ devRRect)) {
+ return;
+ }
+ }
+
+ }
+ }
+
}
- // until we can rotate rrects...
- if (!usePath && !fContext->getMatrix().rectStaysRect()) {
+
+ bool usePath = false;
+
+ if (paint.getMaskFilter()) {
usePath = true;
+ } else {
+ const SkPathEffect* pe = paint.getPathEffect();
+ if (NULL != pe && !strokeInfo.isDashed()) {
+ usePath = true;
+ }
}
+
if (usePath) {
SkPath path;
path.addRRect(rect);
this->drawPath(draw, path, paint, NULL, true);
return;
}
+
+ fContext->drawRRect(grPaint, rect, strokeInfo);
+}
- GrPaint grPaint;
- if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
- return;
+void SkGpuDevice::drawDRRect(const SkDraw& draw, const SkRRect& outer,
+ const SkRRect& inner, const SkPaint& paint) {
+ SkStrokeRec stroke(paint);
+ if (stroke.isFillStyle()) {
+
+ CHECK_FOR_ANNOTATION(paint);
+ CHECK_SHOULD_DRAW(draw, false);
+
+ GrPaint grPaint;
+ SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
+
+ if (NULL == paint.getMaskFilter() && NULL == paint.getPathEffect()) {
+ fContext->drawDRRect(grPaint, outer, inner);
+ return;
+ }
}
- SkStrokeRec stroke(paint);
- fContext->drawRRect(grPaint, rect, stroke);
+ SkPath path;
+ path.addRRect(outer);
+ path.addRRect(inner);
+ path.setFillType(SkPath::kEvenOdd_FillType);
+
+ this->drawPath(draw, path, paint, NULL, true);
}
-///////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////////
void SkGpuDevice::drawOval(const SkDraw& draw, const SkRect& oval,
const SkPaint& paint) {
CHECK_FOR_ANNOTATION(paint);
CHECK_SHOULD_DRAW(draw, false);
+ GrStrokeInfo strokeInfo(paint);
+
bool usePath = false;
// some basic reasons we might need to call drawPath...
- if (paint.getMaskFilter() || paint.getPathEffect()) {
+ if (paint.getMaskFilter()) {
usePath = true;
+ } else {
+ const SkPathEffect* pe = paint.getPathEffect();
+ if (NULL != pe && !strokeInfo.isDashed()) {
+ usePath = true;
+ }
}
if (usePath) {
@@ -716,16 +594,12 @@ void SkGpuDevice::drawOval(const SkDraw& draw, const SkRect& oval,
}
GrPaint grPaint;
- if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
- return;
- }
- SkStrokeRec stroke(paint);
+ SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
- fContext->drawOval(grPaint, oval, stroke);
+ fContext->drawOval(grPaint, oval, strokeInfo);
}
#include "SkMaskFilter.h"
-#include "SkBounder.h"
///////////////////////////////////////////////////////////////////////////////
@@ -752,7 +626,7 @@ bool draw_mask(GrContext* context, const SkRect& maskRect,
}
bool draw_with_mask_filter(GrContext* context, const SkPath& devPath,
- SkMaskFilter* filter, const SkRegion& clip, SkBounder* bounder,
+ SkMaskFilter* filter, const SkRegion& clip,
GrPaint* grp, SkPaint::Style style) {
SkMask srcM, dstM;
@@ -771,9 +645,6 @@ bool draw_with_mask_filter(GrContext* context, const SkPath& devPath,
if (clip.quickReject(dstM.fBounds)) {
return false;
}
- if (bounder && !bounder->doIRect(dstM.fBounds)) {
- return false;
- }
// we now have a device-aligned 8bit mask in dstM, ready to be drawn using
// the current clip (and identity matrix) and GrPaint settings
@@ -801,7 +672,7 @@ bool draw_with_mask_filter(GrContext* context, const SkPath& devPath,
bool create_mask_GPU(GrContext* context,
const SkRect& maskRect,
const SkPath& devPath,
- const SkStrokeRec& stroke,
+ const GrStrokeInfo& strokeInfo,
bool doAA,
GrAutoScratchTexture* mask) {
GrTextureDesc desc;
@@ -846,17 +717,14 @@ bool create_mask_GPU(GrContext* context,
SkMatrix translate;
translate.setTranslate(-maskRect.fLeft, -maskRect.fTop);
am.set(context, translate);
- context->drawPath(tempPaint, devPath, stroke);
+ context->drawPath(tempPaint, devPath, strokeInfo);
return true;
}
SkBitmap wrap_texture(GrTexture* texture) {
- SkImageInfo info;
- texture->asImageInfo(&info);
-
SkBitmap result;
- result.setConfig(info);
- result.setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref();
+ result.setInfo(texture->info());
+ result.setPixelRef(SkNEW_ARGS(SkGrPixelRef, (result.info(), texture)))->unref();
return result;
}
@@ -869,21 +737,20 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
CHECK_SHOULD_DRAW(draw, false);
GrPaint grPaint;
- if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
- return;
- }
+ SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
// If we have a prematrix, apply it to the path, optimizing for the case
// where the original path can in fact be modified in place (even though
// its parameter type is const).
SkPath* pathPtr = const_cast<SkPath*>(&origSrcPath);
- SkPath tmpPath, effectPath;
+ SkTLazy<SkPath> tmpPath;
+ SkTLazy<SkPath> effectPath;
if (prePathMatrix) {
SkPath* result = pathPtr;
if (!pathIsMutable) {
- result = &tmpPath;
+ result = tmpPath.init();
pathIsMutable = true;
}
// should I push prePathMatrix on our MV stack temporarily, instead
@@ -894,25 +761,30 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
// at this point we're done with prePathMatrix
SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
- SkStrokeRec stroke(paint);
+ GrStrokeInfo strokeInfo(paint);
SkPathEffect* pathEffect = paint.getPathEffect();
const SkRect* cullRect = NULL; // TODO: what is our bounds?
- if (pathEffect && pathEffect->filterPath(&effectPath, *pathPtr, &stroke,
+ SkStrokeRec* strokePtr = strokeInfo.getStrokeRecPtr();
+ if (pathEffect && pathEffect->filterPath(effectPath.init(), *pathPtr, strokePtr,
cullRect)) {
- pathPtr = &effectPath;
+ pathPtr = effectPath.get();
+ pathIsMutable = true;
+ strokeInfo.removeDash();
}
+ const SkStrokeRec& stroke = strokeInfo.getStrokeRec();
if (paint.getMaskFilter()) {
if (!stroke.isHairlineStyle()) {
- if (stroke.applyToPath(&tmpPath, *pathPtr)) {
- pathPtr = &tmpPath;
+ SkPath* strokedPath = pathIsMutable ? pathPtr : tmpPath.init();
+ if (stroke.applyToPath(strokedPath, *pathPtr)) {
+ pathPtr = strokedPath;
pathIsMutable = true;
- stroke.setFillStyle();
+ strokeInfo.setFillStyle();
}
}
// avoid possibly allocating a new path in transform if we can
- SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath;
+ SkPath* devPathPtr = pathIsMutable ? pathPtr : tmpPath.init();
// transform the path into device space
pathPtr->transform(fContext->getMatrix(), devPathPtr);
@@ -922,24 +794,32 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
draw.fClip->getBounds(),
fContext->getMatrix(),
&maskRect)) {
+ // The context's matrix may change while creating the mask, so save the CTM here to
+ // pass to filterMaskGPU.
+ const SkMatrix ctm = fContext->getMatrix();
+
SkIRect finalIRect;
maskRect.roundOut(&finalIRect);
if (draw.fClip->quickReject(finalIRect)) {
// clipped out
return;
}
- if (NULL != draw.fBounder && !draw.fBounder->doIRect(finalIRect)) {
- // nothing to draw
+
+ if (paint.getMaskFilter()->directFilterMaskGPU(fContext, &grPaint,
+ stroke, *devPathPtr)) {
+ // the mask filter was able to draw itself directly, so there's nothing
+ // left to do.
return;
}
GrAutoScratchTexture mask;
- if (create_mask_GPU(fContext, maskRect, *devPathPtr, stroke,
+ if (create_mask_GPU(fContext, maskRect, *devPathPtr, strokeInfo,
grPaint.isAntiAlias(), &mask)) {
GrTexture* filtered;
- if (paint.getMaskFilter()->filterMaskGPU(mask.texture(), maskRect, &filtered, true)) {
+ if (paint.getMaskFilter()->filterMaskGPU(mask.texture(),
+ ctm, maskRect, &filtered, true)) {
// filterMaskGPU gives us ownership of a ref to the result
SkAutoTUnref<GrTexture> atu(filtered);
@@ -964,11 +844,11 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
SkPaint::Style style = stroke.isHairlineStyle() ? SkPaint::kStroke_Style :
SkPaint::kFill_Style;
draw_with_mask_filter(fContext, *devPathPtr, paint.getMaskFilter(),
- *draw.fClip, draw.fBounder, &grPaint, style);
+ *draw.fClip, &grPaint, style);
return;
}
- fContext->drawPath(grPaint, *pathPtr, stroke);
+ fContext->drawPath(grPaint, *pathPtr, strokeInfo);
}
static const int kBmpSmallTileSize = 1 << 10;
@@ -1013,6 +893,8 @@ static void determine_clipped_src_rect(const GrContext* context,
SkRect clippedSrcRect = SkRect::Make(*clippedSrcIRect);
inv.mapRect(&clippedSrcRect);
if (NULL != srcRectPtr) {
+ // we've setup src space 0,0 to map to the top left of the src rect.
+ clippedSrcRect.offset(srcRectPtr->fLeft, srcRectPtr->fTop);
if (!clippedSrcRect.intersect(*srcRectPtr)) {
clippedSrcIRect->setEmpty();
return;
@@ -1061,7 +943,7 @@ bool SkGpuDevice::shouldTileBitmap(const SkBitmap& bitmap,
// a texture
size_t bmpSize = bitmap.getSize();
size_t cacheSize;
- fContext->getTextureCacheLimits(NULL, &cacheSize);
+ fContext->getResourceCacheLimits(NULL, &cacheSize);
if (bmpSize < cacheSize / 2) {
return false;
}
@@ -1075,13 +957,17 @@ bool SkGpuDevice::shouldTileBitmap(const SkBitmap& bitmap,
return usedTileBytes < 2 * bmpSize;
}
-void SkGpuDevice::drawBitmap(const SkDraw& draw,
+void SkGpuDevice::drawBitmap(const SkDraw& origDraw,
const SkBitmap& bitmap,
const SkMatrix& m,
const SkPaint& paint) {
- // We cannot call drawBitmapRect here since 'm' could be anything
- this->drawBitmapCommon(draw, bitmap, NULL, m, paint,
- SkCanvas::kNone_DrawBitmapRectFlag);
+ SkMatrix concat;
+ SkTCopyOnFirstWrite<SkDraw> draw(origDraw);
+ if (!m.isIdentity()) {
+ concat.setConcat(*draw->fMatrix, m);
+ draw.writable()->fMatrix = &concat;
+ }
+ this->drawBitmapCommon(*draw, bitmap, NULL, NULL, paint, SkCanvas::kNone_DrawBitmapRectFlag);
}
// This method outsets 'iRect' by 'outset' all around and then clamps its extents to
@@ -1117,22 +1003,97 @@ static inline void clamped_outset_with_offset(SkIRect* iRect,
}
}
+static bool has_aligned_samples(const SkRect& srcRect,
+ const SkRect& transformedRect) {
+ // detect pixel disalignment
+ if (SkScalarAbs(SkScalarRoundToScalar(transformedRect.left()) -
+ transformedRect.left()) < COLOR_BLEED_TOLERANCE &&
+ SkScalarAbs(SkScalarRoundToScalar(transformedRect.top()) -
+ transformedRect.top()) < COLOR_BLEED_TOLERANCE &&
+ SkScalarAbs(transformedRect.width() - srcRect.width()) <
+ COLOR_BLEED_TOLERANCE &&
+ SkScalarAbs(transformedRect.height() - srcRect.height()) <
+ COLOR_BLEED_TOLERANCE) {
+ return true;
+ }
+ return false;
+}
+
+static bool may_color_bleed(const SkRect& srcRect,
+ const SkRect& transformedRect,
+ const SkMatrix& m) {
+ // Only gets called if has_aligned_samples returned false.
+ // So we can assume that sampling is axis aligned but not texel aligned.
+ SkASSERT(!has_aligned_samples(srcRect, transformedRect));
+ SkRect innerSrcRect(srcRect), innerTransformedRect,
+ outerTransformedRect(transformedRect);
+ innerSrcRect.inset(SK_ScalarHalf, SK_ScalarHalf);
+ m.mapRect(&innerTransformedRect, innerSrcRect);
+
+ // The gap between outerTransformedRect and innerTransformedRect
+ // represents the projection of the source border area, which is
+ // problematic for color bleeding. We must check whether any
+ // destination pixels sample the border area.
+ outerTransformedRect.inset(COLOR_BLEED_TOLERANCE, COLOR_BLEED_TOLERANCE);
+ innerTransformedRect.outset(COLOR_BLEED_TOLERANCE, COLOR_BLEED_TOLERANCE);
+ SkIRect outer, inner;
+ outerTransformedRect.round(&outer);
+ innerTransformedRect.round(&inner);
+ // If the inner and outer rects round to the same result, it means the
+ // border does not overlap any pixel centers. Yay!
+ return inner != outer;
+}
+
+static bool needs_texture_domain(const SkBitmap& bitmap,
+ const SkRect& srcRect,
+ GrTextureParams &params,
+ const SkMatrix& contextMatrix,
+ bool bicubic) {
+ bool needsTextureDomain = false;
+
+ if (bicubic || params.filterMode() != GrTextureParams::kNone_FilterMode) {
+ // Need texture domain if drawing a sub rect
+ needsTextureDomain = srcRect.width() < bitmap.width() ||
+ srcRect.height() < bitmap.height();
+ if (!bicubic && needsTextureDomain && contextMatrix.rectStaysRect()) {
+ // sampling is axis-aligned
+ SkRect transformedRect;
+ contextMatrix.mapRect(&transformedRect, srcRect);
+
+ if (has_aligned_samples(srcRect, transformedRect)) {
+ params.setFilterMode(GrTextureParams::kNone_FilterMode);
+ needsTextureDomain = false;
+ } else {
+ needsTextureDomain = may_color_bleed(srcRect, transformedRect, contextMatrix);
+ }
+ }
+ }
+ return needsTextureDomain;
+}
+
void SkGpuDevice::drawBitmapCommon(const SkDraw& draw,
const SkBitmap& bitmap,
const SkRect* srcRectPtr,
- const SkMatrix& m,
+ const SkSize* dstSizePtr,
const SkPaint& paint,
SkCanvas::DrawBitmapRectFlags flags) {
CHECK_SHOULD_DRAW(draw, false);
SkRect srcRect;
+ SkSize dstSize;
// If there is no src rect, or the src rect contains the entire bitmap then we're effectively
// in the (easier) bleed case, so update flags.
if (NULL == srcRectPtr) {
- srcRect.set(0, 0, SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height()));
+ SkScalar w = SkIntToScalar(bitmap.width());
+ SkScalar h = SkIntToScalar(bitmap.height());
+ dstSize.fWidth = w;
+ dstSize.fHeight = h;
+ srcRect.set(0, 0, w, h);
flags = (SkCanvas::DrawBitmapRectFlags) (flags | SkCanvas::kBleed_DrawBitmapRectFlag);
} else {
+ SkASSERT(NULL != dstSizePtr);
srcRect = *srcRectPtr;
+ dstSize = *dstSizePtr;
if (srcRect.fLeft <= 0 && srcRect.fTop <= 0 &&
srcRect.fRight >= bitmap.width() && srcRect.fBottom >= bitmap.height()) {
flags = (SkCanvas::DrawBitmapRectFlags) (flags | SkCanvas::kBleed_DrawBitmapRectFlag);
@@ -1142,10 +1103,13 @@ void SkGpuDevice::drawBitmapCommon(const SkDraw& draw,
if (paint.getMaskFilter()){
// Convert the bitmap to a shader so that the rect can be drawn
// through drawRect, which supports mask filters.
- SkMatrix newM(m);
SkBitmap tmp; // subset of bitmap, if necessary
const SkBitmap* bitmapPtr = &bitmap;
+ SkMatrix localM;
if (NULL != srcRectPtr) {
+ localM.setTranslate(-srcRectPtr->fLeft, -srcRectPtr->fTop);
+ localM.postScale(dstSize.fWidth / srcRectPtr->width(),
+ dstSize.fHeight / srcRectPtr->height());
// In bleed mode we position and trim the bitmap based on the src rect which is
// already accounted for in 'm' and 'srcRect'. In clamp mode we need to chop out
// the desired portion of the bitmap and then update 'm' and 'srcRect' to
@@ -1162,76 +1126,73 @@ void SkGpuDevice::drawBitmapCommon(const SkDraw& draw,
}
bitmapPtr = &tmp;
srcRect.offset(-offset.fX, -offset.fY);
+
// The source rect has changed so update the matrix
- newM.preTranslate(offset.fX, offset.fY);
+ localM.preTranslate(offset.fX, offset.fY);
}
+ } else {
+ localM.reset();
}
- SkPaint paintWithTexture(paint);
- paintWithTexture.setShader(SkShader::CreateBitmapShader(*bitmapPtr,
- SkShader::kClamp_TileMode, SkShader::kClamp_TileMode))->unref();
-
- // Transform 'newM' needs to be concatenated to the current matrix,
- // rather than transforming the primitive directly, so that 'newM' will
- // also affect the behavior of the mask filter.
- SkMatrix drawMatrix;
- drawMatrix.setConcat(fContext->getMatrix(), newM);
- SkDraw transformedDraw(draw);
- transformedDraw.fMatrix = &drawMatrix;
-
- this->drawRect(transformedDraw, srcRect, paintWithTexture);
+ SkPaint paintWithShader(paint);
+ paintWithShader.setShader(SkShader::CreateBitmapShader(*bitmapPtr,
+ SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &localM))->unref();
+ SkRect dstRect = {0, 0, dstSize.fWidth, dstSize.fHeight};
+ this->drawRect(draw, dstRect, paintWithShader);
return;
}
+ // If there is no mask filter than it is OK to handle the src rect -> dst rect scaling using
+ // the view matrix rather than a local matrix.
+ SkMatrix m;
+ m.setScale(dstSize.fWidth / srcRect.width(),
+ dstSize.fHeight / srcRect.height());
fContext->concatMatrix(m);
GrTextureParams params;
SkPaint::FilterLevel paintFilterLevel = paint.getFilterLevel();
GrTextureParams::FilterMode textureFilterMode;
- int tileFilterPad;
bool doBicubic = false;
switch(paintFilterLevel) {
case SkPaint::kNone_FilterLevel:
- tileFilterPad = 0;
textureFilterMode = GrTextureParams::kNone_FilterMode;
break;
case SkPaint::kLow_FilterLevel:
- tileFilterPad = 1;
textureFilterMode = GrTextureParams::kBilerp_FilterMode;
break;
case SkPaint::kMedium_FilterLevel:
- tileFilterPad = 1;
- textureFilterMode = GrTextureParams::kMipMap_FilterMode;
- break;
- case SkPaint::kHigh_FilterLevel: {
- // Minification can look bad with the bicubic effect.
- if (fContext->getMatrix().getMinStretch() >= SK_Scalar1 &&
- (flags & SkCanvas::kBleed_DrawBitmapRectFlag)) {
- // We will install an effect that does the filtering in the shader.
- textureFilterMode = GrTextureParams::kNone_FilterMode;
- tileFilterPad = GrBicubicEffect::kFilterTexelPad;
- doBicubic = true;
- } else {
- // We don't yet support doing bicubic filtering with an interior clamp. Fall back
- // to MIPs
+ if (fContext->getMatrix().getMinScale() < SK_Scalar1) {
textureFilterMode = GrTextureParams::kMipMap_FilterMode;
- tileFilterPad = 1;
+ } else {
+ // Don't trigger MIP level generation unnecessarily.
+ textureFilterMode = GrTextureParams::kBilerp_FilterMode;
}
break;
- }
+ case SkPaint::kHigh_FilterLevel:
+ // Minification can look bad with the bicubic effect.
+ doBicubic =
+ GrBicubicEffect::ShouldUseBicubic(fContext->getMatrix(), &textureFilterMode);
+ break;
default:
SkErrorInternals::SetError( kInvalidPaint_SkError,
"Sorry, I don't understand the filtering "
"mode you asked for. Falling back to "
"MIPMaps.");
- tileFilterPad = 1;
textureFilterMode = GrTextureParams::kMipMap_FilterMode;
break;
}
+ int tileFilterPad;
+ if (doBicubic) {
+ tileFilterPad = GrBicubicEffect::kFilterTexelPad;
+ } else if (GrTextureParams::kNone_FilterMode == textureFilterMode) {
+ tileFilterPad = 0;
+ } else {
+ tileFilterPad = 1;
+ }
params.setFilterMode(textureFilterMode);
int maxTileSize = fContext->getMaxTextureSize() - 2 * tileFilterPad;
@@ -1244,7 +1205,18 @@ void SkGpuDevice::drawBitmapCommon(const SkDraw& draw,
doBicubic);
} else {
// take the simple case
- this->internalDrawBitmap(bitmap, srcRect, params, paint, flags, doBicubic);
+ bool needsTextureDomain = needs_texture_domain(bitmap,
+ srcRect,
+ params,
+ fContext->getMatrix(),
+ doBicubic);
+ this->internalDrawBitmap(bitmap,
+ srcRect,
+ params,
+ paint,
+ flags,
+ doBicubic,
+ needsTextureDomain);
}
}
@@ -1258,6 +1230,11 @@ void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap,
SkCanvas::DrawBitmapRectFlags flags,
int tileSize,
bool bicubic) {
+ // The following pixel lock is technically redundant, but it is desirable
+ // to lock outside of the tile loop to prevent redecoding the whole image
+ // at each tile in cases where 'bitmap' holds an SkDiscardablePixelRef that
+ // is larger than the limit of the discardable memory pool.
+ SkAutoLockPixels alp(bitmap);
SkRect clippedSrcRect = SkRect::Make(clippedSrcIRect);
int nx = bitmap.width() / tileSize;
@@ -1284,6 +1261,12 @@ void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap,
SkPoint offset = SkPoint::Make(SkIntToScalar(iTileR.fLeft),
SkIntToScalar(iTileR.fTop));
+ // Adjust the context matrix to draw at the right x,y in device space
+ SkMatrix tmpM;
+ GrContext::AutoMatrix am;
+ tmpM.setTranslate(offset.fX - srcRect.fLeft, offset.fY - srcRect.fTop);
+ am.setPreConcat(fContext, tmpM);
+
if (SkPaint::kNone_FilterLevel != paint.getFilterLevel() || bicubic) {
SkIRect iClampRect;
@@ -1292,8 +1275,6 @@ void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap,
// but stay within the bitmap bounds
iClampRect = SkIRect::MakeWH(bitmap.width(), bitmap.height());
} else {
- SkASSERT(!bicubic); // Bicubic is not supported with non-bleed yet.
-
// In texture-domain/clamp mode we only want to expand the
// tile on edges interior to "srcRect" (i.e., we want to
// not bleed across the original clamped edges)
@@ -1306,57 +1287,24 @@ void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap,
if (bitmap.extractSubset(&tmpB, iTileR)) {
// now offset it to make it "local" to our tmp bitmap
tileR.offset(-offset.fX, -offset.fY);
- SkMatrix tmpM;
- tmpM.setTranslate(offset.fX, offset.fY);
- GrContext::AutoMatrix am;
- am.setPreConcat(fContext, tmpM);
- this->internalDrawBitmap(tmpB, tileR, params, paint, flags, bicubic);
+ GrTextureParams paramsTemp = params;
+ bool needsTextureDomain = needs_texture_domain(bitmap,
+ srcRect,
+ paramsTemp,
+ fContext->getMatrix(),
+ bicubic);
+ this->internalDrawBitmap(tmpB,
+ tileR,
+ paramsTemp,
+ paint,
+ flags,
+ bicubic,
+ needsTextureDomain);
}
}
}
}
-static bool has_aligned_samples(const SkRect& srcRect,
- const SkRect& transformedRect) {
- // detect pixel disalignment
- if (SkScalarAbs(SkScalarRoundToScalar(transformedRect.left()) -
- transformedRect.left()) < COLOR_BLEED_TOLERANCE &&
- SkScalarAbs(SkScalarRoundToScalar(transformedRect.top()) -
- transformedRect.top()) < COLOR_BLEED_TOLERANCE &&
- SkScalarAbs(transformedRect.width() - srcRect.width()) <
- COLOR_BLEED_TOLERANCE &&
- SkScalarAbs(transformedRect.height() - srcRect.height()) <
- COLOR_BLEED_TOLERANCE) {
- return true;
- }
- return false;
-}
-
-static bool may_color_bleed(const SkRect& srcRect,
- const SkRect& transformedRect,
- const SkMatrix& m) {
- // Only gets called if has_aligned_samples returned false.
- // So we can assume that sampling is axis aligned but not texel aligned.
- SkASSERT(!has_aligned_samples(srcRect, transformedRect));
- SkRect innerSrcRect(srcRect), innerTransformedRect,
- outerTransformedRect(transformedRect);
- innerSrcRect.inset(SK_ScalarHalf, SK_ScalarHalf);
- m.mapRect(&innerTransformedRect, innerSrcRect);
-
- // The gap between outerTransformedRect and innerTransformedRect
- // represents the projection of the source border area, which is
- // problematic for color bleeding. We must check whether any
- // destination pixels sample the border area.
- outerTransformedRect.inset(COLOR_BLEED_TOLERANCE, COLOR_BLEED_TOLERANCE);
- innerTransformedRect.outset(COLOR_BLEED_TOLERANCE, COLOR_BLEED_TOLERANCE);
- SkIRect outer, inner;
- outerTransformedRect.round(&outer);
- innerTransformedRect.round(&inner);
- // If the inner and outer rects round to the same result, it means the
- // border does not overlap any pixel centers. Yay!
- return inner != outer;
-}
-
/*
* This is called by drawBitmap(), which has to handle images that may be too
@@ -1370,7 +1318,8 @@ void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap,
const GrTextureParams& params,
const SkPaint& paint,
SkCanvas::DrawBitmapRectFlags flags,
- bool bicubic) {
+ bool bicubic,
+ bool needsTextureDomain) {
SkASSERT(bitmap.width() <= fContext->getMaxTextureSize() &&
bitmap.height() <= fContext->getMaxTextureSize());
@@ -1380,7 +1329,7 @@ void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap,
return;
}
- SkRect dstRect(srcRect);
+ SkRect dstRect = {0, 0, srcRect.width(), srcRect.height() };
SkRect paintRect;
SkScalar wInv = SkScalarInvert(SkIntToScalar(texture->width()));
SkScalar hInv = SkScalarInvert(SkIntToScalar(texture->height()));
@@ -1389,32 +1338,9 @@ void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap,
SkScalarMul(srcRect.fRight, wInv),
SkScalarMul(srcRect.fBottom, hInv));
- bool needsTextureDomain = false;
- if (!(flags & SkCanvas::kBleed_DrawBitmapRectFlag) &&
- params.filterMode() != GrTextureParams::kNone_FilterMode) {
- SkASSERT(!bicubic);
- // Need texture domain if drawing a sub rect.
- needsTextureDomain = srcRect.width() < bitmap.width() ||
- srcRect.height() < bitmap.height();
- if (needsTextureDomain && fContext->getMatrix().rectStaysRect()) {
- const SkMatrix& matrix = fContext->getMatrix();
- // sampling is axis-aligned
- SkRect transformedRect;
- matrix.mapRect(&transformedRect, srcRect);
-
- if (has_aligned_samples(srcRect, transformedRect)) {
- // We could also turn off filtering here (but we already did a cache lookup with
- // params).
- needsTextureDomain = false;
- } else {
- needsTextureDomain = may_color_bleed(srcRect, transformedRect, matrix);
- }
- }
- }
-
SkRect textureDomain = SkRect::MakeEmpty();
SkAutoTUnref<GrEffectRef> effect;
- if (needsTextureDomain) {
+ if (needsTextureDomain && !(flags & SkCanvas::kBleed_DrawBitmapRectFlag)) {
// Use a constrained texture domain to avoid color bleeding
SkScalar left, top, right, bottom;
if (srcRect.width() > SK_Scalar1) {
@@ -1432,11 +1358,15 @@ void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap,
top = bottom = SkScalarHalf(paintRect.top() + paintRect.bottom());
}
textureDomain.setLTRB(left, top, right, bottom);
- effect.reset(GrTextureDomainEffect::Create(texture,
- SkMatrix::I(),
- textureDomain,
- GrTextureDomain::kClamp_Mode,
- params.filterMode()));
+ if (bicubic) {
+ effect.reset(GrBicubicEffect::Create(texture, SkMatrix::I(), textureDomain));
+ } else {
+ effect.reset(GrTextureDomainEffect::Create(texture,
+ SkMatrix::I(),
+ textureDomain,
+ GrTextureDomain::kClamp_Mode,
+ params.filterMode()));
+ }
} else if (bicubic) {
SkASSERT(GrTextureParams::kNone_FilterMode == params.filterMode());
SkShader::TileMode tileModes[2] = { params.getTileModeX(), params.getTileModeY() };
@@ -1449,18 +1379,18 @@ void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap,
// the rest from the SkPaint.
GrPaint grPaint;
grPaint.addColorEffect(effect);
- bool alphaOnly = !(SkBitmap::kA8_Config == bitmap.config());
- if (!skPaint2GrPaintNoShader(this, paint, alphaOnly, false, &grPaint)) {
- return;
- }
+ bool alphaOnly = !(kAlpha_8_SkColorType == bitmap.colorType());
+ GrColor grColor = (alphaOnly) ? SkColor2GrColorJustAlpha(paint.getColor()) :
+ SkColor2GrColor(paint.getColor());
+ SkPaint2GrPaintNoShader(this->context(), paint, grColor, false, &grPaint);
fContext->drawRectToRect(grPaint, dstRect, paintRect, NULL);
}
static bool filter_texture(SkBaseDevice* device, GrContext* context,
- GrTexture* texture, SkImageFilter* filter,
- int w, int h, const SkMatrix& ctm, SkBitmap* result,
- SkIPoint* offset) {
+ GrTexture* texture, const SkImageFilter* filter,
+ int w, int h, const SkImageFilter::Context& ctx,
+ SkBitmap* result, SkIPoint* offset) {
SkASSERT(filter);
SkDeviceImageFilterProxy proxy(device);
@@ -1468,7 +1398,7 @@ static bool filter_texture(SkBaseDevice* device, GrContext* context,
// Save the render target and set it to NULL, so we don't accidentally draw to it in the
// filter. Also set the clip wide open and the matrix to identity.
GrContext::AutoWideOpenIdentityDraw awo(context, NULL);
- return filter->filterImageGPU(&proxy, wrap_texture(texture), ctm, result, offset);
+ return filter->filterImageGPU(&proxy, wrap_texture(texture), ctx, result, offset);
} else {
return false;
}
@@ -1492,18 +1422,24 @@ void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
SkAutoCachedTexture act(this, bitmap, NULL, &texture);
SkImageFilter* filter = paint.getImageFilter();
- SkIPoint offset = SkIPoint::Make(left, top);
// This bitmap will own the filtered result as a texture.
SkBitmap filteredBitmap;
if (NULL != filter) {
+ SkIPoint offset = SkIPoint::Make(0, 0);
SkMatrix matrix(*draw.fMatrix);
matrix.postTranslate(SkIntToScalar(-left), SkIntToScalar(-top));
- if (filter_texture(this, fContext, texture, filter, w, h, matrix, &filteredBitmap,
+ SkIRect clipBounds = SkIRect::MakeWH(bitmap.width(), bitmap.height());
+ SkImageFilter::Cache* cache = SkImageFilter::Cache::Create();
+ SkAutoUnref aur(cache);
+ SkImageFilter::Context ctx(matrix, clipBounds, cache);
+ if (filter_texture(this, fContext, texture, filter, w, h, ctx, &filteredBitmap,
&offset)) {
texture = (GrTexture*) filteredBitmap.getTexture();
w = filteredBitmap.width();
h = filteredBitmap.height();
+ left += offset.x();
+ top += offset.y();
} else {
return;
}
@@ -1512,13 +1448,12 @@ void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
GrPaint grPaint;
grPaint.addColorTextureEffect(texture, SkMatrix::I());
- if(!skPaint2GrPaintNoShader(this, paint, true, false, &grPaint)) {
- return;
- }
+ SkPaint2GrPaintNoShader(this->context(), paint, SkColor2GrColorJustAlpha(paint.getColor()),
+ false, &grPaint);
fContext->drawRectToRect(grPaint,
- SkRect::MakeXYWH(SkIntToScalar(offset.fX),
- SkIntToScalar(offset.fY),
+ SkRect::MakeXYWH(SkIntToScalar(left),
+ SkIntToScalar(top),
SkIntToScalar(w),
SkIntToScalar(h)),
SkRect::MakeXYWH(0,
@@ -1527,7 +1462,7 @@ void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
SK_Scalar1 * h / texture->height()));
}
-void SkGpuDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
+void SkGpuDevice::drawBitmapRect(const SkDraw& origDraw, const SkBitmap& bitmap,
const SkRect* src, const SkRect& dst,
const SkPaint& paint,
SkCanvas::DrawBitmapRectFlags flags) {
@@ -1544,6 +1479,7 @@ void SkGpuDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
} else {
tmpSrc = bitmapBounds;
}
+
matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
// clip the tmpSrc to the bounds of the bitmap. No check needed if src==null.
@@ -1555,7 +1491,21 @@ void SkGpuDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
}
}
- this->drawBitmapCommon(draw, bitmap, &tmpSrc, matrix, paint, flags);
+ SkRect tmpDst;
+ matrix.mapRect(&tmpDst, tmpSrc);
+
+ SkTCopyOnFirstWrite<SkDraw> draw(origDraw);
+ if (0 != tmpDst.fLeft || 0 != tmpDst.fTop) {
+ // Translate so that tempDst's top left is at the origin.
+ matrix = *origDraw.fMatrix;
+ matrix.preTranslate(tmpDst.fLeft, tmpDst.fTop);
+ draw.writable()->fMatrix = &matrix;
+ }
+ SkSize dstSize;
+ dstSize.fWidth = tmpDst.width();
+ dstSize.fHeight = tmpDst.height();
+
+ this->drawBitmapCommon(*draw, bitmap, &tmpSrc, &dstSize, paint, flags);
}
void SkGpuDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device,
@@ -1588,7 +1538,11 @@ void SkGpuDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device,
SkIPoint offset = SkIPoint::Make(0, 0);
SkMatrix matrix(*draw.fMatrix);
matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y));
- if (filter_texture(this, fContext, devTex, filter, w, h, matrix, &filteredBitmap,
+ SkIRect clipBounds = SkIRect::MakeWH(devTex->width(), devTex->height());
+ SkImageFilter::Cache* cache = SkImageFilter::Cache::Create();
+ SkAutoUnref aur(cache);
+ SkImageFilter::Context ctx(matrix, clipBounds, cache);
+ if (filter_texture(this, fContext, devTex, filter, w, h, ctx, &filteredBitmap,
&offset)) {
devTex = filteredBitmap.getTexture();
w = filteredBitmap.width();
@@ -1603,9 +1557,8 @@ void SkGpuDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device,
GrPaint grPaint;
grPaint.addColorTextureEffect(devTex, SkMatrix::I());
- if (!skPaint2GrPaintNoShader(this, paint, true, false, &grPaint)) {
- return;
- }
+ SkPaint2GrPaintNoShader(this->context(), paint, SkColor2GrColorJustAlpha(paint.getColor()),
+ false, &grPaint);
SkRect dstRect = SkRect::MakeXYWH(SkIntToScalar(x),
SkIntToScalar(y),
@@ -1620,12 +1573,12 @@ void SkGpuDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device,
fContext->drawRectToRect(grPaint, dstRect, srcRect);
}
-bool SkGpuDevice::canHandleImageFilter(SkImageFilter* filter) {
+bool SkGpuDevice::canHandleImageFilter(const SkImageFilter* filter) {
return filter->canFilterImageGPU();
}
-bool SkGpuDevice::filterImage(SkImageFilter* filter, const SkBitmap& src,
- const SkMatrix& ctm,
+bool SkGpuDevice::filterImage(const SkImageFilter* filter, const SkBitmap& src,
+ const SkImageFilter::Context& ctx,
SkBitmap* result, SkIPoint* offset) {
// want explicitly our impl, so guard against a subclass of us overriding it
if (!this->SkGpuDevice::canHandleImageFilter(filter)) {
@@ -1642,8 +1595,8 @@ bool SkGpuDevice::filterImage(SkImageFilter* filter, const SkBitmap& src,
// must be pushed upstack.
SkAutoCachedTexture act(this, src, NULL, &texture);
- return filter_texture(this, fContext, texture, filter, src.width(), src.height(), ctm, result,
- offset);
+ return filter_texture(this, fContext, texture, filter, src.width(), src.height(), ctx,
+ result, offset);
}
///////////////////////////////////////////////////////////////////////////////
@@ -1663,41 +1616,68 @@ void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
const SkPaint& paint) {
CHECK_SHOULD_DRAW(draw, false);
+ // If both textures and vertex-colors are NULL, strokes hairlines with the paint's color.
+ if ((NULL == texs || NULL == paint.getShader()) && NULL == colors) {
+ texs = NULL;
+ SkPaint copy(paint);
+ copy.setStyle(SkPaint::kStroke_Style);
+ copy.setStrokeWidth(0);
+
+ VertState state(vertexCount, indices, indexCount);
+ VertState::Proc vertProc = state.chooseProc(vmode);
+
+ SkPoint* pts = new SkPoint[vertexCount * 6];
+ int i = 0;
+ while (vertProc(&state)) {
+ pts[i] = vertices[state.f0];
+ pts[i + 1] = vertices[state.f1];
+ pts[i + 2] = vertices[state.f1];
+ pts[i + 3] = vertices[state.f2];
+ pts[i + 4] = vertices[state.f2];
+ pts[i + 5] = vertices[state.f0];
+ i += 6;
+ }
+ draw.drawPoints(SkCanvas::kLines_PointMode, i, pts, copy, true);
+ return;
+ }
+
GrPaint grPaint;
// we ignore the shader if texs is null.
if (NULL == texs) {
- if (!skPaint2GrPaintNoShader(this, paint, false, NULL == colors, &grPaint)) {
- return;
- }
+ SkPaint2GrPaintNoShader(this->context(), paint, SkColor2GrColor(paint.getColor()),
+ NULL == colors, &grPaint);
} else {
- if (!skPaint2GrPaintShader(this, paint, NULL == colors, &grPaint)) {
- return;
- }
+ SkPaint2GrPaintShader(this->context(), paint, NULL == colors, &grPaint);
}
+#if 0
if (NULL != xmode && NULL != texs && NULL != colors) {
if (!SkXfermode::IsMode(xmode, SkXfermode::kModulate_Mode)) {
SkDebugf("Unsupported vertex-color/texture xfer mode.\n");
-#if 0
- return
-#endif
+ return;
}
}
+#endif
SkAutoSTMalloc<128, GrColor> convertedColors(0);
if (NULL != colors) {
// need to convert byte order and from non-PM to PM
convertedColors.reset(vertexCount);
+ SkColor color;
for (int i = 0; i < vertexCount; ++i) {
- convertedColors[i] = SkColor2GrColor(colors[i]);
+ color = colors[i];
+ if (paint.getAlpha() != 255) {
+ color = SkColorSetA(color, SkMulDiv255Round(SkColorGetA(color), paint.getAlpha()));
+ }
+ convertedColors[i] = SkColor2GrColor(color);
}
colors = convertedColors.get();
}
fContext->drawVertices(grPaint,
gVertexMode2PrimitiveType[vmode],
vertexCount,
- (GrPoint*) vertices,
- (GrPoint*) texs,
+ vertices,
+ texs,
colors,
indices,
indexCount);
@@ -1705,93 +1685,28 @@ void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
///////////////////////////////////////////////////////////////////////////////
-static void GlyphCacheAuxProc(void* data) {
- GrFontScaler* scaler = (GrFontScaler*)data;
- SkSafeUnref(scaler);
-}
-
-static GrFontScaler* get_gr_font_scaler(SkGlyphCache* cache) {
- void* auxData;
- GrFontScaler* scaler = NULL;
- if (cache->getAuxProcData(GlyphCacheAuxProc, &auxData)) {
- scaler = (GrFontScaler*)auxData;
- }
- if (NULL == scaler) {
- scaler = SkNEW_ARGS(SkGrFontScaler, (cache));
- cache->setAuxProc(GlyphCacheAuxProc, scaler);
- }
- return scaler;
-}
-
-static void SkGPU_Draw1Glyph(const SkDraw1Glyph& state,
- SkFixed fx, SkFixed fy,
- const SkGlyph& glyph) {
- SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
-
- GrSkDrawProcs* procs = static_cast<GrSkDrawProcs*>(state.fDraw->fProcs);
-
- if (NULL == procs->fFontScaler) {
- procs->fFontScaler = get_gr_font_scaler(state.fCache);
- }
-
- procs->fTextContext->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
- glyph.getSubXFixed(),
- glyph.getSubYFixed()),
- SkFixedFloorToFixed(fx),
- SkFixedFloorToFixed(fy),
- procs->fFontScaler);
-}
-
-SkDrawProcs* SkGpuDevice::initDrawForText(GrTextContext* context) {
-
- // deferred allocation
- if (NULL == fDrawProcs) {
- fDrawProcs = SkNEW(GrSkDrawProcs);
- fDrawProcs->fD1GProc = SkGPU_Draw1Glyph;
- fDrawProcs->fContext = fContext;
-#if SK_DISTANCEFIELD_FONTS
- fDrawProcs->fFlags = 0;
-#endif
- }
-
- // init our (and GL's) state
- fDrawProcs->fTextContext = context;
- fDrawProcs->fFontScaler = NULL;
- return fDrawProcs;
-}
-
void SkGpuDevice::drawText(const SkDraw& draw, const void* text,
size_t byteLength, SkScalar x, SkScalar y,
const SkPaint& paint) {
CHECK_SHOULD_DRAW(draw, false);
- if (fContext->getMatrix().hasPerspective()) {
- // this guy will just call our drawPath()
- draw.drawText((const char*)text, byteLength, x, y, paint);
- } else {
- SkDraw myDraw(draw);
+ if (fMainTextContext->canDraw(paint)) {
+ GrPaint grPaint;
+ SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
+ SkDEBUGCODE(this->validate();)
+
+ fMainTextContext->drawText(grPaint, paint, (const char *)text, byteLength, x, y);
+ } else if (fFallbackTextContext && fFallbackTextContext->canDraw(paint)) {
GrPaint grPaint;
- if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
- return;
- }
-#if SK_DISTANCEFIELD_FONTS
- if (paint.getRasterizer()) {
-#endif
- GrBitmapTextContext context(fContext, grPaint, paint.getColor());
- myDraw.fProcs = this->initDrawForText(&context);
- this->INHERITED::drawText(myDraw, text, byteLength, x, y, paint);
-#if SK_DISTANCEFIELD_FONTS
- } else {
- GrDistanceFieldTextContext context(fContext, grPaint, paint.getColor(),
- paint.getTextSize()/SkDrawProcs::kBaseDFFontSize);
- myDraw.fProcs = this->initDrawForText(&context);
- fDrawProcs->fFlags |= SkDrawProcs::kSkipBakedGlyphTransform_Flag;
- fDrawProcs->fFlags |= SkDrawProcs::kUseScaledGlyphs_Flag;
- this->INHERITED::drawText(myDraw, text, byteLength, x, y, paint);
- fDrawProcs->fFlags = 0;
- }
-#endif
+ SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
+
+ SkDEBUGCODE(this->validate();)
+
+ fFallbackTextContext->drawText(grPaint, paint, (const char *)text, byteLength, x, y);
+ } else {
+ // this guy will just call our drawPath()
+ draw.drawText_asPaths((const char*)text, byteLength, x, y, paint);
}
}
@@ -1799,38 +1714,28 @@ void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text,
size_t byteLength, const SkScalar pos[],
SkScalar constY, int scalarsPerPos,
const SkPaint& paint) {
+ GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawPosText", fContext);
CHECK_SHOULD_DRAW(draw, false);
- if (fContext->getMatrix().hasPerspective()) {
- // this guy will just call our drawPath()
- draw.drawPosText((const char*)text, byteLength, pos, constY,
- scalarsPerPos, paint);
- } else {
- SkDraw myDraw(draw);
+ if (fMainTextContext->canDraw(paint)) {
+ GrPaint grPaint;
+ SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
+
+ SkDEBUGCODE(this->validate();)
+ fMainTextContext->drawPosText(grPaint, paint, (const char *)text, byteLength, pos,
+ constY, scalarsPerPos);
+ } else if (fFallbackTextContext && fFallbackTextContext->canDraw(paint)) {
GrPaint grPaint;
- if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
- return;
- }
-#if SK_DISTANCEFIELD_FONTS
- if (paint.getRasterizer()) {
-#endif
- GrBitmapTextContext context(fContext, grPaint, paint.getColor());
- myDraw.fProcs = this->initDrawForText(&context);
- this->INHERITED::drawPosText(myDraw, text, byteLength, pos, constY,
- scalarsPerPos, paint);
-#if SK_DISTANCEFIELD_FONTS
- } else {
- GrDistanceFieldTextContext context(fContext, grPaint, paint.getColor(),
- paint.getTextSize()/SkDrawProcs::kBaseDFFontSize);
- myDraw.fProcs = this->initDrawForText(&context);
- fDrawProcs->fFlags |= SkDrawProcs::kSkipBakedGlyphTransform_Flag;
- fDrawProcs->fFlags |= SkDrawProcs::kUseScaledGlyphs_Flag;
- this->INHERITED::drawPosText(myDraw, text, byteLength, pos, constY,
- scalarsPerPos, paint);
- fDrawProcs->fFlags = 0;
- }
-#endif
+ SkPaint2GrPaintShader(this->context(), paint, true, &grPaint);
+
+ SkDEBUGCODE(this->validate();)
+
+ fFallbackTextContext->drawPosText(grPaint, paint, (const char *)text, byteLength, pos,
+ constY, scalarsPerPos);
+ } else {
+ draw.drawPosText_asPaths((const char*)text, byteLength, pos, constY,
+ scalarsPerPos, paint);
}
}
@@ -1875,24 +1780,22 @@ void SkGpuDevice::flush() {
///////////////////////////////////////////////////////////////////////////////
-SkBaseDevice* SkGpuDevice::onCreateCompatibleDevice(SkBitmap::Config config,
- int width, int height,
- bool isOpaque,
- Usage usage) {
+SkBaseDevice* SkGpuDevice::onCreateDevice(const SkImageInfo& info, Usage usage) {
GrTextureDesc desc;
desc.fConfig = fRenderTarget->config();
desc.fFlags = kRenderTarget_GrTextureFlagBit;
- desc.fWidth = width;
- desc.fHeight = height;
+ desc.fWidth = info.width();
+ desc.fHeight = info.height();
desc.fSampleCnt = fRenderTarget->numSamples();
SkAutoTUnref<GrTexture> texture;
// Skia's convention is to only clear a device if it is non-opaque.
- bool needClear = !isOpaque;
+ unsigned flags = info.isOpaque() ? 0 : kNeedClear_Flag;
#if CACHE_COMPATIBLE_DEVICE_TEXTURES
// layers are never draw in repeat modes, so we can request an approx
// match and ignore any padding.
+ flags |= kCached_Flag;
const GrContext::ScratchTexMatch match = (kSaveLayer_Usage == usage) ?
GrContext::kApprox_ScratchTexMatch :
GrContext::kExact_ScratchTexMatch;
@@ -1901,21 +1804,212 @@ SkBaseDevice* SkGpuDevice::onCreateCompatibleDevice(SkBitmap::Config config,
texture.reset(fContext->createUncachedTexture(desc, NULL, 0));
#endif
if (NULL != texture.get()) {
- return SkNEW_ARGS(SkGpuDevice,(fContext, texture, needClear));
+ return SkGpuDevice::Create(texture, flags);
} else {
- GrPrintf("---- failed to create compatible device texture [%d %d]\n", width, height);
+ GrPrintf("---- failed to create compatible device texture [%d %d]\n",
+ info.width(), info.height());
return NULL;
}
}
-SkGpuDevice::SkGpuDevice(GrContext* context,
- GrTexture* texture,
- bool needClear)
- : SkBitmapDevice(make_bitmap(context, texture->asRenderTarget())) {
+SkSurface* SkGpuDevice::newSurface(const SkImageInfo& info) {
+ return SkSurface::NewRenderTarget(fContext, info, fRenderTarget->numSamples());
+}
+
+void SkGpuDevice::EXPERIMENTAL_optimize(const SkPicture* picture) {
+ SkPicture::AccelData::Key key = GPUAccelData::ComputeAccelDataKey();
+
+ const SkPicture::AccelData* existing = picture->EXPERIMENTAL_getAccelData(key);
+ if (NULL != existing) {
+ return;
+ }
+
+ SkAutoTUnref<GPUAccelData> data(SkNEW_ARGS(GPUAccelData, (key)));
+
+ picture->EXPERIMENTAL_addAccelData(data);
+
+ GatherGPUInfo(picture, data);
+}
+
+static void wrap_texture(GrTexture* texture, int width, int height, SkBitmap* result) {
+ SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
+ result->setInfo(info);
+ result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref();
+}
- SkASSERT(texture && texture->asRenderTarget());
- // This constructor is called from onCreateCompatibleDevice. It has locked the RT in the texture
- // cache. We pass true for the third argument so that it will get unlocked.
- this->initFromRenderTarget(context, texture->asRenderTarget(), true);
- fNeedClear = needClear;
+void SkGpuDevice::EXPERIMENTAL_purge(const SkPicture* picture) {
+
+}
+
+bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* canvas, const SkPicture* picture) {
+
+ SkPicture::AccelData::Key key = GPUAccelData::ComputeAccelDataKey();
+
+ const SkPicture::AccelData* data = picture->EXPERIMENTAL_getAccelData(key);
+ if (NULL == data) {
+ return false;
+ }
+
+ const GPUAccelData *gpuData = static_cast<const GPUAccelData*>(data);
+
+ if (0 == gpuData->numSaveLayers()) {
+ return false;
+ }
+
+ SkAutoTArray<bool> pullForward(gpuData->numSaveLayers());
+ for (int i = 0; i < gpuData->numSaveLayers(); ++i) {
+ pullForward[i] = false;
+ }
+
+ SkRect clipBounds;
+ if (!canvas->getClipBounds(&clipBounds)) {
+ return true;
+ }
+ SkIRect query;
+ clipBounds.roundOut(&query);
+
+ const SkPicture::OperationList& ops = picture->EXPERIMENTAL_getActiveOps(query);
+
+ // This code pre-renders the entire layer since it will be cached and potentially
+ // reused with different clips (e.g., in different tiles). Because of this the
+ // clip will not be limiting the size of the pre-rendered layer. kSaveLayerMaxSize
+ // is used to limit which clips are pre-rendered.
+ static const int kSaveLayerMaxSize = 256;
+
+ if (ops.valid()) {
+ // In this case the picture has been generated with a BBH so we use
+ // the BBH to limit the pre-rendering to just the layers needed to cover
+ // the region being drawn
+ for (int i = 0; i < ops.numOps(); ++i) {
+ uint32_t offset = ops.offset(i);
+
+ // For now we're saving all the layers in the GPUAccelData so they
+ // can be nested. Additionally, the nested layers appear before
+ // their parent in the list.
+ for (int j = 0 ; j < gpuData->numSaveLayers(); ++j) {
+ const GPUAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(j);
+
+ if (pullForward[j]) {
+ continue; // already pulling forward
+ }
+
+ if (offset < info.fSaveLayerOpID || offset > info.fRestoreOpID) {
+ continue; // the op isn't in this range
+ }
+
+ // TODO: once this code is more stable unsuitable layers can
+ // just be omitted during the optimization stage
+ if (!info.fValid ||
+ kSaveLayerMaxSize < info.fSize.fWidth ||
+ kSaveLayerMaxSize < info.fSize.fHeight ||
+ info.fIsNested) {
+ continue; // this layer is unsuitable
+ }
+
+ pullForward[j] = true;
+ }
+ }
+ } else {
+ // In this case there is no BBH associated with the picture. Pre-render
+ // all the layers that intersect the drawn region
+ for (int j = 0; j < gpuData->numSaveLayers(); ++j) {
+ const GPUAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(j);
+
+ SkIRect layerRect = SkIRect::MakeXYWH(info.fOffset.fX,
+ info.fOffset.fY,
+ info.fSize.fWidth,
+ info.fSize.fHeight);
+
+ if (!SkIRect::Intersects(query, layerRect)) {
+ continue;
+ }
+
+ // TODO: once this code is more stable unsuitable layers can
+ // just be omitted during the optimization stage
+ if (!info.fValid ||
+ kSaveLayerMaxSize < info.fSize.fWidth ||
+ kSaveLayerMaxSize < info.fSize.fHeight ||
+ info.fIsNested) {
+ continue;
+ }
+
+ pullForward[j] = true;
+ }
+ }
+
+ SkPicturePlayback::PlaybackReplacements replacements;
+
+ for (int i = 0; i < gpuData->numSaveLayers(); ++i) {
+ if (pullForward[i]) {
+ GrCachedLayer* layer = fContext->getLayerCache()->findLayerOrCreate(picture, i);
+
+ const GPUAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(i);
+
+ if (NULL != picture->fPlayback) {
+ SkPicturePlayback::PlaybackReplacements::ReplacementInfo* layerInfo =
+ replacements.push();
+ layerInfo->fStart = info.fSaveLayerOpID;
+ layerInfo->fStop = info.fRestoreOpID;
+ layerInfo->fPos = info.fOffset;
+
+ GrTextureDesc desc;
+ desc.fFlags = kRenderTarget_GrTextureFlagBit;
+ desc.fWidth = info.fSize.fWidth;
+ desc.fHeight = info.fSize.fHeight;
+ desc.fConfig = kSkia8888_GrPixelConfig;
+ // TODO: need to deal with sample count
+
+ bool bNeedsRendering = true;
+
+ // This just uses scratch textures and doesn't cache the texture.
+ // This can yield a lot of re-rendering
+ if (NULL == layer->getTexture()) {
+ layer->setTexture(fContext->lockAndRefScratchTexture(desc,
+ GrContext::kApprox_ScratchTexMatch));
+ if (NULL == layer->getTexture()) {
+ continue;
+ }
+ } else {
+ bNeedsRendering = false;
+ }
+
+ layerInfo->fBM = SkNEW(SkBitmap);
+ wrap_texture(layer->getTexture(), desc.fWidth, desc.fHeight, layerInfo->fBM);
+
+ SkASSERT(info.fPaint);
+ layerInfo->fPaint = info.fPaint;
+
+ if (bNeedsRendering) {
+ SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(
+ layer->getTexture()->asRenderTarget()));
+
+ SkCanvas* canvas = surface->getCanvas();
+
+ canvas->setMatrix(info.fCTM);
+ canvas->clear(SK_ColorTRANSPARENT);
+
+ picture->fPlayback->setDrawLimits(info.fSaveLayerOpID, info.fRestoreOpID);
+ picture->fPlayback->draw(*canvas, NULL);
+ picture->fPlayback->setDrawLimits(0, 0);
+ canvas->flush();
+ }
+ }
+ }
+ }
+
+ // Playback using new layers
+ picture->fPlayback->setReplacements(&replacements);
+ picture->fPlayback->draw(*canvas, NULL);
+ picture->fPlayback->setReplacements(NULL);
+
+ for (int i = 0; i < gpuData->numSaveLayers(); ++i) {
+ GrCachedLayer* layer = fContext->getLayerCache()->findLayerOrCreate(picture, i);
+
+ if (NULL != layer->getTexture()) {
+ fContext->unlockScratchTexture(layer->getTexture());
+ layer->setTexture(NULL);
+ }
+ }
+
+ return true;
}
diff --git a/chromium/third_party/skia/src/gpu/SkGr.cpp b/chromium/third_party/skia/src/gpu/SkGr.cpp
index a3f0eefa91f..a1b379fe8c8 100644
--- a/chromium/third_party/skia/src/gpu/SkGr.cpp
+++ b/chromium/third_party/skia/src/gpu/SkGr.cpp
@@ -6,10 +6,20 @@
*/
#include "SkGr.h"
+#include "SkColorFilter.h"
#include "SkConfig8888.h"
+#include "SkData.h"
#include "SkMessageBus.h"
#include "SkPixelRef.h"
#include "GrResourceCache.h"
+#include "GrGpu.h"
+#include "effects/GrDitherEffect.h"
+#include "GrDrawTargetCaps.h"
+
+#ifndef SK_IGNORE_ETC1_SUPPORT
+# include "ktx.h"
+# include "etc1.h"
+#endif
/* Fill out buffer with the compressed format Ganesh expects from a colortable
based bitmap. [palette (colortable) + indices].
@@ -23,7 +33,7 @@
as the colortable.count says it is.
*/
static void build_compressed_data(void* buffer, const SkBitmap& bitmap) {
- SkASSERT(SkBitmap::kIndex8_Config == bitmap.config());
+ SkASSERT(kIndex_8_SkColorType == bitmap.colorType());
SkAutoLockPixels alp(bitmap);
if (!bitmap.readyToDraw()) {
@@ -34,11 +44,22 @@ static void build_compressed_data(void* buffer, const SkBitmap& bitmap) {
SkColorTable* ctable = bitmap.getColorTable();
char* dst = (char*)buffer;
- uint32_t* colorTableDst = reinterpret_cast<uint32_t*>(dst);
- const uint32_t* colorTableSrc = reinterpret_cast<const uint32_t*>(ctable->lockColors());
- SkConvertConfig8888Pixels(colorTableDst, 0, SkCanvas::kRGBA_Premul_Config8888,
- colorTableSrc, 0, SkCanvas::kNative_Premul_Config8888,
- ctable->count(), 1);
+ const int count = ctable->count();
+
+ SkDstPixelInfo dstPI;
+ dstPI.fColorType = kRGBA_8888_SkColorType;
+ dstPI.fAlphaType = kPremul_SkAlphaType;
+ dstPI.fPixels = buffer;
+ dstPI.fRowBytes = count * sizeof(SkPMColor);
+
+ SkSrcPixelInfo srcPI;
+ srcPI.fColorType = kN32_SkColorType;
+ srcPI.fAlphaType = kPremul_SkAlphaType;
+ srcPI.fPixels = ctable->lockColors();
+ srcPI.fRowBytes = count * sizeof(SkPMColor);
+
+ srcPI.convertPixelsTo(&dstPI, count, 1);
+
ctable->unlockColors();
// always skip a full 256 number of entries, even if we memcpy'd fewer
@@ -65,18 +86,19 @@ static void generate_bitmap_cache_id(const SkBitmap& bitmap, GrCacheID* id) {
// Our id includes the offset, width, and height so that bitmaps created by extractSubset()
// are unique.
uint32_t genID = bitmap.getGenerationID();
- size_t offset = bitmap.pixelRefOffset();
- int16_t width = static_cast<int16_t>(bitmap.width());
- int16_t height = static_cast<int16_t>(bitmap.height());
+ SkIPoint origin = bitmap.pixelRefOrigin();
+ int16_t width = SkToS16(bitmap.width());
+ int16_t height = SkToS16(bitmap.height());
GrCacheID::Key key;
- memcpy(key.fData8, &genID, 4);
- memcpy(key.fData8 + 4, &width, 2);
- memcpy(key.fData8 + 6, &height, 2);
- memcpy(key.fData8 + 8, &offset, sizeof(size_t));
- static const size_t kKeyDataSize = 8 + sizeof(size_t);
+ memcpy(key.fData8 + 0, &genID, 4);
+ memcpy(key.fData8 + 4, &origin.fX, 4);
+ memcpy(key.fData8 + 8, &origin.fY, 4);
+ memcpy(key.fData8 + 12, &width, 2);
+ memcpy(key.fData8 + 14, &height, 2);
+ static const size_t kKeyDataSize = 16;
memset(key.fData8 + kKeyDataSize, 0, sizeof(key) - kKeyDataSize);
- GR_STATIC_ASSERT(sizeof(key) >= 8 + sizeof(size_t));
+ GR_STATIC_ASSERT(sizeof(key) >= kKeyDataSize);
static const GrCacheID::Domain gBitmapTextureDomain = GrCacheID::GenerateDomain();
id->reset(gBitmapTextureDomain, key);
}
@@ -85,7 +107,7 @@ static void generate_bitmap_texture_desc(const SkBitmap& bitmap, GrTextureDesc*
desc->fFlags = kNone_GrTextureFlags;
desc->fWidth = bitmap.width();
desc->fHeight = bitmap.height();
- desc->fConfig = SkBitmapConfig2GrPixelConfig(bitmap.config());
+ desc->fConfig = SkImageInfo2GrPixelConfig(bitmap.info());
desc->fSampleCnt = 0;
}
@@ -111,6 +133,66 @@ static void add_genID_listener(GrResourceKey key, SkPixelRef* pixelRef) {
pixelRef->addGenIDChangeListener(SkNEW_ARGS(GrResourceInvalidator, (key)));
}
+#ifndef SK_IGNORE_ETC1_SUPPORT
+static GrTexture *load_etc1_texture(GrContext* ctx,
+ const GrTextureParams* params,
+ const SkBitmap &bm, GrTextureDesc desc) {
+ SkAutoTUnref<SkData> data(bm.pixelRef()->refEncodedData());
+
+ // Is this even encoded data?
+ if (NULL == data) {
+ return NULL;
+ }
+
+ // Is this a valid PKM encoded data?
+ const uint8_t *bytes = data->bytes();
+ if (etc1_pkm_is_valid(bytes)) {
+ uint32_t encodedWidth = etc1_pkm_get_width(bytes);
+ uint32_t encodedHeight = etc1_pkm_get_height(bytes);
+
+ // Does the data match the dimensions of the bitmap? If not,
+ // then we don't know how to scale the image to match it...
+ if (encodedWidth != static_cast<uint32_t>(bm.width()) ||
+ encodedHeight != static_cast<uint32_t>(bm.height())) {
+ return NULL;
+ }
+
+ // Everything seems good... skip ahead to the data.
+ bytes += ETC_PKM_HEADER_SIZE;
+ desc.fConfig = kETC1_GrPixelConfig;
+ } else if (SkKTXFile::is_ktx(bytes)) {
+ SkKTXFile ktx(data);
+
+ // Is it actually an ETC1 texture?
+ if (!ktx.isETC1()) {
+ return NULL;
+ }
+
+ // Does the data match the dimensions of the bitmap? If not,
+ // then we don't know how to scale the image to match it...
+ if (ktx.width() != bm.width() || ktx.height() != bm.height()) {
+ return NULL;
+ }
+
+ bytes = ktx.pixelData();
+ desc.fConfig = kETC1_GrPixelConfig;
+ } else {
+ return NULL;
+ }
+
+ // This texture is likely to be used again so leave it in the cache
+ GrCacheID cacheID;
+ generate_bitmap_cache_id(bm, &cacheID);
+
+ GrResourceKey key;
+ GrTexture* result = ctx->createTexture(params, desc, cacheID, bytes, 0, &key);
+ if (NULL != result) {
+ add_genID_listener(key, bm.pixelRef());
+ }
+ return result;
+}
+#endif // SK_IGNORE_ETC1_SUPPORT
+
static GrTexture* sk_gr_create_bitmap_texture(GrContext* ctx,
bool cache,
const GrTextureParams* params,
@@ -122,7 +204,7 @@ static GrTexture* sk_gr_create_bitmap_texture(GrContext* ctx,
GrTextureDesc desc;
generate_bitmap_texture_desc(*bitmap, &desc);
- if (SkBitmap::kIndex8_Config == bitmap->config()) {
+ if (kIndex_8_SkColorType == bitmap->colorType()) {
// build_compressed_data doesn't do npot->pot expansion
// and paletted textures can't be sub-updated
if (ctx->supportsIndex8PixelConfig(params, bitmap->width(), bitmap->height())) {
@@ -154,13 +236,34 @@ static GrTexture* sk_gr_create_bitmap_texture(GrContext* ctx,
return result;
}
} else {
- origBitmap.copyTo(&tmpBitmap, SkBitmap::kARGB_8888_Config);
+ origBitmap.copyTo(&tmpBitmap, kN32_SkColorType);
// now bitmap points to our temp, which has been promoted to 32bits
bitmap = &tmpBitmap;
- desc.fConfig = SkBitmapConfig2GrPixelConfig(bitmap->config());
+ desc.fConfig = SkImageInfo2GrPixelConfig(bitmap->info());
}
}
+ // Is this an ETC1 encoded texture?
+#ifndef SK_IGNORE_ETC1_SUPPORT
+ else if (
+ // We do not support scratch ETC1 textures, hence they should all be at least
+ // trying to go to the cache.
+ cache
+ // Make sure that the underlying device supports ETC1 textures before we go ahead
+ // and check the data.
+ && ctx->getGpu()->caps()->isConfigTexturable(kETC1_GrPixelConfig)
+ // If the bitmap had compressed data and was then uncompressed, it'll still return
+ // compressed data on 'refEncodedData' and upload it. Probably not good, since if
+ // the bitmap has available pixels, then they might not be what the decompressed
+ // data is.
+ && !(bitmap->readyToDraw())) {
+ GrTexture *texture = load_etc1_texture(ctx, params, *bitmap, desc);
+ if (NULL != texture) {
+ return texture;
+ }
+ }
+#endif // SK_IGNORE_ETC1_SUPPORT
+
SkAutoLockPixels alp(*bitmap);
if (!bitmap->readyToDraw()) {
return NULL;
@@ -241,6 +344,7 @@ void GrUnlockAndUnrefCachedBitmapTexture(GrTexture* texture) {
///////////////////////////////////////////////////////////////////////////////
+#ifdef SK_SUPPORT_LEGACY_BITMAP_CONFIG
GrPixelConfig SkBitmapConfig2GrPixelConfig(SkBitmap::Config config) {
switch (config) {
case SkBitmap::kA8_Config:
@@ -258,6 +362,30 @@ GrPixelConfig SkBitmapConfig2GrPixelConfig(SkBitmap::Config config) {
return kUnknown_GrPixelConfig;
}
}
+#endif
+
+// alphatype is ignore for now, but if GrPixelConfig is expanded to encompass
+// alpha info, that will be considered.
+GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType ct, SkAlphaType) {
+ switch (ct) {
+ case kUnknown_SkColorType:
+ return kUnknown_GrPixelConfig;
+ case kAlpha_8_SkColorType:
+ return kAlpha_8_GrPixelConfig;
+ case kRGB_565_SkColorType:
+ return kRGB_565_GrPixelConfig;
+ case kARGB_4444_SkColorType:
+ return kRGBA_4444_GrPixelConfig;
+ case kRGBA_8888_SkColorType:
+ return kRGBA_8888_GrPixelConfig;
+ case kBGRA_8888_SkColorType:
+ return kBGRA_8888_GrPixelConfig;
+ case kIndex_8_SkColorType:
+ return kIndex_8_GrPixelConfig;
+ }
+ SkASSERT(0); // shouldn't get here
+ return kUnknown_GrPixelConfig;
+}
bool GrPixelConfig2ColorType(GrPixelConfig config, SkColorType* ctOut) {
SkColorType ct;
@@ -288,3 +416,129 @@ bool GrPixelConfig2ColorType(GrPixelConfig config, SkColorType* ctOut) {
}
return true;
}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SkPaint2GrPaintNoShader(GrContext* context, const SkPaint& skPaint, GrColor grColor,
+ bool constantColor, GrPaint* grPaint) {
+
+ grPaint->setDither(skPaint.isDither());
+ grPaint->setAntiAlias(skPaint.isAntiAlias());
+
+ SkXfermode::Coeff sm;
+ SkXfermode::Coeff dm;
+
+ SkXfermode* mode = skPaint.getXfermode();
+ GrEffectRef* xferEffect = NULL;
+ if (SkXfermode::AsNewEffectOrCoeff(mode, &xferEffect, &sm, &dm)) {
+ if (NULL != xferEffect) {
+ grPaint->addColorEffect(xferEffect)->unref();
+ sm = SkXfermode::kOne_Coeff;
+ dm = SkXfermode::kZero_Coeff;
+ }
+ } else {
+ //SkDEBUGCODE(SkDebugf("Unsupported xfer mode.\n");)
+ // Fall back to src-over
+ sm = SkXfermode::kOne_Coeff;
+ dm = SkXfermode::kISA_Coeff;
+ }
+ grPaint->setBlendFunc(sk_blend_to_grblend(sm), sk_blend_to_grblend(dm));
+
+ //set the color of the paint to the one of the parameter
+ grPaint->setColor(grColor);
+
+ SkColorFilter* colorFilter = skPaint.getColorFilter();
+ if (NULL != colorFilter) {
+ // if the source color is a constant then apply the filter here once rather than per pixel
+ // in a shader.
+ if (constantColor) {
+ SkColor filtered = colorFilter->filterColor(skPaint.getColor());
+ grPaint->setColor(SkColor2GrColor(filtered));
+ } else {
+ SkAutoTUnref<GrEffectRef> effect(colorFilter->asNewEffect(context));
+ if (NULL != effect.get()) {
+ grPaint->addColorEffect(effect);
+ }
+ }
+ }
+
+#ifndef SK_IGNORE_GPU_DITHER
+ // If the dither flag is set, then we need to see if the underlying context
+ // supports it. If not, then install a dither effect.
+ if (skPaint.isDither() && grPaint->numColorStages() > 0) {
+ // What are we rendering into?
+ const GrRenderTarget *target = context->getRenderTarget();
+ SkASSERT(NULL != target);
+
+ // Suspect the dithering flag has no effect on these configs, otherwise
+ // fall back on setting the appropriate state.
+ if (target->config() == kRGBA_8888_GrPixelConfig ||
+ target->config() == kBGRA_8888_GrPixelConfig) {
+ // The dither flag is set and the target is likely
+ // not going to be dithered by the GPU.
+ SkAutoTUnref<GrEffectRef> effect(GrDitherEffect::Create());
+ if (NULL != effect.get()) {
+ grPaint->addColorEffect(effect);
+ grPaint->setDither(false);
+ }
+ }
+ }
+#endif
+}
+
+/**
+ * Unlike GrContext::AutoMatrix, this doesn't require setting a new matrix. GrContext::AutoMatrix
+ * likes to set the new matrix in its constructor because it is usually necessary to simulataneously
+ * update a GrPaint. This AutoMatrix is used while initially setting up GrPaint, however.
+ */
+class AutoMatrix {
+public:
+ AutoMatrix(GrContext* context) {
+ fMatrix = context->getMatrix();
+ fContext = context;
+ }
+ ~AutoMatrix() {
+ SkASSERT(NULL != fContext);
+ fContext->setMatrix(fMatrix);
+ }
+private:
+ GrContext* fContext;
+ SkMatrix fMatrix;
+};
+
+void SkPaint2GrPaintShader(GrContext* context, const SkPaint& skPaint,
+ bool constantColor, GrPaint* grPaint) {
+ SkShader* shader = skPaint.getShader();
+ if (NULL == shader) {
+ SkPaint2GrPaintNoShader(context, skPaint, SkColor2GrColor(skPaint.getColor()),
+ constantColor, grPaint);
+ return;
+ }
+
+ // SkShader::asNewEffect() may do offscreen rendering. Save off the current RT, clip, and
+ // matrix. We don't reset the matrix on the context because SkShader::asNewEffect may use
+ // GrContext::getMatrix() to know the transformation from local coords to device space.
+ GrColor grColor = SkColor2GrColor(skPaint.getColor());
+
+ // Start a new block here in order to preserve our context state after calling
+ // asNewEffect(). Since these calls get passed back to the client, we don't really
+ // want them messing around with the context.
+ {
+ GrContext::AutoRenderTarget art(context, NULL);
+ GrContext::AutoClip ac(context, GrContext::AutoClip::kWideOpen_InitialClip);
+ AutoMatrix am(context);
+
+ // setup the shader as the first color effect on the paint
+ // the default grColor is the paint's color
+ GrEffectRef* grEffect = NULL;
+ if (shader->asNewEffect(context, skPaint, NULL, &grColor, &grEffect) && NULL != grEffect) {
+ SkAutoTUnref<GrEffectRef> effect(grEffect);
+ grPaint->addColorEffect(effect);
+ constantColor = false;
+ }
+ }
+
+ // The grcolor is automatically set when calling asneweffect.
+ // If the shader can be seen as an effect it returns true and adds its effect to the grpaint.
+ SkPaint2GrPaintNoShader(context, skPaint, grColor, constantColor, grPaint);
+}
diff --git a/chromium/third_party/skia/src/gpu/SkGrFontScaler.cpp b/chromium/third_party/skia/src/gpu/SkGrFontScaler.cpp
index 8fdae48a2ad..44856906e3e 100644
--- a/chromium/third_party/skia/src/gpu/SkGrFontScaler.cpp
+++ b/chromium/third_party/skia/src/gpu/SkGrFontScaler.cpp
@@ -10,6 +10,7 @@
#include "GrTemplates.h"
#include "SkGr.h"
#include "SkDescriptor.h"
+#include "SkDistanceFieldGen.h"
#include "SkGlyphCache.h"
class SkGrDescKey : public GrKey {
@@ -102,14 +103,23 @@ const GrKey* SkGrFontScaler::getKey() {
return fKey;
}
-bool SkGrFontScaler::getPackedGlyphBounds(GrGlyph::PackedID packed,
- SkIRect* bounds) {
+bool SkGrFontScaler::getPackedGlyphBounds(GrGlyph::PackedID packed, SkIRect* bounds) {
const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
- GrGlyph::UnpackFixedX(packed),
- GrGlyph::UnpackFixedY(packed));
+ GrGlyph::UnpackFixedX(packed),
+ GrGlyph::UnpackFixedY(packed));
bounds->setXYWH(glyph.fLeft, glyph.fTop, glyph.fWidth, glyph.fHeight);
+
return true;
+}
+
+bool SkGrFontScaler::getPackedGlyphDFBounds(GrGlyph::PackedID packed, SkIRect* bounds) {
+ const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
+ GrGlyph::UnpackFixedX(packed),
+ GrGlyph::UnpackFixedY(packed));
+ bounds->setXYWH(glyph.fLeft, glyph.fTop, glyph.fWidth, glyph.fHeight);
+ bounds->outset(SK_DistanceFieldPad, SK_DistanceFieldPad);
+ return true;
}
namespace {
@@ -142,8 +152,8 @@ bool SkGrFontScaler::getPackedGlyphImage(GrGlyph::PackedID packed,
int width, int height,
int dstRB, void* dst) {
const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
- GrGlyph::UnpackFixedX(packed),
- GrGlyph::UnpackFixedY(packed));
+ GrGlyph::UnpackFixedX(packed),
+ GrGlyph::UnpackFixedY(packed));
SkASSERT(glyph.fWidth == width);
SkASSERT(glyph.fHeight == height);
const void* src = fStrike->findImage(glyph);
@@ -175,7 +185,7 @@ bool SkGrFontScaler::getPackedGlyphImage(GrGlyph::PackedID packed,
break;
}
default:
- GrCrash("Invalid GrMaskFormat");
+ SkFAIL("Invalid GrMaskFormat");
}
} else if (srcRB == dstRB) {
memcpy(dst, src, dstRB * height);
@@ -190,6 +200,24 @@ bool SkGrFontScaler::getPackedGlyphImage(GrGlyph::PackedID packed,
return true;
}
+bool SkGrFontScaler::getPackedGlyphDFImage(GrGlyph::PackedID packed,
+ int width, int height,
+ void* dst) {
+ const SkGlyph& glyph = fStrike->getGlyphIDMetrics(GrGlyph::UnpackID(packed),
+ GrGlyph::UnpackFixedX(packed),
+ GrGlyph::UnpackFixedY(packed));
+ SkASSERT(glyph.fWidth + 2*SK_DistanceFieldPad == width);
+ SkASSERT(glyph.fHeight + 2*SK_DistanceFieldPad == height);
+ const void* src = fStrike->findDistanceField(glyph);
+ if (NULL == src) {
+ return false;
+ }
+
+ memcpy(dst, src, width * height);
+
+ return true;
+}
+
// we should just return const SkPath* (NULL means false)
bool SkGrFontScaler::getGlyphPath(uint16_t glyphID, SkPath* path) {
diff --git a/chromium/third_party/skia/src/gpu/SkGrPixelRef.cpp b/chromium/third_party/skia/src/gpu/SkGrPixelRef.cpp
index ddd60ff864e..2131f41b17b 100644
--- a/chromium/third_party/skia/src/gpu/SkGrPixelRef.cpp
+++ b/chromium/third_party/skia/src/gpu/SkGrPixelRef.cpp
@@ -23,18 +23,22 @@ SkROLockPixelsPixelRef::SkROLockPixelsPixelRef(const SkImageInfo& info)
SkROLockPixelsPixelRef::~SkROLockPixelsPixelRef() {}
-void* SkROLockPixelsPixelRef::onLockPixels(SkColorTable** ctable) {
- if (ctable) {
- *ctable = NULL;
- }
+bool SkROLockPixelsPixelRef::onNewLockPixels(LockRec* rec) {
fBitmap.reset();
// SkDebugf("---------- calling readpixels in support of lockpixels\n");
if (!this->onReadPixels(&fBitmap, NULL)) {
SkDebugf("SkROLockPixelsPixelRef::onLockPixels failed!\n");
- return NULL;
+ return false;
}
fBitmap.lockPixels();
- return fBitmap.getPixels();
+ if (NULL == fBitmap.getPixels()) {
+ return false;
+ }
+
+ rec->fPixels = fBitmap.getPixels();
+ rec->fColorTable = NULL;
+ rec->fRowBytes = fBitmap.rowBytes();
+ return true;
}
void SkROLockPixelsPixelRef::onUnlockPixels() {
@@ -47,9 +51,9 @@ bool SkROLockPixelsPixelRef::onLockPixelsAreWritable() const {
///////////////////////////////////////////////////////////////////////////////
-static SkGrPixelRef* copyToTexturePixelRef(GrTexture* texture, SkBitmap::Config dstConfig,
+static SkGrPixelRef* copyToTexturePixelRef(GrTexture* texture, SkColorType dstCT,
const SkIRect* subset) {
- if (NULL == texture) {
+ if (NULL == texture || kUnknown_SkColorType == dstCT) {
return NULL;
}
GrContext* context = texture->getContext();
@@ -73,16 +77,8 @@ static SkGrPixelRef* copyToTexturePixelRef(GrTexture* texture, SkBitmap::Config
topLeft = NULL;
}
desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
- desc.fConfig = SkBitmapConfig2GrPixelConfig(dstConfig);
+ desc.fConfig = SkImageInfo2GrPixelConfig(dstCT, kPremul_SkAlphaType);
- SkImageInfo info;
- if (!GrPixelConfig2ColorType(desc.fConfig, &info.fColorType)) {
- return NULL;
- }
- info.fWidth = desc.fWidth;
- info.fHeight = desc.fHeight;
- info.fAlphaType = kPremul_SkAlphaType;
-
GrTexture* dst = context->createUncachedTexture(desc, NULL, 0);
if (NULL == dst) {
return NULL;
@@ -100,6 +96,7 @@ static SkGrPixelRef* copyToTexturePixelRef(GrTexture* texture, SkBitmap::Config
dst->releaseRenderTarget();
#endif
+ SkImageInfo info = SkImageInfo::Make(desc.fWidth, desc.fHeight, dstCT, kPremul_SkAlphaType);
SkGrPixelRef* pixelRef = SkNEW_ARGS(SkGrPixelRef, (info, dst));
SkSafeUnref(dst);
return pixelRef;
@@ -123,6 +120,11 @@ SkGrPixelRef::SkGrPixelRef(const SkImageInfo& info, GrSurface* surface,
}
fUnlock = transferCacheLock;
SkSafeRef(surface);
+
+ if (fSurface) {
+ SkASSERT(info.fWidth <= fSurface->width());
+ SkASSERT(info.fHeight <= fSurface->height());
+ }
}
SkGrPixelRef::~SkGrPixelRef() {
@@ -143,22 +145,22 @@ GrTexture* SkGrPixelRef::getTexture() {
return NULL;
}
-SkPixelRef* SkGrPixelRef::deepCopy(SkBitmap::Config dstConfig, const SkIRect* subset) {
+SkPixelRef* SkGrPixelRef::deepCopy(SkColorType dstCT, const SkIRect* subset) {
if (NULL == fSurface) {
return NULL;
}
-
+
// Note that when copying a render-target-backed pixel ref, we
// return a texture-backed pixel ref instead. This is because
// render-target pixel refs are usually created in conjunction with
// a GrTexture owned elsewhere (e.g., SkGpuDevice), and cannot live
// independently of that texture. Texture-backed pixel refs, on the other
// hand, own their GrTextures, and are thus self-contained.
- return copyToTexturePixelRef(fSurface->asTexture(), dstConfig, subset);
+ return copyToTexturePixelRef(fSurface->asTexture(), dstCT, subset);
}
bool SkGrPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) {
- if (NULL == fSurface || !fSurface->isValid()) {
+ if (NULL == fSurface || fSurface->wasDestroyed()) {
return false;
}
@@ -170,12 +172,11 @@ bool SkGrPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) {
height = subset->height();
} else {
left = 0;
- width = fSurface->width();
+ width = this->info().fWidth;
top = 0;
- height = fSurface->height();
+ height = this->info().fHeight;
}
- dst->setConfig(SkBitmap::kARGB_8888_Config, width, height);
- if (!dst->allocPixels()) {
+ if (!dst->allocPixels(SkImageInfo::MakeN32Premul(width, height))) {
SkDebugf("SkGrPixelRef::onReadPixels failed to alloc bitmap for result!\n");
return false;
}
diff --git a/chromium/third_party/skia/src/gpu/effects/GrBezierEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrBezierEffect.cpp
index c9a2bea0522..862c1d2c179 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrBezierEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/GrBezierEffect.cpp
@@ -29,7 +29,7 @@ public:
virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {}
private:
- GrBezierEdgeType fEdgeType;
+ GrEffectEdgeType fEdgeType;
typedef GrGLVertexEffect INHERITED;
};
@@ -59,7 +59,7 @@ void GrGLConicEffect::emitCode(GrGLFullShaderBuilder* builder,
builder->fsCodeAppend("\t\tfloat edgeAlpha;\n");
switch (fEdgeType) {
- case kHairAA_GrBezierEdgeType: {
+ case kHairlineAA_GrEffectEdgeType: {
SkAssertResult(builder->enableFeature(
GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
builder->fsCodeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName);
@@ -81,7 +81,7 @@ void GrGLConicEffect::emitCode(GrGLFullShaderBuilder* builder,
// builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
break;
}
- case kFillAA_GrBezierEdgeType: {
+ case kFillAA_GrEffectEdgeType: {
SkAssertResult(builder->enableFeature(
GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
builder->fsCodeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName);
@@ -102,12 +102,14 @@ void GrGLConicEffect::emitCode(GrGLFullShaderBuilder* builder,
// builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
break;
}
- case kFillNoAA_GrBezierEdgeType: {
+ case kFillBW_GrEffectEdgeType: {
builder->fsCodeAppendf("\t\tedgeAlpha = %s.x*%s.x - %s.y*%s.z;\n", fsName, fsName,
fsName, fsName);
builder->fsCodeAppend("\t\tedgeAlpha = float(edgeAlpha < 0.0);\n");
break;
}
+ default:
+ SkFAIL("Shouldn't get here");
}
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
@@ -127,7 +129,7 @@ const GrBackendEffectFactory& GrConicEffect::getFactory() const {
return GrTBackendEffectFactory<GrConicEffect>::getInstance();
}
-GrConicEffect::GrConicEffect(GrBezierEdgeType edgeType) : GrVertexEffect() {
+GrConicEffect::GrConicEffect(GrEffectEdgeType edgeType) : GrVertexEffect() {
this->addVertexAttrib(kVec4f_GrSLType);
fEdgeType = edgeType;
}
@@ -145,8 +147,13 @@ GrEffectRef* GrConicEffect::TestCreate(SkRandom* random,
GrContext*,
const GrDrawTargetCaps& caps,
GrTexture*[]) {
- const GrBezierEdgeType edgeType = static_cast<GrBezierEdgeType>(random->nextULessThan(3));
- return GrConicEffect::Create(edgeType, caps);
+ GrEffectRef* effect;
+ do {
+ GrEffectEdgeType edgeType = static_cast<GrEffectEdgeType>(
+ random->nextULessThan(kGrEffectEdgeTypeCnt));
+ effect = GrConicEffect::Create(edgeType, caps);
+ } while (NULL == effect);
+ return effect;
}
//////////////////////////////////////////////////////////////////////////////
@@ -170,7 +177,7 @@ public:
virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {}
private:
- GrBezierEdgeType fEdgeType;
+ GrEffectEdgeType fEdgeType;
typedef GrGLVertexEffect INHERITED;
};
@@ -198,7 +205,7 @@ void GrGLQuadEffect::emitCode(GrGLFullShaderBuilder* builder,
builder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsName);
switch (fEdgeType) {
- case kHairAA_GrBezierEdgeType: {
+ case kHairlineAA_GrEffectEdgeType: {
SkAssertResult(builder->enableFeature(
GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
@@ -214,7 +221,7 @@ void GrGLQuadEffect::emitCode(GrGLFullShaderBuilder* builder,
// builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
break;
}
- case kFillAA_GrBezierEdgeType: {
+ case kFillAA_GrEffectEdgeType: {
SkAssertResult(builder->enableFeature(
GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
@@ -230,12 +237,14 @@ void GrGLQuadEffect::emitCode(GrGLFullShaderBuilder* builder,
// builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
break;
}
- case kFillNoAA_GrBezierEdgeType: {
+ case kFillBW_GrEffectEdgeType: {
builder->fsCodeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName,
fsName);
builder->fsCodeAppend("\t\tedgeAlpha = float(edgeAlpha < 0.0);\n");
break;
}
+ default:
+ SkFAIL("Shouldn't get here");
}
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
@@ -258,7 +267,7 @@ const GrBackendEffectFactory& GrQuadEffect::getFactory() const {
return GrTBackendEffectFactory<GrQuadEffect>::getInstance();
}
-GrQuadEffect::GrQuadEffect(GrBezierEdgeType edgeType) : GrVertexEffect() {
+GrQuadEffect::GrQuadEffect(GrEffectEdgeType edgeType) : GrVertexEffect() {
this->addVertexAttrib(kVec4f_GrSLType);
fEdgeType = edgeType;
}
@@ -276,8 +285,13 @@ GrEffectRef* GrQuadEffect::TestCreate(SkRandom* random,
GrContext*,
const GrDrawTargetCaps& caps,
GrTexture*[]) {
- const GrBezierEdgeType edgeType = static_cast<GrBezierEdgeType>(random->nextULessThan(3));
- return GrQuadEffect::Create(edgeType, caps);
+ GrEffectRef* effect;
+ do {
+ GrEffectEdgeType edgeType = static_cast<GrEffectEdgeType>(
+ random->nextULessThan(kGrEffectEdgeTypeCnt));
+ effect = GrQuadEffect::Create(edgeType, caps);
+ } while (NULL == effect);
+ return effect;
}
//////////////////////////////////////////////////////////////////////////////
@@ -301,7 +315,7 @@ public:
virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {}
private:
- GrBezierEdgeType fEdgeType;
+ GrEffectEdgeType fEdgeType;
typedef GrGLVertexEffect INHERITED;
};
@@ -331,7 +345,7 @@ void GrGLCubicEffect::emitCode(GrGLFullShaderBuilder* builder,
builder->fsCodeAppend("\t\tfloat edgeAlpha;\n");
switch (fEdgeType) {
- case kHairAA_GrBezierEdgeType: {
+ case kHairlineAA_GrEffectEdgeType: {
SkAssertResult(builder->enableFeature(
GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
builder->fsCodeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName);
@@ -353,7 +367,7 @@ void GrGLCubicEffect::emitCode(GrGLFullShaderBuilder* builder,
// builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
break;
}
- case kFillAA_GrBezierEdgeType: {
+ case kFillAA_GrEffectEdgeType: {
SkAssertResult(builder->enableFeature(
GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
builder->fsCodeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName);
@@ -374,12 +388,14 @@ void GrGLCubicEffect::emitCode(GrGLFullShaderBuilder* builder,
// builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
break;
}
- case kFillNoAA_GrBezierEdgeType: {
+ case kFillBW_GrEffectEdgeType: {
builder->fsCodeAppendf("\t\tedgeAlpha = %s.x*%s.x*%s.x - %s.y*%s.z;\n",
fsName, fsName, fsName, fsName, fsName);
builder->fsCodeAppend("\t\tedgeAlpha = float(edgeAlpha < 0.0);\n");
break;
}
+ default:
+ SkFAIL("Shouldn't get here");
}
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
@@ -399,7 +415,7 @@ const GrBackendEffectFactory& GrCubicEffect::getFactory() const {
return GrTBackendEffectFactory<GrCubicEffect>::getInstance();
}
-GrCubicEffect::GrCubicEffect(GrBezierEdgeType edgeType) : GrVertexEffect() {
+GrCubicEffect::GrCubicEffect(GrEffectEdgeType edgeType) : GrVertexEffect() {
this->addVertexAttrib(kVec4f_GrSLType);
fEdgeType = edgeType;
}
@@ -417,6 +433,11 @@ GrEffectRef* GrCubicEffect::TestCreate(SkRandom* random,
GrContext*,
const GrDrawTargetCaps& caps,
GrTexture*[]) {
- const GrBezierEdgeType edgeType = static_cast<GrBezierEdgeType>(random->nextULessThan(3));
- return GrCubicEffect::Create(edgeType, caps);
+ GrEffectRef* effect;
+ do {
+ GrEffectEdgeType edgeType = static_cast<GrEffectEdgeType>(
+ random->nextULessThan(kGrEffectEdgeTypeCnt));
+ effect = GrCubicEffect::Create(edgeType, caps);
+ } while (NULL == effect);
+ return effect;
}
diff --git a/chromium/third_party/skia/src/gpu/effects/GrBezierEffect.h b/chromium/third_party/skia/src/gpu/effects/GrBezierEffect.h
index 5de7b80b750..e2fc592bdc0 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrBezierEffect.h
+++ b/chromium/third_party/skia/src/gpu/effects/GrBezierEffect.h
@@ -11,20 +11,7 @@
#include "GrDrawTargetCaps.h"
#include "GrEffect.h"
#include "GrVertexEffect.h"
-
-enum GrBezierEdgeType {
- kFillAA_GrBezierEdgeType,
- kHairAA_GrBezierEdgeType,
- kFillNoAA_GrBezierEdgeType,
-};
-
-static inline bool GrBezierEdgeTypeIsFill(const GrBezierEdgeType edgeType) {
- return (kHairAA_GrBezierEdgeType != edgeType);
-}
-
-static inline bool GrBezierEdgeTypeIsAA(const GrBezierEdgeType edgeType) {
- return (kFillNoAA_GrBezierEdgeType != edgeType);
-}
+#include "GrTypesPriv.h"
/**
* Shader is based off of Loop-Blinn Quadratic GPU Rendering
@@ -70,25 +57,28 @@ class GrGLConicEffect;
class GrConicEffect : public GrVertexEffect {
public:
- static GrEffectRef* Create(const GrBezierEdgeType edgeType, const GrDrawTargetCaps& caps) {
- GR_CREATE_STATIC_EFFECT(gConicFillAA, GrConicEffect, (kFillAA_GrBezierEdgeType));
- GR_CREATE_STATIC_EFFECT(gConicHairAA, GrConicEffect, (kHairAA_GrBezierEdgeType));
- GR_CREATE_STATIC_EFFECT(gConicFillNoAA, GrConicEffect, (kFillNoAA_GrBezierEdgeType));
- if (kFillAA_GrBezierEdgeType == edgeType) {
- if (!caps.shaderDerivativeSupport()) {
+ static GrEffectRef* Create(const GrEffectEdgeType edgeType, const GrDrawTargetCaps& caps) {
+ GR_CREATE_STATIC_EFFECT(gConicFillAA, GrConicEffect, (kFillAA_GrEffectEdgeType));
+ GR_CREATE_STATIC_EFFECT(gConicHairAA, GrConicEffect, (kHairlineAA_GrEffectEdgeType));
+ GR_CREATE_STATIC_EFFECT(gConicFillBW, GrConicEffect, (kFillBW_GrEffectEdgeType));
+ switch (edgeType) {
+ case kFillAA_GrEffectEdgeType:
+ if (!caps.shaderDerivativeSupport()) {
+ return NULL;
+ }
+ gConicFillAA->ref();
+ return gConicFillAA;
+ case kHairlineAA_GrEffectEdgeType:
+ if (!caps.shaderDerivativeSupport()) {
+ return NULL;
+ }
+ gConicHairAA->ref();
+ return gConicHairAA;
+ case kFillBW_GrEffectEdgeType:
+ gConicFillBW->ref();
+ return gConicFillBW;
+ default:
return NULL;
- }
- gConicFillAA->ref();
- return gConicFillAA;
- } else if (kHairAA_GrBezierEdgeType == edgeType) {
- if (!caps.shaderDerivativeSupport()) {
- return NULL;
- }
- gConicHairAA->ref();
- return gConicHairAA;
- } else {
- gConicFillNoAA->ref();
- return gConicFillNoAA;
}
}
@@ -96,9 +86,9 @@ public:
static const char* Name() { return "Conic"; }
- inline bool isAntiAliased() const { return GrBezierEdgeTypeIsAA(fEdgeType); }
- inline bool isFilled() const { return GrBezierEdgeTypeIsFill(fEdgeType); }
- inline GrBezierEdgeType getEdgeType() const { return fEdgeType; }
+ inline bool isAntiAliased() const { return GrEffectEdgeTypeIsAA(fEdgeType); }
+ inline bool isFilled() const { return GrEffectEdgeTypeIsFill(fEdgeType); }
+ inline GrEffectEdgeType getEdgeType() const { return fEdgeType; }
typedef GrGLConicEffect GLEffect;
@@ -110,11 +100,11 @@ public:
virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
private:
- GrConicEffect(GrBezierEdgeType);
+ GrConicEffect(GrEffectEdgeType);
virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE;
- GrBezierEdgeType fEdgeType;
+ GrEffectEdgeType fEdgeType;
GR_DECLARE_EFFECT_TEST;
@@ -134,25 +124,28 @@ class GrGLQuadEffect;
class GrQuadEffect : public GrVertexEffect {
public:
- static GrEffectRef* Create(const GrBezierEdgeType edgeType, const GrDrawTargetCaps& caps) {
- GR_CREATE_STATIC_EFFECT(gQuadFillAA, GrQuadEffect, (kFillAA_GrBezierEdgeType));
- GR_CREATE_STATIC_EFFECT(gQuadHairAA, GrQuadEffect, (kHairAA_GrBezierEdgeType));
- GR_CREATE_STATIC_EFFECT(gQuadFillNoAA, GrQuadEffect, (kFillNoAA_GrBezierEdgeType));
- if (kFillAA_GrBezierEdgeType == edgeType) {
- if (!caps.shaderDerivativeSupport()) {
- return NULL;
- }
- gQuadFillAA->ref();
- return gQuadFillAA;
- } else if (kHairAA_GrBezierEdgeType == edgeType) {
- if (!caps.shaderDerivativeSupport()) {
+ static GrEffectRef* Create(const GrEffectEdgeType edgeType, const GrDrawTargetCaps& caps) {
+ GR_CREATE_STATIC_EFFECT(gQuadFillAA, GrQuadEffect, (kFillAA_GrEffectEdgeType));
+ GR_CREATE_STATIC_EFFECT(gQuadHairAA, GrQuadEffect, (kHairlineAA_GrEffectEdgeType));
+ GR_CREATE_STATIC_EFFECT(gQuadFillBW, GrQuadEffect, (kFillBW_GrEffectEdgeType));
+ switch (edgeType) {
+ case kFillAA_GrEffectEdgeType:
+ if (!caps.shaderDerivativeSupport()) {
+ return NULL;
+ }
+ gQuadFillAA->ref();
+ return gQuadFillAA;
+ case kHairlineAA_GrEffectEdgeType:
+ if (!caps.shaderDerivativeSupport()) {
+ return NULL;
+ }
+ gQuadHairAA->ref();
+ return gQuadHairAA;
+ case kFillBW_GrEffectEdgeType:
+ gQuadFillBW->ref();
+ return gQuadFillBW;
+ default:
return NULL;
- }
- gQuadHairAA->ref();
- return gQuadHairAA;
- } else {
- gQuadFillNoAA->ref();
- return gQuadFillNoAA;
}
}
@@ -160,9 +153,9 @@ public:
static const char* Name() { return "Quad"; }
- inline bool isAntiAliased() const { return GrBezierEdgeTypeIsAA(fEdgeType); }
- inline bool isFilled() const { return GrBezierEdgeTypeIsFill(fEdgeType); }
- inline GrBezierEdgeType getEdgeType() const { return fEdgeType; }
+ inline bool isAntiAliased() const { return GrEffectEdgeTypeIsAA(fEdgeType); }
+ inline bool isFilled() const { return GrEffectEdgeTypeIsFill(fEdgeType); }
+ inline GrEffectEdgeType getEdgeType() const { return fEdgeType; }
typedef GrGLQuadEffect GLEffect;
@@ -174,11 +167,11 @@ public:
virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
private:
- GrQuadEffect(GrBezierEdgeType);
+ GrQuadEffect(GrEffectEdgeType);
virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE;
- GrBezierEdgeType fEdgeType;
+ GrEffectEdgeType fEdgeType;
GR_DECLARE_EFFECT_TEST;
@@ -200,25 +193,28 @@ class GrGLCubicEffect;
class GrCubicEffect : public GrVertexEffect {
public:
- static GrEffectRef* Create(const GrBezierEdgeType edgeType, const GrDrawTargetCaps& caps) {
- GR_CREATE_STATIC_EFFECT(gCubicFillAA, GrCubicEffect, (kFillAA_GrBezierEdgeType));
- GR_CREATE_STATIC_EFFECT(gCubicHairAA, GrCubicEffect, (kHairAA_GrBezierEdgeType));
- GR_CREATE_STATIC_EFFECT(gCubicFillNoAA, GrCubicEffect, (kFillNoAA_GrBezierEdgeType));
- if (kFillAA_GrBezierEdgeType == edgeType) {
- if (!caps.shaderDerivativeSupport()) {
- return NULL;
- }
- gCubicFillAA->ref();
- return gCubicFillAA;
- } else if (kHairAA_GrBezierEdgeType == edgeType) {
- if (!caps.shaderDerivativeSupport()) {
+ static GrEffectRef* Create(const GrEffectEdgeType edgeType, const GrDrawTargetCaps& caps) {
+ GR_CREATE_STATIC_EFFECT(gCubicFillAA, GrCubicEffect, (kFillAA_GrEffectEdgeType));
+ GR_CREATE_STATIC_EFFECT(gCubicHairAA, GrCubicEffect, (kHairlineAA_GrEffectEdgeType));
+ GR_CREATE_STATIC_EFFECT(gCubicFillBW, GrCubicEffect, (kFillBW_GrEffectEdgeType));
+ switch (edgeType) {
+ case kFillAA_GrEffectEdgeType:
+ if (!caps.shaderDerivativeSupport()) {
+ return NULL;
+ }
+ gCubicFillAA->ref();
+ return gCubicFillAA;
+ case kHairlineAA_GrEffectEdgeType:
+ if (!caps.shaderDerivativeSupport()) {
+ return NULL;
+ }
+ gCubicHairAA->ref();
+ return gCubicHairAA;
+ case kFillBW_GrEffectEdgeType:
+ gCubicFillBW->ref();
+ return gCubicFillBW;
+ default:
return NULL;
- }
- gCubicHairAA->ref();
- return gCubicHairAA;
- } else {
- gCubicFillNoAA->ref();
- return gCubicFillNoAA;
}
}
@@ -226,9 +222,9 @@ public:
static const char* Name() { return "Cubic"; }
- inline bool isAntiAliased() const { return GrBezierEdgeTypeIsAA(fEdgeType); }
- inline bool isFilled() const { return GrBezierEdgeTypeIsFill(fEdgeType); }
- inline GrBezierEdgeType getEdgeType() const { return fEdgeType; }
+ inline bool isAntiAliased() const { return GrEffectEdgeTypeIsAA(fEdgeType); }
+ inline bool isFilled() const { return GrEffectEdgeTypeIsFill(fEdgeType); }
+ inline GrEffectEdgeType getEdgeType() const { return fEdgeType; }
typedef GrGLCubicEffect GLEffect;
@@ -240,11 +236,11 @@ public:
virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
private:
- GrCubicEffect(GrBezierEdgeType);
+ GrCubicEffect(GrEffectEdgeType);
virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE;
- GrBezierEdgeType fEdgeType;
+ GrEffectEdgeType fEdgeType;
GR_DECLARE_EFFECT_TEST;
diff --git a/chromium/third_party/skia/src/gpu/effects/GrBicubicEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrBicubicEffect.cpp
index a6e08f20b52..9c6d1a3f8ca 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrBicubicEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/GrBicubicEffect.cpp
@@ -14,6 +14,7 @@ class GrGLBicubicEffect : public GrGLEffect {
public:
GrGLBicubicEffect(const GrBackendEffectFactory& factory,
const GrDrawEffect&);
+
virtual void emitCode(GrGLShaderBuilder*,
const GrDrawEffect&,
EffectKey,
@@ -24,11 +25,17 @@ public:
virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
+ static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
+ const GrTextureDomain& domain = drawEffect.castEffect<GrBicubicEffect>().domain();
+ return GrTextureDomain::GLDomain::DomainKey(domain);
+ }
+
private:
typedef GrGLUniformManager::UniformHandle UniformHandle;
- UniformHandle fCoefficientsUni;
- UniformHandle fImageIncrementUni;
+ UniformHandle fCoefficientsUni;
+ UniformHandle fImageIncrementUni;
+ GrTextureDomain::GLDomain fDomain;
typedef GrGLEffect INHERITED;
};
@@ -38,13 +45,13 @@ GrGLBicubicEffect::GrGLBicubicEffect(const GrBackendEffectFactory& factory, cons
}
void GrGLBicubicEffect::emitCode(GrGLShaderBuilder* builder,
- const GrDrawEffect&,
+ const GrDrawEffect& drawEffect,
EffectKey key,
const char* outputColor,
const char* inputColor,
const TransformedCoordsArray& coords,
const TextureSamplerArray& samplers) {
- sk_ignore_unused_variable(inputColor);
+ const GrTextureDomain& domain = drawEffect.castEffect<GrBicubicEffect>().domain();
SkString coords2D = builder->ensureFSCoords2D(coords, 0);
fCoefficientsUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
@@ -81,42 +88,60 @@ void GrGLBicubicEffect::emitCode(GrGLShaderBuilder* builder,
builder->fsCodeAppendf("\tcoord /= %s;\n", imgInc);
builder->fsCodeAppend("\tvec2 f = fract(coord);\n");
builder->fsCodeAppendf("\tcoord = (coord - f + vec2(0.5)) * %s;\n", imgInc);
+ builder->fsCodeAppend("\tvec4 rowColors[4];\n");
for (int y = 0; y < 4; ++y) {
for (int x = 0; x < 4; ++x) {
SkString coord;
coord.printf("coord + %s * vec2(%d, %d)", imgInc, x - 1, y - 1);
- builder->fsCodeAppendf("\tvec4 s%d%d = ", x, y);
- builder->fsAppendTextureLookup(samplers[0], coord.c_str());
- builder->fsCodeAppend(";\n");
+ SkString sampleVar;
+ sampleVar.printf("rowColors[%d]", x);
+ fDomain.sampleTexture(builder, domain, sampleVar.c_str(), coord, samplers[0]);
}
- builder->fsCodeAppendf("\tvec4 s%d = %s(%s, f.x, s0%d, s1%d, s2%d, s3%d);\n", y, cubicBlendName.c_str(), coeff, y, y, y, y);
+ builder->fsCodeAppendf("\tvec4 s%d = %s(%s, f.x, rowColors[0], rowColors[1], rowColors[2], rowColors[3]);\n", y, cubicBlendName.c_str(), coeff);
}
- builder->fsCodeAppendf("\t%s = %s(%s, f.y, s0, s1, s2, s3);\n", outputColor, cubicBlendName.c_str(), coeff);
+ SkString bicubicColor;
+ bicubicColor.printf("%s(%s, f.y, s0, s1, s2, s3)", cubicBlendName.c_str(), coeff);
+ builder->fsCodeAppendf("\t%s = %s;\n", outputColor, (GrGLSLExpr4(bicubicColor.c_str()) * GrGLSLExpr4(inputColor)).c_str());
}
void GrGLBicubicEffect::setData(const GrGLUniformManager& uman,
const GrDrawEffect& drawEffect) {
const GrBicubicEffect& effect = drawEffect.castEffect<GrBicubicEffect>();
- GrTexture& texture = *effect.texture(0);
+ const GrTexture& texture = *effect.texture(0);
float imageIncrement[2];
imageIncrement[0] = 1.0f / texture.width();
imageIncrement[1] = 1.0f / texture.height();
uman.set2fv(fImageIncrementUni, 1, imageIncrement);
uman.setMatrix4f(fCoefficientsUni, effect.coefficients());
+ fDomain.setData(uman, effect.domain(), texture.origin());
}
-GrBicubicEffect::GrBicubicEffect(GrTexture* texture,
- const SkScalar coefficients[16],
- const SkMatrix &matrix,
- const SkShader::TileMode tileModes[2])
- : INHERITED(texture, matrix, GrTextureParams(tileModes, GrTextureParams::kNone_FilterMode)) {
+static inline void convert_row_major_scalar_coeffs_to_column_major_floats(float dst[16],
+ const SkScalar src[16]) {
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
- // Convert from row-major scalars to column-major floats.
- fCoefficients[x * 4 + y] = SkScalarToFloat(coefficients[y * 4 + x]);
+ dst[x * 4 + y] = SkScalarToFloat(src[y * 4 + x]);
}
}
- this->setWillNotUseInputColor();
+}
+
+GrBicubicEffect::GrBicubicEffect(GrTexture* texture,
+ const SkScalar coefficients[16],
+ const SkMatrix &matrix,
+ const SkShader::TileMode tileModes[2])
+ : INHERITED(texture, matrix, GrTextureParams(tileModes, GrTextureParams::kNone_FilterMode))
+ , fDomain(GrTextureDomain::IgnoredDomain()) {
+ convert_row_major_scalar_coeffs_to_column_major_floats(fCoefficients, coefficients);
+}
+
+GrBicubicEffect::GrBicubicEffect(GrTexture* texture,
+ const SkScalar coefficients[16],
+ const SkMatrix &matrix,
+ const SkRect& domain)
+ : INHERITED(texture, matrix, GrTextureParams(SkShader::kClamp_TileMode,
+ GrTextureParams::kNone_FilterMode))
+ , fDomain(domain, GrTextureDomain::kClamp_Mode) {
+ convert_row_major_scalar_coeffs_to_column_major_floats(fCoefficients, coefficients);
}
GrBicubicEffect::~GrBicubicEffect() {
@@ -133,7 +158,7 @@ bool GrBicubicEffect::onIsEqual(const GrEffect& sBase) const {
}
void GrBicubicEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
- // FIXME: Perhaps we can do better.
+ // FIXME: Perhaps we can do better.
*validFlags = 0;
return;
}
@@ -152,3 +177,36 @@ GrEffectRef* GrBicubicEffect::TestCreate(SkRandom* random,
}
return GrBicubicEffect::Create(textures[texIdx], coefficients);
}
+
+//////////////////////////////////////////////////////////////////////////////
+
+bool GrBicubicEffect::ShouldUseBicubic(const SkMatrix& matrix,
+ GrTextureParams::FilterMode* filterMode) {
+ if (matrix.isIdentity()) {
+ *filterMode = GrTextureParams::kNone_FilterMode;
+ return false;
+ }
+
+ SkScalar scales[2];
+ if (!matrix.getMinMaxScales(scales) || scales[0] < SK_Scalar1) {
+ // Bicubic doesn't handle arbitrary minimization well, as src texels can be skipped
+ // entirely,
+ *filterMode = GrTextureParams::kMipMap_FilterMode;
+ return false;
+ }
+ // At this point if scales[1] == SK_Scalar1 then the matrix doesn't do any scaling.
+ if (scales[1] == SK_Scalar1) {
+ if (matrix.rectStaysRect() && SkScalarIsInt(matrix.getTranslateX()) &&
+ SkScalarIsInt(matrix.getTranslateY())) {
+ *filterMode = GrTextureParams::kNone_FilterMode;
+ } else {
+ // Use bilerp to handle rotation or fractional translation.
+ *filterMode = GrTextureParams::kBilerp_FilterMode;
+ }
+ return false;
+ }
+ // When we use the bicubic filtering effect each sample is read from the texture using
+ // nearest neighbor sampling.
+ *filterMode = GrTextureParams::kNone_FilterMode;
+ return true;
+}
diff --git a/chromium/third_party/skia/src/gpu/effects/GrBicubicEffect.h b/chromium/third_party/skia/src/gpu/effects/GrBicubicEffect.h
index 85bec771b47..1998e68780c 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrBicubicEffect.h
+++ b/chromium/third_party/skia/src/gpu/effects/GrBicubicEffect.h
@@ -9,6 +9,7 @@
#define GrBicubicTextureEffect_DEFINED
#include "GrSingleTextureEffect.h"
+#include "GrTextureDomain.h"
#include "GrDrawEffect.h"
#include "gl/GrGLEffect.h"
#include "GrTBackendEffectFactory.h"
@@ -31,46 +32,71 @@ public:
virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
- /**
- * Create a simple Mitchell filter effect.
- */
- static GrEffectRef* Create(GrTexture* tex) {
- return Create(tex, gMitchellCoefficients);
- }
+ const GrTextureDomain& domain() const { return fDomain; }
/**
- * Create a simple filter effect with custom bicubic coefficients.
+ * Create a simple filter effect with custom bicubic coefficients and optional domain.
*/
- static GrEffectRef* Create(GrTexture* tex, const SkScalar coefficients[16]) {
- const SkShader::TileMode tm[] = { SkShader::kClamp_TileMode, SkShader::kClamp_TileMode };
- return Create(tex, coefficients, MakeDivByTextureWHMatrix(tex), tm);
+ static GrEffectRef* Create(GrTexture* tex, const SkScalar coefficients[16],
+ const SkRect* domain = NULL) {
+ if (NULL == domain) {
+ static const SkShader::TileMode kTileModes[] = { SkShader::kClamp_TileMode,
+ SkShader::kClamp_TileMode };
+ return Create(tex, coefficients, MakeDivByTextureWHMatrix(tex), kTileModes);
+ } else {
+ AutoEffectUnref effect(SkNEW_ARGS(GrBicubicEffect, (tex, coefficients,
+ MakeDivByTextureWHMatrix(tex),
+ *domain)));
+ return CreateEffectRef(effect);
+ }
}
/**
* Create a Mitchell filter effect with specified texture matrix and x/y tile modes.
*/
- static GrEffectRef* Create(GrTexture* tex,
- const SkMatrix& matrix,
+ static GrEffectRef* Create(GrTexture* tex, const SkMatrix& matrix,
SkShader::TileMode tileModes[2]) {
return Create(tex, gMitchellCoefficients, matrix, tileModes);
}
/**
- * The most general Create method. This allows specification of the bicubic coefficients, the
- * texture matrix, and the x/y tilemodes.
+ * Create a filter effect with custom bicubic coefficients, the texture matrix, and the x/y
+ * tilemodes.
*/
static GrEffectRef* Create(GrTexture* tex, const SkScalar coefficients[16],
- const SkMatrix& matrix,
- const SkShader::TileMode tileModes[2]) {
+ const SkMatrix& matrix, const SkShader::TileMode tileModes[2]) {
AutoEffectUnref effect(SkNEW_ARGS(GrBicubicEffect, (tex, coefficients, matrix, tileModes)));
return CreateEffectRef(effect);
}
+ /**
+ * Create a Mitchell filter effect with a texture matrix and a domain.
+ */
+ static GrEffectRef* Create(GrTexture* tex, const SkMatrix& matrix, const SkRect& domain) {
+ AutoEffectUnref effect(SkNEW_ARGS(GrBicubicEffect, (tex, gMitchellCoefficients, matrix,
+ domain)));
+ return CreateEffectRef(effect);
+ }
+
+ /**
+ * Determines whether the bicubic effect should be used based on the transformation from the
+ * local coords to the device. Returns true if the bicubic effect should be used. filterMode
+ * is set to appropriate filtering mode to use regardless of the return result (e.g. when this
+ * returns false it may indicate that the best fallback is to use kMipMap, kBilerp, or
+ * kNearest).
+ */
+ static bool ShouldUseBicubic(const SkMatrix& localCoordsToDevice,
+ GrTextureParams::FilterMode* filterMode);
+
private:
GrBicubicEffect(GrTexture*, const SkScalar coefficients[16],
const SkMatrix &matrix, const SkShader::TileMode tileModes[2]);
+ GrBicubicEffect(GrTexture*, const SkScalar coefficients[16],
+ const SkMatrix &matrix, const SkRect& domain);
virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
- float fCoefficients[16];
+
+ float fCoefficients[16];
+ GrTextureDomain fDomain;
GR_DECLARE_EFFECT_TEST;
diff --git a/chromium/third_party/skia/src/gpu/effects/GrConfigConversionEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrConfigConversionEffect.cpp
index daf51414f29..f33ad239c51 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrConfigConversionEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/GrConfigConversionEffect.cpp
@@ -61,7 +61,7 @@ public:
outputColor, outputColor, outputColor, swiz, outputColor, outputColor);
break;
default:
- GrCrash("Unknown conversion op.");
+ SkFAIL("Unknown conversion op.");
break;
}
}
@@ -154,9 +154,9 @@ void GrConfigConversionEffect::TestForPreservingPMConversions(GrContext* context
for (int x = 0; x < 256; ++x) {
uint8_t* color = reinterpret_cast<uint8_t*>(&srcData[256*y + x]);
color[3] = y;
- color[2] = GrMin(x, y);
- color[1] = GrMin(x, y);
- color[0] = GrMin(x, y);
+ color[2] = SkTMin(x, y);
+ color[1] = SkTMin(x, y);
+ color[0] = SkTMin(x, y);
}
}
@@ -190,7 +190,7 @@ void GrConfigConversionEffect::TestForPreservingPMConversions(GrContext* context
bool failed = true;
- for (size_t i = 0; i < GR_ARRAY_COUNT(kConversionRules) && failed; ++i) {
+ for (size_t i = 0; i < SK_ARRAY_COUNT(kConversionRules) && failed; ++i) {
*pmToUPMRule = kConversionRules[i][0];
*upmToPMRule = kConversionRules[i][1];
diff --git a/chromium/third_party/skia/src/gpu/effects/GrConvexPolyEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrConvexPolyEffect.cpp
new file mode 100644
index 00000000000..d24b45e10b5
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/effects/GrConvexPolyEffect.cpp
@@ -0,0 +1,374 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrConvexPolyEffect.h"
+
+#include "gl/GrGLEffect.h"
+#include "gl/GrGLSL.h"
+#include "GrTBackendEffectFactory.h"
+
+#include "SkPath.h"
+
+//////////////////////////////////////////////////////////////////////////////
+class GLAARectEffect;
+
+class AARectEffect : public GrEffect {
+public:
+ typedef GLAARectEffect GLEffect;
+
+ const SkRect& getRect() const { return fRect; }
+
+ static const char* Name() { return "AARect"; }
+
+ static GrEffectRef* Create(GrEffectEdgeType edgeType, const SkRect& rect) {
+ return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(AARectEffect, (edgeType, rect))));
+ }
+
+ virtual void getConstantColorComponents(GrColor* color,
+ uint32_t* validFlags) const SK_OVERRIDE {
+ if (fRect.isEmpty()) {
+ // An empty rect will have no coverage anywhere.
+ *color = 0x00000000;
+ *validFlags = kRGBA_GrColorComponentFlags;
+ } else {
+ *validFlags = 0;
+ }
+ }
+
+ GrEffectEdgeType getEdgeType() const { return fEdgeType; }
+
+ virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
+
+private:
+ AARectEffect(GrEffectEdgeType edgeType, const SkRect& rect) : fRect(rect), fEdgeType(edgeType) {
+ this->setWillReadFragmentPosition();
+ }
+
+ virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
+ const AARectEffect& aare = CastEffect<AARectEffect>(other);
+ return fRect == aare.fRect;
+ }
+
+ SkRect fRect;
+ GrEffectEdgeType fEdgeType;
+
+ typedef GrEffect INHERITED;
+
+ GR_DECLARE_EFFECT_TEST;
+
+};
+
+GR_DEFINE_EFFECT_TEST(AARectEffect);
+
+GrEffectRef* AARectEffect::TestCreate(SkRandom* random,
+ GrContext*,
+ const GrDrawTargetCaps& caps,
+ GrTexture*[]) {
+ SkRect rect = SkRect::MakeLTRB(random->nextSScalar1(),
+ random->nextSScalar1(),
+ random->nextSScalar1(),
+ random->nextSScalar1());
+ GrEffectRef* effect;
+ do {
+ GrEffectEdgeType edgeType = static_cast<GrEffectEdgeType>(random->nextULessThan(
+ kGrEffectEdgeTypeCnt));
+
+ effect = AARectEffect::Create(edgeType, rect);
+ } while (NULL == effect);
+ return effect;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+class GLAARectEffect : public GrGLEffect {
+public:
+ GLAARectEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
+
+ virtual void emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect& drawEffect,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray&) SK_OVERRIDE;
+
+ static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
+
+ virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
+
+private:
+ GrGLUniformManager::UniformHandle fRectUniform;
+ SkRect fPrevRect;
+ typedef GrGLEffect INHERITED;
+};
+
+GLAARectEffect::GLAARectEffect(const GrBackendEffectFactory& factory,
+ const GrDrawEffect& drawEffect)
+ : INHERITED (factory) {
+ fPrevRect.fLeft = SK_ScalarNaN;
+}
+
+void GLAARectEffect::emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect& drawEffect,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray& samplers) {
+ const AARectEffect& aare = drawEffect.castEffect<AARectEffect>();
+ const char *rectName;
+ // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5),
+ // respectively.
+ fRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kVec4f_GrSLType,
+ "rect",
+ &rectName);
+ const char* fragmentPos = builder->fragmentPosition();
+ if (GrEffectEdgeTypeIsAA(aare.getEdgeType())) {
+ // The amount of coverage removed in x and y by the edges is computed as a pair of negative
+ // numbers, xSub and ySub.
+ builder->fsCodeAppend("\t\tfloat xSub, ySub;\n");
+ builder->fsCodeAppendf("\t\txSub = min(%s.x - %s.x, 0.0);\n", fragmentPos, rectName);
+ builder->fsCodeAppendf("\t\txSub += min(%s.z - %s.x, 0.0);\n", rectName, fragmentPos);
+ builder->fsCodeAppendf("\t\tySub = min(%s.y - %s.y, 0.0);\n", fragmentPos, rectName);
+ builder->fsCodeAppendf("\t\tySub += min(%s.w - %s.y, 0.0);\n", rectName, fragmentPos);
+ // Now compute coverage in x and y and multiply them to get the fraction of the pixel
+ // covered.
+ builder->fsCodeAppendf("\t\tfloat alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n");
+ } else {
+ builder->fsCodeAppendf("\t\tfloat alpha = 1.0;\n");
+ builder->fsCodeAppendf("\t\talpha *= (%s.x - %s.x) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName);
+ builder->fsCodeAppendf("\t\talpha *= (%s.z - %s.x) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos);
+ builder->fsCodeAppendf("\t\talpha *= (%s.y - %s.y) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName);
+ builder->fsCodeAppendf("\t\talpha *= (%s.w - %s.y) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos);
+ }
+
+ if (GrEffectEdgeTypeIsInverseFill(aare.getEdgeType())) {
+ builder->fsCodeAppend("\t\talpha = 1.0 - alpha;\n");
+ }
+ builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor,
+ (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
+}
+
+void GLAARectEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) {
+ const AARectEffect& aare = drawEffect.castEffect<AARectEffect>();
+ const SkRect& rect = aare.getRect();
+ if (rect != fPrevRect) {
+ uman.set4f(fRectUniform, rect.fLeft + 0.5f, rect.fTop + 0.5f,
+ rect.fRight - 0.5f, rect.fBottom - 0.5f);
+ fPrevRect = rect;
+ }
+}
+
+GrGLEffect::EffectKey GLAARectEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
+ const AARectEffect& aare = drawEffect.castEffect<AARectEffect>();
+ return aare.getEdgeType();
+}
+
+const GrBackendEffectFactory& AARectEffect::getFactory() const {
+ return GrTBackendEffectFactory<AARectEffect>::getInstance();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+class GrGLConvexPolyEffect : public GrGLEffect {
+public:
+ GrGLConvexPolyEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
+
+ virtual void emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect& drawEffect,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray&) SK_OVERRIDE;
+
+ static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
+
+ virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
+
+private:
+ GrGLUniformManager::UniformHandle fEdgeUniform;
+ SkScalar fPrevEdges[3 * GrConvexPolyEffect::kMaxEdges];
+ typedef GrGLEffect INHERITED;
+};
+
+GrGLConvexPolyEffect::GrGLConvexPolyEffect(const GrBackendEffectFactory& factory,
+ const GrDrawEffect& drawEffect)
+ : INHERITED (factory) {
+ fPrevEdges[0] = SK_ScalarNaN;
+}
+
+void GrGLConvexPolyEffect::emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect& drawEffect,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray& samplers) {
+ const GrConvexPolyEffect& cpe = drawEffect.castEffect<GrConvexPolyEffect>();
+
+ const char *edgeArrayName;
+ fEdgeUniform = builder->addUniformArray(GrGLShaderBuilder::kFragment_Visibility,
+ kVec3f_GrSLType,
+ "edges",
+ cpe.getEdgeCount(),
+ &edgeArrayName);
+ builder->fsCodeAppend("\t\tfloat alpha = 1.0;\n");
+ builder->fsCodeAppend("\t\tfloat edge;\n");
+ const char* fragmentPos = builder->fragmentPosition();
+ for (int i = 0; i < cpe.getEdgeCount(); ++i) {
+ builder->fsCodeAppendf("\t\tedge = dot(%s[%d], vec3(%s.x, %s.y, 1));\n",
+ edgeArrayName, i, fragmentPos, fragmentPos);
+ if (GrEffectEdgeTypeIsAA(cpe.getEdgeType())) {
+ builder->fsCodeAppend("\t\tedge = clamp(edge, 0.0, 1.0);\n");
+ } else {
+ builder->fsCodeAppend("\t\tedge = edge >= 0.5 ? 1.0 : 0.0;\n");
+ }
+ builder->fsCodeAppend("\t\talpha *= edge;\n");
+ }
+
+ // Woe is me. See skbug.com/2149.
+ if (kTegra2_GrGLRenderer == builder->ctxInfo().renderer()) {
+ builder->fsCodeAppend("\t\tif (-1.0 == alpha) {\n\t\t\tdiscard;\n\t\t}\n");
+ }
+
+ if (GrEffectEdgeTypeIsInverseFill(cpe.getEdgeType())) {
+ builder->fsCodeAppend("\talpha = 1.0 - alpha;\n");
+ }
+ builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
+ (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
+}
+
+void GrGLConvexPolyEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) {
+ const GrConvexPolyEffect& cpe = drawEffect.castEffect<GrConvexPolyEffect>();
+ size_t byteSize = 3 * cpe.getEdgeCount() * sizeof(SkScalar);
+ if (0 != memcmp(fPrevEdges, cpe.getEdges(), byteSize)) {
+ uman.set3fv(fEdgeUniform, cpe.getEdgeCount(), cpe.getEdges());
+ memcpy(fPrevEdges, cpe.getEdges(), byteSize);
+ }
+}
+
+GrGLEffect::EffectKey GrGLConvexPolyEffect::GenKey(const GrDrawEffect& drawEffect,
+ const GrGLCaps&) {
+ const GrConvexPolyEffect& cpe = drawEffect.castEffect<GrConvexPolyEffect>();
+ GR_STATIC_ASSERT(kGrEffectEdgeTypeCnt <= 8);
+ return (cpe.getEdgeCount() << 3) | cpe.getEdgeType();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+GrEffectRef* GrConvexPolyEffect::Create(GrEffectEdgeType type, const SkPath& path, const SkVector* offset) {
+ if (kHairlineAA_GrEffectEdgeType == type) {
+ return NULL;
+ }
+ if (path.getSegmentMasks() != SkPath::kLine_SegmentMask ||
+ !path.isConvex()) {
+ return NULL;
+ }
+
+ if (path.countPoints() > kMaxEdges) {
+ return NULL;
+ }
+
+ SkPoint pts[kMaxEdges];
+ SkScalar edges[3 * kMaxEdges];
+
+ SkPath::Direction dir;
+ SkAssertResult(path.cheapComputeDirection(&dir));
+
+ SkVector t;
+ if (NULL == offset) {
+ t.set(0, 0);
+ } else {
+ t = *offset;
+ }
+
+ int count = path.getPoints(pts, kMaxEdges);
+ int n = 0;
+ for (int lastPt = count - 1, i = 0; i < count; lastPt = i++) {
+ if (pts[lastPt] != pts[i]) {
+ SkVector v = pts[i] - pts[lastPt];
+ v.normalize();
+ if (SkPath::kCCW_Direction == dir) {
+ edges[3 * n] = v.fY;
+ edges[3 * n + 1] = -v.fX;
+ } else {
+ edges[3 * n] = -v.fY;
+ edges[3 * n + 1] = v.fX;
+ }
+ SkPoint p = pts[i] + t;
+ edges[3 * n + 2] = -(edges[3 * n] * p.fX + edges[3 * n + 1] * p.fY);
+ ++n;
+ }
+ }
+ if (path.isInverseFillType()) {
+ type = GrInvertEffectEdgeType(type);
+ }
+ return Create(type, n, edges);
+}
+
+GrEffectRef* GrConvexPolyEffect::Create(GrEffectEdgeType edgeType, const SkRect& rect) {
+ if (kHairlineAA_GrEffectEdgeType == edgeType){
+ return NULL;
+ }
+ return AARectEffect::Create(edgeType, rect);
+}
+
+GrConvexPolyEffect::~GrConvexPolyEffect() {}
+
+void GrConvexPolyEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
+ *validFlags = 0;
+}
+
+const GrBackendEffectFactory& GrConvexPolyEffect::getFactory() const {
+ return GrTBackendEffectFactory<GrConvexPolyEffect>::getInstance();
+}
+
+GrConvexPolyEffect::GrConvexPolyEffect(GrEffectEdgeType edgeType, int n, const SkScalar edges[])
+ : fEdgeType(edgeType)
+ , fEdgeCount(n) {
+ // Factory function should have already ensured this.
+ SkASSERT(n <= kMaxEdges);
+ memcpy(fEdges, edges, 3 * n * sizeof(SkScalar));
+ // Outset the edges by 0.5 so that a pixel with center on an edge is 50% covered in the AA case
+ // and 100% covered in the non-AA case.
+ for (int i = 0; i < n; ++i) {
+ fEdges[3 * i + 2] += SK_ScalarHalf;
+ }
+ this->setWillReadFragmentPosition();
+}
+
+bool GrConvexPolyEffect::onIsEqual(const GrEffect& other) const {
+ const GrConvexPolyEffect& cpe = CastEffect<GrConvexPolyEffect>(other);
+ // ignore the fact that 0 == -0 and just use memcmp.
+ return (cpe.fEdgeType == fEdgeType && cpe.fEdgeCount == fEdgeCount &&
+ 0 == memcmp(cpe.fEdges, fEdges, 3 * fEdgeCount * sizeof(SkScalar)));
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+GR_DEFINE_EFFECT_TEST(GrConvexPolyEffect);
+
+GrEffectRef* GrConvexPolyEffect::TestCreate(SkRandom* random,
+ GrContext*,
+ const GrDrawTargetCaps& caps,
+ GrTexture*[]) {
+ int count = random->nextULessThan(kMaxEdges) + 1;
+ SkScalar edges[kMaxEdges * 3];
+ for (int i = 0; i < 3 * count; ++i) {
+ edges[i] = random->nextSScalar1();
+ }
+
+ GrEffectRef* effect;
+ do {
+ GrEffectEdgeType edgeType = static_cast<GrEffectEdgeType>(
+ random->nextULessThan(kGrEffectEdgeTypeCnt));
+ effect = GrConvexPolyEffect::Create(edgeType, count, edges);
+ } while (NULL == effect);
+ return effect;
+}
diff --git a/chromium/third_party/skia/src/gpu/effects/GrConvexPolyEffect.h b/chromium/third_party/skia/src/gpu/effects/GrConvexPolyEffect.h
new file mode 100644
index 00000000000..0e508c7c487
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/effects/GrConvexPolyEffect.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrConvexPolyEffect_DEFINED
+#define GrConvexPolyEffect_DEFINED
+
+#include "GrDrawTargetCaps.h"
+#include "GrEffect.h"
+#include "GrTypesPriv.h"
+
+class GrGLConvexPolyEffect;
+class SkPath;
+
+/**
+ * An effect that renders a convex polygon. It is intended to be used as a coverage effect.
+ * Bounding geometry is rendered and the effect computes coverage based on the fragment's
+ * position relative to the polygon.
+ */
+class GrConvexPolyEffect : public GrEffect {
+public:
+ enum {
+ kMaxEdges = 8,
+ };
+
+ /**
+ * edges is a set of n edge equations where n is limited to kMaxEdges. It contains 3*n values.
+ * The edges should form a convex polygon. The positive half-plane is considered to be the
+ * inside. The equations should be normalized such that the first two coefficients are a unit
+ * 2d vector.
+ *
+ * Currently the edges are specified in device space. In the future we may prefer to specify
+ * them in src space. There are a number of ways this could be accomplished but we'd probably
+ * have to modify the effect/shaderbuilder interface to make it possible (e.g. give access
+ * to the view matrix or untransformed positions in the fragment shader).
+ */
+ static GrEffectRef* Create(GrEffectEdgeType edgeType, int n, const SkScalar edges[]) {
+ if (n <= 0 || n > kMaxEdges || kHairlineAA_GrEffectEdgeType == edgeType) {
+ return NULL;
+ }
+ return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(GrConvexPolyEffect,
+ (edgeType, n, edges))));
+ }
+
+ /**
+ * Creates an effect that clips against the path. If the path is not a convex polygon, is
+ * inverse filled, or has too many edges, this will return NULL. If offset is non-NULL, then
+ * the path is translated by the vector.
+ */
+ static GrEffectRef* Create(GrEffectEdgeType, const SkPath&, const SkVector* offset = NULL);
+
+ /**
+ * Creates an effect that fills inside the rect with AA edges..
+ */
+ static GrEffectRef* Create(GrEffectEdgeType, const SkRect&);
+
+ virtual ~GrConvexPolyEffect();
+
+ static const char* Name() { return "ConvexPoly"; }
+
+ GrEffectEdgeType getEdgeType() const { return fEdgeType; }
+
+ int getEdgeCount() const { return fEdgeCount; }
+
+ const SkScalar* getEdges() const { return fEdges; }
+
+ typedef GrGLConvexPolyEffect GLEffect;
+
+ virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
+
+ virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
+
+private:
+ GrConvexPolyEffect(GrEffectEdgeType edgeType, int n, const SkScalar edges[]);
+
+ virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE;
+
+ GrEffectEdgeType fEdgeType;
+ int fEdgeCount;
+ SkScalar fEdges[3 * kMaxEdges];
+
+ GR_DECLARE_EFFECT_TEST;
+
+ typedef GrEffect INHERITED;
+};
+
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/effects/GrConvolutionEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrConvolutionEffect.cpp
index 57cdece9d82..aad7c878c98 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrConvolutionEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/GrConvolutionEffect.cpp
@@ -118,7 +118,7 @@ void GrGLConvolutionEffect::setData(const GrGLUniformManager& uman,
imageIncrement[1] = ySign / texture.height();
break;
default:
- GrCrash("Unknown filter direction.");
+ SkFAIL("Unknown filter direction.");
}
uman.set2fv(fImageIncrementUni, 1, imageIncrement);
if (conv.useBounds()) {
diff --git a/chromium/third_party/skia/src/gpu/effects/GrDashingEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrDashingEffect.cpp
new file mode 100644
index 00000000000..8d9c08f3f38
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/effects/GrDashingEffect.cpp
@@ -0,0 +1,628 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrDashingEffect.h"
+
+#include "../GrAARectRenderer.h"
+
+#include "effects/GrVertexEffect.h"
+#include "gl/GrGLEffect.h"
+#include "gl/GrGLVertexEffect.h"
+#include "gl/GrGLSL.h"
+#include "GrContext.h"
+#include "GrCoordTransform.h"
+#include "GrDrawTarget.h"
+#include "GrDrawTargetCaps.h"
+#include "GrEffect.h"
+#include "GrGpu.h"
+#include "GrStrokeInfo.h"
+#include "GrTBackendEffectFactory.h"
+#include "SkGr.h"
+
+///////////////////////////////////////////////////////////////////////////////
+
+// Returns whether or not the gpu can fast path the dash line effect.
+static bool can_fast_path_dash(const SkPoint pts[2], const GrStrokeInfo& strokeInfo,
+ const GrDrawTarget& target, const SkMatrix& viewMatrix) {
+ if (target.getDrawState().getRenderTarget()->isMultisampled()) {
+ return false;
+ }
+
+ // Pts must be either horizontal or vertical in src space
+ if (pts[0].fX != pts[1].fX && pts[0].fY != pts[1].fY) {
+ return false;
+ }
+
+ // May be able to relax this to include skew. As of now cannot do perspective
+ // because of the non uniform scaling of bloating a rect
+ if (!viewMatrix.preservesRightAngles()) {
+ return false;
+ }
+
+ if (!strokeInfo.isDashed() || 2 != strokeInfo.dashCount()) {
+ return false;
+ }
+
+ const SkPathEffect::DashInfo& info = strokeInfo.getDashInfo();
+ if (0 == info.fIntervals[0] && 0 == info.fIntervals[1]) {
+ return false;
+ }
+
+ SkPaint::Cap cap = strokeInfo.getStrokeRec().getCap();
+ // Current we do don't handle Round or Square cap dashes
+ if (SkPaint::kRound_Cap == cap) {
+ return false;
+ }
+
+ return true;
+}
+
+namespace {
+
+struct DashLineVertex {
+ SkPoint fPos;
+ SkPoint fDashPos;
+};
+
+extern const GrVertexAttrib gDashLineVertexAttribs[] = {
+ { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding },
+ { kVec2f_GrVertexAttribType, sizeof(SkPoint), kEffect_GrVertexAttribBinding },
+};
+
+};
+static void calc_dash_scaling(SkScalar* parallelScale, SkScalar* perpScale,
+ const SkMatrix& viewMatrix, const SkPoint pts[2]) {
+ SkVector vecSrc = pts[1] - pts[0];
+ SkScalar magSrc = vecSrc.length();
+ SkScalar invSrc = magSrc ? SkScalarInvert(magSrc) : 0;
+ vecSrc.scale(invSrc);
+
+ SkVector vecSrcPerp;
+ vecSrc.rotateCW(&vecSrcPerp);
+ viewMatrix.mapVectors(&vecSrc, 1);
+ viewMatrix.mapVectors(&vecSrcPerp, 1);
+
+ // parallelScale tells how much to scale along the line parallel to the dash line
+ // perpScale tells how much to scale in the direction perpendicular to the dash line
+ *parallelScale = vecSrc.length();
+ *perpScale = vecSrcPerp.length();
+}
+
+// calculates the rotation needed to aligned pts to the x axis with pts[0] < pts[1]
+// Stores the rotation matrix in rotMatrix, and the mapped points in ptsRot
+static void align_to_x_axis(const SkPoint pts[2], SkMatrix* rotMatrix, SkPoint ptsRot[2] = NULL) {
+ SkVector vec = pts[1] - pts[0];
+ SkScalar mag = vec.length();
+ SkScalar inv = mag ? SkScalarInvert(mag) : 0;
+
+ vec.scale(inv);
+ rotMatrix->setSinCos(-vec.fY, vec.fX, pts[0].fX, pts[0].fY);
+ if (ptsRot) {
+ rotMatrix->mapPoints(ptsRot, pts, 2);
+ // correction for numerical issues if map doesn't make ptsRot exactly horizontal
+ ptsRot[1].fY = pts[0].fY;
+ }
+}
+
+// Assumes phase < sum of all intervals
+static SkScalar calc_start_adjustment(const SkPathEffect::DashInfo& info) {
+ SkASSERT(info.fPhase < info.fIntervals[0] + info.fIntervals[1]);
+ if (info.fPhase >= info.fIntervals[0] && info.fPhase != 0) {
+ SkScalar srcIntervalLen = info.fIntervals[0] + info.fIntervals[1];
+ return srcIntervalLen - info.fPhase;
+ }
+ return 0;
+}
+
+static SkScalar calc_end_adjustment(const SkPathEffect::DashInfo& info, const SkPoint pts[2],
+ SkScalar phase, SkScalar* endingInt) {
+ if (pts[1].fX <= pts[0].fX) {
+ return 0;
+ }
+ SkScalar srcIntervalLen = info.fIntervals[0] + info.fIntervals[1];
+ SkScalar totalLen = pts[1].fX - pts[0].fX;
+ SkScalar temp = SkScalarDiv(totalLen, srcIntervalLen);
+ SkScalar numFullIntervals = SkScalarFloorToScalar(temp);
+ *endingInt = totalLen - numFullIntervals * srcIntervalLen + phase;
+ temp = SkScalarDiv(*endingInt, srcIntervalLen);
+ *endingInt = *endingInt - SkScalarFloorToScalar(temp) * srcIntervalLen;
+ if (0 == *endingInt) {
+ *endingInt = srcIntervalLen;
+ }
+ if (*endingInt > info.fIntervals[0]) {
+ if (0 == info.fIntervals[0]) {
+ *endingInt -= 0.01f; // make sure we capture the last zero size pnt (used if has caps)
+ }
+ return *endingInt - info.fIntervals[0];
+ }
+ return 0;
+}
+
+static void setup_dashed_rect(const SkRect& rect, DashLineVertex* verts, int idx, const SkMatrix& matrix,
+ SkScalar offset, SkScalar bloat, SkScalar len, SkScalar stroke) {
+
+ SkScalar startDashX = offset - bloat;
+ SkScalar endDashX = offset + len + bloat;
+ SkScalar startDashY = -stroke - bloat;
+ SkScalar endDashY = stroke + bloat;
+ verts[idx].fDashPos = SkPoint::Make(startDashX , startDashY);
+ verts[idx + 1].fDashPos = SkPoint::Make(startDashX, endDashY);
+ verts[idx + 2].fDashPos = SkPoint::Make(endDashX, endDashY);
+ verts[idx + 3].fDashPos = SkPoint::Make(endDashX, startDashY);
+
+ verts[idx].fPos = SkPoint::Make(rect.fLeft, rect.fTop);
+ verts[idx + 1].fPos = SkPoint::Make(rect.fLeft, rect.fBottom);
+ verts[idx + 2].fPos = SkPoint::Make(rect.fRight, rect.fBottom);
+ verts[idx + 3].fPos = SkPoint::Make(rect.fRight, rect.fTop);
+
+ matrix.mapPointsWithStride(&verts[idx].fPos, sizeof(DashLineVertex), 4);
+}
+
+
+bool GrDashingEffect::DrawDashLine(const SkPoint pts[2], const GrPaint& paint,
+ const GrStrokeInfo& strokeInfo, GrGpu* gpu,
+ GrDrawTarget* target, const SkMatrix& vm) {
+
+ if (!can_fast_path_dash(pts, strokeInfo, *target, vm)) {
+ return false;
+ }
+
+ const SkPathEffect::DashInfo& info = strokeInfo.getDashInfo();
+
+ SkPaint::Cap cap = strokeInfo.getStrokeRec().getCap();
+
+ SkScalar srcStrokeWidth = strokeInfo.getStrokeRec().getWidth();
+
+ // the phase should be normalized to be [0, sum of all intervals)
+ SkASSERT(info.fPhase >= 0 && info.fPhase < info.fIntervals[0] + info.fIntervals[1]);
+
+ SkScalar srcPhase = info.fPhase;
+
+ // Rotate the src pts so they are aligned horizontally with pts[0].fX < pts[1].fX
+ SkMatrix srcRotInv;
+ SkPoint ptsRot[2];
+ if (pts[0].fY != pts[1].fY || pts[0].fX > pts[1].fX) {
+ SkMatrix rotMatrix;
+ align_to_x_axis(pts, &rotMatrix, ptsRot);
+ if(!rotMatrix.invert(&srcRotInv)) {
+ GrPrintf("Failed to create invertible rotation matrix!\n");
+ return false;
+ }
+ } else {
+ srcRotInv.reset();
+ memcpy(ptsRot, pts, 2 * sizeof(SkPoint));
+ }
+
+ bool useAA = paint.isAntiAlias();
+
+ // Scale corrections of intervals and stroke from view matrix
+ SkScalar parallelScale;
+ SkScalar perpScale;
+ calc_dash_scaling(&parallelScale, &perpScale, vm, ptsRot);
+
+ bool hasCap = SkPaint::kSquare_Cap == cap && 0 != srcStrokeWidth;
+
+ // We always want to at least stroke out half a pixel on each side in device space
+ // so 0.5f / perpScale gives us this min in src space
+ SkScalar halfSrcStroke = SkMaxScalar(srcStrokeWidth * 0.5f, 0.5f / perpScale);
+
+ SkScalar strokeAdj;
+ if (!hasCap) {
+ strokeAdj = 0.f;
+ } else {
+ strokeAdj = halfSrcStroke;
+ }
+
+ SkScalar startAdj = 0;
+
+ SkMatrix combinedMatrix = srcRotInv;
+ combinedMatrix.postConcat(vm);
+
+ bool lineDone = false;
+ SkRect startRect;
+ bool hasStartRect = false;
+ // If we are using AA, check to see if we are drawing a partial dash at the start. If so
+ // draw it separately here and adjust our start point accordingly
+ if (useAA) {
+ if (srcPhase > 0 && srcPhase < info.fIntervals[0]) {
+ SkPoint startPts[2];
+ startPts[0] = ptsRot[0];
+ startPts[1].fY = startPts[0].fY;
+ startPts[1].fX = SkMinScalar(startPts[0].fX + info.fIntervals[0] - srcPhase,
+ ptsRot[1].fX);
+ startRect.set(startPts, 2);
+ startRect.outset(strokeAdj, halfSrcStroke);
+
+ hasStartRect = true;
+ startAdj = info.fIntervals[0] + info.fIntervals[1] - srcPhase;
+ }
+ }
+
+ // adjustments for start and end of bounding rect so we only draw dash intervals
+ // contained in the original line segment.
+ startAdj += calc_start_adjustment(info);
+ if (startAdj != 0) {
+ ptsRot[0].fX += startAdj;
+ srcPhase = 0;
+ }
+ SkScalar endingInterval = 0;
+ SkScalar endAdj = calc_end_adjustment(info, ptsRot, srcPhase, &endingInterval);
+ ptsRot[1].fX -= endAdj;
+ if (ptsRot[0].fX >= ptsRot[1].fX) {
+ lineDone = true;
+ }
+
+ SkRect endRect;
+ bool hasEndRect = false;
+ // If we are using AA, check to see if we are drawing a partial dash at then end. If so
+ // draw it separately here and adjust our end point accordingly
+ if (useAA && !lineDone) {
+ // If we adjusted the end then we will not be drawing a partial dash at the end.
+ // If we didn't adjust the end point then we just need to make sure the ending
+ // dash isn't a full dash
+ if (0 == endAdj && endingInterval != info.fIntervals[0]) {
+ SkPoint endPts[2];
+ endPts[1] = ptsRot[1];
+ endPts[0].fY = endPts[1].fY;
+ endPts[0].fX = endPts[1].fX - endingInterval;
+
+ endRect.set(endPts, 2);
+ endRect.outset(strokeAdj, halfSrcStroke);
+
+ hasEndRect = true;
+ endAdj = endingInterval + info.fIntervals[1];
+
+ ptsRot[1].fX -= endAdj;
+ if (ptsRot[0].fX >= ptsRot[1].fX) {
+ lineDone = true;
+ }
+ }
+ }
+
+ if (startAdj != 0) {
+ srcPhase = 0;
+ }
+
+ // Change the dashing info from src space into device space
+ SkScalar devIntervals[2];
+ devIntervals[0] = info.fIntervals[0] * parallelScale;
+ devIntervals[1] = info.fIntervals[1] * parallelScale;
+ SkScalar devPhase = srcPhase * parallelScale;
+ SkScalar strokeWidth = srcStrokeWidth * perpScale;
+
+ if ((strokeWidth < 1.f && !useAA) || 0.f == strokeWidth) {
+ strokeWidth = 1.f;
+ }
+
+ SkScalar halfDevStroke = strokeWidth * 0.5f;
+
+ if (SkPaint::kSquare_Cap == cap && 0 != srcStrokeWidth) {
+ // add cap to on interveal and remove from off interval
+ devIntervals[0] += strokeWidth;
+ devIntervals[1] -= strokeWidth;
+ }
+ SkScalar startOffset = devIntervals[1] * 0.5f + devPhase;
+
+ SkScalar bloatX = useAA ? 0.5f / parallelScale : 0.f;
+ SkScalar bloatY = useAA ? 0.5f / perpScale : 0.f;
+
+ SkScalar devBloat = useAA ? 0.5f : 0.f;
+
+ GrDrawState* drawState = target->drawState();
+ if (devIntervals[1] <= 0.f && useAA) {
+ // Case when we end up drawing a solid AA rect
+ // Reset the start rect to draw this single solid rect
+ // but it requires to upload a new intervals uniform so we can mimic
+ // one giant dash
+ ptsRot[0].fX -= hasStartRect ? startAdj : 0;
+ ptsRot[1].fX += hasEndRect ? endAdj : 0;
+ startRect.set(ptsRot, 2);
+ startRect.outset(strokeAdj, halfSrcStroke);
+ hasStartRect = true;
+ hasEndRect = false;
+ lineDone = true;
+
+ SkPoint devicePts[2];
+ vm.mapPoints(devicePts, ptsRot, 2);
+ SkScalar lineLength = SkPoint::Distance(devicePts[0], devicePts[1]);
+ if (hasCap) {
+ lineLength += 2.f * halfDevStroke;
+ }
+ devIntervals[0] = lineLength;
+ }
+ if (devIntervals[1] > 0.f || useAA) {
+ SkPathEffect::DashInfo devInfo;
+ devInfo.fPhase = devPhase;
+ devInfo.fCount = 2;
+ devInfo.fIntervals = devIntervals;
+ GrEffectEdgeType edgeType= useAA ? kFillAA_GrEffectEdgeType :
+ kFillBW_GrEffectEdgeType;
+ drawState->addCoverageEffect(
+ GrDashingEffect::Create(edgeType, devInfo, strokeWidth), 1)->unref();
+ }
+
+ // Set up the vertex data for the line and start/end dashes
+ drawState->setVertexAttribs<gDashLineVertexAttribs>(SK_ARRAY_COUNT(gDashLineVertexAttribs));
+
+ int totalRectCnt = 0;
+
+ totalRectCnt += !lineDone ? 1 : 0;
+ totalRectCnt += hasStartRect ? 1 : 0;
+ totalRectCnt += hasEndRect ? 1 : 0;
+
+ GrDrawTarget::AutoReleaseGeometry geo(target, totalRectCnt * 4, 0);
+ if (!geo.succeeded()) {
+ GrPrintf("Failed to get space for vertices!\n");
+ return false;
+ }
+
+ DashLineVertex* verts = reinterpret_cast<DashLineVertex*>(geo.vertices());
+
+ int curVIdx = 0;
+
+ // Draw interior part of dashed line
+ if (!lineDone) {
+ SkPoint devicePts[2];
+ vm.mapPoints(devicePts, ptsRot, 2);
+ SkScalar lineLength = SkPoint::Distance(devicePts[0], devicePts[1]);
+ if (hasCap) {
+ lineLength += 2.f * halfDevStroke;
+ }
+
+ SkRect bounds;
+ bounds.set(ptsRot[0].fX, ptsRot[0].fY, ptsRot[1].fX, ptsRot[1].fY);
+ bounds.outset(bloatX + strokeAdj, bloatY + halfSrcStroke);
+ setup_dashed_rect(bounds, verts, curVIdx, combinedMatrix, startOffset, devBloat,
+ lineLength, halfDevStroke);
+ curVIdx += 4;
+ }
+
+ if (hasStartRect) {
+ SkASSERT(useAA); // so that we know bloatX and bloatY have been set
+ startRect.outset(bloatX, bloatY);
+ setup_dashed_rect(startRect, verts, curVIdx, combinedMatrix, startOffset, devBloat,
+ devIntervals[0], halfDevStroke);
+ curVIdx += 4;
+ }
+
+ if (hasEndRect) {
+ SkASSERT(useAA); // so that we know bloatX and bloatY have been set
+ endRect.outset(bloatX, bloatY);
+ setup_dashed_rect(endRect, verts, curVIdx, combinedMatrix, startOffset, devBloat,
+ devIntervals[0], halfDevStroke);
+ }
+
+ target->setIndexSourceToBuffer(gpu->getContext()->getQuadIndexBuffer());
+ target->drawIndexedInstances(kTriangles_GrPrimitiveType, totalRectCnt, 4, 6);
+ target->resetIndexSource();
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+class GLDashingLineEffect;
+
+class DashingLineEffect : public GrVertexEffect {
+public:
+ typedef SkPathEffect::DashInfo DashInfo;
+
+ /**
+ * The effect calculates the coverage for the case of a horizontal line in device space.
+ * The matrix that is passed in should be able to convert a line in source space to a
+ * horizontal line in device space. Additionally, the coord transform matrix should translate
+ * the the start of line to origin, and the shift it along the positive x-axis by the phase
+ * and half the off interval.
+ */
+ static GrEffectRef* Create(GrEffectEdgeType edgeType, const DashInfo& info,
+ SkScalar strokeWidth);
+
+ virtual ~DashingLineEffect();
+
+ static const char* Name() { return "DashingEffect"; }
+
+ GrEffectEdgeType getEdgeType() const { return fEdgeType; }
+
+ const SkRect& getRect() const { return fRect; }
+
+ SkScalar getIntervalLength() const { return fIntervalLength; }
+
+ typedef GLDashingLineEffect GLEffect;
+
+ virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
+
+ virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
+
+private:
+ DashingLineEffect(GrEffectEdgeType edgeType, const DashInfo& info, SkScalar strokeWidth);
+
+ virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE;
+
+ GrEffectEdgeType fEdgeType;
+ SkRect fRect;
+ SkScalar fIntervalLength;
+
+ GR_DECLARE_EFFECT_TEST;
+
+ typedef GrEffect INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+class GLDashingLineEffect : public GrGLVertexEffect {
+public:
+ GLDashingLineEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
+
+ virtual void emitCode(GrGLFullShaderBuilder* builder,
+ const GrDrawEffect& drawEffect,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray&) SK_OVERRIDE;
+
+ static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
+
+ virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
+
+private:
+ GrGLUniformManager::UniformHandle fRectUniform;
+ GrGLUniformManager::UniformHandle fIntervalUniform;
+ SkRect fPrevRect;
+ SkScalar fPrevIntervalLength;
+ typedef GrGLVertexEffect INHERITED;
+};
+
+GLDashingLineEffect::GLDashingLineEffect(const GrBackendEffectFactory& factory,
+ const GrDrawEffect& drawEffect)
+ : INHERITED (factory) {
+ fPrevRect.fLeft = SK_ScalarNaN;
+ fPrevIntervalLength = SK_ScalarMax;
+
+}
+
+void GLDashingLineEffect::emitCode(GrGLFullShaderBuilder* builder,
+ const GrDrawEffect& drawEffect,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray& samplers) {
+ const DashingLineEffect& de = drawEffect.castEffect<DashingLineEffect>();
+ const char *rectName;
+ // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5),
+ // respectively.
+ fRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kVec4f_GrSLType,
+ "rect",
+ &rectName);
+ const char *intervalName;
+ // The interval uniform's refers to the total length of the interval (on + off)
+ fIntervalUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kFloat_GrSLType,
+ "interval",
+ &intervalName);
+
+ const char *vsCoordName, *fsCoordName;
+ builder->addVarying(kVec2f_GrSLType, "Coord", &vsCoordName, &fsCoordName);
+ const SkString* attr0Name =
+ builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
+ builder->vsCodeAppendf("\t%s = %s;\n", vsCoordName, attr0Name->c_str());
+
+ // transforms all points so that we can compare them to our test rect
+ builder->fsCodeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s) * %s;\n",
+ fsCoordName, fsCoordName, intervalName, intervalName);
+ builder->fsCodeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n", fsCoordName);
+ if (GrEffectEdgeTypeIsAA(de.getEdgeType())) {
+ // The amount of coverage removed in x and y by the edges is computed as a pair of negative
+ // numbers, xSub and ySub.
+ builder->fsCodeAppend("\t\tfloat xSub, ySub;\n");
+ builder->fsCodeAppendf("\t\txSub = min(fragPosShifted.x - %s.x, 0.0);\n", rectName);
+ builder->fsCodeAppendf("\t\txSub += min(%s.z - fragPosShifted.x, 0.0);\n", rectName);
+ builder->fsCodeAppendf("\t\tySub = min(fragPosShifted.y - %s.y, 0.0);\n", rectName);
+ builder->fsCodeAppendf("\t\tySub += min(%s.w - fragPosShifted.y, 0.0);\n", rectName);
+ // Now compute coverage in x and y and multiply them to get the fraction of the pixel
+ // covered.
+ builder->fsCodeAppendf("\t\tfloat alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n");
+ } else {
+ // Assuming the bounding geometry is tight so no need to check y values
+ builder->fsCodeAppendf("\t\tfloat alpha = 1.0;\n");
+ builder->fsCodeAppendf("\t\talpha *= (fragPosShifted.x - %s.x) > -0.5 ? 1.0 : 0.0;\n", rectName);
+ builder->fsCodeAppendf("\t\talpha *= (%s.z - fragPosShifted.x) >= -0.5 ? 1.0 : 0.0;\n", rectName);
+ }
+ builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor,
+ (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
+}
+
+void GLDashingLineEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) {
+ const DashingLineEffect& de = drawEffect.castEffect<DashingLineEffect>();
+ const SkRect& rect = de.getRect();
+ SkScalar intervalLength = de.getIntervalLength();
+ if (rect != fPrevRect || intervalLength != fPrevIntervalLength) {
+ uman.set4f(fRectUniform, rect.fLeft + 0.5f, rect.fTop + 0.5f,
+ rect.fRight - 0.5f, rect.fBottom - 0.5f);
+ uman.set1f(fIntervalUniform, intervalLength);
+ fPrevRect = rect;
+ fPrevIntervalLength = intervalLength;
+ }
+}
+
+GrGLEffect::EffectKey GLDashingLineEffect::GenKey(const GrDrawEffect& drawEffect,
+ const GrGLCaps&) {
+ const DashingLineEffect& de = drawEffect.castEffect<DashingLineEffect>();
+ return de.getEdgeType();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+GrEffectRef* DashingLineEffect::Create(GrEffectEdgeType edgeType, const DashInfo& info,
+ SkScalar strokeWidth) {
+ if (info.fCount != 2) {
+ return NULL;
+ }
+
+ return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(DashingLineEffect,
+ (edgeType, info, strokeWidth))));
+}
+
+DashingLineEffect::~DashingLineEffect() {}
+
+void DashingLineEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
+ *validFlags = 0;
+}
+
+const GrBackendEffectFactory& DashingLineEffect::getFactory() const {
+ return GrTBackendEffectFactory<DashingLineEffect>::getInstance();
+}
+
+DashingLineEffect::DashingLineEffect(GrEffectEdgeType edgeType, const DashInfo& info,
+ SkScalar strokeWidth)
+ : fEdgeType(edgeType) {
+ SkScalar onLen = info.fIntervals[0];
+ SkScalar offLen = info.fIntervals[1];
+ SkScalar halfOffLen = SkScalarHalf(offLen);
+ SkScalar halfStroke = SkScalarHalf(strokeWidth);
+ fIntervalLength = onLen + offLen;
+ fRect.set(halfOffLen, -halfStroke, halfOffLen + onLen, halfStroke);
+
+ this->addVertexAttrib(kVec2f_GrSLType);
+}
+
+bool DashingLineEffect::onIsEqual(const GrEffect& other) const {
+ const DashingLineEffect& de = CastEffect<DashingLineEffect>(other);
+ return (fEdgeType == de.fEdgeType &&
+ fRect == de.fRect &&
+ fIntervalLength == de.fIntervalLength);
+}
+
+GR_DEFINE_EFFECT_TEST(DashingLineEffect);
+
+GrEffectRef* DashingLineEffect::TestCreate(SkRandom* random,
+ GrContext*,
+ const GrDrawTargetCaps& caps,
+ GrTexture*[]) {
+ GrEffectRef* effect;
+ GrEffectEdgeType edgeType = static_cast<GrEffectEdgeType>(random->nextULessThan(
+ kGrEffectEdgeTypeCnt));
+ SkScalar strokeWidth = random->nextRangeScalar(0, 100.f);
+ DashInfo info;
+ info.fCount = 2;
+ SkAutoTArray<SkScalar> intervals(info.fCount);
+ info.fIntervals = intervals.get();
+ info.fIntervals[0] = random->nextRangeScalar(0, 10.f);
+ info.fIntervals[1] = random->nextRangeScalar(0, 10.f);
+ info.fPhase = random->nextRangeScalar(0, info.fIntervals[0] + info.fIntervals[1]);
+
+ effect = DashingLineEffect::Create(edgeType, info, strokeWidth);
+ return effect;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+GrEffectRef* GrDashingEffect::Create(GrEffectEdgeType edgeType, const SkPathEffect::DashInfo& info,
+ SkScalar strokeWidth) {
+ return DashingLineEffect::Create(edgeType, info, strokeWidth);
+}
diff --git a/chromium/third_party/skia/src/gpu/effects/GrDashingEffect.h b/chromium/third_party/skia/src/gpu/effects/GrDashingEffect.h
new file mode 100644
index 00000000000..809601778f2
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/effects/GrDashingEffect.h
@@ -0,0 +1,37 @@
+
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrDashingEffect_DEFINED
+#define GrDashingEffect_DEFINED
+
+#include "GrTypesPriv.h"
+#include "SkPathEffect.h"
+
+class GrGpu;
+class GrDrawTarget;
+class GrPaint;
+class GrStrokeInfo;
+
+class GrGLDashingEffect;
+class SkPath;
+
+namespace GrDashingEffect {
+ bool DrawDashLine(const SkPoint pts[2], const GrPaint& paint, const GrStrokeInfo& strokeInfo,
+ GrGpu* gpu, GrDrawTarget* target, const SkMatrix& vm);
+
+ /**
+ * An effect that renders a dashed line. It is intended to be used as a coverage effect.
+ * The effect is meant for dashed lines that only have a single on/off interval pair.
+ * Bounding geometry is rendered and the effect computes coverage based on the fragment's
+ * position relative to the dashed line.
+ */
+ GrEffectRef* Create(GrEffectEdgeType edgeType, const SkPathEffect::DashInfo& info,
+ SkScalar strokeWidth);
+}
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/effects/GrDistanceFieldTextureEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrDistanceFieldTextureEffect.cpp
index 8c38f9bebf9..29f09851078 100755
--- a/chromium/third_party/skia/src/gpu/effects/GrDistanceFieldTextureEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/GrDistanceFieldTextureEffect.cpp
@@ -13,14 +13,27 @@
#include "GrTBackendEffectFactory.h"
#include "GrTexture.h"
-// The distance field is constructed as unsigned char values, so that the zero value is at 128.
-// Hence our zero threshold is 128/255.
-#define THRESHOLD "0.50196078431"
+#include "SkDistanceFieldGen.h"
+
+// To get optical sizes people don't complain about when we blit correctly,
+// we need to slightly bold each glyph. On the Mac, we need a larger bold value.
+#if defined(SK_BUILD_FOR_MAC)
+#define SK_DistanceFieldLCDFactor "0.33"
+#define SK_DistanceFieldNonLCDFactor "0.25"
+#else
+#define SK_DistanceFieldLCDFactor "0.05"
+#define SK_DistanceFieldNonLCDFactor "0.05"
+#endif
+
+// Assuming a radius of the diagonal of the fragment, hence a factor of sqrt(2)/2
+#define SK_DistanceFieldAAFactor "0.7071"
class GrGLDistanceFieldTextureEffect : public GrGLVertexEffect {
public:
- GrGLDistanceFieldTextureEffect(const GrBackendEffectFactory& factory, const GrDrawEffect& drawEffect)
- : INHERITED (factory) {}
+ GrGLDistanceFieldTextureEffect(const GrBackendEffectFactory& factory,
+ const GrDrawEffect& drawEffect)
+ : INHERITED (factory)
+ , fTextureSize(SkISize::Make(-1,-1)) {}
virtual void emitCode(GrGLFullShaderBuilder* builder,
const GrDrawEffect& drawEffect,
@@ -31,44 +44,145 @@ public:
const TextureSamplerArray& samplers) SK_OVERRIDE {
SkASSERT(1 == drawEffect.castEffect<GrDistanceFieldTextureEffect>().numVertexAttribs());
+ SkAssertResult(builder->enableFeature(GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
+ const GrDistanceFieldTextureEffect& dfTexEffect =
+ drawEffect.castEffect<GrDistanceFieldTextureEffect>();
+
SkString fsCoordName;
- const char* vsVaryingName;
- const char* fsVaryingNamePtr;
- builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsVaryingName, &fsVaryingNamePtr);
- fsCoordName = fsVaryingNamePtr;
+ const char* vsCoordName;
+ const char* fsCoordNamePtr;
+ builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fsCoordNamePtr);
+ fsCoordName = fsCoordNamePtr;
- const char* attrName =
+ const char* attrName0 =
builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0])->c_str();
- builder->vsCodeAppendf("\t%s = %s;\n", vsVaryingName, attrName);
+ builder->vsCodeAppendf("\t%s = %s;\n", vsCoordName, attrName0);
+
+ const char* textureSizeUniName = NULL;
+ fTextureSizeUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kVec2f_GrSLType, "TextureSize",
+ &textureSizeUniName);
builder->fsCodeAppend("\tvec4 texColor = ");
builder->fsAppendTextureLookup(samplers[0],
fsCoordName.c_str(),
kVec2f_GrSLType);
builder->fsCodeAppend(";\n");
- builder->fsCodeAppend("\tfloat distance = texColor.r;\n");
- // this gives us a smooth step across approximately one fragment
- // (assuming a radius of the diagonal of the fragment, hence a factor of sqrt(2)/2)
- builder->fsCodeAppend("\tfloat afwidth = 0.7071*length(vec2(dFdx(distance), dFdy(distance)));\n");
- builder->fsCodeAppend("\tfloat val = smoothstep("THRESHOLD"-afwidth, "THRESHOLD"+afwidth, distance);\n");
+ builder->fsCodeAppend("\tfloat distance = "
+ SK_DistanceFieldMultiplier "*(texColor.r - " SK_DistanceFieldThreshold ")"
+ "+ " SK_DistanceFieldNonLCDFactor ";\n");
+
+ // we adjust for the effect of the transformation on the distance by using
+ // the length of the gradient of the texture coordinates. We use st coordinates
+ // to ensure we're mapping 1:1 from texel space to pixel space.
+ builder->fsCodeAppendf("\tvec2 uv = %s;\n", fsCoordName.c_str());
+ builder->fsCodeAppendf("\tvec2 st = uv*%s;\n", textureSizeUniName);
+ builder->fsCodeAppend("\tfloat afwidth;\n");
+ if (dfTexEffect.isSimilarity()) {
+ // this gives us a smooth step across approximately one fragment
+ builder->fsCodeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*dFdx(st.x);\n");
+ } else {
+ builder->fsCodeAppend("\tvec2 Jdx = dFdx(st);\n");
+ builder->fsCodeAppend("\tvec2 Jdy = dFdy(st);\n");
+
+ builder->fsCodeAppend("\tvec2 uv_grad;\n");
+ if (builder->ctxInfo().caps()->dropsTileOnZeroDivide()) {
+ // this is to compensate for the Adreno, which likes to drop tiles on division by 0
+ builder->fsCodeAppend("\tfloat uv_len2 = dot(uv, uv);\n");
+ builder->fsCodeAppend("\tif (uv_len2 < 0.0001) {\n");
+ builder->fsCodeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n");
+ builder->fsCodeAppend("\t} else {\n");
+ builder->fsCodeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n");
+ builder->fsCodeAppend("\t}\n");
+ } else {
+ builder->fsCodeAppend("\tuv_grad = normalize(uv);\n");
+ }
+ builder->fsCodeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*Jdy.x,\n");
+ builder->fsCodeAppend("\t uv_grad.x*Jdx.y + uv_grad.y*Jdy.y);\n");
+
+ // this gives us a smooth step across approximately one fragment
+ builder->fsCodeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*length(grad);\n");
+ }
+ builder->fsCodeAppend("\tfloat val = smoothstep(-afwidth, afwidth, distance);\n");
+
+#ifdef SK_GAMMA_APPLY_TO_A8
+ // adjust based on gamma
+ const char* luminanceUniName = NULL;
+ // width, height, 1/(3*width)
+ fLuminanceUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kFloat_GrSLType, "Luminance",
+ &luminanceUniName);
+
+ builder->fsCodeAppendf("\tuv = vec2(val, %s);\n", luminanceUniName);
+ builder->fsCodeAppend("\tvec4 gammaColor = ");
+ builder->fsAppendTextureLookup(samplers[1], "uv", kVec2f_GrSLType);
+ builder->fsCodeAppend(";\n");
+ builder->fsCodeAppend("\tval = gammaColor.r;\n");
+#endif
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
(GrGLSLExpr4(inputColor) * GrGLSLExpr1("val")).c_str());
}
virtual void setData(const GrGLUniformManager& uman,
- const GrDrawEffect& drawEffect) SK_OVERRIDE {}
+ const GrDrawEffect& drawEffect) SK_OVERRIDE {
+ SkASSERT(fTextureSizeUni.isValid());
+
+ GrTexture* texture = drawEffect.effect()->get()->texture(0);
+ if (texture->width() != fTextureSize.width() ||
+ texture->height() != fTextureSize.height()) {
+ fTextureSize = SkISize::Make(texture->width(), texture->height());
+ uman.set2f(fTextureSizeUni,
+ SkIntToScalar(fTextureSize.width()),
+ SkIntToScalar(fTextureSize.height()));
+ }
+#ifdef SK_GAMMA_APPLY_TO_A8
+ const GrDistanceFieldTextureEffect& dfTexEffect =
+ drawEffect.castEffect<GrDistanceFieldTextureEffect>();
+ float luminance = dfTexEffect.getLuminance();
+ if (luminance != fLuminance) {
+ uman.set1f(fLuminanceUni, luminance);
+ fLuminance = luminance;
+ }
+#endif
+ }
+
+ static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
+ const GrDistanceFieldTextureEffect& dfTexEffect =
+ drawEffect.castEffect<GrDistanceFieldTextureEffect>();
+
+ return dfTexEffect.isSimilarity() ? 0x1 : 0x0;
+ }
private:
+ GrGLUniformManager::UniformHandle fTextureSizeUni;
+ SkISize fTextureSize;
+ GrGLUniformManager::UniformHandle fLuminanceUni;
+ float fLuminance;
+
typedef GrGLVertexEffect INHERITED;
};
///////////////////////////////////////////////////////////////////////////////
GrDistanceFieldTextureEffect::GrDistanceFieldTextureEffect(GrTexture* texture,
- const GrTextureParams& params)
- : fTextureAccess(texture, params) {
+ const GrTextureParams& params,
+#ifdef SK_GAMMA_APPLY_TO_A8
+ GrTexture* gamma,
+ const GrTextureParams& gammaParams,
+ float luminance,
+#endif
+ bool similarity)
+ : fTextureAccess(texture, params)
+#ifdef SK_GAMMA_APPLY_TO_A8
+ , fGammaTextureAccess(gamma, gammaParams)
+ , fLuminance(luminance)
+#endif
+ , fIsSimilarity(similarity) {
this->addTextureAccess(&fTextureAccess);
+#ifdef SK_GAMMA_APPLY_TO_A8
+ this->addTextureAccess(&fGammaTextureAccess);
+#endif
this->addVertexAttrib(kVec2f_GrSLType);
}
@@ -101,6 +215,10 @@ GrEffectRef* GrDistanceFieldTextureEffect::TestCreate(SkRandom* random,
GrTexture* textures[]) {
int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx :
GrEffectUnitTest::kAlphaTextureIdx;
+#ifdef SK_GAMMA_APPLY_TO_A8
+ int texIdx2 = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx :
+ GrEffectUnitTest::kAlphaTextureIdx;
+#endif
static const SkShader::TileMode kTileModes[] = {
SkShader::kClamp_TileMode,
SkShader::kRepeat_TileMode,
@@ -112,6 +230,271 @@ GrEffectRef* GrDistanceFieldTextureEffect::TestCreate(SkRandom* random,
};
GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
GrTextureParams::kNone_FilterMode);
+#ifdef SK_GAMMA_APPLY_TO_A8
+ GrTextureParams params2(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
+ GrTextureParams::kNone_FilterMode);
+#endif
+
+ return GrDistanceFieldTextureEffect::Create(textures[texIdx], params,
+#ifdef SK_GAMMA_APPLY_TO_A8
+ textures[texIdx2], params2,
+ random->nextF(),
+#endif
+ random->nextBool());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+class GrGLDistanceFieldLCDTextureEffect : public GrGLVertexEffect {
+public:
+ GrGLDistanceFieldLCDTextureEffect(const GrBackendEffectFactory& factory,
+ const GrDrawEffect& drawEffect)
+ : INHERITED (factory)
+ , fTextureSize(SkISize::Make(-1,-1)) {}
+
+ virtual void emitCode(GrGLFullShaderBuilder* builder,
+ const GrDrawEffect& drawEffect,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray& samplers) SK_OVERRIDE {
+ SkASSERT(1 == drawEffect.castEffect<GrDistanceFieldLCDTextureEffect>().numVertexAttribs());
+
+ SkAssertResult(builder->enableFeature(GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
+ const GrDistanceFieldLCDTextureEffect& dfTexEffect =
+ drawEffect.castEffect<GrDistanceFieldLCDTextureEffect>();
+
+ SkString fsCoordName;
+ const char* vsCoordName;
+ const char* fsCoordNamePtr;
+ builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fsCoordNamePtr);
+ fsCoordName = fsCoordNamePtr;
+
+ const char* attrName0 =
+ builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0])->c_str();
+ builder->vsCodeAppendf("\t%s = %s;\n", vsCoordName, attrName0);
+
+ const char* textureSizeUniName = NULL;
+ // width, height, 1/(3*width)
+ fTextureSizeUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kVec3f_GrSLType, "TextureSize",
+ &textureSizeUniName);
+
+ // create LCD offset adjusted by inverse of transform
+ builder->fsCodeAppendf("\tvec2 uv = %s;\n", fsCoordName.c_str());
+ builder->fsCodeAppendf("\tvec2 st = uv*%s.xy;\n", textureSizeUniName);
+ if (dfTexEffect.isUniformScale()) {
+ builder->fsCodeAppend("\tfloat dx = dFdx(st.x);\n");
+ builder->fsCodeAppendf("\tvec2 offset = vec2(dx*%s.z, 0.0);\n", textureSizeUniName);
+ } else {
+ builder->fsCodeAppend("\tvec2 Jdx = dFdx(st);\n");
+ builder->fsCodeAppend("\tvec2 Jdy = dFdy(st);\n");
+ builder->fsCodeAppendf("\tvec2 offset = %s.z*Jdx;\n", textureSizeUniName);
+ }
+
+ // green is distance to uv center
+ builder->fsCodeAppend("\tvec4 texColor = ");
+ builder->fsAppendTextureLookup(samplers[0], "uv", kVec2f_GrSLType);
+ builder->fsCodeAppend(";\n");
+ builder->fsCodeAppend("\tvec3 distance;\n");
+ builder->fsCodeAppend("\tdistance.y = texColor.r;\n");
+ // red is distance to left offset
+ builder->fsCodeAppend("\tvec2 uv_adjusted = uv - offset;\n");
+ builder->fsCodeAppend("\ttexColor = ");
+ builder->fsAppendTextureLookup(samplers[0], "uv_adjusted", kVec2f_GrSLType);
+ builder->fsCodeAppend(";\n");
+ builder->fsCodeAppend("\tdistance.x = texColor.r;\n");
+ // blue is distance to right offset
+ builder->fsCodeAppend("\tuv_adjusted = uv + offset;\n");
+ builder->fsCodeAppend("\ttexColor = ");
+ builder->fsAppendTextureLookup(samplers[0], "uv_adjusted", kVec2f_GrSLType);
+ builder->fsCodeAppend(";\n");
+ builder->fsCodeAppend("\tdistance.z = texColor.r;\n");
+
+ builder->fsCodeAppend("\tdistance = "
+ "vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_DistanceFieldThreshold"))"
+ "+ vec3(" SK_DistanceFieldLCDFactor ");\n");
+
+ // we adjust for the effect of the transformation on the distance by using
+ // the length of the gradient of the texture coordinates. We use st coordinates
+ // to ensure we're mapping 1:1 from texel space to pixel space.
+
+ // To be strictly correct, we should compute the anti-aliasing factor separately
+ // for each color component. However, this is only important when using perspective
+ // transformations, and even then using a single factor seems like a reasonable
+ // trade-off between quality and speed.
+ builder->fsCodeAppend("\tfloat afwidth;\n");
+ if (dfTexEffect.isUniformScale()) {
+ // this gives us a smooth step across approximately one fragment
+ builder->fsCodeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*dx;\n");
+ } else {
+ builder->fsCodeAppend("\tvec2 uv_grad;\n");
+ if (builder->ctxInfo().caps()->dropsTileOnZeroDivide()) {
+ // this is to compensate for the Adreno, which likes to drop tiles on division by 0
+ builder->fsCodeAppend("\tfloat uv_len2 = dot(uv, uv);\n");
+ builder->fsCodeAppend("\tif (uv_len2 < 0.0001) {\n");
+ builder->fsCodeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n");
+ builder->fsCodeAppend("\t} else {\n");
+ builder->fsCodeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n");
+ builder->fsCodeAppend("\t}\n");
+ } else {
+ builder->fsCodeAppend("\tuv_grad = normalize(uv);\n");
+ }
+ builder->fsCodeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*Jdy.x,\n");
+ builder->fsCodeAppend("\t uv_grad.x*Jdx.y + uv_grad.y*Jdy.y);\n");
+
+ // this gives us a smooth step across approximately one fragment
+ builder->fsCodeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*length(grad);\n");
+ }
+
+ builder->fsCodeAppend("\tvec4 val = vec4(smoothstep(vec3(-afwidth), vec3(afwidth), distance), 1.0);\n");
+
+ // adjust based on gamma
+ const char* textColorUniName = NULL;
+ // width, height, 1/(3*width)
+ fTextColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kVec3f_GrSLType, "TextColor",
+ &textColorUniName);
+
+ builder->fsCodeAppendf("\tuv = vec2(val.x, %s.x);\n", textColorUniName);
+ builder->fsCodeAppend("\tvec4 gammaColor = ");
+ builder->fsAppendTextureLookup(samplers[1], "uv", kVec2f_GrSLType);
+ builder->fsCodeAppend(";\n");
+ builder->fsCodeAppend("\tval.x = gammaColor.r;\n");
+
+ builder->fsCodeAppendf("\tuv = vec2(val.y, %s.y);\n", textColorUniName);
+ builder->fsCodeAppend("\tgammaColor = ");
+ builder->fsAppendTextureLookup(samplers[1], "uv", kVec2f_GrSLType);
+ builder->fsCodeAppend(";\n");
+ builder->fsCodeAppend("\tval.y = gammaColor.r;\n");
- return GrDistanceFieldTextureEffect::Create(textures[texIdx], params);
+ builder->fsCodeAppendf("\tuv = vec2(val.z, %s.z);\n", textColorUniName);
+ builder->fsCodeAppend("\tgammaColor = ");
+ builder->fsAppendTextureLookup(samplers[1], "uv", kVec2f_GrSLType);
+ builder->fsCodeAppend(";\n");
+ builder->fsCodeAppend("\tval.z = gammaColor.r;\n");
+
+ builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
+ (GrGLSLExpr4(inputColor) * GrGLSLExpr4("val")).c_str());
+ }
+
+ virtual void setData(const GrGLUniformManager& uman,
+ const GrDrawEffect& drawEffect) SK_OVERRIDE {
+ SkASSERT(fTextureSizeUni.isValid());
+ SkASSERT(fTextColorUni.isValid());
+
+ const GrDistanceFieldLCDTextureEffect& dfTexEffect =
+ drawEffect.castEffect<GrDistanceFieldLCDTextureEffect>();
+ GrTexture* texture = drawEffect.effect()->get()->texture(0);
+ if (texture->width() != fTextureSize.width() ||
+ texture->height() != fTextureSize.height()) {
+ fTextureSize = SkISize::Make(texture->width(), texture->height());
+ float delta = 1.0f/(3.0f*texture->width());
+ if (dfTexEffect.useBGR()) {
+ delta = -delta;
+ }
+ uman.set3f(fTextureSizeUni,
+ SkIntToScalar(fTextureSize.width()),
+ SkIntToScalar(fTextureSize.height()),
+ delta);
+ }
+
+ GrColor textColor = dfTexEffect.getTextColor();
+ if (textColor != fTextColor) {
+ static const float ONE_OVER_255 = 1.f / 255.f;
+ uman.set3f(fTextColorUni,
+ GrColorUnpackR(textColor) * ONE_OVER_255,
+ GrColorUnpackG(textColor) * ONE_OVER_255,
+ GrColorUnpackB(textColor) * ONE_OVER_255);
+ fTextColor = textColor;
+ }
+ }
+
+ static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
+ const GrDistanceFieldLCDTextureEffect& dfTexEffect =
+ drawEffect.castEffect<GrDistanceFieldLCDTextureEffect>();
+
+ return dfTexEffect.isUniformScale() ? 0x01 : 0x00;;
+ }
+
+private:
+ GrGLUniformManager::UniformHandle fTextureSizeUni;
+ SkISize fTextureSize;
+ GrGLUniformManager::UniformHandle fTextColorUni;
+ SkColor fTextColor;
+
+ typedef GrGLVertexEffect INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+GrDistanceFieldLCDTextureEffect::GrDistanceFieldLCDTextureEffect(
+ GrTexture* texture, const GrTextureParams& params,
+ GrTexture* gamma, const GrTextureParams& gParams,
+ SkColor textColor,
+ bool uniformScale, bool useBGR)
+ : fTextureAccess(texture, params)
+ , fGammaTextureAccess(gamma, gParams)
+ , fTextColor(textColor)
+ , fUniformScale(uniformScale)
+ , fUseBGR(useBGR) {
+ this->addTextureAccess(&fTextureAccess);
+ this->addTextureAccess(&fGammaTextureAccess);
+ this->addVertexAttrib(kVec2f_GrSLType);
+}
+
+bool GrDistanceFieldLCDTextureEffect::onIsEqual(const GrEffect& other) const {
+ const GrDistanceFieldLCDTextureEffect& cte =
+ CastEffect<GrDistanceFieldLCDTextureEffect>(other);
+ return (fTextureAccess == cte.fTextureAccess && fGammaTextureAccess == cte.fGammaTextureAccess);
+}
+
+void GrDistanceFieldLCDTextureEffect::getConstantColorComponents(GrColor* color,
+ uint32_t* validFlags) const {
+ if ((*validFlags & kA_GrColorComponentFlag) && 0xFF == GrColorUnpackA(*color) &&
+ GrPixelConfigIsOpaque(this->texture(0)->config())) {
+ *validFlags = kA_GrColorComponentFlag;
+ } else {
+ *validFlags = 0;
+ }
+}
+
+const GrBackendEffectFactory& GrDistanceFieldLCDTextureEffect::getFactory() const {
+ return GrTBackendEffectFactory<GrDistanceFieldLCDTextureEffect>::getInstance();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+GR_DEFINE_EFFECT_TEST(GrDistanceFieldLCDTextureEffect);
+
+GrEffectRef* GrDistanceFieldLCDTextureEffect::TestCreate(SkRandom* random,
+ GrContext*,
+ const GrDrawTargetCaps&,
+ GrTexture* textures[]) {
+ int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx :
+ GrEffectUnitTest::kAlphaTextureIdx;
+ int texIdx2 = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx :
+ GrEffectUnitTest::kAlphaTextureIdx;
+ static const SkShader::TileMode kTileModes[] = {
+ SkShader::kClamp_TileMode,
+ SkShader::kRepeat_TileMode,
+ SkShader::kMirror_TileMode,
+ };
+ SkShader::TileMode tileModes[] = {
+ kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
+ kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))],
+ };
+ GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
+ GrTextureParams::kNone_FilterMode);
+ GrTextureParams params2(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
+ GrTextureParams::kNone_FilterMode);
+ GrColor textColor = GrColorPackRGBA(random->nextULessThan(256),
+ random->nextULessThan(256),
+ random->nextULessThan(256),
+ random->nextULessThan(256));
+ return GrDistanceFieldLCDTextureEffect::Create(textures[texIdx], params,
+ textures[texIdx2], params2,
+ textColor,
+ random->nextBool(), random->nextBool());
}
diff --git a/chromium/third_party/skia/src/gpu/effects/GrDistanceFieldTextureEffect.h b/chromium/third_party/skia/src/gpu/effects/GrDistanceFieldTextureEffect.h
index fc37ddb99a2..692290ccdb3 100755..100644
--- a/chromium/third_party/skia/src/gpu/effects/GrDistanceFieldTextureEffect.h
+++ b/chromium/third_party/skia/src/gpu/effects/GrDistanceFieldTextureEffect.h
@@ -12,36 +12,111 @@
#include "GrVertexEffect.h"
class GrGLDistanceFieldTextureEffect;
+class GrGLDistanceFieldLCDTextureEffect;
/**
* The output color of this effect is a modulation of the input color and a sample from a
* distance field texture (using a smoothed step function near 0.5).
* It allows explicit specification of the filtering and wrap modes (GrTextureParams). The input
- * coords are a custom attribute.
+ * coords are a custom attribute. Gamma correction is handled via a texture LUT.
*/
class GrDistanceFieldTextureEffect : public GrVertexEffect {
public:
- static GrEffectRef* Create(GrTexture* tex, const GrTextureParams& p) {
- AutoEffectUnref effect(SkNEW_ARGS(GrDistanceFieldTextureEffect, (tex, p)));
+#ifdef SK_GAMMA_APPLY_TO_A8
+ static GrEffectRef* Create(GrTexture* tex, const GrTextureParams& params,
+ GrTexture* gamma, const GrTextureParams& gammaParams, float lum,
+ bool similarity) {
+ AutoEffectUnref effect(SkNEW_ARGS(GrDistanceFieldTextureEffect, (tex, params,
+ gamma, gammaParams, lum,
+ similarity)));
+#else
+ static GrEffectRef* Create(GrTexture* tex, const GrTextureParams& params,
+ bool similarity) {
+ AutoEffectUnref effect(SkNEW_ARGS(GrDistanceFieldTextureEffect, (tex, params,
+ similarity)));
+#endif
return CreateEffectRef(effect);
}
virtual ~GrDistanceFieldTextureEffect() {}
- static const char* Name() { return "Texture"; }
+ static const char* Name() { return "DistanceFieldTexture"; }
virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
+#ifdef SK_GAMMA_APPLY_TO_A8
+ float getLuminance() const { return fLuminance; }
+#endif
+ bool isSimilarity() const { return fIsSimilarity; }
typedef GrGLDistanceFieldTextureEffect GLEffect;
virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
private:
- GrDistanceFieldTextureEffect(GrTexture* texture, const GrTextureParams& params);
+ GrDistanceFieldTextureEffect(GrTexture* texture, const GrTextureParams& params,
+#ifdef SK_GAMMA_APPLY_TO_A8
+ GrTexture* gamma, const GrTextureParams& gammaParams, float lum,
+#endif
+ bool uniformScale);
+
+ virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE;
+
+ GrTextureAccess fTextureAccess;
+#ifdef SK_GAMMA_APPLY_TO_A8
+ GrTextureAccess fGammaTextureAccess;
+ float fLuminance;
+#endif
+ bool fIsSimilarity;
+
+ GR_DECLARE_EFFECT_TEST;
+
+ typedef GrVertexEffect INHERITED;
+};
+
+/**
+ * The output color of this effect is a modulation of the input color and samples from a
+ * distance field texture (using a smoothed step function near 0.5), adjusted for LCD displays.
+ * It allows explicit specification of the filtering and wrap modes (GrTextureParams). The input
+ * coords are a custom attribute. Gamma correction is handled via a texture LUT.
+ */
+class GrDistanceFieldLCDTextureEffect : public GrVertexEffect {
+public:
+ static GrEffectRef* Create(GrTexture* tex, const GrTextureParams& params,
+ GrTexture* gamma, const GrTextureParams& gammaParams,
+ SkColor textColor,
+ bool uniformScale, bool useBGR) {
+ AutoEffectUnref effect(SkNEW_ARGS(GrDistanceFieldLCDTextureEffect,
+ (tex, params, gamma, gammaParams, textColor, uniformScale,
+ useBGR)));
+ return CreateEffectRef(effect);
+ }
+
+ virtual ~GrDistanceFieldLCDTextureEffect() {}
+
+ static const char* Name() { return "DistanceFieldLCDTexture"; }
+
+ virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
+ GrColor getTextColor() const { return fTextColor; }
+ bool isUniformScale() const { return fUniformScale; }
+ bool useBGR() const { return fUseBGR; }
+
+ typedef GrGLDistanceFieldLCDTextureEffect GLEffect;
+
+ virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
+
+private:
+ GrDistanceFieldLCDTextureEffect(GrTexture* texture, const GrTextureParams& params,
+ GrTexture* gamma, const GrTextureParams& gammaParams,
+ SkColor textColor,
+ bool uniformScale, bool useBGR);
virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE;
GrTextureAccess fTextureAccess;
+ GrTextureAccess fGammaTextureAccess;
+ GrColor fTextColor;
+ bool fUniformScale;
+ bool fUseBGR;
GR_DECLARE_EFFECT_TEST;
diff --git a/chromium/third_party/skia/src/gpu/effects/GrDitherEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrDitherEffect.cpp
new file mode 100644
index 00000000000..7409e5ff715
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/effects/GrDitherEffect.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrDitherEffect.h"
+
+#include "gl/GrGLEffect.h"
+#include "gl/GrGLSL.h"
+#include "GrTBackendEffectFactory.h"
+
+#include "SkRect.h"
+
+//////////////////////////////////////////////////////////////////////////////
+
+class GLDitherEffect;
+
+class DitherEffect : public GrEffect {
+public:
+ static GrEffectRef* Create() {
+ return CreateEffectRef(AutoEffectUnref(SkNEW(DitherEffect)));
+ }
+
+ virtual ~DitherEffect() {};
+ static const char* Name() { return "Dither"; }
+
+ typedef GLDitherEffect GLEffect;
+
+ virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
+
+ virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
+ return GrTBackendEffectFactory<DitherEffect>::getInstance();
+ }
+
+private:
+ DitherEffect() {
+ this->setWillReadFragmentPosition();
+ }
+
+ // All dither effects are equal
+ virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE { return true; }
+
+ GR_DECLARE_EFFECT_TEST;
+
+ typedef GrEffect INHERITED;
+};
+
+void DitherEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
+ *validFlags = 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+GR_DEFINE_EFFECT_TEST(DitherEffect);
+
+GrEffectRef* DitherEffect::TestCreate(SkRandom*,
+ GrContext*,
+ const GrDrawTargetCaps&,
+ GrTexture*[]) {
+ return DitherEffect::Create();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+class GLDitherEffect : public GrGLEffect {
+public:
+ GLDitherEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
+
+ virtual void emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect& drawEffect,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray&) SK_OVERRIDE;
+
+private:
+ typedef GrGLEffect INHERITED;
+};
+
+GLDitherEffect::GLDitherEffect(const GrBackendEffectFactory& factory,
+ const GrDrawEffect& drawEffect)
+ : INHERITED (factory) {
+}
+
+void GLDitherEffect::emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect& drawEffect,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray& samplers) {
+ // Generate a random number based on the fragment position. For this
+ // random number generator, we use the "GLSL rand" function
+ // that seems to be floating around on the internet. It works under
+ // the assumption that sin(<big number>) oscillates with high frequency
+ // and sampling it will generate "randomness". Since we're using this
+ // for rendering and not cryptography it should be OK.
+
+ // For each channel c, add the random offset to the pixel to either bump
+ // it up or let it remain constant during quantization.
+ builder->fsCodeAppendf("\t\tfloat r = "
+ "fract(sin(dot(%s.xy ,vec2(12.9898,78.233))) * 43758.5453);\n",
+ builder->fragmentPosition());
+ builder->fsCodeAppendf("\t\t%s = (1.0/255.0) * vec4(r, r, r, r) + %s;\n",
+ outputColor, GrGLSLExpr4(inputColor).c_str());
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+GrEffectRef* GrDitherEffect::Create() {
+ return DitherEffect::Create();
+}
diff --git a/chromium/third_party/skia/src/gpu/effects/GrDitherEffect.h b/chromium/third_party/skia/src/gpu/effects/GrDitherEffect.h
new file mode 100644
index 00000000000..63036c0c7f2
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/effects/GrDitherEffect.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrDitherEffect_DEFINED
+#define GrDitherEffect_DEFINED
+
+#include "GrTypes.h"
+#include "GrTypesPriv.h"
+
+class GrEffectRef;
+
+namespace GrDitherEffect {
+ /**
+ * Creates an effect that dithers the resulting color to an RGBA8 framebuffer
+ */
+ GrEffectRef* Create();
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/effects/GrOvalEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrOvalEffect.cpp
new file mode 100644
index 00000000000..f2ee27880f5
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/effects/GrOvalEffect.cpp
@@ -0,0 +1,387 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrOvalEffect.h"
+
+#include "gl/GrGLEffect.h"
+#include "gl/GrGLSL.h"
+#include "GrTBackendEffectFactory.h"
+
+#include "SkRect.h"
+
+//////////////////////////////////////////////////////////////////////////////
+
+class GLCircleEffect;
+
+class CircleEffect : public GrEffect {
+public:
+ static GrEffectRef* Create(GrEffectEdgeType, const SkPoint& center, SkScalar radius);
+
+ virtual ~CircleEffect() {};
+ static const char* Name() { return "Circle"; }
+
+ const SkPoint& getCenter() const { return fCenter; }
+ SkScalar getRadius() const { return fRadius; }
+
+ GrEffectEdgeType getEdgeType() const { return fEdgeType; }
+
+ typedef GLCircleEffect GLEffect;
+
+ virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
+
+ virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
+
+private:
+ CircleEffect(GrEffectEdgeType, const SkPoint& center, SkScalar radius);
+
+ virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
+
+ SkPoint fCenter;
+ SkScalar fRadius;
+ GrEffectEdgeType fEdgeType;
+
+ GR_DECLARE_EFFECT_TEST;
+
+ typedef GrEffect INHERITED;
+};
+
+GrEffectRef* CircleEffect::Create(GrEffectEdgeType edgeType,
+ const SkPoint& center,
+ SkScalar radius) {
+ SkASSERT(radius >= 0);
+ return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(CircleEffect,
+ (edgeType, center, radius))));
+}
+
+void CircleEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
+ *validFlags = 0;
+}
+
+const GrBackendEffectFactory& CircleEffect::getFactory() const {
+ return GrTBackendEffectFactory<CircleEffect>::getInstance();
+}
+
+CircleEffect::CircleEffect(GrEffectEdgeType edgeType, const SkPoint& c, SkScalar r)
+ : fCenter(c)
+ , fRadius(r)
+ , fEdgeType(edgeType) {
+ this->setWillReadFragmentPosition();
+}
+
+bool CircleEffect::onIsEqual(const GrEffect& other) const {
+ const CircleEffect& ce = CastEffect<CircleEffect>(other);
+ return fEdgeType == ce.fEdgeType && fCenter == ce.fCenter && fRadius == ce.fRadius;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+GR_DEFINE_EFFECT_TEST(CircleEffect);
+
+GrEffectRef* CircleEffect::TestCreate(SkRandom* random,
+ GrContext*,
+ const GrDrawTargetCaps& caps,
+ GrTexture*[]) {
+ SkPoint center;
+ center.fX = random->nextRangeScalar(0.f, 1000.f);
+ center.fY = random->nextRangeScalar(0.f, 1000.f);
+ SkScalar radius = random->nextRangeF(0.f, 1000.f);
+ GrEffectEdgeType et;
+ do {
+ et = (GrEffectEdgeType)random->nextULessThan(kGrEffectEdgeTypeCnt);
+ } while (kHairlineAA_GrEffectEdgeType == et);
+ return CircleEffect::Create(et, center, radius);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+class GLCircleEffect : public GrGLEffect {
+public:
+ GLCircleEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
+
+ virtual void emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect& drawEffect,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray&) SK_OVERRIDE;
+
+ static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
+
+ virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
+
+private:
+ GrGLUniformManager::UniformHandle fCircleUniform;
+ SkPoint fPrevCenter;
+ SkScalar fPrevRadius;
+
+ typedef GrGLEffect INHERITED;
+};
+
+GLCircleEffect::GLCircleEffect(const GrBackendEffectFactory& factory,
+ const GrDrawEffect& drawEffect)
+ : INHERITED (factory) {
+ fPrevRadius = -1.f;
+}
+
+void GLCircleEffect::emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect& drawEffect,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray& samplers) {
+ const CircleEffect& ce = drawEffect.castEffect<CircleEffect>();
+ const char *circleName;
+ // The circle uniform is (center.x, center.y, radius + 0.5) for regular fills and
+ // (... ,radius - 0.5) for inverse fills.
+ fCircleUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kVec3f_GrSLType,
+ "circle",
+ &circleName);
+ const char* fragmentPos = builder->fragmentPosition();
+
+ SkASSERT(kHairlineAA_GrEffectEdgeType != ce.getEdgeType());
+ if (GrEffectEdgeTypeIsInverseFill(ce.getEdgeType())) {
+ builder->fsCodeAppendf("\t\tfloat d = length(%s.xy - %s.xy) - %s.z;\n",
+ circleName, fragmentPos, circleName);
+ } else {
+ builder->fsCodeAppendf("\t\tfloat d = %s.z - length(%s.xy - %s.xy);\n",
+ circleName, fragmentPos, circleName);
+ }
+ if (GrEffectEdgeTypeIsAA(ce.getEdgeType())) {
+ builder->fsCodeAppend("\t\td = clamp(d, 0.0, 1.0);\n");
+ } else {
+ builder->fsCodeAppend("\t\td = d > 0.5 ? 1.0 : 0.0;\n");
+ }
+
+ builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor,
+ (GrGLSLExpr4(inputColor) * GrGLSLExpr1("d")).c_str());
+}
+
+GrGLEffect::EffectKey GLCircleEffect::GenKey(const GrDrawEffect& drawEffect,
+ const GrGLCaps&) {
+ const CircleEffect& ce = drawEffect.castEffect<CircleEffect>();
+ return ce.getEdgeType();
+}
+
+void GLCircleEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) {
+ const CircleEffect& ce = drawEffect.castEffect<CircleEffect>();
+ if (ce.getRadius() != fPrevRadius || ce.getCenter() != fPrevCenter) {
+ SkScalar radius = ce.getRadius();
+ if (GrEffectEdgeTypeIsInverseFill(ce.getEdgeType())) {
+ radius -= 0.5f;
+ } else {
+ radius += 0.5f;
+ }
+ uman.set3f(fCircleUniform, ce.getCenter().fX, ce.getCenter().fY, radius);
+ fPrevCenter = ce.getCenter();
+ fPrevRadius = ce.getRadius();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+class GLEllipseEffect;
+
+class EllipseEffect : public GrEffect {
+public:
+ static GrEffectRef* Create(GrEffectEdgeType, const SkPoint& center, SkScalar rx, SkScalar ry);
+
+ virtual ~EllipseEffect() {};
+ static const char* Name() { return "Ellipse"; }
+
+ const SkPoint& getCenter() const { return fCenter; }
+ SkVector getRadii() const { return fRadii; }
+
+ GrEffectEdgeType getEdgeType() const { return fEdgeType; }
+
+ typedef GLEllipseEffect GLEffect;
+
+ virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
+
+ virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
+
+private:
+ EllipseEffect(GrEffectEdgeType, const SkPoint& center, SkScalar rx, SkScalar ry);
+
+ virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
+
+ SkPoint fCenter;
+ SkVector fRadii;
+ GrEffectEdgeType fEdgeType;
+
+ GR_DECLARE_EFFECT_TEST;
+
+ typedef GrEffect INHERITED;
+};
+
+GrEffectRef* EllipseEffect::Create(GrEffectEdgeType edgeType,
+ const SkPoint& center,
+ SkScalar rx,
+ SkScalar ry) {
+ SkASSERT(rx >= 0 && ry >= 0);
+ return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(EllipseEffect,
+ (edgeType, center, rx, ry))));
+}
+
+void EllipseEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
+ *validFlags = 0;
+}
+
+const GrBackendEffectFactory& EllipseEffect::getFactory() const {
+ return GrTBackendEffectFactory<EllipseEffect>::getInstance();
+}
+
+EllipseEffect::EllipseEffect(GrEffectEdgeType edgeType, const SkPoint& c, SkScalar rx, SkScalar ry)
+ : fCenter(c)
+ , fRadii(SkVector::Make(rx, ry))
+ , fEdgeType(edgeType) {
+ this->setWillReadFragmentPosition();
+}
+
+bool EllipseEffect::onIsEqual(const GrEffect& other) const {
+ const EllipseEffect& ee = CastEffect<EllipseEffect>(other);
+ return fEdgeType == ee.fEdgeType && fCenter == ee.fCenter && fRadii == ee.fRadii;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+GR_DEFINE_EFFECT_TEST(EllipseEffect);
+
+GrEffectRef* EllipseEffect::TestCreate(SkRandom* random,
+ GrContext*,
+ const GrDrawTargetCaps& caps,
+ GrTexture*[]) {
+ SkPoint center;
+ center.fX = random->nextRangeScalar(0.f, 1000.f);
+ center.fY = random->nextRangeScalar(0.f, 1000.f);
+ SkScalar rx = random->nextRangeF(0.f, 1000.f);
+ SkScalar ry = random->nextRangeF(0.f, 1000.f);
+ GrEffectEdgeType et;
+ do {
+ et = (GrEffectEdgeType)random->nextULessThan(kGrEffectEdgeTypeCnt);
+ } while (kHairlineAA_GrEffectEdgeType == et);
+ return EllipseEffect::Create(et, center, rx, ry);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+class GLEllipseEffect : public GrGLEffect {
+public:
+ GLEllipseEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
+
+ virtual void emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect& drawEffect,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray&) SK_OVERRIDE;
+
+ static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
+
+ virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
+
+private:
+ GrGLUniformManager::UniformHandle fEllipseUniform;
+ SkPoint fPrevCenter;
+ SkVector fPrevRadii;
+
+ typedef GrGLEffect INHERITED;
+};
+
+GLEllipseEffect::GLEllipseEffect(const GrBackendEffectFactory& factory,
+ const GrDrawEffect& drawEffect)
+ : INHERITED (factory) {
+ fPrevRadii.fX = -1.f;
+}
+
+void GLEllipseEffect::emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect& drawEffect,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray& samplers) {
+ const EllipseEffect& ee = drawEffect.castEffect<EllipseEffect>();
+ const char *ellipseName;
+ // The ellipse uniform is (center.x, center.y, 1 / rx^2, 1 / ry^2)
+ fEllipseUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kVec4f_GrSLType,
+ "ellipse",
+ &ellipseName);
+ const char* fragmentPos = builder->fragmentPosition();
+
+ // d is the offset to the ellipse center
+ builder->fsCodeAppendf("\t\tvec2 d = %s.xy - %s.xy;\n", fragmentPos, ellipseName);
+ builder->fsCodeAppendf("\t\tvec2 Z = d * %s.zw;\n", ellipseName);
+ // implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1.
+ builder->fsCodeAppend("\t\tfloat implicit = dot(Z, d) - 1.0;\n");
+ // grad_dot is the squared length of the gradient of the implicit.
+ builder->fsCodeAppendf("\t\tfloat grad_dot = 4.0 * dot(Z, Z);\n");
+ // avoid calling inversesqrt on zero.
+ builder->fsCodeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n");
+ builder->fsCodeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_dot);\n");
+
+ switch (ee.getEdgeType()) {
+ case kFillAA_GrEffectEdgeType:
+ builder->fsCodeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1.0);\n");
+ break;
+ case kInverseFillAA_GrEffectEdgeType:
+ builder->fsCodeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1.0);\n");
+ break;
+ case kFillBW_GrEffectEdgeType:
+ builder->fsCodeAppend("\t\tfloat alpha = approx_dist > 0.0 ? 0.0 : 1.0;\n");
+ break;
+ case kInverseFillBW_GrEffectEdgeType:
+ builder->fsCodeAppend("\t\tfloat alpha = approx_dist > 0.0 ? 1.0 : 0.0;\n");
+ break;
+ case kHairlineAA_GrEffectEdgeType:
+ SkFAIL("Hairline not expected here.");
+ }
+
+ builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor,
+ (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
+}
+
+GrGLEffect::EffectKey GLEllipseEffect::GenKey(const GrDrawEffect& drawEffect,
+ const GrGLCaps&) {
+ const EllipseEffect& ee = drawEffect.castEffect<EllipseEffect>();
+ return ee.getEdgeType();
+}
+
+void GLEllipseEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) {
+ const EllipseEffect& ee = drawEffect.castEffect<EllipseEffect>();
+ if (ee.getRadii() != fPrevRadii || ee.getCenter() != fPrevCenter) {
+ SkScalar invRXSqd = 1.f / (ee.getRadii().fX * ee.getRadii().fX);
+ SkScalar invRYSqd = 1.f / (ee.getRadii().fY * ee.getRadii().fY);
+ uman.set4f(fEllipseUniform, ee.getCenter().fX, ee.getCenter().fY, invRXSqd, invRYSqd);
+ fPrevCenter = ee.getCenter();
+ fPrevRadii = ee.getRadii();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+GrEffectRef* GrOvalEffect::Create(GrEffectEdgeType edgeType, const SkRect& oval) {
+ if (kHairlineAA_GrEffectEdgeType == edgeType) {
+ return NULL;
+ }
+ SkScalar w = oval.width();
+ SkScalar h = oval.height();
+ if (SkScalarNearlyEqual(w, h)) {
+ w /= 2;
+ return CircleEffect::Create(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + w), w);
+ } else {
+ w /= 2;
+ h /= 2;
+ return EllipseEffect::Create(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + h), w, h);
+ }
+
+ return NULL;
+}
diff --git a/chromium/third_party/skia/src/gpu/effects/GrOvalEffect.h b/chromium/third_party/skia/src/gpu/effects/GrOvalEffect.h
new file mode 100644
index 00000000000..796ee5befb5
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/effects/GrOvalEffect.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrOvalEffect_DEFINED
+#define GrOvalEffect_DEFINED
+
+#include "GrTypes.h"
+#include "GrTypesPriv.h"
+
+class GrEffectRef;
+struct SkRect;
+
+namespace GrOvalEffect {
+ /**
+ * Creates an effect that performs clipping against an oval.
+ */
+ GrEffectRef* Create(GrEffectEdgeType, const SkRect&);
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/effects/GrRRectEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrRRectEffect.cpp
new file mode 100644
index 00000000000..11d8a18e616
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/effects/GrRRectEffect.cpp
@@ -0,0 +1,730 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrRRectEffect.h"
+
+#include "gl/GrGLEffect.h"
+#include "gl/GrGLSL.h"
+#include "GrConvexPolyEffect.h"
+#include "GrOvalEffect.h"
+#include "GrTBackendEffectFactory.h"
+
+#include "SkRRect.h"
+
+// The effects defined here only handle rrect radii >= kRadiusMin.
+static const SkScalar kRadiusMin = SK_ScalarHalf;
+
+//////////////////////////////////////////////////////////////////////////////
+
+class GLCircularRRectEffect;
+
+class CircularRRectEffect : public GrEffect {
+public:
+
+ enum CornerFlags {
+ kTopLeft_CornerFlag = (1 << SkRRect::kUpperLeft_Corner),
+ kTopRight_CornerFlag = (1 << SkRRect::kUpperRight_Corner),
+ kBottomRight_CornerFlag = (1 << SkRRect::kLowerRight_Corner),
+ kBottomLeft_CornerFlag = (1 << SkRRect::kLowerLeft_Corner),
+
+ kLeft_CornerFlags = kTopLeft_CornerFlag | kBottomLeft_CornerFlag,
+ kTop_CornerFlags = kTopLeft_CornerFlag | kTopRight_CornerFlag,
+ kRight_CornerFlags = kTopRight_CornerFlag | kBottomRight_CornerFlag,
+ kBottom_CornerFlags = kBottomLeft_CornerFlag | kBottomRight_CornerFlag,
+
+ kAll_CornerFlags = kTopLeft_CornerFlag | kTopRight_CornerFlag |
+ kBottomLeft_CornerFlag | kBottomRight_CornerFlag,
+
+ kNone_CornerFlags = 0
+ };
+
+ // The flags are used to indicate which corners are circluar (unflagged corners are assumed to
+ // be square).
+ static GrEffectRef* Create(GrEffectEdgeType, uint32_t circularCornerFlags, const SkRRect&);
+
+ virtual ~CircularRRectEffect() {};
+ static const char* Name() { return "CircularRRect"; }
+
+ const SkRRect& getRRect() const { return fRRect; }
+
+ uint32_t getCircularCornerFlags() const { return fCircularCornerFlags; }
+
+ GrEffectEdgeType getEdgeType() const { return fEdgeType; }
+
+ typedef GLCircularRRectEffect GLEffect;
+
+ virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
+
+ virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
+
+private:
+ CircularRRectEffect(GrEffectEdgeType, uint32_t circularCornerFlags, const SkRRect&);
+
+ virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE;
+
+ SkRRect fRRect;
+ GrEffectEdgeType fEdgeType;
+ uint32_t fCircularCornerFlags;
+
+ GR_DECLARE_EFFECT_TEST;
+
+ typedef GrEffect INHERITED;
+};
+
+GrEffectRef* CircularRRectEffect::Create(GrEffectEdgeType edgeType,
+ uint32_t circularCornerFlags,
+ const SkRRect& rrect) {
+ if (kFillAA_GrEffectEdgeType != edgeType && kInverseFillAA_GrEffectEdgeType != edgeType) {
+ return NULL;
+ }
+ return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(CircularRRectEffect,
+ (edgeType, circularCornerFlags, rrect))));
+}
+
+void CircularRRectEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
+ *validFlags = 0;
+}
+
+const GrBackendEffectFactory& CircularRRectEffect::getFactory() const {
+ return GrTBackendEffectFactory<CircularRRectEffect>::getInstance();
+}
+
+CircularRRectEffect::CircularRRectEffect(GrEffectEdgeType edgeType, uint32_t circularCornerFlags,
+ const SkRRect& rrect)
+ : fRRect(rrect)
+ , fEdgeType(edgeType)
+ , fCircularCornerFlags(circularCornerFlags) {
+ this->setWillReadFragmentPosition();
+}
+
+bool CircularRRectEffect::onIsEqual(const GrEffect& other) const {
+ const CircularRRectEffect& crre = CastEffect<CircularRRectEffect>(other);
+ // The corner flags are derived from fRRect, so no need to check them.
+ return fEdgeType == crre.fEdgeType && fRRect == crre.fRRect;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+GR_DEFINE_EFFECT_TEST(CircularRRectEffect);
+
+GrEffectRef* CircularRRectEffect::TestCreate(SkRandom* random,
+ GrContext*,
+ const GrDrawTargetCaps& caps,
+ GrTexture*[]) {
+ SkScalar w = random->nextRangeScalar(20.f, 1000.f);
+ SkScalar h = random->nextRangeScalar(20.f, 1000.f);
+ SkScalar r = random->nextRangeF(kRadiusMin, 9.f);
+ SkRRect rrect;
+ rrect.setRectXY(SkRect::MakeWH(w, h), r, r);
+ GrEffectRef* effect;
+ do {
+ GrEffectEdgeType et = (GrEffectEdgeType)random->nextULessThan(kGrEffectEdgeTypeCnt);
+ effect = GrRRectEffect::Create(et, rrect);
+ } while (NULL == effect);
+ return effect;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+class GLCircularRRectEffect : public GrGLEffect {
+public:
+ GLCircularRRectEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
+
+ virtual void emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect& drawEffect,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray&) SK_OVERRIDE;
+
+ static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
+
+ virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
+
+private:
+ GrGLUniformManager::UniformHandle fInnerRectUniform;
+ GrGLUniformManager::UniformHandle fRadiusPlusHalfUniform;
+ SkRRect fPrevRRect;
+ typedef GrGLEffect INHERITED;
+};
+
+GLCircularRRectEffect::GLCircularRRectEffect(const GrBackendEffectFactory& factory,
+ const GrDrawEffect& drawEffect)
+ : INHERITED (factory) {
+ fPrevRRect.setEmpty();
+}
+
+void GLCircularRRectEffect::emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect& drawEffect,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray& samplers) {
+ const CircularRRectEffect& crre = drawEffect.castEffect<CircularRRectEffect>();
+ const char *rectName;
+ const char *radiusPlusHalfName;
+ // The inner rect is the rrect bounds inset by the radius. Its left, top, right, and bottom
+ // edges correspond to components x, y, z, and w, respectively. When a side of the rrect has
+ // only rectangular corners, that side's value corresponds to the rect edge's value outset by
+ // half a pixel.
+ fInnerRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kVec4f_GrSLType,
+ "innerRect",
+ &rectName);
+ fRadiusPlusHalfUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kFloat_GrSLType,
+ "radiusPlusHalf",
+ &radiusPlusHalfName);
+ const char* fragmentPos = builder->fragmentPosition();
+ // At each quarter-circle corner we compute a vector that is the offset of the fragment position
+ // from the circle center. The vector is pinned in x and y to be in the quarter-plane relevant
+ // to that corner. This means that points near the interior near the rrect top edge will have
+ // a vector that points straight up for both the TL left and TR corners. Computing an
+ // alpha from this vector at either the TR or TL corner will give the correct result. Similarly,
+ // fragments near the other three edges will get the correct AA. Fragments in the interior of
+ // the rrect will have a (0,0) vector at all four corners. So long as the radius > 0.5 they will
+ // correctly produce an alpha value of 1 at all four corners. We take the min of all the alphas.
+ // The code below is a simplified version of the above that performs maxs on the vector
+ // components before computing distances and alpha values so that only one distance computation
+ // need be computed to determine the min alpha.
+ //
+ // For the cases where one half of the rrect is rectangular we drop one of the x or y
+ // computations, compute a separate rect edge alpha for the rect side, and mul the two computed
+ // alphas together.
+ switch (crre.getCircularCornerFlags()) {
+ case CircularRRectEffect::kAll_CornerFlags:
+ builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos);
+ builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName);
+ builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n");
+ builder->fsCodeAppendf("\t\tfloat alpha = clamp(%s - length(dxy), 0.0, 1.0);\n",
+ radiusPlusHalfName);
+ break;
+ case CircularRRectEffect::kTopLeft_CornerFlag:
+ builder->fsCodeAppendf("\t\tvec2 dxy = max(%s.xy - %s.xy, 0.0);\n",
+ rectName, fragmentPos);
+ builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);\n",
+ rectName, fragmentPos);
+ builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);\n",
+ rectName, fragmentPos);
+ builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * rightAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
+ radiusPlusHalfName);
+ break;
+ case CircularRRectEffect::kTopRight_CornerFlag:
+ builder->fsCodeAppendf("\t\tvec2 dxy = max(vec2(%s.x - %s.z, %s.y - %s.y), 0.0);\n",
+ fragmentPos, rectName, rectName, fragmentPos);
+ builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);\n",
+ fragmentPos, rectName);
+ builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);\n",
+ rectName, fragmentPos);
+ builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * leftAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
+ radiusPlusHalfName);
+ break;
+ case CircularRRectEffect::kBottomRight_CornerFlag:
+ builder->fsCodeAppendf("\t\tvec2 dxy = max(%s.xy - %s.zw, 0.0);\n",
+ fragmentPos, rectName);
+ builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);\n",
+ fragmentPos, rectName);
+ builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n",
+ fragmentPos, rectName);
+ builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * leftAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
+ radiusPlusHalfName);
+ break;
+ case CircularRRectEffect::kBottomLeft_CornerFlag:
+ builder->fsCodeAppendf("\t\tvec2 dxy = max(vec2(%s.x - %s.x, %s.y - %s.w), 0.0);\n",
+ rectName, fragmentPos, fragmentPos, rectName);
+ builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);\n",
+ rectName, fragmentPos);
+ builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n",
+ fragmentPos, rectName);
+ builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * rightAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
+ radiusPlusHalfName);
+ break;
+ case CircularRRectEffect::kLeft_CornerFlags:
+ builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos);
+ builder->fsCodeAppendf("\t\tfloat dy1 = %s.y - %s.w;\n", fragmentPos, rectName);
+ builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy0.x, max(dxy0.y, dy1)), 0.0);\n");
+ builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.0, 1.0);\n",
+ rectName, fragmentPos);
+ builder->fsCodeAppendf("\t\tfloat alpha = rightAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
+ radiusPlusHalfName);
+ break;
+ case CircularRRectEffect::kTop_CornerFlags:
+ builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos);
+ builder->fsCodeAppendf("\t\tfloat dx1 = %s.x - %s.z;\n", fragmentPos, rectName);
+ builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dxy0.x, dx1), dxy0.y), 0.0);\n");
+ builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0.0, 1.0);\n",
+ rectName, fragmentPos);
+ builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
+ radiusPlusHalfName);
+ break;
+ case CircularRRectEffect::kRight_CornerFlags:
+ builder->fsCodeAppendf("\t\tfloat dy0 = %s.y - %s.y;\n", rectName, fragmentPos);
+ builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName);
+ builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy1.x, max(dy0, dxy1.y)), 0.0);\n");
+ builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0, 1.0);\n",
+ fragmentPos, rectName);
+ builder->fsCodeAppendf("\t\tfloat alpha = leftAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
+ radiusPlusHalfName);
+ break;
+ case CircularRRectEffect::kBottom_CornerFlags:
+ builder->fsCodeAppendf("\t\tfloat dx0 = %s.x - %s.x;\n", rectName, fragmentPos);
+ builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName);
+ builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dx0, dxy1.x), dxy1.y), 0.0);\n");
+ builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n",
+ fragmentPos, rectName);
+ builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * clamp(%s - length(dxy), 0.0, 1.0);\n",
+ radiusPlusHalfName);
+ break;
+ }
+
+ if (kInverseFillAA_GrEffectEdgeType == crre.getEdgeType()) {
+ builder->fsCodeAppend("\t\talpha = 1.0 - alpha;\n");
+ }
+
+ builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor,
+ (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
+}
+
+GrGLEffect::EffectKey GLCircularRRectEffect::GenKey(const GrDrawEffect& drawEffect,
+ const GrGLCaps&) {
+ const CircularRRectEffect& crre = drawEffect.castEffect<CircularRRectEffect>();
+ GR_STATIC_ASSERT(kGrEffectEdgeTypeCnt <= 8);
+ return (crre.getCircularCornerFlags() << 3) | crre.getEdgeType();
+}
+
+void GLCircularRRectEffect::setData(const GrGLUniformManager& uman,
+ const GrDrawEffect& drawEffect) {
+ const CircularRRectEffect& crre = drawEffect.castEffect<CircularRRectEffect>();
+ const SkRRect& rrect = crre.getRRect();
+ if (rrect != fPrevRRect) {
+ SkRect rect = rrect.getBounds();
+ SkScalar radius = 0;
+ switch (crre.getCircularCornerFlags()) {
+ case CircularRRectEffect::kAll_CornerFlags:
+ SkASSERT(rrect.isSimpleCircular());
+ radius = rrect.getSimpleRadii().fX;
+ SkASSERT(radius >= kRadiusMin);
+ rect.inset(radius, radius);
+ break;
+ case CircularRRectEffect::kTopLeft_CornerFlag:
+ radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX;
+ rect.fLeft += radius;
+ rect.fTop += radius;
+ rect.fRight += 0.5f;
+ rect.fBottom += 0.5f;
+ break;
+ case CircularRRectEffect::kTopRight_CornerFlag:
+ radius = rrect.radii(SkRRect::kUpperRight_Corner).fX;
+ rect.fLeft -= 0.5f;
+ rect.fTop += radius;
+ rect.fRight -= radius;
+ rect.fBottom += 0.5f;
+ break;
+ case CircularRRectEffect::kBottomRight_CornerFlag:
+ radius = rrect.radii(SkRRect::kLowerRight_Corner).fX;
+ rect.fLeft -= 0.5f;
+ rect.fTop -= 0.5f;
+ rect.fRight -= radius;
+ rect.fBottom -= radius;
+ break;
+ case CircularRRectEffect::kBottomLeft_CornerFlag:
+ radius = rrect.radii(SkRRect::kLowerLeft_Corner).fX;
+ rect.fLeft += radius;
+ rect.fTop -= 0.5f;
+ rect.fRight += 0.5f;
+ rect.fBottom -= radius;
+ break;
+ case CircularRRectEffect::kLeft_CornerFlags:
+ radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX;
+ rect.fLeft += radius;
+ rect.fTop += radius;
+ rect.fRight += 0.5f;
+ rect.fBottom -= radius;
+ break;
+ case CircularRRectEffect::kTop_CornerFlags:
+ radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX;
+ rect.fLeft += radius;
+ rect.fTop += radius;
+ rect.fRight -= radius;
+ rect.fBottom += 0.5f;
+ break;
+ case CircularRRectEffect::kRight_CornerFlags:
+ radius = rrect.radii(SkRRect::kUpperRight_Corner).fX;
+ rect.fLeft -= 0.5f;
+ rect.fTop += radius;
+ rect.fRight -= radius;
+ rect.fBottom -= radius;
+ break;
+ case CircularRRectEffect::kBottom_CornerFlags:
+ radius = rrect.radii(SkRRect::kLowerLeft_Corner).fX;
+ rect.fLeft += radius;
+ rect.fTop -= 0.5f;
+ rect.fRight -= radius;
+ rect.fBottom -= radius;
+ break;
+ default:
+ SkFAIL("Should have been one of the above cases.");
+ }
+ uman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
+ uman.set1f(fRadiusPlusHalfUniform, radius + 0.5f);
+ fPrevRRect = rrect;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+class GLEllipticalRRectEffect;
+
+class EllipticalRRectEffect : public GrEffect {
+public:
+ static GrEffectRef* Create(GrEffectEdgeType, const SkRRect&);
+
+ virtual ~EllipticalRRectEffect() {};
+ static const char* Name() { return "EllipticalRRect"; }
+
+ const SkRRect& getRRect() const { return fRRect; }
+
+
+ GrEffectEdgeType getEdgeType() const { return fEdgeType; }
+
+ typedef GLEllipticalRRectEffect GLEffect;
+
+ virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
+
+ virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
+
+private:
+ EllipticalRRectEffect(GrEffectEdgeType, const SkRRect&);
+
+ virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE;
+
+ SkRRect fRRect;
+ GrEffectEdgeType fEdgeType;
+
+ GR_DECLARE_EFFECT_TEST;
+
+ typedef GrEffect INHERITED;
+};
+
+GrEffectRef* EllipticalRRectEffect::Create(GrEffectEdgeType edgeType, const SkRRect& rrect) {
+ if (kFillAA_GrEffectEdgeType != edgeType && kInverseFillAA_GrEffectEdgeType != edgeType) {
+ return NULL;
+ }
+ return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(EllipticalRRectEffect, (edgeType, rrect))));
+}
+
+void EllipticalRRectEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
+ *validFlags = 0;
+}
+
+const GrBackendEffectFactory& EllipticalRRectEffect::getFactory() const {
+ return GrTBackendEffectFactory<EllipticalRRectEffect>::getInstance();
+}
+
+EllipticalRRectEffect::EllipticalRRectEffect(GrEffectEdgeType edgeType, const SkRRect& rrect)
+ : fRRect(rrect)
+ , fEdgeType(edgeType){
+ this->setWillReadFragmentPosition();
+}
+
+bool EllipticalRRectEffect::onIsEqual(const GrEffect& other) const {
+ const EllipticalRRectEffect& erre = CastEffect<EllipticalRRectEffect>(other);
+ return fEdgeType == erre.fEdgeType && fRRect == erre.fRRect;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+GR_DEFINE_EFFECT_TEST(EllipticalRRectEffect);
+
+GrEffectRef* EllipticalRRectEffect::TestCreate(SkRandom* random,
+ GrContext*,
+ const GrDrawTargetCaps& caps,
+ GrTexture*[]) {
+ SkScalar w = random->nextRangeScalar(20.f, 1000.f);
+ SkScalar h = random->nextRangeScalar(20.f, 1000.f);
+ SkVector r[4];
+ r[SkRRect::kUpperLeft_Corner].fX = random->nextRangeF(kRadiusMin, 9.f);
+ // ensure at least one corner really is elliptical
+ do {
+ r[SkRRect::kUpperLeft_Corner].fY = random->nextRangeF(kRadiusMin, 9.f);
+ } while (r[SkRRect::kUpperLeft_Corner].fY == r[SkRRect::kUpperLeft_Corner].fX);
+
+ SkRRect rrect;
+ if (random->nextBool()) {
+ // half the time create a four-radii rrect.
+ r[SkRRect::kLowerRight_Corner].fX = random->nextRangeF(kRadiusMin, 9.f);
+ r[SkRRect::kLowerRight_Corner].fY = random->nextRangeF(kRadiusMin, 9.f);
+
+ r[SkRRect::kUpperRight_Corner].fX = r[SkRRect::kLowerRight_Corner].fX;
+ r[SkRRect::kUpperRight_Corner].fY = r[SkRRect::kUpperLeft_Corner].fY;
+
+ r[SkRRect::kLowerLeft_Corner].fX = r[SkRRect::kUpperLeft_Corner].fX;
+ r[SkRRect::kLowerLeft_Corner].fY = r[SkRRect::kLowerRight_Corner].fY;
+
+ rrect.setRectRadii(SkRect::MakeWH(w, h), r);
+ } else {
+ rrect.setRectXY(SkRect::MakeWH(w, h), r[SkRRect::kUpperLeft_Corner].fX,
+ r[SkRRect::kUpperLeft_Corner].fY);
+ }
+ GrEffectRef* effect;
+ do {
+ GrEffectEdgeType et = (GrEffectEdgeType)random->nextULessThan(kGrEffectEdgeTypeCnt);
+ effect = GrRRectEffect::Create(et, rrect);
+ } while (NULL == effect);
+ return effect;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+class GLEllipticalRRectEffect : public GrGLEffect {
+public:
+ GLEllipticalRRectEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
+
+ virtual void emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect& drawEffect,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray&) SK_OVERRIDE;
+
+ static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
+
+ virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
+
+private:
+ GrGLUniformManager::UniformHandle fInnerRectUniform;
+ GrGLUniformManager::UniformHandle fInvRadiiSqdUniform;
+ SkRRect fPrevRRect;
+ typedef GrGLEffect INHERITED;
+};
+
+GLEllipticalRRectEffect::GLEllipticalRRectEffect(const GrBackendEffectFactory& factory,
+ const GrDrawEffect& drawEffect)
+ : INHERITED (factory) {
+ fPrevRRect.setEmpty();
+}
+
+void GLEllipticalRRectEffect::emitCode(GrGLShaderBuilder* builder,
+ const GrDrawEffect& drawEffect,
+ EffectKey key,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray&,
+ const TextureSamplerArray& samplers) {
+ const EllipticalRRectEffect& erre = drawEffect.castEffect<EllipticalRRectEffect>();
+ const char *rectName;
+ // The inner rect is the rrect bounds inset by the x/y radii
+ fInnerRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kVec4f_GrSLType,
+ "innerRect",
+ &rectName);
+ const char* fragmentPos = builder->fragmentPosition();
+ // At each quarter-ellipse corner we compute a vector that is the offset of the fragment pos
+ // to the ellipse center. The vector is pinned in x and y to be in the quarter-plane relevant
+ // to that corner. This means that points near the interior near the rrect top edge will have
+ // a vector that points straight up for both the TL left and TR corners. Computing an
+ // alpha from this vector at either the TR or TL corner will give the correct result. Similarly,
+ // fragments near the other three edges will get the correct AA. Fragments in the interior of
+ // the rrect will have a (0,0) vector at all four corners. So long as the radii > 0.5 they will
+ // correctly produce an alpha value of 1 at all four corners. We take the min of all the alphas.
+ // The code below is a simplified version of the above that performs maxs on the vector
+ // components before computing distances and alpha values so that only one distance computation
+ // need be computed to determine the min alpha.
+ builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos);
+ builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName);
+ switch (erre.getRRect().getType()) {
+ case SkRRect::kSimple_Type: {
+ const char *invRadiiXYSqdName;
+ fInvRadiiSqdUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kVec2f_GrSLType,
+ "invRadiiXY",
+ &invRadiiXYSqdName);
+ builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n");
+ // Z is the x/y offsets divided by squared radii.
+ builder->fsCodeAppendf("\t\tvec2 Z = dxy * %s;\n", invRadiiXYSqdName);
+ break;
+ }
+ case SkRRect::kNinePatch_Type: {
+ const char *invRadiiLTRBSqdName;
+ fInvRadiiSqdUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kVec4f_GrSLType,
+ "invRadiiLTRB",
+ &invRadiiLTRBSqdName);
+ builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n");
+ // Z is the x/y offsets divided by squared radii. We only care about the (at most) one
+ // corner where both the x and y offsets are positive, hence the maxes. (The inverse
+ // squared radii will always be positive.)
+ builder->fsCodeAppendf("\t\tvec2 Z = max(max(dxy0 * %s.xy, dxy1 * %s.zw), 0.0);\n",
+ invRadiiLTRBSqdName, invRadiiLTRBSqdName);
+ break;
+ }
+ default:
+ SkFAIL("RRect should always be simple or nine-patch.");
+ }
+ // implicit is the evaluation of (x/a)^2 + (y/b)^2 - 1.
+ builder->fsCodeAppend("\t\tfloat implicit = dot(Z, dxy) - 1.0;\n");
+ // grad_dot is the squared length of the gradient of the implicit.
+ builder->fsCodeAppendf("\t\tfloat grad_dot = 4.0 * dot(Z, Z);\n");
+ // avoid calling inversesqrt on zero.
+ builder->fsCodeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n");
+ builder->fsCodeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_dot);\n");
+
+ if (kFillAA_GrEffectEdgeType == erre.getEdgeType()) {
+ builder->fsCodeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1.0);\n");
+ } else {
+ builder->fsCodeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1.0);\n");
+ }
+
+ builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor,
+ (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
+}
+
+GrGLEffect::EffectKey GLEllipticalRRectEffect::GenKey(const GrDrawEffect& drawEffect,
+ const GrGLCaps&) {
+ const EllipticalRRectEffect& erre = drawEffect.castEffect<EllipticalRRectEffect>();
+ GR_STATIC_ASSERT(kLast_GrEffectEdgeType < (1 << 3));
+ return erre.getRRect().getType() | erre.getEdgeType() << 3;
+}
+
+void GLEllipticalRRectEffect::setData(const GrGLUniformManager& uman,
+ const GrDrawEffect& drawEffect) {
+ const EllipticalRRectEffect& erre = drawEffect.castEffect<EllipticalRRectEffect>();
+ const SkRRect& rrect = erre.getRRect();
+ if (rrect != fPrevRRect) {
+ SkRect rect = rrect.getBounds();
+ const SkVector& r0 = rrect.radii(SkRRect::kUpperLeft_Corner);
+ SkASSERT(r0.fX >= kRadiusMin);
+ SkASSERT(r0.fY >= kRadiusMin);
+ switch (erre.getRRect().getType()) {
+ case SkRRect::kSimple_Type:
+ rect.inset(r0.fX, r0.fY);
+ uman.set2f(fInvRadiiSqdUniform, 1.f / (r0.fX * r0.fX),
+ 1.f / (r0.fY * r0.fY));
+ break;
+ case SkRRect::kNinePatch_Type: {
+ const SkVector& r1 = rrect.radii(SkRRect::kLowerRight_Corner);
+ SkASSERT(r1.fX >= kRadiusMin);
+ SkASSERT(r1.fY >= kRadiusMin);
+ rect.fLeft += r0.fX;
+ rect.fTop += r0.fY;
+ rect.fRight -= r1.fX;
+ rect.fBottom -= r1.fY;
+ uman.set4f(fInvRadiiSqdUniform, 1.f / (r0.fX * r0.fX),
+ 1.f / (r0.fY * r0.fY),
+ 1.f / (r1.fX * r1.fX),
+ 1.f / (r1.fY * r1.fY));
+ break;
+ }
+ default:
+ SkFAIL("RRect should always be simple or nine-patch.");
+ }
+ uman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
+ fPrevRRect = rrect;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+GrEffectRef* GrRRectEffect::Create(GrEffectEdgeType edgeType, const SkRRect& rrect) {
+ if (rrect.isRect()) {
+ return GrConvexPolyEffect::Create(edgeType, rrect.getBounds());
+ }
+
+ if (rrect.isOval()) {
+ return GrOvalEffect::Create(edgeType, rrect.getBounds());
+ }
+
+ if (rrect.isSimple()) {
+ if (rrect.getSimpleRadii().fX < kRadiusMin || rrect.getSimpleRadii().fY < kRadiusMin) {
+ // In this case the corners are extremely close to rectangular and we collapse the
+ // clip to a rectangular clip.
+ return GrConvexPolyEffect::Create(edgeType, rrect.getBounds());
+ }
+ if (rrect.getSimpleRadii().fX == rrect.getSimpleRadii().fY) {
+ return CircularRRectEffect::Create(edgeType, CircularRRectEffect::kAll_CornerFlags,
+ rrect);
+ } else {
+ return EllipticalRRectEffect::Create(edgeType, rrect);
+ }
+ }
+
+ if (rrect.isComplex() || rrect.isNinePatch()) {
+ // Check for the "tab" cases - two adjacent circular corners and two square corners.
+ SkScalar circularRadius = 0;
+ uint32_t cornerFlags = 0;
+
+ SkVector radii[4];
+ bool squashedRadii = false;
+ for (int c = 0; c < 4; ++c) {
+ radii[c] = rrect.radii((SkRRect::Corner)c);
+ SkASSERT((0 == radii[c].fX) == (0 == radii[c].fY));
+ if (0 == radii[c].fX) {
+ // The corner is square, so no need to squash or flag as circular.
+ continue;
+ }
+ if (radii[c].fX < kRadiusMin || radii[c].fY < kRadiusMin) {
+ radii[c].set(0, 0);
+ squashedRadii = true;
+ continue;
+ }
+ if (radii[c].fX != radii[c].fY) {
+ cornerFlags = ~0U;
+ break;
+ }
+ if (!cornerFlags) {
+ circularRadius = radii[c].fX;
+ cornerFlags = 1 << c;
+ } else {
+ if (radii[c].fX != circularRadius) {
+ cornerFlags = ~0U;
+ break;
+ }
+ cornerFlags |= 1 << c;
+ }
+ }
+
+ switch (cornerFlags) {
+ case CircularRRectEffect::kAll_CornerFlags:
+ // This rrect should have been caught in the simple case above. Though, it would
+ // be correctly handled in the fallthrough code.
+ SkASSERT(false);
+ case CircularRRectEffect::kTopLeft_CornerFlag:
+ case CircularRRectEffect::kTopRight_CornerFlag:
+ case CircularRRectEffect::kBottomRight_CornerFlag:
+ case CircularRRectEffect::kBottomLeft_CornerFlag:
+ case CircularRRectEffect::kLeft_CornerFlags:
+ case CircularRRectEffect::kTop_CornerFlags:
+ case CircularRRectEffect::kRight_CornerFlags:
+ case CircularRRectEffect::kBottom_CornerFlags: {
+ SkTCopyOnFirstWrite<SkRRect> rr(rrect);
+ if (squashedRadii) {
+ rr.writable()->setRectRadii(rrect.getBounds(), radii);
+ }
+ return CircularRRectEffect::Create(edgeType, cornerFlags, *rr);
+ }
+ case CircularRRectEffect::kNone_CornerFlags:
+ return GrConvexPolyEffect::Create(edgeType, rrect.getBounds());
+ default: {
+ if (squashedRadii) {
+ // If we got here then we squashed some but not all the radii to zero. (If all
+ // had been squashed cornerFlags would be 0.) The elliptical effect doesn't
+ // support some rounded and some square corners.
+ return NULL;
+ }
+ if (rrect.isNinePatch()) {
+ return EllipticalRRectEffect::Create(edgeType, rrect);
+ }
+ return NULL;
+ }
+ }
+ }
+
+ return NULL;
+}
diff --git a/chromium/third_party/skia/src/gpu/effects/GrRRectEffect.h b/chromium/third_party/skia/src/gpu/effects/GrRRectEffect.h
new file mode 100644
index 00000000000..45ac5f43cfb
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/effects/GrRRectEffect.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrRRectEffect_DEFINED
+#define GrRRectEffect_DEFINED
+
+#include "GrTypes.h"
+#include "GrTypesPriv.h"
+
+class GrEffectRef;
+class SkRRect;
+
+namespace GrRRectEffect {
+ /**
+ * Creates an effect that performs anti-aliased clipping against a SkRRect. It doesn't support
+ * all varieties of SkRRect so the caller must check for a NULL return.
+ */
+ GrEffectRef* Create(GrEffectEdgeType, const SkRRect&);
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/effects/GrSimpleTextureEffect.cpp b/chromium/third_party/skia/src/gpu/effects/GrSimpleTextureEffect.cpp
index b27b737f39f..841561baa97 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrSimpleTextureEffect.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/GrSimpleTextureEffect.cpp
@@ -73,7 +73,7 @@ GrEffectRef* GrSimpleTextureEffect::TestCreate(SkRandom* random,
kLocal_GrCoordSet,
kPosition_GrCoordSet
};
- GrCoordSet coordSet = kCoordSets[random->nextULessThan(GR_ARRAY_COUNT(kCoordSets))];
+ GrCoordSet coordSet = kCoordSets[random->nextULessThan(SK_ARRAY_COUNT(kCoordSets))];
const SkMatrix& matrix = GrEffectUnitTest::TestMatrix(random);
return GrSimpleTextureEffect::Create(textures[texIdx], matrix, coordSet);
diff --git a/chromium/third_party/skia/src/gpu/effects/GrTextureDomain.cpp b/chromium/third_party/skia/src/gpu/effects/GrTextureDomain.cpp
index 70d61592245..656000b0595 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrTextureDomain.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/GrTextureDomain.cpp
@@ -16,7 +16,7 @@ GrTextureDomain::GrTextureDomain(const SkRect& domain, Mode mode, int index)
: fIndex(index) {
static const SkRect kFullRect = {0, 0, SK_Scalar1, SK_Scalar1};
- if (domain.contains(kFullRect)) {
+ if (domain.contains(kFullRect) && kClamp_Mode == mode) {
fMode = kIgnore_Mode;
} else {
fMode = mode;
diff --git a/chromium/third_party/skia/src/gpu/effects/GrTextureDomain.h b/chromium/third_party/skia/src/gpu/effects/GrTextureDomain.h
index f64d5c3cf58..b4c0b297f11 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrTextureDomain.h
+++ b/chromium/third_party/skia/src/gpu/effects/GrTextureDomain.h
@@ -31,6 +31,12 @@ public:
};
static const int kModeCount = kLastMode + 1;
+ static const GrTextureDomain& IgnoredDomain() {
+ static const SkRect gDummyRect = {0, 0, 0, 0};
+ static const GrTextureDomain gDomain(gDummyRect, kIgnore_Mode);
+ return gDomain;
+ }
+
/**
* @param index Pass a value >= 0 if using multiple texture domains in the same effect.
* It is used to keep inserted variables from causing name collisions.
diff --git a/chromium/third_party/skia/src/gpu/effects/GrTextureStripAtlas.cpp b/chromium/third_party/skia/src/gpu/effects/GrTextureStripAtlas.cpp
index 877215ecea2..0aa9dc35142 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrTextureStripAtlas.cpp
+++ b/chromium/third_party/skia/src/gpu/effects/GrTextureStripAtlas.cpp
@@ -158,7 +158,7 @@ int GrTextureStripAtlas::lockRow(const SkBitmap& data) {
fDesc.fContext->writeTexturePixels(fTexture,
0, rowNumber * fDesc.fRowHeight,
fDesc.fWidth, fDesc.fRowHeight,
- SkBitmapConfig2GrPixelConfig(data.config()),
+ SkImageInfo2GrPixelConfig(data.info()),
data.getPixels(),
data.rowBytes(),
GrContext::kDontFlush_PixelOpsFlag);
diff --git a/chromium/third_party/skia/src/gpu/effects/GrTextureStripAtlas.h b/chromium/third_party/skia/src/gpu/effects/GrTextureStripAtlas.h
index e06e273e26b..5227cc38bd7 100644
--- a/chromium/third_party/skia/src/gpu/effects/GrTextureStripAtlas.h
+++ b/chromium/third_party/skia/src/gpu/effects/GrTextureStripAtlas.h
@@ -79,7 +79,7 @@ private:
* The state of a single row in our cache, next/prev pointers allow these to be chained
* together to represent LRU status
*/
- struct AtlasRow : public SkNoncopyable {
+ struct AtlasRow : SkNoncopyable {
AtlasRow() : fKey(kEmptyAtlasRowKey), fLocks(0), fNext(NULL), fPrev(NULL) { }
// GenerationID of the bitmap that is represented by this row, 0xffffffff means "empty"
uint32_t fKey;
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLAssembleInterface.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLAssembleInterface.cpp
new file mode 100644
index 00000000000..98dabffe13c
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLAssembleInterface.cpp
@@ -0,0 +1,295 @@
+
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "GrGLAssembleInterface.h"
+#include "GrGLUtil.h"
+
+#define GET_PROC(F) functions->f ## F = (GrGL ## F ## Proc) get(ctx, "gl" #F)
+#define GET_PROC_SUFFIX(F, S) functions->f ## F = (GrGL ## F ## Proc) get(ctx, "gl" #F #S)
+#define GET_PROC_LOCAL(F) GrGL ## F ## Proc F = (GrGL ## F ## Proc) get(ctx, "gl" #F)
+
+const GrGLInterface* GrGLAssembleGLInterface(void* ctx, GrGLGetProc get) {
+ GET_PROC_LOCAL(GetString);
+ GET_PROC_LOCAL(GetStringi);
+ GET_PROC_LOCAL(GetIntegerv);
+
+ // GetStringi may be NULL depending on the GL version.
+ if (NULL == GetString || NULL == GetIntegerv) {
+ return NULL;
+ }
+
+ const char* versionString = (const char*) GetString(GR_GL_VERSION);
+ GrGLVersion glVer = GrGLGetVersionFromString(versionString);
+
+ if (glVer < GR_GL_VER(1,5) || GR_GL_INVALID_VER == glVer) {
+ // We must have array and element_array buffer objects.
+ return NULL;
+ }
+
+ GrGLExtensions extensions;
+ if (!extensions.init(kGL_GrGLStandard, GetString, GetStringi, GetIntegerv)) {
+ return NULL;
+ }
+
+ GrGLInterface* interface = SkNEW(GrGLInterface());
+ GrGLInterface::Functions* functions = &interface->fFunctions;
+
+ GET_PROC(ActiveTexture);
+ GET_PROC(AttachShader);
+ GET_PROC(BindAttribLocation);
+ GET_PROC(BindBuffer);
+ if (glVer >= GR_GL_VER(3,0)) {
+ GET_PROC(BindFragDataLocation);
+ }
+ GET_PROC(BeginQuery);
+ GET_PROC(BindTexture);
+ GET_PROC(BlendFunc);
+
+ if (glVer >= GR_GL_VER(1,4) ||
+ extensions.has("GL_ARB_imaging") ||
+ extensions.has("GL_EXT_blend_color")) {
+ GET_PROC(BlendColor);
+ }
+
+ GET_PROC(BufferData);
+ GET_PROC(BufferSubData);
+ GET_PROC(Clear);
+ GET_PROC(ClearColor);
+ GET_PROC(ClearStencil);
+ GET_PROC(ColorMask);
+ GET_PROC(CompileShader);
+ GET_PROC(CompressedTexImage2D);
+ GET_PROC(CompressedTexSubImage2D);
+ GET_PROC(CopyTexSubImage2D);
+ GET_PROC(CreateProgram);
+ GET_PROC(CreateShader);
+ GET_PROC(CullFace);
+ GET_PROC(DeleteBuffers);
+ GET_PROC(DeleteProgram);
+ GET_PROC(DeleteQueries);
+ GET_PROC(DeleteShader);
+ GET_PROC(DeleteTextures);
+ GET_PROC(DepthMask);
+ GET_PROC(Disable);
+ GET_PROC(DisableVertexAttribArray);
+ GET_PROC(DrawArrays);
+ GET_PROC(DrawBuffer);
+ GET_PROC(DrawBuffers);
+ GET_PROC(DrawElements);
+ GET_PROC(Enable);
+ GET_PROC(EnableVertexAttribArray);
+ GET_PROC(EndQuery);
+ GET_PROC(Finish);
+ GET_PROC(Flush);
+ GET_PROC(FrontFace);
+ GET_PROC(GenBuffers);
+ GET_PROC(GenerateMipmap);
+ GET_PROC(GetBufferParameteriv);
+ GET_PROC(GetError);
+ GET_PROC(GetIntegerv);
+ GET_PROC(GetQueryObjectiv);
+ GET_PROC(GetQueryObjectuiv);
+ if (glVer >= GR_GL_VER(3,3) || extensions.has("GL_ARB_timer_query")) {
+ GET_PROC(GetQueryObjecti64v);
+ GET_PROC(GetQueryObjectui64v);
+ GET_PROC(QueryCounter);
+ } else if (extensions.has("GL_EXT_timer_query")) {
+ GET_PROC_SUFFIX(GetQueryObjecti64v, EXT);
+ GET_PROC_SUFFIX(GetQueryObjectui64v, EXT);
+ }
+ GET_PROC(GetQueryiv);
+ GET_PROC(GetProgramInfoLog);
+ GET_PROC(GetProgramiv);
+ GET_PROC(GetShaderInfoLog);
+ GET_PROC(GetShaderiv);
+ GET_PROC(GetString);
+ GET_PROC(GetStringi);
+ GET_PROC(GetTexLevelParameteriv);
+ GET_PROC(GenQueries);
+ GET_PROC(GenTextures);
+ GET_PROC(GetUniformLocation);
+ GET_PROC(LineWidth);
+ GET_PROC(LinkProgram);
+ GET_PROC(MapBuffer);
+ if (extensions.has("GL_EXT_direct_state_access")) {
+ GET_PROC_SUFFIX(MatrixLoadf, EXT);
+ GET_PROC_SUFFIX(MatrixLoadIdentity, EXT);
+ }
+ GET_PROC(PixelStorei);
+ GET_PROC(ReadBuffer);
+ GET_PROC(ReadPixels);
+ GET_PROC(Scissor);
+ GET_PROC(ShaderSource);
+ GET_PROC(StencilFunc);
+ GET_PROC(StencilFuncSeparate);
+ GET_PROC(StencilMask);
+ GET_PROC(StencilMaskSeparate);
+ GET_PROC(StencilOp);
+ GET_PROC(StencilOpSeparate);
+ GET_PROC(TexImage2D);
+ GET_PROC(TexParameteri);
+ GET_PROC(TexParameteriv);
+ if (glVer >= GR_GL_VER(4,2) || extensions.has("GL_ARB_texture_storage")) {
+ GET_PROC(TexStorage2D);
+ } else if (extensions.has("GL_EXT_texture_storage")) {
+ GET_PROC_SUFFIX(TexStorage2D, EXT);
+ }
+ GET_PROC(TexSubImage2D);
+ GET_PROC(Uniform1f);
+ GET_PROC(Uniform1i);
+ GET_PROC(Uniform1fv);
+ GET_PROC(Uniform1iv);
+ GET_PROC(Uniform2f);
+ GET_PROC(Uniform2i);
+ GET_PROC(Uniform2fv);
+ GET_PROC(Uniform2iv);
+ GET_PROC(Uniform3f);
+ GET_PROC(Uniform3i);
+ GET_PROC(Uniform3fv);
+ GET_PROC(Uniform3iv);
+ GET_PROC(Uniform4f);
+ GET_PROC(Uniform4i);
+ GET_PROC(Uniform4fv);
+ GET_PROC(Uniform4iv);
+ GET_PROC(UniformMatrix2fv);
+ GET_PROC(UniformMatrix3fv);
+ GET_PROC(UniformMatrix4fv);
+ GET_PROC(UnmapBuffer);
+ GET_PROC(UseProgram);
+ GET_PROC(VertexAttrib4fv);
+ GET_PROC(VertexAttribPointer);
+ GET_PROC(Viewport);
+ GET_PROC(BindFragDataLocationIndexed);
+
+ if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_ARB_vertex_array_object")) {
+ // no ARB suffix for GL_ARB_vertex_array_object
+ GET_PROC(BindVertexArray);
+ GET_PROC(GenVertexArrays);
+ GET_PROC(DeleteVertexArrays);
+ }
+
+ if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_ARB_map_buffer_range")) {
+ GET_PROC(MapBufferRange);
+ GET_PROC(FlushMappedBufferRange);
+ }
+
+ // First look for GL3.0 FBO or GL_ARB_framebuffer_object (same since
+ // GL_ARB_framebuffer_object doesn't use ARB suffix.)
+ if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_ARB_framebuffer_object")) {
+ GET_PROC(GenFramebuffers);
+ GET_PROC(GetFramebufferAttachmentParameteriv);
+ GET_PROC(GetRenderbufferParameteriv);
+ GET_PROC(BindFramebuffer);
+ GET_PROC(FramebufferTexture2D);
+ GET_PROC(CheckFramebufferStatus);
+ GET_PROC(DeleteFramebuffers);
+ GET_PROC(RenderbufferStorage);
+ GET_PROC(GenRenderbuffers);
+ GET_PROC(DeleteRenderbuffers);
+ GET_PROC(FramebufferRenderbuffer);
+ GET_PROC(BindRenderbuffer);
+ GET_PROC(RenderbufferStorageMultisample);
+ GET_PROC(BlitFramebuffer);
+ } else if (extensions.has("GL_EXT_framebuffer_object")) {
+ GET_PROC_SUFFIX(GenFramebuffers, EXT);
+ GET_PROC_SUFFIX(GetFramebufferAttachmentParameteriv, EXT);
+ GET_PROC_SUFFIX(GetRenderbufferParameteriv, EXT);
+ GET_PROC_SUFFIX(BindFramebuffer, EXT);
+ GET_PROC_SUFFIX(FramebufferTexture2D, EXT);
+ GET_PROC_SUFFIX(CheckFramebufferStatus, EXT);
+ GET_PROC_SUFFIX(DeleteFramebuffers, EXT);
+ GET_PROC_SUFFIX(RenderbufferStorage, EXT);
+ GET_PROC_SUFFIX(GenRenderbuffers, EXT);
+ GET_PROC_SUFFIX(DeleteRenderbuffers, EXT);
+ GET_PROC_SUFFIX(FramebufferRenderbuffer, EXT);
+ GET_PROC_SUFFIX(BindRenderbuffer, EXT);
+ if (extensions.has("GL_EXT_framebuffer_multisample")) {
+ GET_PROC_SUFFIX(RenderbufferStorageMultisample, EXT);
+ }
+ if (extensions.has("GL_EXT_framebuffer_blit")) {
+ GET_PROC_SUFFIX(BlitFramebuffer, EXT);
+ }
+ } else {
+ // we must have FBOs
+ delete interface;
+ return NULL;
+ }
+
+ if (extensions.has("GL_NV_path_rendering")) {
+ GET_PROC_SUFFIX(PathCommands, NV);
+ GET_PROC_SUFFIX(PathCoords, NV);
+ GET_PROC_SUFFIX(PathSubCommands, NV);
+ GET_PROC_SUFFIX(PathSubCoords, NV);
+ GET_PROC_SUFFIX(PathString, NV);
+ GET_PROC_SUFFIX(PathGlyphs, NV);
+ GET_PROC_SUFFIX(PathGlyphRange, NV);
+ GET_PROC_SUFFIX(WeightPaths, NV);
+ GET_PROC_SUFFIX(CopyPath, NV);
+ GET_PROC_SUFFIX(InterpolatePaths, NV);
+ GET_PROC_SUFFIX(TransformPath, NV);
+ GET_PROC_SUFFIX(PathParameteriv, NV);
+ GET_PROC_SUFFIX(PathParameteri, NV);
+ GET_PROC_SUFFIX(PathParameterfv, NV);
+ GET_PROC_SUFFIX(PathParameterf, NV);
+ GET_PROC_SUFFIX(PathDashArray, NV);
+ GET_PROC_SUFFIX(GenPaths, NV);
+ GET_PROC_SUFFIX(DeletePaths, NV);
+ GET_PROC_SUFFIX(IsPath, NV);
+ GET_PROC_SUFFIX(PathStencilFunc, NV);
+ GET_PROC_SUFFIX(PathStencilDepthOffset, NV);
+ GET_PROC_SUFFIX(StencilFillPath, NV);
+ GET_PROC_SUFFIX(StencilStrokePath, NV);
+ GET_PROC_SUFFIX(StencilFillPathInstanced, NV);
+ GET_PROC_SUFFIX(StencilStrokePathInstanced, NV);
+ GET_PROC_SUFFIX(PathCoverDepthFunc, NV);
+ GET_PROC_SUFFIX(PathColorGen, NV);
+ GET_PROC_SUFFIX(PathTexGen, NV);
+ GET_PROC_SUFFIX(PathFogGen, NV);
+ GET_PROC_SUFFIX(CoverFillPath, NV);
+ GET_PROC_SUFFIX(CoverStrokePath, NV);
+ GET_PROC_SUFFIX(CoverFillPathInstanced, NV);
+ GET_PROC_SUFFIX(CoverStrokePathInstanced, NV);
+ GET_PROC_SUFFIX(GetPathParameteriv, NV);
+ GET_PROC_SUFFIX(GetPathParameterfv, NV);
+ GET_PROC_SUFFIX(GetPathCommands, NV);
+ GET_PROC_SUFFIX(GetPathCoords, NV);
+ GET_PROC_SUFFIX(GetPathDashArray, NV);
+ GET_PROC_SUFFIX(GetPathMetrics, NV);
+ GET_PROC_SUFFIX(GetPathMetricRange, NV);
+ GET_PROC_SUFFIX(GetPathSpacing, NV);
+ GET_PROC_SUFFIX(GetPathColorGeniv, NV);
+ GET_PROC_SUFFIX(GetPathColorGenfv, NV);
+ GET_PROC_SUFFIX(GetPathTexGeniv, NV);
+ GET_PROC_SUFFIX(GetPathTexGenfv, NV);
+ GET_PROC_SUFFIX(IsPointInFillPath, NV);
+ GET_PROC_SUFFIX(IsPointInStrokePath, NV);
+ GET_PROC_SUFFIX(GetPathLength, NV);
+ GET_PROC_SUFFIX(PointAlongPath, NV);
+ }
+
+ if (extensions.has("GL_EXT_debug_marker")) {
+ GET_PROC_SUFFIX(InsertEventMarker, EXT);
+ GET_PROC_SUFFIX(PushGroupMarker, EXT);
+ GET_PROC_SUFFIX(PopGroupMarker, EXT);
+ }
+
+ if (glVer >= GR_GL_VER(4,3) || extensions.has("GL_ARB_invalidate_subdata")) {
+ GET_PROC(InvalidateBufferData);
+ GET_PROC(InvalidateBufferSubData);
+ GET_PROC(InvalidateFramebuffer);
+ GET_PROC(InvalidateSubFramebuffer);
+ GET_PROC(InvalidateTexImage);
+ GET_PROC(InvalidateTexSubImage);
+ }
+
+ interface->fStandard = kGL_GrGLStandard;
+ interface->fExtensions.swap(&extensions);
+
+ return interface;
+}
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLAssembleInterface.h b/chromium/third_party/skia/src/gpu/gl/GrGLAssembleInterface.h
new file mode 100644
index 00000000000..36a45134474
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLAssembleInterface.h
@@ -0,0 +1,18 @@
+
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "gl/GrGLInterface.h"
+
+typedef void(*GrGLFuncPtr)();
+typedef GrGLFuncPtr (*GrGLGetProc)(void* ctx, const char name[]);
+
+/**
+ * Generic function for creating a GrGLInterface for an OpenGL (but not GLES) context. It calls
+ * get() to get each function address. ctx is a generic ptr passed to and interpreted by get().
+ */
+const GrGLInterface* GrGLAssembleGLInterface(void* ctx, GrGLGetProc get);
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLBufferImpl.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLBufferImpl.cpp
index 3c75b9fe6a1..ae578a20fa8 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLBufferImpl.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLBufferImpl.cpp
@@ -23,23 +23,25 @@
GrGLBufferImpl::GrGLBufferImpl(GrGpuGL* gpu, const Desc& desc, GrGLenum bufferType)
: fDesc(desc)
, fBufferType(bufferType)
- , fLockPtr(NULL) {
+ , fMapPtr(NULL) {
if (0 == desc.fID) {
fCPUData = sk_malloc_flags(desc.fSizeInBytes, SK_MALLOC_THROW);
+ fGLSizeInBytes = 0;
} else {
fCPUData = NULL;
+ // We assume that the GL buffer was created at the desc's size initially.
+ fGLSizeInBytes = fDesc.fSizeInBytes;
}
VALIDATE();
}
void GrGLBufferImpl::release(GrGpuGL* gpu) {
+ VALIDATE();
// make sure we've not been abandoned or already released
if (NULL != fCPUData) {
- VALIDATE();
sk_free(fCPUData);
fCPUData = NULL;
} else if (fDesc.fID && !fDesc.fIsWrapped) {
- VALIDATE();
GL_CALL(gpu, DeleteBuffers(1, &fDesc.fID));
if (GR_GL_ARRAY_BUFFER == fBufferType) {
gpu->notifyVertexBufferDelete(fDesc.fID);
@@ -48,15 +50,19 @@ void GrGLBufferImpl::release(GrGpuGL* gpu) {
gpu->notifyIndexBufferDelete(fDesc.fID);
}
fDesc.fID = 0;
+ fGLSizeInBytes = 0;
}
- fLockPtr = NULL;
+ fMapPtr = NULL;
+ VALIDATE();
}
void GrGLBufferImpl::abandon() {
fDesc.fID = 0;
- fLockPtr = NULL;
+ fGLSizeInBytes = 0;
+ fMapPtr = NULL;
sk_free(fCPUData);
fCPUData = NULL;
+ VALIDATE();
}
void GrGLBufferImpl::bind(GrGpuGL* gpu) const {
@@ -67,45 +73,95 @@ void GrGLBufferImpl::bind(GrGpuGL* gpu) const {
SkASSERT(GR_GL_ELEMENT_ARRAY_BUFFER == fBufferType);
gpu->bindIndexBufferAndDefaultVertexArray(fDesc.fID);
}
+ VALIDATE();
}
-void* GrGLBufferImpl::lock(GrGpuGL* gpu) {
+void* GrGLBufferImpl::map(GrGpuGL* gpu) {
VALIDATE();
- SkASSERT(!this->isLocked());
+ SkASSERT(!this->isMapped());
if (0 == fDesc.fID) {
- fLockPtr = fCPUData;
- } else if (gpu->caps()->bufferLockSupport()) {
- this->bind(gpu);
- // Let driver know it can discard the old data
- GL_CALL(gpu, BufferData(fBufferType,
- (GrGLsizeiptr) fDesc.fSizeInBytes,
- NULL,
- fDesc.fDynamic ? DYNAMIC_USAGE_PARAM : GR_GL_STATIC_DRAW));
- GR_GL_CALL_RET(gpu->glInterface(),
- fLockPtr,
- MapBuffer(fBufferType, GR_GL_WRITE_ONLY));
+ fMapPtr = fCPUData;
+ } else {
+ switch (gpu->glCaps().mapBufferType()) {
+ case GrGLCaps::kNone_MapBufferType:
+ VALIDATE();
+ return NULL;
+ case GrGLCaps::kMapBuffer_MapBufferType:
+ this->bind(gpu);
+ // Let driver know it can discard the old data
+ if (GR_GL_USE_BUFFER_DATA_NULL_HINT || fDesc.fSizeInBytes != fGLSizeInBytes) {
+ fGLSizeInBytes = fDesc.fSizeInBytes;
+ GL_CALL(gpu,
+ BufferData(fBufferType, fGLSizeInBytes, NULL,
+ fDesc.fDynamic ? DYNAMIC_USAGE_PARAM : GR_GL_STATIC_DRAW));
+ }
+ GR_GL_CALL_RET(gpu->glInterface(), fMapPtr,
+ MapBuffer(fBufferType, GR_GL_WRITE_ONLY));
+ break;
+ case GrGLCaps::kMapBufferRange_MapBufferType: {
+ this->bind(gpu);
+ // Make sure the GL buffer size agrees with fDesc before mapping.
+ if (fDesc.fSizeInBytes != fGLSizeInBytes) {
+ fGLSizeInBytes = fDesc.fSizeInBytes;
+ GL_CALL(gpu,
+ BufferData(fBufferType, fGLSizeInBytes, NULL,
+ fDesc.fDynamic ? DYNAMIC_USAGE_PARAM : GR_GL_STATIC_DRAW));
+ }
+ static const GrGLbitfield kAccess = GR_GL_MAP_INVALIDATE_BUFFER_BIT |
+ GR_GL_MAP_WRITE_BIT;
+ GR_GL_CALL_RET(gpu->glInterface(),
+ fMapPtr,
+ MapBufferRange(fBufferType, 0, fGLSizeInBytes, kAccess));
+ break;
+ }
+ case GrGLCaps::kChromium_MapBufferType:
+ this->bind(gpu);
+ // Make sure the GL buffer size agrees with fDesc before mapping.
+ if (fDesc.fSizeInBytes != fGLSizeInBytes) {
+ fGLSizeInBytes = fDesc.fSizeInBytes;
+ GL_CALL(gpu,
+ BufferData(fBufferType, fGLSizeInBytes, NULL,
+ fDesc.fDynamic ? DYNAMIC_USAGE_PARAM : GR_GL_STATIC_DRAW));
+ }
+ GR_GL_CALL_RET(gpu->glInterface(),
+ fMapPtr,
+ MapBufferSubData(fBufferType, 0, fGLSizeInBytes, GR_GL_WRITE_ONLY));
+ break;
+ }
}
- return fLockPtr;
+ VALIDATE();
+ return fMapPtr;
}
-void GrGLBufferImpl::unlock(GrGpuGL* gpu) {
+void GrGLBufferImpl::unmap(GrGpuGL* gpu) {
VALIDATE();
- SkASSERT(this->isLocked());
+ SkASSERT(this->isMapped());
if (0 != fDesc.fID) {
- SkASSERT(gpu->caps()->bufferLockSupport());
- this->bind(gpu);
- GL_CALL(gpu, UnmapBuffer(fBufferType));
+ switch (gpu->glCaps().mapBufferType()) {
+ case GrGLCaps::kNone_MapBufferType:
+ SkDEBUGFAIL("Shouldn't get here.");
+ return;
+ case GrGLCaps::kMapBuffer_MapBufferType: // fall through
+ case GrGLCaps::kMapBufferRange_MapBufferType:
+ this->bind(gpu);
+ GL_CALL(gpu, UnmapBuffer(fBufferType));
+ break;
+ case GrGLCaps::kChromium_MapBufferType:
+ this->bind(gpu);
+ GR_GL_CALL(gpu->glInterface(), UnmapBufferSubData(fMapPtr));
+ break;
+ }
}
- fLockPtr = NULL;
+ fMapPtr = NULL;
}
-bool GrGLBufferImpl::isLocked() const {
+bool GrGLBufferImpl::isMapped() const {
VALIDATE();
- return NULL != fLockPtr;
+ return NULL != fMapPtr;
}
bool GrGLBufferImpl::updateData(GrGpuGL* gpu, const void* src, size_t srcSizeInBytes) {
- SkASSERT(!this->isLocked());
+ SkASSERT(!this->isMapped());
VALIDATE();
if (srcSizeInBytes > fDesc.fSizeInBytes) {
return false;
@@ -127,13 +183,14 @@ bool GrGLBufferImpl::updateData(GrGpuGL* gpu, const void* src, size_t srcSizeInB
// draws that reference the old contents. With this hint it can
// assign a different allocation for the new contents to avoid
// flushing the gpu past draws consuming the old contents.
- GL_CALL(gpu, BufferData(fBufferType, (GrGLsizeiptr) fDesc.fSizeInBytes, NULL, usage));
+ fGLSizeInBytes = fDesc.fSizeInBytes;
+ GL_CALL(gpu, BufferData(fBufferType, fGLSizeInBytes, NULL, usage));
GL_CALL(gpu, BufferSubData(fBufferType, 0, (GrGLsizeiptr) srcSizeInBytes, src));
}
#else
// Note that we're cheating on the size here. Currently no methods
// allow a partial update that preserves contents of non-updated
- // portions of the buffer (lock() does a glBufferData(..size, NULL..))
+ // portions of the buffer (map() does a glBufferData(..size, NULL..))
bool doSubData = false;
#if GR_GL_MAC_BUFFER_OBJECT_PERFOMANCE_WORKAROUND
static int N = 0;
@@ -147,10 +204,12 @@ bool GrGLBufferImpl::updateData(GrGpuGL* gpu, const void* src, size_t srcSizeInB
// Chromium's command buffer may turn a glBufferSubData where the size
// exactly matches the buffer size into a glBufferData. So we tack 1
// extra byte onto the glBufferData.
- GL_CALL(gpu, BufferData(fBufferType, srcSizeInBytes + 1, NULL, usage));
+ fGLSizeInBytes = srcSizeInBytes + 1;
+ GL_CALL(gpu, BufferData(fBufferType, fGLSizeInBytes, NULL, usage));
GL_CALL(gpu, BufferSubData(fBufferType, 0, srcSizeInBytes, src));
} else {
- GL_CALL(gpu, BufferData(fBufferType, srcSizeInBytes, src, usage));
+ fGLSizeInBytes = srcSizeInBytes;
+ GL_CALL(gpu, BufferData(fBufferType, fGLSizeInBytes, src, usage));
}
#endif
return true;
@@ -161,5 +220,7 @@ void GrGLBufferImpl::validate() const {
// The following assert isn't valid when the buffer has been abandoned:
// SkASSERT((0 == fDesc.fID) == (NULL != fCPUData));
SkASSERT(0 != fDesc.fID || !fDesc.fIsWrapped);
- SkASSERT(NULL == fCPUData || NULL == fLockPtr || fCPUData == fLockPtr);
+ SkASSERT(NULL == fCPUData || 0 == fGLSizeInBytes);
+ SkASSERT(NULL == fMapPtr || NULL != fCPUData || fGLSizeInBytes == fDesc.fSizeInBytes);
+ SkASSERT(NULL == fCPUData || NULL == fMapPtr || fCPUData == fMapPtr);
}
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLBufferImpl.h b/chromium/third_party/skia/src/gpu/gl/GrGLBufferImpl.h
index ab2555650f1..279075f4c9e 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLBufferImpl.h
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLBufferImpl.h
@@ -17,7 +17,7 @@ class GrGpuGL;
* This class serves as the implementation of GrGL*Buffer classes. It was written to avoid code
* duplication in those classes.
*/
-class GrGLBufferImpl : public SkNoncopyable {
+class GrGLBufferImpl : SkNoncopyable {
public:
struct Desc {
bool fIsWrapped;
@@ -40,10 +40,9 @@ public:
void bind(GrGpuGL* gpu) const;
- void* lock(GrGpuGL* gpu);
- void* lockPtr() const { return fLockPtr; }
- void unlock(GrGpuGL* gpu);
- bool isLocked() const;
+ void* map(GrGpuGL* gpu);
+ void unmap(GrGpuGL* gpu);
+ bool isMapped() const;
bool updateData(GrGpuGL* gpu, const void* src, size_t srcSizeInBytes);
private:
@@ -52,7 +51,9 @@ private:
Desc fDesc;
GrGLenum fBufferType; // GL_ARRAY_BUFFER or GL_ELEMENT_ARRAY_BUFFER
void* fCPUData;
- void* fLockPtr;
+ void* fMapPtr;
+ size_t fGLSizeInBytes; // In certain cases we make the size of the GL buffer object
+ // smaller or larger than the size in fDesc.
typedef SkNoncopyable INHERITED;
};
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLCaps.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLCaps.cpp
index 8d8c02254a5..fdf6cacc08b 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLCaps.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLCaps.cpp
@@ -23,12 +23,14 @@ void GrGLCaps::reset() {
fStencilVerifiedColorConfigs.reset();
fMSFBOType = kNone_MSFBOType;
fFBFetchType = kNone_FBFetchType;
+ fInvalidateFBType = kNone_InvalidateFBType;
+ fLATCAlias = kLATC_LATCAlias;
+ fMapBufferType = kNone_MapBufferType;
fMaxFragmentUniformVectors = 0;
fMaxVertexAttributes = 0;
fMaxFragmentTextureUnits = 0;
fMaxFixedFunctionTextureCoords = 0;
fRGBA8RenderbufferSupport = false;
- fBGRAFormatSupport = false;
fBGRAIsInternalFormat = false;
fTextureSwizzleSupport = false;
fUnpackRowLengthSupport = false;
@@ -44,28 +46,29 @@ void GrGLCaps::reset() {
fVertexArrayObjectSupport = false;
fUseNonVBOVertexAndIndexDynamicData = false;
fIsCoreProfile = false;
- fFixedFunctionSupport = false;
- fDiscardFBSupport = false;
fFullClearIsFree = false;
+ fDropsTileOnZeroDivide = false;
}
GrGLCaps::GrGLCaps(const GrGLCaps& caps) : GrDrawTargetCaps() {
*this = caps;
}
-GrGLCaps& GrGLCaps::operator = (const GrGLCaps& caps) {
+GrGLCaps& GrGLCaps::operator= (const GrGLCaps& caps) {
INHERITED::operator=(caps);
fVerifiedColorConfigs = caps.fVerifiedColorConfigs;
fStencilFormats = caps.fStencilFormats;
fStencilVerifiedColorConfigs = caps.fStencilVerifiedColorConfigs;
+ fLATCAlias = caps.fLATCAlias;
fMaxFragmentUniformVectors = caps.fMaxFragmentUniformVectors;
fMaxVertexAttributes = caps.fMaxVertexAttributes;
fMaxFragmentTextureUnits = caps.fMaxFragmentTextureUnits;
fMaxFixedFunctionTextureCoords = caps.fMaxFixedFunctionTextureCoords;
fMSFBOType = caps.fMSFBOType;
fFBFetchType = caps.fFBFetchType;
+ fInvalidateFBType = caps.fInvalidateFBType;
+ fMapBufferType = caps.fMapBufferType;
fRGBA8RenderbufferSupport = caps.fRGBA8RenderbufferSupport;
- fBGRAFormatSupport = caps.fBGRAFormatSupport;
fBGRAIsInternalFormat = caps.fBGRAIsInternalFormat;
fTextureSwizzleSupport = caps.fTextureSwizzleSupport;
fUnpackRowLengthSupport = caps.fUnpackRowLengthSupport;
@@ -81,32 +84,31 @@ GrGLCaps& GrGLCaps::operator = (const GrGLCaps& caps) {
fVertexArrayObjectSupport = caps.fVertexArrayObjectSupport;
fUseNonVBOVertexAndIndexDynamicData = caps.fUseNonVBOVertexAndIndexDynamicData;
fIsCoreProfile = caps.fIsCoreProfile;
- fFixedFunctionSupport = caps.fFixedFunctionSupport;
- fDiscardFBSupport = caps.fDiscardFBSupport;
fFullClearIsFree = caps.fFullClearIsFree;
+ fDropsTileOnZeroDivide = caps.fDropsTileOnZeroDivide;
return *this;
}
-void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
+bool GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
this->reset();
if (!ctxInfo.isInitialized()) {
- return;
+ return false;
}
- GrGLBinding binding = ctxInfo.binding();
+ GrGLStandard standard = ctxInfo.standard();
GrGLVersion version = ctxInfo.version();
/**************************************************************************
* Caps specific to GrGLCaps
**************************************************************************/
- if (kES_GrGLBinding == binding) {
+ if (kGLES_GrGLStandard == standard) {
GR_GL_GetIntegerv(gli, GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS,
&fMaxFragmentUniformVectors);
} else {
- SkASSERT(kDesktop_GrGLBinding == binding);
+ SkASSERT(kGL_GrGLStandard == standard);
GrGLint max;
GR_GL_GetIntegerv(gli, GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max);
fMaxFragmentUniformVectors = max / 4;
@@ -116,7 +118,6 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
fIsCoreProfile = SkToBool(profileMask & GR_GL_CONTEXT_CORE_PROFILE_BIT);
}
if (!fIsCoreProfile) {
- fFixedFunctionSupport = true;
GR_GL_GetIntegerv(gli, GR_GL_MAX_TEXTURE_COORDS, &fMaxFixedFunctionTextureCoords);
// Sanity check
SkASSERT(fMaxFixedFunctionTextureCoords > 0 && fMaxFixedFunctionTextureCoords < 128);
@@ -125,7 +126,7 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
GR_GL_GetIntegerv(gli, GR_GL_MAX_VERTEX_ATTRIBS, &fMaxVertexAttributes);
GR_GL_GetIntegerv(gli, GR_GL_MAX_TEXTURE_IMAGE_UNITS, &fMaxFragmentTextureUnits);
- if (kDesktop_GrGLBinding == binding) {
+ if (kGL_GrGLStandard == standard) {
fRGBA8RenderbufferSupport = true;
} else {
fRGBA8RenderbufferSupport = version >= GR_GL_VER(3,0) ||
@@ -133,28 +134,14 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
ctxInfo.hasExtension("GL_ARM_rgba8");
}
- if (kDesktop_GrGLBinding == binding) {
- fBGRAFormatSupport = version >= GR_GL_VER(1,2) ||
- ctxInfo.hasExtension("GL_EXT_bgra");
- } else {
- if (ctxInfo.hasExtension("GL_APPLE_texture_format_BGRA8888")) {
- fBGRAFormatSupport = true;
- } else if (ctxInfo.hasExtension("GL_EXT_texture_format_BGRA8888")) {
- fBGRAFormatSupport = true;
- fBGRAIsInternalFormat = true;
- }
- SkASSERT(fBGRAFormatSupport ||
- kSkia8888_GrPixelConfig != kBGRA_8888_GrPixelConfig);
- }
-
- if (kDesktop_GrGLBinding == binding) {
+ if (kGL_GrGLStandard == standard) {
fTextureSwizzleSupport = version >= GR_GL_VER(3,3) ||
ctxInfo.hasExtension("GL_ARB_texture_swizzle");
} else {
fTextureSwizzleSupport = version >= GR_GL_VER(3,0);
}
- if (kDesktop_GrGLBinding == binding) {
+ if (kGL_GrGLStandard == standard) {
fUnpackRowLengthSupport = true;
fUnpackFlipYSupport = false;
fPackRowLengthSupport = true;
@@ -169,10 +156,10 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
ctxInfo.hasExtension("GL_ANGLE_pack_reverse_row_order");
}
- fTextureUsageSupport = (kES_GrGLBinding == binding) &&
+ fTextureUsageSupport = (kGLES_GrGLStandard == standard) &&
ctxInfo.hasExtension("GL_ANGLE_texture_usage");
- if (kDesktop_GrGLBinding == binding) {
+ if (kGL_GrGLStandard == standard) {
// The EXT version can apply to either GL or GLES.
fTexStorageSupport = version >= GR_GL_VER(4,2) ||
ctxInfo.hasExtension("GL_ARB_texture_storage") ||
@@ -186,7 +173,7 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
// ARB_texture_rg is part of OpenGL 3.0, but mesa doesn't support it if
// it doesn't have ARB_texture_rg extension.
- if (kDesktop_GrGLBinding == binding) {
+ if (kGL_GrGLStandard == standard) {
if (ctxInfo.isMesa()) {
fTextureRedSupport = ctxInfo.hasExtension("GL_ARB_texture_rg");
} else {
@@ -198,13 +185,13 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
ctxInfo.hasExtension("GL_EXT_texture_rg");
}
- fImagingSupport = kDesktop_GrGLBinding == binding &&
+ fImagingSupport = kGL_GrGLStandard == standard &&
ctxInfo.hasExtension("GL_ARB_imaging");
// ES 2 only guarantees RGBA/uchar + one other format/type combo for
// ReadPixels. The other format has to checked at run-time since it
// can change based on which render target is bound
- fTwoFormatLimit = kES_GrGLBinding == binding;
+ fTwoFormatLimit = kGLES_GrGLStandard == standard;
// Known issue on at least some Intel platforms:
// http://code.google.com/p/skia/issues/detail?id=946
@@ -222,13 +209,21 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
fUseNonVBOVertexAndIndexDynamicData = true;
}
- fDiscardFBSupport = ctxInfo.hasExtension("GL_EXT_discard_framebuffer");
+ if ((kGL_GrGLStandard == standard && version >= GR_GL_VER(4,3)) ||
+ (kGLES_GrGLStandard == standard && version >= GR_GL_VER(3,0)) ||
+ ctxInfo.hasExtension("GL_ARB_invalidate_subdata")) {
+ fDiscardRenderTargetSupport = true;
+ fInvalidateFBType = kInvalidate_InvalidateFBType;
+ } else if (ctxInfo.hasExtension("GL_EXT_discard_framebuffer")) {
+ fDiscardRenderTargetSupport = true;
+ fInvalidateFBType = kDiscard_InvalidateFBType;
+ }
if (kARM_GrGLVendor == ctxInfo.vendor() || kImagination_GrGLVendor == ctxInfo.vendor()) {
fFullClearIsFree = true;
}
- if (kDesktop_GrGLBinding == binding) {
+ if (kGL_GrGLStandard == standard) {
fVertexArrayObjectSupport = version >= GR_GL_VER(3, 0) ||
ctxInfo.hasExtension("GL_ARB_vertex_array_object");
} else {
@@ -236,7 +231,7 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
ctxInfo.hasExtension("GL_OES_vertex_array_object");
}
- if (kES_GrGLBinding == binding) {
+ if (kGLES_GrGLStandard == standard) {
if (ctxInfo.hasExtension("GL_EXT_shader_framebuffer_fetch")) {
fFBFetchType = kEXT_FBFetchType;
} else if (ctxInfo.hasExtension("GL_NV_shader_framebuffer_fetch")) {
@@ -244,26 +239,16 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
}
}
+ // Adreno GPUs have a tendency to drop tiles when there is a divide-by-zero in a shader
+ fDropsTileOnZeroDivide = kQualcomm_GrGLVendor == ctxInfo.vendor();
+
this->initFSAASupport(ctxInfo, gli);
this->initStencilFormats(ctxInfo);
/**************************************************************************
* GrDrawTargetCaps fields
**************************************************************************/
- GrGLint numFormats;
- GR_GL_GetIntegerv(gli, GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
- if (numFormats) {
- SkAutoSTMalloc<10, GrGLint> formats(numFormats);
- GR_GL_GetIntegerv(gli, GR_GL_COMPRESSED_TEXTURE_FORMATS, formats);
- for (int i = 0; i < numFormats; ++i) {
- if (formats[i] == GR_GL_PALETTE8_RGBA8) {
- f8BitPaletteSupport = true;
- break;
- }
- }
- }
-
- if (kDesktop_GrGLBinding == binding) {
+ if (kGL_GrGLStandard == standard) {
// we could also look for GL_ATI_separate_stencil extension or
// GL_EXT_stencil_two_side but they use different function signatures
// than GL2.0+ (and than each other).
@@ -277,37 +262,59 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
fStencilWrapOpsSupport = true;
}
- if (kDesktop_GrGLBinding == binding) {
- fBufferLockSupport = true; // we require VBO support and the desktop VBO extension includes
- // glMapBuffer.
+ if (kGL_GrGLStandard == standard) {
+ fMapBufferFlags = kCanMap_MapFlag; // we require VBO support and the desktop VBO
+ // extension includes glMapBuffer.
+ if (version >= GR_GL_VER(3, 0) || ctxInfo.hasExtension("GL_ARB_map_buffer_range")) {
+ fMapBufferFlags |= kSubset_MapFlag;
+ fMapBufferType = kMapBufferRange_MapBufferType;
+ } else {
+ fMapBufferType = kMapBuffer_MapBufferType;
+ }
} else {
- fBufferLockSupport = ctxInfo.hasExtension("GL_OES_mapbuffer");
+ // Unextended GLES2 doesn't have any buffer mapping.
+ fMapBufferFlags = kNone_MapBufferType;
+ if (ctxInfo.hasExtension("GL_CHROMIUM_map_sub")) {
+ fMapBufferFlags = kCanMap_MapFlag | kSubset_MapFlag;
+ fMapBufferType = kChromium_MapBufferType;
+ } else if (version >= GR_GL_VER(3, 0) || ctxInfo.hasExtension("GL_EXT_map_buffer_range")) {
+ fMapBufferFlags = kCanMap_MapFlag | kSubset_MapFlag;
+ fMapBufferType = kMapBufferRange_MapBufferType;
+ } else if (ctxInfo.hasExtension("GL_OES_mapbuffer")) {
+ fMapBufferFlags = kCanMap_MapFlag;
+ fMapBufferType = kMapBuffer_MapBufferType;
+ }
}
- if (kDesktop_GrGLBinding == binding) {
- if (ctxInfo.version() >= GR_GL_VER(2,0) ||
- ctxInfo.hasExtension("GL_ARB_texture_non_power_of_two")) {
- fNPOTTextureTileSupport = true;
- } else {
- fNPOTTextureTileSupport = false;
- }
+ if (kGL_GrGLStandard == standard) {
+ SkASSERT(ctxInfo.version() >= GR_GL_VER(2,0) ||
+ ctxInfo.hasExtension("GL_ARB_texture_non_power_of_two"));
+ fNPOTTextureTileSupport = true;
+ fMipMapSupport = true;
} else {
// Unextended ES2 supports NPOT textures with clamp_to_edge and non-mip filters only
// ES3 has no limitations.
fNPOTTextureTileSupport = ctxInfo.version() >= GR_GL_VER(3,0) ||
ctxInfo.hasExtension("GL_OES_texture_npot");
+ // ES2 supports MIP mapping for POT textures but our caps don't allow for limited MIP
+ // support. The OES extension or ES 3.0 allow for MIPS on NPOT textures. So, apparently,
+ // does the undocumented GL_IMG_texture_npot extension. This extension does not seem to
+ // to alllow arbitrary wrap modes, however.
+ fMipMapSupport = fNPOTTextureTileSupport || ctxInfo.hasExtension("GL_IMG_texture_npot");
}
- fHWAALineSupport = (kDesktop_GrGLBinding == binding);
+ fHWAALineSupport = (kGL_GrGLStandard == standard);
GR_GL_GetIntegerv(gli, GR_GL_MAX_TEXTURE_SIZE, &fMaxTextureSize);
GR_GL_GetIntegerv(gli, GR_GL_MAX_RENDERBUFFER_SIZE, &fMaxRenderTargetSize);
// Our render targets are always created with textures as the color
// attachment, hence this min:
- fMaxRenderTargetSize = GrMin(fMaxTextureSize, fMaxRenderTargetSize);
+ fMaxRenderTargetSize = SkTMin(fMaxTextureSize, fMaxRenderTargetSize);
+
+ fPathRenderingSupport = ctxInfo.hasExtension("GL_NV_path_rendering") &&
+ ctxInfo.hasExtension("GL_EXT_direct_state_access");
- fPathRenderingSupport = GR_GL_USE_NV_PATH_RENDERING &&
- ctxInfo.hasExtension("GL_NV_path_rendering");
+ fGpuTracingSupport = ctxInfo.hasExtension("GL_EXT_debug_marker");
fDstReadInShaderSupport = kNone_FBFetchType != fFBFetchType;
@@ -316,7 +323,7 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
kQualcomm_GrGLVendor != ctxInfo.vendor();
// Enable supported shader-related caps
- if (kDesktop_GrGLBinding == binding) {
+ if (kGL_GrGLStandard == standard) {
fDualSourceBlendingSupport = ctxInfo.version() >= GR_GL_VER(3,3) ||
ctxInfo.hasExtension("GL_ARB_blend_func_extended");
fShaderDerivativeSupport = true;
@@ -333,7 +340,10 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
GR_GL_GetIntegerv(gli, GR_GL_MAX_SAMPLES, &fMaxSampleCount);
}
+ this->initConfigTexturableTable(ctxInfo, gli);
this->initConfigRenderableTable(ctxInfo);
+
+ return true;
}
void GrGLCaps::initConfigRenderableTable(const GrGLContextInfo& ctxInfo) {
@@ -366,12 +376,14 @@ void GrGLCaps::initConfigRenderableTable(const GrGLContextInfo& ctxInfo) {
// Same as ES 2.0 except R8 and RGBA8 are supported without extensions (the functions called
// below already account for this).
+ GrGLStandard standard = ctxInfo.standard();
+
enum {
kNo_MSAA = 0,
kYes_MSAA = 1,
};
- if (kDesktop_GrGLBinding == ctxInfo.binding()) {
+ if (kGL_GrGLStandard == standard) {
// Post 3.0 we will get R8
// Prior to 3.0 we will get ALPHA8 (with GL_ARB_framebuffer_object)
if (ctxInfo.version() >= GR_GL_VER(3,0) ||
@@ -385,7 +397,7 @@ void GrGLCaps::initConfigRenderableTable(const GrGLContextInfo& ctxInfo) {
fConfigRenderSupport[kAlpha_8_GrPixelConfig][kYes_MSAA] = fTextureRedSupport;
}
- if (kDesktop_GrGLBinding != ctxInfo.binding()) {
+ if (kGL_GrGLStandard != standard) {
// only available in ES
fConfigRenderSupport[kRGB_565_GrPixelConfig][kNo_MSAA] = true;
fConfigRenderSupport[kRGB_565_GrPixelConfig][kYes_MSAA] = true;
@@ -400,12 +412,12 @@ void GrGLCaps::initConfigRenderableTable(const GrGLContextInfo& ctxInfo) {
fConfigRenderSupport[kRGBA_8888_GrPixelConfig][kYes_MSAA] = true;
}
- if (this->fBGRAFormatSupport) {
+ if (this->isConfigTexturable(kBGRA_8888_GrPixelConfig)) {
fConfigRenderSupport[kBGRA_8888_GrPixelConfig][kNo_MSAA] = true;
// The GL_EXT_texture_format_BGRA8888 extension does not add BGRA to the list of
// configs that are color-renderable and can be passed to glRenderBufferStorageMultisample.
// Chromium may have an extension to allow BGRA renderbuffers to work on desktop platforms.
- if (ctxInfo.extensions().has("GL_CHROMIUM_renderbuffer_format_BGRA8888")) {
+ if (ctxInfo.hasExtension("GL_CHROMIUM_renderbuffer_format_BGRA8888")) {
fConfigRenderSupport[kBGRA_8888_GrPixelConfig][kYes_MSAA] = true;
} else {
fConfigRenderSupport[kBGRA_8888_GrPixelConfig][kYes_MSAA] =
@@ -422,6 +434,105 @@ void GrGLCaps::initConfigRenderableTable(const GrGLContextInfo& ctxInfo) {
}
}
+void GrGLCaps::initConfigTexturableTable(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
+ GrGLStandard standard = ctxInfo.standard();
+ GrGLVersion version = ctxInfo.version();
+
+ // Base texture support
+ fConfigTextureSupport[kAlpha_8_GrPixelConfig] = true;
+ fConfigTextureSupport[kRGB_565_GrPixelConfig] = true;
+ fConfigTextureSupport[kRGBA_4444_GrPixelConfig] = true;
+ fConfigTextureSupport[kRGBA_8888_GrPixelConfig] = true;
+
+ // Check for 8-bit palette..
+ GrGLint numFormats;
+ GR_GL_GetIntegerv(gli, GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
+ if (numFormats) {
+ SkAutoSTMalloc<10, GrGLint> formats(numFormats);
+ GR_GL_GetIntegerv(gli, GR_GL_COMPRESSED_TEXTURE_FORMATS, formats);
+ for (int i = 0; i < numFormats; ++i) {
+ if (GR_GL_PALETTE8_RGBA8 == formats[i]) {
+ fConfigTextureSupport[kIndex_8_GrPixelConfig] = true;
+ break;
+ }
+ }
+ }
+
+ // Check for BGRA
+ if (kGL_GrGLStandard == standard) {
+ fConfigTextureSupport[kBGRA_8888_GrPixelConfig] =
+ version >= GR_GL_VER(1,2) || ctxInfo.hasExtension("GL_EXT_bgra");
+ } else {
+ if (ctxInfo.hasExtension("GL_APPLE_texture_format_BGRA8888")) {
+ fConfigTextureSupport[kBGRA_8888_GrPixelConfig] = true;
+ } else if (ctxInfo.hasExtension("GL_EXT_texture_format_BGRA8888")) {
+ fConfigTextureSupport[kBGRA_8888_GrPixelConfig] = true;
+ fBGRAIsInternalFormat = true;
+ }
+ SkASSERT(fConfigTextureSupport[kBGRA_8888_GrPixelConfig] ||
+ kSkia8888_GrPixelConfig != kBGRA_8888_GrPixelConfig);
+ }
+
+ // Compressed texture support
+
+ // glCompressedTexImage2D is available on all OpenGL ES devices...
+ // however, it is only available on standard OpenGL after version 1.3
+ bool hasCompressTex2D = (kGL_GrGLStandard != standard || version >= GR_GL_VER(1, 3));
+
+ // Check for ETC1
+ bool hasETC1 = false;
+
+ // First check version for support
+ if (kGL_GrGLStandard == standard) {
+ hasETC1 = hasCompressTex2D &&
+ (version >= GR_GL_VER(4, 3) ||
+ ctxInfo.hasExtension("GL_ARB_ES3_compatibility"));
+ } else {
+ hasETC1 = hasCompressTex2D &&
+ (version >= GR_GL_VER(3, 0) ||
+ ctxInfo.hasExtension("GL_OES_compressed_ETC1_RGB8_texture") ||
+ // ETC2 is a superset of ETC1, so we can just check for that, too.
+ (ctxInfo.hasExtension("GL_OES_compressed_ETC2_RGB8_texture") &&
+ ctxInfo.hasExtension("GL_OES_compressed_ETC2_RGBA8_texture")));
+ }
+ fConfigTextureSupport[kETC1_GrPixelConfig] = hasETC1;
+
+ // Check for LATC under its various forms
+ LATCAlias alias = kLATC_LATCAlias;
+ bool hasLATC = hasCompressTex2D &&
+ (ctxInfo.hasExtension("GL_EXT_texture_compression_latc") ||
+ ctxInfo.hasExtension("GL_NV_texture_compression_latc"));
+
+ // Check for RGTC
+ if (!hasLATC) {
+ // If we're using OpenGL 3.0 or later, then we have RGTC, an identical compression format.
+ if (kGL_GrGLStandard == standard) {
+ hasLATC = version >= GR_GL_VER(3, 0);
+ }
+
+ if (!hasLATC) {
+ hasLATC =
+ ctxInfo.hasExtension("GL_EXT_texture_compression_rgtc") ||
+ ctxInfo.hasExtension("GL_ARB_texture_compression_rgtc");
+ }
+
+ if (hasLATC) {
+ alias = kRGTC_LATCAlias;
+ }
+ }
+
+ // Check for 3DC
+ if (!hasLATC) {
+ hasLATC = ctxInfo.hasExtension("GL_AMD_compressed_3DC_texture");
+ if (hasLATC) {
+ alias = k3DC_LATCAlias;
+ }
+ }
+
+ fConfigTextureSupport[kLATC_GrPixelConfig] = hasLATC;
+ fLATCAlias = alias;
+}
+
bool GrGLCaps::readPixelsSupported(const GrGLInterface* intf,
GrGLenum format,
GrGLenum type) const {
@@ -454,14 +565,14 @@ bool GrGLCaps::readPixelsSupported(const GrGLInterface* intf,
void GrGLCaps::initFSAASupport(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
fMSFBOType = kNone_MSFBOType;
- if (kDesktop_GrGLBinding != ctxInfo.binding()) {
+ if (kGL_GrGLStandard != ctxInfo.standard()) {
// We prefer the EXT/IMG extension over ES3 MSAA because we've observed
// ES3 driver bugs on at least one device with a tiled GPU (N10).
if (ctxInfo.hasExtension("GL_EXT_multisampled_render_to_texture")) {
fMSFBOType = kES_EXT_MsToTexture_MSFBOType;
} else if (ctxInfo.hasExtension("GL_IMG_multisampled_render_to_texture")) {
fMSFBOType = kES_IMG_MsToTexture_MSFBOType;
- } else if (!GR_GL_IGNORE_ES3_MSAA && ctxInfo.version() >= GR_GL_VER(3,0)) {
+ } else if (ctxInfo.version() >= GR_GL_VER(3,0)) {
fMSFBOType = GrGLCaps::kES_3_0_MSFBOType;
} else if (ctxInfo.hasExtension("GL_CHROMIUM_framebuffer_multisample")) {
// chrome's extension is equivalent to the EXT msaa
@@ -502,7 +613,7 @@ void GrGLCaps::initStencilFormats(const GrGLContextInfo& ctxInfo) {
// gS = {GR_GL_STENCIL_INDEX, kUnknownBitCount, kUnknownBitCount, false},
gDS = {GR_GL_DEPTH_STENCIL, kUnknownBitCount, kUnknownBitCount, true };
- if (kDesktop_GrGLBinding == ctxInfo.binding()) {
+ if (kGL_GrGLStandard == ctxInfo.standard()) {
bool supportsPackedDS =
ctxInfo.version() >= GR_GL_VER(3,0) ||
ctxInfo.hasExtension("GL_EXT_packed_depth_stencil") ||
@@ -558,7 +669,7 @@ void GrGLCaps::markColorConfigAndStencilFormatAsVerified(
return;
}
}
- GrCrash("Why are we seeing a stencil format that "
+ SkFAIL("Why are we seeing a stencil format that "
"GrGLCaps doesn't know about.");
}
@@ -579,7 +690,7 @@ bool GrGLCaps::isColorConfigAndStencilFormatVerified(
return fStencilVerifiedColorConfigs[i].isVerified(config);
}
}
- GrCrash("Why are we seeing a stencil format that "
+ SkFAIL("Why are we seeing a stencil format that "
"GLCaps doesn't know about.");
return false;
}
@@ -612,7 +723,7 @@ SkString GrGLCaps::dump() const {
GR_STATIC_ASSERT(4 == kES_Apple_MSFBOType);
GR_STATIC_ASSERT(5 == kES_IMG_MsToTexture_MSFBOType);
GR_STATIC_ASSERT(6 == kES_EXT_MsToTexture_MSFBOType);
- GR_STATIC_ASSERT(GR_ARRAY_COUNT(kMSFBOExtStr) == kLast_MSFBOType + 1);
+ GR_STATIC_ASSERT(SK_ARRAY_COUNT(kMSFBOExtStr) == kLast_MSFBOType + 1);
static const char* kFBFetchTypeStr[] = {
"None",
@@ -622,21 +733,42 @@ SkString GrGLCaps::dump() const {
GR_STATIC_ASSERT(0 == kNone_FBFetchType);
GR_STATIC_ASSERT(1 == kEXT_FBFetchType);
GR_STATIC_ASSERT(2 == kNV_FBFetchType);
- GR_STATIC_ASSERT(GR_ARRAY_COUNT(kFBFetchTypeStr) == kLast_FBFetchType + 1);
+ GR_STATIC_ASSERT(SK_ARRAY_COUNT(kFBFetchTypeStr) == kLast_FBFetchType + 1);
+ static const char* kInvalidateFBTypeStr[] = {
+ "None",
+ "Discard",
+ "Invalidate",
+ };
+ GR_STATIC_ASSERT(0 == kNone_InvalidateFBType);
+ GR_STATIC_ASSERT(1 == kDiscard_InvalidateFBType);
+ GR_STATIC_ASSERT(2 == kInvalidate_InvalidateFBType);
+ GR_STATIC_ASSERT(SK_ARRAY_COUNT(kInvalidateFBTypeStr) == kLast_InvalidateFBType + 1);
+
+ static const char* kMapBufferTypeStr[] = {
+ "None",
+ "MapBuffer",
+ "MapBufferRange",
+ "Chromium",
+ };
+ GR_STATIC_ASSERT(0 == kNone_MapBufferType);
+ GR_STATIC_ASSERT(1 == kMapBuffer_MapBufferType);
+ GR_STATIC_ASSERT(2 == kMapBufferRange_MapBufferType);
+ GR_STATIC_ASSERT(3 == kChromium_MapBufferType);
+ GR_STATIC_ASSERT(SK_ARRAY_COUNT(kMapBufferTypeStr) == kLast_MapBufferType + 1);
r.appendf("Core Profile: %s\n", (fIsCoreProfile ? "YES" : "NO"));
- r.appendf("Fixed Function Support: %s\n", (fFixedFunctionSupport ? "YES" : "NO"));
r.appendf("MSAA Type: %s\n", kMSFBOExtStr[fMSFBOType]);
r.appendf("FB Fetch Type: %s\n", kFBFetchTypeStr[fFBFetchType]);
+ r.appendf("Invalidate FB Type: %s\n", kInvalidateFBTypeStr[fInvalidateFBType]);
+ r.appendf("Map Buffer Type: %s\n", kMapBufferTypeStr[fMapBufferType]);
r.appendf("Max FS Uniform Vectors: %d\n", fMaxFragmentUniformVectors);
r.appendf("Max FS Texture Units: %d\n", fMaxFragmentTextureUnits);
- if (fFixedFunctionSupport) {
+ if (!fIsCoreProfile) {
r.appendf("Max Fixed Function Texture Coords: %d\n", fMaxFixedFunctionTextureCoords);
}
r.appendf("Max Vertex Attributes: %d\n", fMaxVertexAttributes);
r.appendf("Support RGBA8 Render Buffer: %s\n", (fRGBA8RenderbufferSupport ? "YES": "NO"));
- r.appendf("BGRA support: %s\n", (fBGRAFormatSupport ? "YES": "NO"));
r.appendf("BGRA is an internal format: %s\n", (fBGRAIsInternalFormat ? "YES": "NO"));
r.appendf("Support texture swizzle: %s\n", (fTextureSwizzleSupport ? "YES": "NO"));
r.appendf("Unpack Row length support: %s\n", (fUnpackRowLengthSupport ? "YES": "NO"));
@@ -654,7 +786,7 @@ SkString GrGLCaps::dump() const {
r.appendf("Vertex array object support: %s\n", (fVertexArrayObjectSupport ? "YES": "NO"));
r.appendf("Use non-VBO for dynamic data: %s\n",
(fUseNonVBOVertexAndIndexDynamicData ? "YES" : "NO"));
- r.appendf("Discard FrameBuffer support: %s\n", (fDiscardFBSupport ? "YES" : "NO"));
r.appendf("Full screen clear is free: %s\n", (fFullClearIsFree ? "YES" : "NO"));
+ r.appendf("Drops tile on zero divide: %s\n", (fDropsTileOnZeroDivide ? "YES" : "NO"));
return r;
}
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLCaps.h b/chromium/third_party/skia/src/gpu/gl/GrGLCaps.h
index 7f0c8874ca2..7f722f912d9 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLCaps.h
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLCaps.h
@@ -75,7 +75,24 @@ public:
/** GL_NV_shader_framebuffer_fetch */
kNV_FBFetchType,
- kLast_FBFetchType = kNV_FBFetchType,
+ kLast_FBFetchType = kNV_FBFetchType
+ };
+
+ enum InvalidateFBType {
+ kNone_InvalidateFBType,
+ kDiscard_InvalidateFBType, //<! glDiscardFramebuffer()
+ kInvalidate_InvalidateFBType, //<! glInvalidateFramebuffer()
+
+ kLast_InvalidateFBType = kInvalidate_InvalidateFBType
+ };
+
+ enum MapBufferType {
+ kNone_MapBufferType,
+ kMapBuffer_MapBufferType, // glMapBuffer()
+ kMapBufferRange_MapBufferType, // glMapBufferRange()
+ kChromium_MapBufferType, // GL_CHROMIUM_map_sub
+
+ kLast_MapBufferType = kChromium_MapBufferType,
};
/**
@@ -97,7 +114,7 @@ public:
* Initializes the GrGLCaps to the set of features supported in the current
* OpenGL context accessible via ctxInfo.
*/
- void init(const GrGLContextInfo& ctxInfo, const GrGLInterface* interface);
+ bool init(const GrGLContextInfo& ctxInfo, const GrGLInterface* interface);
/**
* Call to note that a color config has been verified as a valid color
@@ -159,10 +176,10 @@ public:
FBFetchType fbFetchType() const { return fFBFetchType; }
- /**
- * Returs a string containeng the caps info.
- */
- virtual SkString dump() const SK_OVERRIDE;
+ InvalidateFBType invalidateFBType() const { return fInvalidateFBType; }
+
+ /// What type of buffer mapping is supported?
+ MapBufferType mapBufferType() const { return fMapBufferType; }
/**
* Gets an array of legal stencil formats. These formats are not guaranteed
@@ -188,9 +205,6 @@ public:
/// ES requires an extension to support RGBA8 in RenderBufferStorage
bool rgba8RenderbufferSupport() const { return fRGBA8RenderbufferSupport; }
- /// Is GL_BGRA supported
- bool bgraFormatSupport() const { return fBGRAFormatSupport; }
-
/**
* Depending on the ES extensions present the BGRA external format may
* correspond either a BGRA or RGBA internalFormat. On desktop GL it is
@@ -243,13 +257,29 @@ public:
bool isCoreProfile() const { return fIsCoreProfile; }
- bool fixedFunctionSupport() const { return fFixedFunctionSupport; }
-
- /// Is there support for discarding the frame buffer
- bool discardFBSupport() const { return fDiscardFBSupport; }
bool fullClearIsFree() const { return fFullClearIsFree; }
+ bool dropsTileOnZeroDivide() const { return fDropsTileOnZeroDivide; }
+
+ /**
+ * Returns a string containing the caps info.
+ */
+ virtual SkString dump() const SK_OVERRIDE;
+
+ /**
+ * LATC can appear under one of three possible names. In order to know
+ * which GL internal format to use, we need to keep track of which name
+ * we found LATC under. The default is LATC.
+ */
+ enum LATCAlias {
+ kLATC_LATCAlias,
+ kRGTC_LATCAlias,
+ k3DC_LATCAlias
+ };
+
+ LATCAlias latcAlias() const { return fLATCAlias; }
+
private:
/**
* Maintains a bit per GrPixelConfig. It is used to avoid redundantly
@@ -292,6 +322,7 @@ private:
void initStencilFormats(const GrGLContextInfo&);
// This must be called after initFSAASupport().
void initConfigRenderableTable(const GrGLContextInfo&);
+ void initConfigTexturableTable(const GrGLContextInfo&, const GrGLInterface*);
// tracks configs that have been verified to pass the FBO completeness when
// used as a color attachment
@@ -308,12 +339,13 @@ private:
int fMaxFragmentTextureUnits;
int fMaxFixedFunctionTextureCoords;
- MSFBOType fMSFBOType;
-
- FBFetchType fFBFetchType;
+ MSFBOType fMSFBOType;
+ FBFetchType fFBFetchType;
+ InvalidateFBType fInvalidateFBType;
+ MapBufferType fMapBufferType;
+ LATCAlias fLATCAlias;
bool fRGBA8RenderbufferSupport : 1;
- bool fBGRAFormatSupport : 1;
bool fBGRAIsInternalFormat : 1;
bool fTextureSwizzleSupport : 1;
bool fUnpackRowLengthSupport : 1;
@@ -329,9 +361,8 @@ private:
bool fVertexArrayObjectSupport : 1;
bool fUseNonVBOVertexAndIndexDynamicData : 1;
bool fIsCoreProfile : 1;
- bool fFixedFunctionSupport : 1;
- bool fDiscardFBSupport : 1;
bool fFullClearIsFree : 1;
+ bool fDropsTileOnZeroDivide : 1;
typedef GrDrawTargetCaps INHERITED;
};
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLContext.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLContext.cpp
index 7c99a1cd008..5bc5b6f0312 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLContext.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLContext.cpp
@@ -8,16 +8,16 @@
#include "GrGLContext.h"
////////////////////////////////////////////////////////////////////////////////
-GrGLContextInfo& GrGLContextInfo::operator= (const GrGLContextInfo& ctxInfo) {
- fBindingInUse = ctxInfo.fBindingInUse;
- fGLVersion = ctxInfo.fGLVersion;
- fGLSLGeneration = ctxInfo.fGLSLGeneration;
- fVendor = ctxInfo.fVendor;
- fRenderer = ctxInfo.fRenderer;
- fExtensions = ctxInfo.fExtensions;
- fIsMesa = ctxInfo.fIsMesa;
- fIsChromium = ctxInfo.fIsChromium;
- *fGLCaps = *ctxInfo.fGLCaps.get();
+
+GrGLContextInfo& GrGLContextInfo::operator= (const GrGLContextInfo& that) {
+ fInterface.reset(SkSafeRef(that.fInterface.get()));
+ fGLVersion = that.fGLVersion;
+ fGLSLGeneration = that.fGLSLGeneration;
+ fVendor = that.fVendor;
+ fRenderer = that.fRenderer;
+ fIsMesa = that.fIsMesa;
+ fIsChromium = that.fIsChromium;
+ *fGLCaps = *that.fGLCaps.get();
return *this;
}
@@ -25,7 +25,7 @@ bool GrGLContextInfo::initialize(const GrGLInterface* interface) {
this->reset();
// We haven't validated the GrGLInterface yet, so check for GetString
// function pointer
- if (interface->fGetString) {
+ if (interface->fFunctions.fGetString) {
const GrGLubyte* verUByte;
GR_GL_CALL_RET(interface, verUByte, GetString(GR_GL_VERSION));
const char* ver = reinterpret_cast<const char*>(verUByte);
@@ -34,14 +34,16 @@ bool GrGLContextInfo::initialize(const GrGLInterface* interface) {
GR_GL_CALL_RET(interface, rendererUByte, GetString(GR_GL_RENDERER));
const char* renderer = reinterpret_cast<const char*>(rendererUByte);
- GrGLBinding binding = GrGLGetBindingInUseFromString(ver);
-
- if (0 != binding && interface->validate(binding) && fExtensions.init(binding, interface)) {
- fBindingInUse = binding;
+ if (interface->validate()) {
fGLVersion = GrGLGetVersionFromString(ver);
+ if (GR_GL_INVALID_VER == fGLVersion) {
+ return false;
+ }
- fGLSLGeneration = GrGetGLSLGeneration(fBindingInUse, interface);
+ if (!GrGetGLSLGeneration(interface, &fGLSLGeneration)) {
+ return false;
+ }
fVendor = GrGLGetVendor(interface);
@@ -51,56 +53,26 @@ bool GrGLContextInfo::initialize(const GrGLInterface* interface) {
fIsChromium = GrGLIsChromiumFromRendererString(renderer);
- fGLCaps->init(*this, interface);
- return true;
+ // This must occur before caps init.
+ fInterface.reset(SkRef(interface));
+
+ return fGLCaps->init(*this, interface);
}
}
return false;
}
bool GrGLContextInfo::isInitialized() const {
- return kNone_GrGLBinding != fBindingInUse;
+ return NULL != fInterface.get();
}
void GrGLContextInfo::reset() {
- fBindingInUse = kNone_GrGLBinding;
+ fInterface.reset(NULL);
fGLVersion = GR_GL_VER(0, 0);
fGLSLGeneration = static_cast<GrGLSLGeneration>(0);
fVendor = kOther_GrGLVendor;
fRenderer = kOther_GrGLRenderer;
fIsMesa = false;
fIsChromium = false;
- fExtensions.reset();
fGLCaps->reset();
}
-
-////////////////////////////////////////////////////////////////////////////////
-GrGLContext::GrGLContext(const GrGLInterface* interface) {
- fInterface = NULL;
- this->initialize(interface);
-}
-
-GrGLContext::GrGLContext(const GrGLContext& ctx) {
- fInterface = NULL;
- *this = ctx;
-}
-
-GrGLContext& GrGLContext::operator = (const GrGLContext& ctx) {
- SkRefCnt_SafeAssign(fInterface, ctx.fInterface);
- fInfo = ctx.fInfo;
- return *this;
-}
-
-void GrGLContext::reset() {
- SkSafeSetNull(fInterface);
- fInfo.reset();
-}
-
-bool GrGLContext::initialize(const GrGLInterface* interface) {
- if (fInfo.initialize(interface)) {
- fInterface = interface;
- interface->ref();
- return true;
- }
- return false;
-}
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLContext.h b/chromium/third_party/skia/src/gpu/gl/GrGLContext.h
index d2174c56c8c..e6c9f9e040b 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLContext.h
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLContext.h
@@ -19,7 +19,7 @@
/**
* Encapsulates information about an OpenGL context including the OpenGL
- * version, the GrGLBinding type of the context, and GLSL version.
+ * version, the GrGLStandard type of the context, and GLSL version.
*/
class GrGLContextInfo {
public:
@@ -31,10 +31,12 @@ public:
this->reset();
}
- /**
- * Copies a GrGLContextInfo
- */
- GrGLContextInfo& operator= (const GrGLContextInfo& ctxInfo);
+ GrGLContextInfo(const GrGLContextInfo& that) {
+ fGLCaps.reset(SkNEW(GrGLCaps));
+ *this = that;
+ }
+
+ GrGLContextInfo& operator= (const GrGLContextInfo&);
/**
* Initializes a GrGLContextInfo from a GrGLInterface and the currently
@@ -43,7 +45,7 @@ public:
bool initialize(const GrGLInterface* interface);
bool isInitialized() const;
- GrGLBinding binding() const { return fBindingInUse; }
+ GrGLStandard standard() const { return fInterface->fStandard; }
GrGLVersion version() const { return fGLVersion; }
GrGLSLGeneration glslGeneration() const { return fGLSLGeneration; }
GrGLVendor vendor() const { return fVendor; }
@@ -56,16 +58,11 @@ public:
bool isChromium() const { return fIsChromium; }
const GrGLCaps* caps() const { return fGLCaps.get(); }
GrGLCaps* caps() { return fGLCaps; }
- const GrGLExtensions& extensions() const { return fExtensions; }
-
- /**
- * Shortcut for extensions().has(ext);
- */
bool hasExtension(const char* ext) const {
if (!this->isInitialized()) {
return false;
}
- return fExtensions.has(ext);
+ return fInterface->hasExtension(ext);
}
/**
@@ -73,64 +70,41 @@ public:
*/
void reset();
-private:
-
- GrGLBinding fBindingInUse;
- GrGLVersion fGLVersion;
- GrGLSLGeneration fGLSLGeneration;
- GrGLVendor fVendor;
- GrGLRenderer fRenderer;
- GrGLExtensions fExtensions;
- bool fIsMesa;
- bool fIsChromium;
- SkAutoTUnref<GrGLCaps> fGLCaps;
+protected:
+ SkAutoTUnref<const GrGLInterface> fInterface;
+ GrGLVersion fGLVersion;
+ GrGLSLGeneration fGLSLGeneration;
+ GrGLVendor fVendor;
+ GrGLRenderer fRenderer;
+ bool fIsMesa;
+ bool fIsChromium;
+ SkAutoTUnref<GrGLCaps> fGLCaps;
};
/**
- * Encapsulates the GrGLInterface used to make GL calls plus information
- * about the context (via GrGLContextInfo).
+ * Extension of GrGLContextInfo that also provides access to GrGLInterface.
*/
-class GrGLContext {
+class GrGLContext : public GrGLContextInfo {
public:
/**
- * Default constructor
- */
- GrGLContext() { this->reset(); }
-
- /**
* Creates a GrGLContext from a GrGLInterface and the currently
* bound OpenGL context accessible by the GrGLInterface.
*/
- explicit GrGLContext(const GrGLInterface* interface);
-
- /**
- * Copies a GrGLContext
- */
- GrGLContext(const GrGLContext& ctx);
-
- ~GrGLContext() { SkSafeUnref(fInterface); }
+ explicit GrGLContext(const GrGLInterface* interface) {
+ this->initialize(interface);
+ }
- /**
- * Copies a GrGLContext
- */
- GrGLContext& operator= (const GrGLContext& ctx);
+ GrGLContext(const GrGLContext& that) : INHERITED(that) {}
- /**
- * Initializes a GrGLContext from a GrGLInterface and the currently
- * bound OpenGL context accessible by the GrGLInterface.
- */
- bool initialize(const GrGLInterface* interface);
- bool isInitialized() const { return fInfo.isInitialized(); }
+ GrGLContext& operator= (const GrGLContext& that) {
+ this->INHERITED::operator=(that);
+ return *this;
+ }
- const GrGLInterface* interface() const { return fInterface; }
- const GrGLContextInfo& info() const { return fInfo; }
- GrGLContextInfo& info() { return fInfo; }
+ const GrGLInterface* interface() const { return fInterface.get(); }
private:
- void reset();
-
- const GrGLInterface* fInterface;
- GrGLContextInfo fInfo;
+ typedef GrGLContextInfo INHERITED;
};
#endif
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLCreateNullInterface.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLCreateNullInterface.cpp
index c169b1ce387..d047e730f71 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLCreateNullInterface.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLCreateNullInterface.cpp
@@ -100,7 +100,6 @@ GrGLvoid GR_GL_FUNCTION_TYPE nullGLBeginQuery(GrGLenum target, GrGLuint id) {}
GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindAttribLocation(GrGLuint program, GrGLuint index, const char* name) {}
GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindTexture(GrGLenum target, GrGLuint texture) {}
GrGLvoid GR_GL_FUNCTION_TYPE nullGLBindVertexArray(GrGLuint id) {}
-GrGLvoid GR_GL_FUNCTION_TYPE nullGLClientActiveTexture(GrGLenum) {}
GrGLvoid GR_GL_FUNCTION_TYPE nullGLGenBuffers(GrGLsizei n, GrGLuint* ids) {
@@ -126,7 +125,7 @@ GrGLvoid GR_GL_FUNCTION_TYPE nullGLBufferData(GrGLenum target,
id = gCurrElementArrayBuffer;
break;
default:
- GrCrash("Unexpected target to nullGLBufferData");
+ SkFAIL("Unexpected target to nullGLBufferData");
break;
}
@@ -187,8 +186,29 @@ GrGLvoid GR_GL_FUNCTION_TYPE nullGLDeleteBuffers(GrGLsizei n, const GrGLuint* id
}
}
-GrGLvoid* GR_GL_FUNCTION_TYPE nullGLMapBuffer(GrGLenum target, GrGLenum access) {
+GrGLvoid* GR_GL_FUNCTION_TYPE nullGLMapBufferRange(GrGLenum target, GrGLintptr offset,
+ GrGLsizeiptr length, GrGLbitfield access) {
+ GrGLuint id = 0;
+ switch (target) {
+ case GR_GL_ARRAY_BUFFER:
+ id = gCurrArrayBuffer;
+ break;
+ case GR_GL_ELEMENT_ARRAY_BUFFER:
+ id = gCurrElementArrayBuffer;
+ break;
+ }
+
+ if (id > 0) {
+ // We just ignore the offset and length here.
+ GrBufferObj* buffer = look_up(id);
+ SkASSERT(!buffer->mapped());
+ buffer->setMapped(true);
+ return buffer->dataPtr();
+ }
+ return NULL;
+}
+GrGLvoid* GR_GL_FUNCTION_TYPE nullGLMapBuffer(GrGLenum target, GrGLenum access) {
GrGLuint id = 0;
switch (target) {
case GR_GL_ARRAY_BUFFER:
@@ -210,6 +230,11 @@ GrGLvoid* GR_GL_FUNCTION_TYPE nullGLMapBuffer(GrGLenum target, GrGLenum access)
return NULL; // no buffer bound to target
}
+GrGLvoid GR_GL_FUNCTION_TYPE nullGLFlushMappedBufferRange(GrGLenum target,
+ GrGLintptr offset,
+ GrGLsizeiptr length) {}
+
+
GrGLboolean GR_GL_FUNCTION_TYPE nullGLUnmapBuffer(GrGLenum target) {
GrGLuint id = 0;
switch (target) {
@@ -252,7 +277,7 @@ GrGLvoid GR_GL_FUNCTION_TYPE nullGLGetBufferParameteriv(GrGLenum target, GrGLenu
}
break; }
default:
- GrCrash("Unexpected pname to GetBufferParamateriv");
+ SkFAIL("Unexpected pname to GetBufferParamateriv");
break;
}
};
@@ -260,147 +285,144 @@ GrGLvoid GR_GL_FUNCTION_TYPE nullGLGetBufferParameteriv(GrGLenum target, GrGLenu
} // end anonymous namespace
const GrGLInterface* GrGLCreateNullInterface() {
- // The gl functions are not context-specific so we create one global
- // interface
- static SkAutoTUnref<GrGLInterface> glInterface;
- if (!glInterface.get()) {
- GrGLInterface* interface = SkNEW(GrGLInterface);
- glInterface.reset(interface);
- interface->fBindingsExported = kDesktop_GrGLBinding;
- interface->fActiveTexture = nullGLActiveTexture;
- interface->fAttachShader = nullGLAttachShader;
- interface->fBeginQuery = nullGLBeginQuery;
- interface->fBindAttribLocation = nullGLBindAttribLocation;
- interface->fBindBuffer = nullGLBindBuffer;
- interface->fBindFragDataLocation = noOpGLBindFragDataLocation;
- interface->fBindTexture = nullGLBindTexture;
- interface->fBindVertexArray = nullGLBindVertexArray;
- interface->fBlendColor = noOpGLBlendColor;
- interface->fBlendFunc = noOpGLBlendFunc;
- interface->fBufferData = nullGLBufferData;
- interface->fBufferSubData = noOpGLBufferSubData;
- interface->fClear = noOpGLClear;
- interface->fClearColor = noOpGLClearColor;
- interface->fClearStencil = noOpGLClearStencil;
- interface->fClientActiveTexture = nullGLClientActiveTexture;
- interface->fColorMask = noOpGLColorMask;
- interface->fCompileShader = noOpGLCompileShader;
- interface->fCompressedTexImage2D = noOpGLCompressedTexImage2D;
- interface->fCopyTexSubImage2D = noOpGLCopyTexSubImage2D;
- interface->fCreateProgram = nullGLCreateProgram;
- interface->fCreateShader = nullGLCreateShader;
- interface->fCullFace = noOpGLCullFace;
- interface->fDeleteBuffers = nullGLDeleteBuffers;
- interface->fDeleteProgram = nullGLDelete;
- interface->fDeleteQueries = noOpGLDeleteIds;
- interface->fDeleteShader = nullGLDelete;
- interface->fDeleteTextures = noOpGLDeleteIds;
- interface->fDeleteVertexArrays = noOpGLDeleteIds;
- interface->fDepthMask = noOpGLDepthMask;
- interface->fDisable = noOpGLDisable;
- interface->fDisableClientState = noOpGLDisableClientState;
- interface->fDisableVertexAttribArray = noOpGLDisableVertexAttribArray;
- interface->fDrawArrays = noOpGLDrawArrays;
- interface->fDrawBuffer = noOpGLDrawBuffer;
- interface->fDrawBuffers = noOpGLDrawBuffers;
- interface->fDrawElements = noOpGLDrawElements;
- interface->fEnable = noOpGLEnable;
- interface->fEnableClientState = noOpGLEnableClientState;
- interface->fEnableVertexAttribArray = noOpGLEnableVertexAttribArray;
- interface->fEndQuery = noOpGLEndQuery;
- interface->fFinish = noOpGLFinish;
- interface->fFlush = noOpGLFlush;
- interface->fFrontFace = noOpGLFrontFace;
- interface->fGenBuffers = nullGLGenBuffers;
- interface->fGenerateMipmap = nullGLGenerateMipmap;
- interface->fGenQueries = noOpGLGenIds;
- interface->fGenTextures = noOpGLGenIds;
- interface->fGenVertexArrays = noOpGLGenIds;
- interface->fGetBufferParameteriv = nullGLGetBufferParameteriv;
- interface->fGetError = noOpGLGetError;
- interface->fGetIntegerv = noOpGLGetIntegerv;
- interface->fGetQueryObjecti64v = noOpGLGetQueryObjecti64v;
- interface->fGetQueryObjectiv = noOpGLGetQueryObjectiv;
- interface->fGetQueryObjectui64v = noOpGLGetQueryObjectui64v;
- interface->fGetQueryObjectuiv = noOpGLGetQueryObjectuiv;
- interface->fGetQueryiv = noOpGLGetQueryiv;
- interface->fGetProgramInfoLog = noOpGLGetInfoLog;
- interface->fGetProgramiv = noOpGLGetShaderOrProgramiv;
- interface->fGetShaderInfoLog = noOpGLGetInfoLog;
- interface->fGetShaderiv = noOpGLGetShaderOrProgramiv;
- interface->fGetString = noOpGLGetString;
- interface->fGetStringi = noOpGLGetStringi;
- interface->fGetTexLevelParameteriv = noOpGLGetTexLevelParameteriv;
- interface->fGetUniformLocation = noOpGLGetUniformLocation;
- interface->fLoadIdentity = noOpGLLoadIdentity;
- interface->fLoadMatrixf = noOpGLLoadMatrixf;
- interface->fLineWidth = noOpGLLineWidth;
- interface->fLinkProgram = noOpGLLinkProgram;
- interface->fMatrixMode = noOpGLMatrixMode;
- interface->fPixelStorei = nullGLPixelStorei;
- interface->fQueryCounter = noOpGLQueryCounter;
- interface->fReadBuffer = noOpGLReadBuffer;
- interface->fReadPixels = nullGLReadPixels;
- interface->fScissor = noOpGLScissor;
- interface->fShaderSource = noOpGLShaderSource;
- interface->fStencilFunc = noOpGLStencilFunc;
- interface->fStencilFuncSeparate = noOpGLStencilFuncSeparate;
- interface->fStencilMask = noOpGLStencilMask;
- interface->fStencilMaskSeparate = noOpGLStencilMaskSeparate;
- interface->fStencilOp = noOpGLStencilOp;
- interface->fStencilOpSeparate = noOpGLStencilOpSeparate;
- interface->fTexGenf = noOpGLTexGenf;
- interface->fTexGenfv = noOpGLTexGenfv;
- interface->fTexGeni = noOpGLTexGeni;
- interface->fTexImage2D = noOpGLTexImage2D;
- interface->fTexParameteri = noOpGLTexParameteri;
- interface->fTexParameteriv = noOpGLTexParameteriv;
- interface->fTexSubImage2D = noOpGLTexSubImage2D;
- interface->fTexStorage2D = noOpGLTexStorage2D;
- interface->fDiscardFramebuffer = noOpGLDiscardFramebuffer;
- interface->fUniform1f = noOpGLUniform1f;
- interface->fUniform1i = noOpGLUniform1i;
- interface->fUniform1fv = noOpGLUniform1fv;
- interface->fUniform1iv = noOpGLUniform1iv;
- interface->fUniform2f = noOpGLUniform2f;
- interface->fUniform2i = noOpGLUniform2i;
- interface->fUniform2fv = noOpGLUniform2fv;
- interface->fUniform2iv = noOpGLUniform2iv;
- interface->fUniform3f = noOpGLUniform3f;
- interface->fUniform3i = noOpGLUniform3i;
- interface->fUniform3fv = noOpGLUniform3fv;
- interface->fUniform3iv = noOpGLUniform3iv;
- interface->fUniform4f = noOpGLUniform4f;
- interface->fUniform4i = noOpGLUniform4i;
- interface->fUniform4fv = noOpGLUniform4fv;
- interface->fUniform4iv = noOpGLUniform4iv;
- interface->fUniformMatrix2fv = noOpGLUniformMatrix2fv;
- interface->fUniformMatrix3fv = noOpGLUniformMatrix3fv;
- interface->fUniformMatrix4fv = noOpGLUniformMatrix4fv;
- interface->fUseProgram = nullGLUseProgram;
- interface->fVertexAttrib4fv = noOpGLVertexAttrib4fv;
- interface->fVertexAttribPointer = noOpGLVertexAttribPointer;
- interface->fVertexPointer = noOpGLVertexPointer;
- interface->fViewport = nullGLViewport;
- interface->fBindFramebuffer = nullGLBindFramebuffer;
- interface->fBindRenderbuffer = nullGLBindRenderbuffer;
- interface->fCheckFramebufferStatus = noOpGLCheckFramebufferStatus;
- interface->fDeleteFramebuffers = nullGLDeleteFramebuffers;
- interface->fDeleteRenderbuffers = nullGLDeleteRenderbuffers;
- interface->fFramebufferRenderbuffer = nullGLFramebufferRenderbuffer;
- interface->fFramebufferTexture2D = nullGLFramebufferTexture2D;
- interface->fGenFramebuffers = noOpGLGenIds;
- interface->fGenRenderbuffers = noOpGLGenIds;
- interface->fGetFramebufferAttachmentParameteriv = noOpGLGetFramebufferAttachmentParameteriv;
- interface->fGetRenderbufferParameteriv = noOpGLGetRenderbufferParameteriv;
- interface->fRenderbufferStorage = noOpGLRenderbufferStorage;
- interface->fRenderbufferStorageMultisample = noOpGLRenderbufferStorageMultisample;
- interface->fBlitFramebuffer = noOpGLBlitFramebuffer;
- interface->fResolveMultisampleFramebuffer = noOpGLResolveMultisampleFramebuffer;
- interface->fMapBuffer = nullGLMapBuffer;
- interface->fUnmapBuffer = nullGLUnmapBuffer;
- interface->fBindFragDataLocationIndexed = noOpGLBindFragDataLocationIndexed;
- }
- glInterface.get()->ref();
- return glInterface.get();
+ GrGLInterface* interface = SkNEW(GrGLInterface);
+
+ interface->fStandard = kGL_GrGLStandard;
+
+ GrGLInterface::Functions* functions = &interface->fFunctions;
+ functions->fActiveTexture = nullGLActiveTexture;
+ functions->fAttachShader = nullGLAttachShader;
+ functions->fBeginQuery = nullGLBeginQuery;
+ functions->fBindAttribLocation = nullGLBindAttribLocation;
+ functions->fBindBuffer = nullGLBindBuffer;
+ functions->fBindFragDataLocation = noOpGLBindFragDataLocation;
+ functions->fBindTexture = nullGLBindTexture;
+ functions->fBindVertexArray = nullGLBindVertexArray;
+ functions->fBlendColor = noOpGLBlendColor;
+ functions->fBlendFunc = noOpGLBlendFunc;
+ functions->fBufferData = nullGLBufferData;
+ functions->fBufferSubData = noOpGLBufferSubData;
+ functions->fClear = noOpGLClear;
+ functions->fClearColor = noOpGLClearColor;
+ functions->fClearStencil = noOpGLClearStencil;
+ functions->fColorMask = noOpGLColorMask;
+ functions->fCompileShader = noOpGLCompileShader;
+ functions->fCompressedTexImage2D = noOpGLCompressedTexImage2D;
+ functions->fCompressedTexSubImage2D = noOpGLCompressedTexSubImage2D;
+ functions->fCopyTexSubImage2D = noOpGLCopyTexSubImage2D;
+ functions->fCreateProgram = nullGLCreateProgram;
+ functions->fCreateShader = nullGLCreateShader;
+ functions->fCullFace = noOpGLCullFace;
+ functions->fDeleteBuffers = nullGLDeleteBuffers;
+ functions->fDeleteProgram = nullGLDelete;
+ functions->fDeleteQueries = noOpGLDeleteIds;
+ functions->fDeleteShader = nullGLDelete;
+ functions->fDeleteTextures = noOpGLDeleteIds;
+ functions->fDeleteVertexArrays = noOpGLDeleteIds;
+ functions->fDepthMask = noOpGLDepthMask;
+ functions->fDisable = noOpGLDisable;
+ functions->fDisableVertexAttribArray = noOpGLDisableVertexAttribArray;
+ functions->fDrawArrays = noOpGLDrawArrays;
+ functions->fDrawBuffer = noOpGLDrawBuffer;
+ functions->fDrawBuffers = noOpGLDrawBuffers;
+ functions->fDrawElements = noOpGLDrawElements;
+ functions->fEnable = noOpGLEnable;
+ functions->fEnableVertexAttribArray = noOpGLEnableVertexAttribArray;
+ functions->fEndQuery = noOpGLEndQuery;
+ functions->fFinish = noOpGLFinish;
+ functions->fFlush = noOpGLFlush;
+ functions->fFlushMappedBufferRange = nullGLFlushMappedBufferRange;
+ functions->fFrontFace = noOpGLFrontFace;
+ functions->fGenBuffers = nullGLGenBuffers;
+ functions->fGenerateMipmap = nullGLGenerateMipmap;
+ functions->fGenQueries = noOpGLGenIds;
+ functions->fGenTextures = noOpGLGenIds;
+ functions->fGenVertexArrays = noOpGLGenIds;
+ functions->fGetBufferParameteriv = nullGLGetBufferParameteriv;
+ functions->fGetError = noOpGLGetError;
+ functions->fGetIntegerv = noOpGLGetIntegerv;
+ functions->fGetQueryObjecti64v = noOpGLGetQueryObjecti64v;
+ functions->fGetQueryObjectiv = noOpGLGetQueryObjectiv;
+ functions->fGetQueryObjectui64v = noOpGLGetQueryObjectui64v;
+ functions->fGetQueryObjectuiv = noOpGLGetQueryObjectuiv;
+ functions->fGetQueryiv = noOpGLGetQueryiv;
+ functions->fGetProgramInfoLog = noOpGLGetInfoLog;
+ functions->fGetProgramiv = noOpGLGetShaderOrProgramiv;
+ functions->fGetShaderInfoLog = noOpGLGetInfoLog;
+ functions->fGetShaderiv = noOpGLGetShaderOrProgramiv;
+ functions->fGetString = noOpGLGetString;
+ functions->fGetStringi = noOpGLGetStringi;
+ functions->fGetTexLevelParameteriv = noOpGLGetTexLevelParameteriv;
+ functions->fGetUniformLocation = noOpGLGetUniformLocation;
+ functions->fInsertEventMarker = noOpGLInsertEventMarker;
+ functions->fLineWidth = noOpGLLineWidth;
+ functions->fLinkProgram = noOpGLLinkProgram;
+ functions->fMapBuffer = nullGLMapBuffer;
+ functions->fMapBufferRange = nullGLMapBufferRange;
+ functions->fPixelStorei = nullGLPixelStorei;
+ functions->fPopGroupMarker = noOpGLPopGroupMarker;
+ functions->fPushGroupMarker = noOpGLPushGroupMarker;
+ functions->fQueryCounter = noOpGLQueryCounter;
+ functions->fReadBuffer = noOpGLReadBuffer;
+ functions->fReadPixels = nullGLReadPixels;
+ functions->fScissor = noOpGLScissor;
+ functions->fShaderSource = noOpGLShaderSource;
+ functions->fStencilFunc = noOpGLStencilFunc;
+ functions->fStencilFuncSeparate = noOpGLStencilFuncSeparate;
+ functions->fStencilMask = noOpGLStencilMask;
+ functions->fStencilMaskSeparate = noOpGLStencilMaskSeparate;
+ functions->fStencilOp = noOpGLStencilOp;
+ functions->fStencilOpSeparate = noOpGLStencilOpSeparate;
+ functions->fTexImage2D = noOpGLTexImage2D;
+ functions->fTexParameteri = noOpGLTexParameteri;
+ functions->fTexParameteriv = noOpGLTexParameteriv;
+ functions->fTexSubImage2D = noOpGLTexSubImage2D;
+ functions->fTexStorage2D = noOpGLTexStorage2D;
+ functions->fDiscardFramebuffer = noOpGLDiscardFramebuffer;
+ functions->fUniform1f = noOpGLUniform1f;
+ functions->fUniform1i = noOpGLUniform1i;
+ functions->fUniform1fv = noOpGLUniform1fv;
+ functions->fUniform1iv = noOpGLUniform1iv;
+ functions->fUniform2f = noOpGLUniform2f;
+ functions->fUniform2i = noOpGLUniform2i;
+ functions->fUniform2fv = noOpGLUniform2fv;
+ functions->fUniform2iv = noOpGLUniform2iv;
+ functions->fUniform3f = noOpGLUniform3f;
+ functions->fUniform3i = noOpGLUniform3i;
+ functions->fUniform3fv = noOpGLUniform3fv;
+ functions->fUniform3iv = noOpGLUniform3iv;
+ functions->fUniform4f = noOpGLUniform4f;
+ functions->fUniform4i = noOpGLUniform4i;
+ functions->fUniform4fv = noOpGLUniform4fv;
+ functions->fUniform4iv = noOpGLUniform4iv;
+ functions->fUniformMatrix2fv = noOpGLUniformMatrix2fv;
+ functions->fUniformMatrix3fv = noOpGLUniformMatrix3fv;
+ functions->fUniformMatrix4fv = noOpGLUniformMatrix4fv;
+ functions->fUnmapBuffer = nullGLUnmapBuffer;
+ functions->fUseProgram = nullGLUseProgram;
+ functions->fVertexAttrib4fv = noOpGLVertexAttrib4fv;
+ functions->fVertexAttribPointer = noOpGLVertexAttribPointer;
+ functions->fViewport = nullGLViewport;
+ functions->fBindFramebuffer = nullGLBindFramebuffer;
+ functions->fBindRenderbuffer = nullGLBindRenderbuffer;
+ functions->fCheckFramebufferStatus = noOpGLCheckFramebufferStatus;
+ functions->fDeleteFramebuffers = nullGLDeleteFramebuffers;
+ functions->fDeleteRenderbuffers = nullGLDeleteRenderbuffers;
+ functions->fFramebufferRenderbuffer = nullGLFramebufferRenderbuffer;
+ functions->fFramebufferTexture2D = nullGLFramebufferTexture2D;
+ functions->fGenFramebuffers = noOpGLGenIds;
+ functions->fGenRenderbuffers = noOpGLGenIds;
+ functions->fGetFramebufferAttachmentParameteriv = noOpGLGetFramebufferAttachmentParameteriv;
+ functions->fGetRenderbufferParameteriv = noOpGLGetRenderbufferParameteriv;
+ functions->fRenderbufferStorage = noOpGLRenderbufferStorage;
+ functions->fRenderbufferStorageMultisample = noOpGLRenderbufferStorageMultisample;
+ functions->fBlitFramebuffer = noOpGLBlitFramebuffer;
+ functions->fResolveMultisampleFramebuffer = noOpGLResolveMultisampleFramebuffer;
+ functions->fMatrixLoadf = noOpGLMatrixLoadf;
+ functions->fMatrixLoadIdentity = noOpGLMatrixLoadIdentity;
+ functions->fBindFragDataLocationIndexed = noOpGLBindFragDataLocationIndexed;
+
+ interface->fExtensions.init(kGL_GrGLStandard, functions->fGetString, functions->fGetStringi,
+ functions->fGetIntegerv);
+ return interface;
}
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLDefines.h b/chromium/third_party/skia/src/gpu/gl/GrGLDefines.h
index 0dbd425f0da..e2ddde88c40 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLDefines.h
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLDefines.h
@@ -210,6 +210,82 @@
#define GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
#define GR_GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+/* Compressed Texture Formats */
+#define GR_GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
+#define GR_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
+#define GR_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
+#define GR_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
+
+#define GR_GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00
+#define GR_GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01
+#define GR_GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
+#define GR_GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03
+
+#define GR_GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG 0x9137
+#define GR_GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG 0x9138
+
+#define GR_GL_COMPRESSED_RGB8_ETC1 0x8D64
+
+#define GR_GL_COMPRESSED_R11 0x9270
+#define GR_GL_COMPRESSED_SIGNED_R11 0x9271
+#define GR_GL_COMPRESSED_RG11 0x9272
+#define GR_GL_COMPRESSED_SIGNED_RG11 0x9273
+
+#define GR_GL_COMPRESSED_RGB8_ETC2 0x9274
+#define GR_GL_COMPRESSED_SRGB8 0x9275
+#define GR_GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1 0x9276
+#define GR_GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1 0x9277
+#define GR_GL_COMPRESSED_RGBA8_ETC2 0x9278
+#define GR_GL_COMPRESSED_SRGB8_ALPHA8_ETC2 0x9279
+
+#define GR_GL_COMPRESSED_LUMINANCE_LATC1 0x8C70
+#define GR_GL_COMPRESSED_SIGNED_LUMINANCE_LATC1 0x8C71
+#define GR_GL_COMPRESSED_LUMINANCE_ALPHA_LATC2 0x8C72
+#define GR_GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2 0x8C73
+
+#define GR_GL_COMPRESSED_RED_RGTC1 0x8DBB
+#define GR_GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
+#define GR_GL_COMPRESSED_RED_GREEN_RGTC2 0x8DBD
+#define GR_GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2 0x8DBE
+
+#define GR_GL_COMPRESSED_3DC_X 0x87F9
+#define GR_GL_COMPRESSED_3DC_XY 0x87FA
+
+#define GR_GL_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C
+#define GR_GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D
+#define GR_GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
+#define GR_GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
+
+#define GR_GL_COMPRESSED_RGBA_ASTC_4x4 0x93B0
+#define GR_GL_COMPRESSED_RGBA_ASTC_5x4 0x93B1
+#define GR_GL_COMPRESSED_RGBA_ASTC_5x5 0x93B2
+#define GR_GL_COMPRESSED_RGBA_ASTC_6x5 0x93B3
+#define GR_GL_COMPRESSED_RGBA_ASTC_6x6 0x93B4
+#define GR_GL_COMPRESSED_RGBA_ASTC_8x5 0x93B5
+#define GR_GL_COMPRESSED_RGBA_ASTC_8x6 0x93B6
+#define GR_GL_COMPRESSED_RGBA_ASTC_8x8 0x93B7
+#define GR_GL_COMPRESSED_RGBA_ASTC_10x5 0x93B8
+#define GR_GL_COMPRESSED_RGBA_ASTC_10x6 0x93B9
+#define GR_GL_COMPRESSED_RGBA_ASTC_10x8 0x93BA
+#define GR_GL_COMPRESSED_RGBA_ASTC_10x10 0x93BB
+#define GR_GL_COMPRESSED_RGBA_ASTC_12x10 0x93BC
+#define GR_GL_COMPRESSED_RGBA_ASTC_12x12 0x93BD
+
+#define GR_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4 0x93D0
+#define GR_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4 0x93D1
+#define GR_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5 0x93D2
+#define GR_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5 0x93D3
+#define GR_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6 0x93D4
+#define GR_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5 0x93D5
+#define GR_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6 0x93D6
+#define GR_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8 0x93D7
+#define GR_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5 0x93D8
+#define GR_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6 0x93D9
+#define GR_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8 0x93DA
+#define GR_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10 0x93DB
+#define GR_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10 0x93DC
+#define GR_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12 0x93DD
+
/* HintMode */
#define GR_GL_DONT_CARE 0x1100
#define GR_GL_FASTEST 0x1101
@@ -601,6 +677,14 @@
/* Vertex Buffer Object */
#define GR_GL_WRITE_ONLY 0x88B9
#define GR_GL_BUFFER_MAPPED 0x88BC
+
+#define GR_GL_MAP_READ_BIT 0x0001
+#define GR_GL_MAP_WRITE_BIT 0x0002
+#define GR_GL_MAP_INVALIDATE_RANGE_BIT 0x0004
+#define GR_GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
+#define GR_GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
+#define GR_GL_MAP_UNSYNCHRONIZED_BIT 0x0020
+
/* Read Format */
#define GR_GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
#define GR_GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
@@ -691,6 +775,11 @@
#define GR_GL_DEPTH_ATTACHMENT 0x8D00
#define GR_GL_STENCIL_ATTACHMENT 0x8D20
+// GL_EXT_discard_framebuffer
+#define GR_GL_COLOR 0x1800
+#define GR_GL_DEPTH 0x1801
+#define GR_GL_STENCIL 0x1802
+
#define GR_GL_NONE 0
#define GR_GL_FRAMEBUFFER_COMPLETE 0x8CD5
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLExtensions.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLExtensions.cpp
index 5ebab14b65a..53013df64da 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLExtensions.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLExtensions.cpp
@@ -12,27 +12,53 @@
#include "SkTSearch.h"
#include "SkTSort.h"
-namespace {
+namespace { // This cannot be static because it is used as a template parameter.
inline bool extension_compare(const SkString& a, const SkString& b) {
return strcmp(a.c_str(), b.c_str()) < 0;
}
}
-bool GrGLExtensions::init(GrGLBinding binding,
+// finds the index of ext in strings or a negative result if ext is not found.
+static int find_string(const SkTArray<SkString>& strings, const char ext[]) {
+ if (strings.empty()) {
+ return -1;
+ }
+ SkString extensionStr(ext);
+ int idx = SkTSearch<SkString, extension_compare>(&strings.front(),
+ strings.count(),
+ extensionStr,
+ sizeof(SkString));
+ return idx;
+}
+
+GrGLExtensions::GrGLExtensions(const GrGLExtensions& that) : fStrings(SkNEW(SkTArray<SkString>)) {
+ *this = that;
+}
+
+GrGLExtensions& GrGLExtensions::operator=(const GrGLExtensions& that) {
+ *fStrings = *that.fStrings;
+ fInitialized = that.fInitialized;
+ return *this;
+}
+
+bool GrGLExtensions::init(GrGLStandard standard,
GrGLGetStringProc getString,
GrGLGetStringiProc getStringi,
GrGLGetIntegervProc getIntegerv) {
- fStrings.reset();
+ fInitialized = false;
+ fStrings->reset();
+
if (NULL == getString) {
return false;
}
// glGetStringi and indexed extensions were added in version 3.0 of desktop GL and ES.
const GrGLubyte* verString = getString(GR_GL_VERSION);
- if (NULL == verString) {
+ GrGLVersion version = GrGLGetVersionFromString((const char*) verString);
+ if (GR_GL_INVALID_VER == version) {
return false;
}
- GrGLVersion version = GrGLGetVersionFromString((const char*) verString);
+
bool indexed = version >= GR_GL_VER(3, 0);
if (indexed) {
@@ -41,10 +67,10 @@ bool GrGLExtensions::init(GrGLBinding binding,
}
GrGLint extensionCnt = 0;
getIntegerv(GR_GL_NUM_EXTENSIONS, &extensionCnt);
- fStrings.push_back_n(extensionCnt);
+ fStrings->push_back_n(extensionCnt);
for (int i = 0; i < extensionCnt; ++i) {
const char* ext = (const char*) getStringi(GR_GL_EXTENSIONS, i);
- fStrings[i] = ext;
+ (*fStrings)[i] = ext;
}
} else {
const char* extensions = (const char*) getString(GR_GL_EXTENSIONS);
@@ -62,35 +88,56 @@ bool GrGLExtensions::init(GrGLBinding binding,
}
// we found an extension
size_t length = strcspn(extensions, " ");
- fStrings.push_back().set(extensions, length);
+ fStrings->push_back().set(extensions, length);
extensions += length;
}
}
- if (!fStrings.empty()) {
+ if (!fStrings->empty()) {
SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
- SkTQSort(&fStrings.front(), &fStrings.back(), cmp);
+ SkTQSort(&fStrings->front(), &fStrings->back(), cmp);
}
+ fInitialized = true;
return true;
}
-bool GrGLExtensions::has(const char* ext) const {
- if (fStrings.empty()) {
+bool GrGLExtensions::has(const char ext[]) const {
+ SkASSERT(fInitialized);
+ return find_string(*fStrings, ext) >= 0;
+}
+
+bool GrGLExtensions::remove(const char ext[]) {
+ SkASSERT(fInitialized);
+ int idx = find_string(*fStrings, ext);
+ if (idx >= 0) {
+ // This is not terribly effecient but we really only expect this function to be called at
+ // most a handful of times when our test programs start.
+ SkAutoTDelete< SkTArray<SkString> > oldStrings(fStrings.detach());
+ fStrings.reset(SkNEW(SkTArray<SkString>(oldStrings->count() - 1)));
+ fStrings->push_back_n(idx, &oldStrings->front());
+ fStrings->push_back_n(oldStrings->count() - idx - 1, &(*oldStrings)[idx] + 1);
+ return true;
+ } else {
return false;
}
- SkString extensionStr(ext);
- int idx = SkTSearch<SkString, extension_compare>(&fStrings.front(),
- fStrings.count(),
- extensionStr,
- sizeof(SkString));
- return idx >= 0;
+}
+
+void GrGLExtensions::add(const char ext[]) {
+ int idx = find_string(*fStrings, ext);
+ if (idx < 0) {
+ // This is not the most effecient approach since we end up doing a full sort of the
+ // extensions after the add
+ fStrings->push_back().set(ext);
+ SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
+ SkTQSort(&fStrings->front(), &fStrings->back(), cmp);
+ }
}
void GrGLExtensions::print(const char* sep) const {
if (NULL == sep) {
sep = " ";
}
- int cnt = fStrings.count();
+ int cnt = fStrings->count();
for (int i = 0; i < cnt; ++i) {
- GrPrintf("%s%s", fStrings[i].c_str(), (i < cnt - 1) ? sep : "");
+ GrPrintf("%s%s", (*fStrings)[i].c_str(), (i < cnt - 1) ? sep : "");
}
}
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLIndexBuffer.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLIndexBuffer.cpp
index b6290b1826b..a137348ef75 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLIndexBuffer.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLIndexBuffer.cpp
@@ -14,7 +14,7 @@ GrGLIndexBuffer::GrGLIndexBuffer(GrGpuGL* gpu, const Desc& desc)
}
void GrGLIndexBuffer::onRelease() {
- if (this->isValid()) {
+ if (!this->wasDestroyed()) {
fImpl.release(this->getGpuGL());
}
@@ -26,30 +26,22 @@ void GrGLIndexBuffer::onAbandon() {
INHERITED::onAbandon();
}
-void* GrGLIndexBuffer::lock() {
- if (this->isValid()) {
- return fImpl.lock(this->getGpuGL());
+void* GrGLIndexBuffer::onMap() {
+ if (!this->wasDestroyed()) {
+ return fImpl.map(this->getGpuGL());
} else {
return NULL;
}
}
-void* GrGLIndexBuffer::lockPtr() const {
- return fImpl.lockPtr();
-}
-
-void GrGLIndexBuffer::unlock() {
- if (this->isValid()) {
- fImpl.unlock(this->getGpuGL());
+void GrGLIndexBuffer::onUnmap() {
+ if (!this->wasDestroyed()) {
+ fImpl.unmap(this->getGpuGL());
}
}
-bool GrGLIndexBuffer::isLocked() const {
- return fImpl.isLocked();
-}
-
-bool GrGLIndexBuffer::updateData(const void* src, size_t srcSizeInBytes) {
- if (this->isValid()) {
+bool GrGLIndexBuffer::onUpdateData(const void* src, size_t srcSizeInBytes) {
+ if (!this->wasDestroyed()) {
return fImpl.updateData(this->getGpuGL(), src, srcSizeInBytes);
} else {
return false;
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLIndexBuffer.h b/chromium/third_party/skia/src/gpu/gl/GrGLIndexBuffer.h
index 32a80860636..5d5de43eee4 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLIndexBuffer.h
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLIndexBuffer.h
@@ -26,26 +26,22 @@ public:
size_t baseOffset() const { return fImpl.baseOffset(); }
void bind() const {
- if (this->isValid()) {
+ if (!this->wasDestroyed()) {
fImpl.bind(this->getGpuGL());
}
}
- // overrides of GrIndexBuffer
- virtual void* lock();
- virtual void* lockPtr() const;
- virtual void unlock();
- virtual bool isLocked() const;
- virtual bool updateData(const void* src, size_t srcSizeInBytes);
-
protected:
- // overrides of GrResource
virtual void onAbandon() SK_OVERRIDE;
virtual void onRelease() SK_OVERRIDE;
private:
+ virtual void* onMap() SK_OVERRIDE;
+ virtual void onUnmap() SK_OVERRIDE;
+ virtual bool onUpdateData(const void* src, size_t srcSizeInBytes) SK_OVERRIDE;
+
GrGpuGL* getGpuGL() const {
- SkASSERT(this->isValid());
+ SkASSERT(!this->wasDestroyed());
return (GrGpuGL*)(this->getGpu());
}
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLInterface.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLInterface.cpp
index e1c69e18a43..b81d9ceeb84 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLInterface.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLInterface.cpp
@@ -18,8 +18,83 @@ void GrGLDefaultInterfaceCallback(const GrGLInterface*) {}
}
#endif
+const GrGLInterface* GrGLInterfaceAddTestDebugMarker(const GrGLInterface* interface,
+ GrGLInsertEventMarkerProc insertEventMarkerFn,
+ GrGLPushGroupMarkerProc pushGroupMarkerFn,
+ GrGLPopGroupMarkerProc popGroupMarkerFn) {
+ GrGLInterface* newInterface = GrGLInterface::NewClone(interface);
+
+ if (!newInterface->fExtensions.has("GL_EXT_debug_marker")) {
+ newInterface->fExtensions.add("GL_EXT_debug_marker");
+ }
+
+ newInterface->fFunctions.fInsertEventMarker = insertEventMarkerFn;
+ newInterface->fFunctions.fPushGroupMarker = pushGroupMarkerFn;
+ newInterface->fFunctions.fPopGroupMarker = popGroupMarkerFn;
+
+ return newInterface;
+}
+
+const GrGLInterface* GrGLInterfaceRemoveNVPR(const GrGLInterface* interface) {
+ GrGLInterface* newInterface = GrGLInterface::NewClone(interface);
+
+ newInterface->fExtensions.remove("GL_NV_path_rendering");
+
+ newInterface->fFunctions.fPathCommands = NULL;
+ newInterface->fFunctions.fPathCoords = NULL;
+ newInterface->fFunctions.fPathSubCommands = NULL;
+ newInterface->fFunctions.fPathSubCoords = NULL;
+ newInterface->fFunctions.fPathString = NULL;
+ newInterface->fFunctions.fPathGlyphs = NULL;
+ newInterface->fFunctions.fPathGlyphRange = NULL;
+ newInterface->fFunctions.fWeightPaths = NULL;
+ newInterface->fFunctions.fCopyPath = NULL;
+ newInterface->fFunctions.fInterpolatePaths = NULL;
+ newInterface->fFunctions.fTransformPath = NULL;
+ newInterface->fFunctions.fPathParameteriv = NULL;
+ newInterface->fFunctions.fPathParameteri = NULL;
+ newInterface->fFunctions.fPathParameterfv = NULL;
+ newInterface->fFunctions.fPathParameterf = NULL;
+ newInterface->fFunctions.fPathDashArray = NULL;
+ newInterface->fFunctions.fGenPaths = NULL;
+ newInterface->fFunctions.fDeletePaths = NULL;
+ newInterface->fFunctions.fIsPath = NULL;
+ newInterface->fFunctions.fPathStencilFunc = NULL;
+ newInterface->fFunctions.fPathStencilDepthOffset = NULL;
+ newInterface->fFunctions.fStencilFillPath = NULL;
+ newInterface->fFunctions.fStencilStrokePath = NULL;
+ newInterface->fFunctions.fStencilFillPathInstanced = NULL;
+ newInterface->fFunctions.fStencilStrokePathInstanced = NULL;
+ newInterface->fFunctions.fPathCoverDepthFunc = NULL;
+ newInterface->fFunctions.fPathColorGen = NULL;
+ newInterface->fFunctions.fPathTexGen = NULL;
+ newInterface->fFunctions.fPathFogGen = NULL;
+ newInterface->fFunctions.fCoverFillPath = NULL;
+ newInterface->fFunctions.fCoverStrokePath = NULL;
+ newInterface->fFunctions.fCoverFillPathInstanced = NULL;
+ newInterface->fFunctions.fCoverStrokePathInstanced = NULL;
+ newInterface->fFunctions.fGetPathParameteriv = NULL;
+ newInterface->fFunctions.fGetPathParameterfv = NULL;
+ newInterface->fFunctions.fGetPathCommands = NULL;
+ newInterface->fFunctions.fGetPathCoords = NULL;
+ newInterface->fFunctions.fGetPathDashArray = NULL;
+ newInterface->fFunctions.fGetPathMetrics = NULL;
+ newInterface->fFunctions.fGetPathMetricRange = NULL;
+ newInterface->fFunctions.fGetPathSpacing = NULL;
+ newInterface->fFunctions.fGetPathColorGeniv = NULL;
+ newInterface->fFunctions.fGetPathColorGenfv = NULL;
+ newInterface->fFunctions.fGetPathTexGeniv = NULL;
+ newInterface->fFunctions.fGetPathTexGenfv = NULL;
+ newInterface->fFunctions.fIsPointInFillPath = NULL;
+ newInterface->fFunctions.fIsPointInStrokePath = NULL;
+ newInterface->fFunctions.fGetPathLength = NULL;
+ newInterface->fFunctions.fPointAlongPath = NULL;
+
+ return newInterface;
+}
+
GrGLInterface::GrGLInterface() {
- fBindingsExported = kNone_GrGLBinding;
+ fStandard = kNone_GrGLStandard;
#if GR_GL_PER_GL_FUNC_CALLBACK
fCallback = GrGLDefaultInterfaceCallback;
@@ -27,394 +102,429 @@ GrGLInterface::GrGLInterface() {
#endif
}
-bool GrGLInterface::validate(GrGLBinding binding) const {
+GrGLInterface* GrGLInterface::NewClone(const GrGLInterface* interface) {
+ SkASSERT(NULL != interface);
+
+ GrGLInterface* clone = SkNEW(GrGLInterface);
+ clone->fStandard = interface->fStandard;
+ clone->fExtensions = interface->fExtensions;
+ clone->fFunctions = interface->fFunctions;
+#if GR_GL_PER_GL_FUNC_CALLBACK
+ clone->fCallback = interface->fCallback;
+ clone->fCallbackData = interface->fCallbackData;
+#endif
+ return clone;
+}
+
+#ifdef SK_DEBUG
+ static int kIsDebug = 1;
+#else
+ static int kIsDebug = 0;
+#endif
- // kNone must be 0 so that the check we're about to do can never succeed if
- // binding == kNone.
- GR_STATIC_ASSERT(kNone_GrGLBinding == 0);
+#define RETURN_FALSE_INTERFACE \
+ if (kIsDebug) { SkDebugf("%s:%d GrGLInterface::validate() failed.\n", __FILE__, __LINE__); } \
+ return false;
- if (0 == (binding & fBindingsExported)) {
- return false;
+bool GrGLInterface::validate() const {
+
+ if (kNone_GrGLStandard == fStandard) {
+ RETURN_FALSE_INTERFACE
}
- GrGLExtensions extensions;
- if (!extensions.init(binding, this)) {
- return false;
+ if (!fExtensions.isInitialized()) {
+ RETURN_FALSE_INTERFACE
}
// functions that are always required
- if (NULL == fActiveTexture ||
- NULL == fAttachShader ||
- NULL == fBindAttribLocation ||
- NULL == fBindBuffer ||
- NULL == fBindTexture ||
- NULL == fBlendFunc ||
- NULL == fBlendColor || // -> GL >= 1.4, ES >= 2.0 or extension
- NULL == fBufferData ||
- NULL == fBufferSubData ||
- NULL == fClear ||
- NULL == fClearColor ||
- NULL == fClearStencil ||
- NULL == fColorMask ||
- NULL == fCompileShader ||
- NULL == fCopyTexSubImage2D ||
- NULL == fCreateProgram ||
- NULL == fCreateShader ||
- NULL == fCullFace ||
- NULL == fDeleteBuffers ||
- NULL == fDeleteProgram ||
- NULL == fDeleteShader ||
- NULL == fDeleteTextures ||
- NULL == fDepthMask ||
- NULL == fDisable ||
- NULL == fDisableVertexAttribArray ||
- NULL == fDrawArrays ||
- NULL == fDrawElements ||
- NULL == fEnable ||
- NULL == fEnableVertexAttribArray ||
- NULL == fFrontFace ||
- NULL == fGenBuffers ||
- NULL == fGenTextures ||
- NULL == fGetBufferParameteriv ||
- NULL == fGenerateMipmap ||
- NULL == fGetError ||
- NULL == fGetIntegerv ||
- NULL == fGetProgramInfoLog ||
- NULL == fGetProgramiv ||
- NULL == fGetShaderInfoLog ||
- NULL == fGetShaderiv ||
- NULL == fGetString ||
- NULL == fGetUniformLocation ||
- NULL == fLinkProgram ||
- NULL == fLineWidth ||
- NULL == fPixelStorei ||
- NULL == fReadPixels ||
- NULL == fScissor ||
- NULL == fShaderSource ||
- NULL == fStencilFunc ||
- NULL == fStencilMask ||
- NULL == fStencilOp ||
- NULL == fTexImage2D ||
- NULL == fTexParameteri ||
- NULL == fTexParameteriv ||
- NULL == fTexSubImage2D ||
- NULL == fUniform1f ||
- NULL == fUniform1i ||
- NULL == fUniform1fv ||
- NULL == fUniform1iv ||
- NULL == fUniform2f ||
- NULL == fUniform2i ||
- NULL == fUniform2fv ||
- NULL == fUniform2iv ||
- NULL == fUniform3f ||
- NULL == fUniform3i ||
- NULL == fUniform3fv ||
- NULL == fUniform3iv ||
- NULL == fUniform4f ||
- NULL == fUniform4i ||
- NULL == fUniform4fv ||
- NULL == fUniform4iv ||
- NULL == fUniformMatrix2fv ||
- NULL == fUniformMatrix3fv ||
- NULL == fUniformMatrix4fv ||
- NULL == fUseProgram ||
- NULL == fVertexAttrib4fv ||
- NULL == fVertexAttribPointer ||
- NULL == fViewport ||
- NULL == fBindFramebuffer ||
- NULL == fBindRenderbuffer ||
- NULL == fCheckFramebufferStatus ||
- NULL == fDeleteFramebuffers ||
- NULL == fDeleteRenderbuffers ||
- NULL == fFinish ||
- NULL == fFlush ||
- NULL == fFramebufferRenderbuffer ||
- NULL == fFramebufferTexture2D ||
- NULL == fGetFramebufferAttachmentParameteriv ||
- NULL == fGetRenderbufferParameteriv ||
- NULL == fGenFramebuffers ||
- NULL == fGenRenderbuffers ||
- NULL == fRenderbufferStorage) {
- return false;
+ if (NULL == fFunctions.fActiveTexture ||
+ NULL == fFunctions.fAttachShader ||
+ NULL == fFunctions.fBindAttribLocation ||
+ NULL == fFunctions.fBindBuffer ||
+ NULL == fFunctions.fBindTexture ||
+ NULL == fFunctions.fBlendFunc ||
+ NULL == fFunctions.fBlendColor || // -> GL >= 1.4, ES >= 2.0 or extension
+ NULL == fFunctions.fBufferData ||
+ NULL == fFunctions.fBufferSubData ||
+ NULL == fFunctions.fClear ||
+ NULL == fFunctions.fClearColor ||
+ NULL == fFunctions.fClearStencil ||
+ NULL == fFunctions.fColorMask ||
+ NULL == fFunctions.fCompileShader ||
+ NULL == fFunctions.fCopyTexSubImage2D ||
+ NULL == fFunctions.fCreateProgram ||
+ NULL == fFunctions.fCreateShader ||
+ NULL == fFunctions.fCullFace ||
+ NULL == fFunctions.fDeleteBuffers ||
+ NULL == fFunctions.fDeleteProgram ||
+ NULL == fFunctions.fDeleteShader ||
+ NULL == fFunctions.fDeleteTextures ||
+ NULL == fFunctions.fDepthMask ||
+ NULL == fFunctions.fDisable ||
+ NULL == fFunctions.fDisableVertexAttribArray ||
+ NULL == fFunctions.fDrawArrays ||
+ NULL == fFunctions.fDrawElements ||
+ NULL == fFunctions.fEnable ||
+ NULL == fFunctions.fEnableVertexAttribArray ||
+ NULL == fFunctions.fFrontFace ||
+ NULL == fFunctions.fGenBuffers ||
+ NULL == fFunctions.fGenTextures ||
+ NULL == fFunctions.fGetBufferParameteriv ||
+ NULL == fFunctions.fGenerateMipmap ||
+ NULL == fFunctions.fGetError ||
+ NULL == fFunctions.fGetIntegerv ||
+ NULL == fFunctions.fGetProgramInfoLog ||
+ NULL == fFunctions.fGetProgramiv ||
+ NULL == fFunctions.fGetShaderInfoLog ||
+ NULL == fFunctions.fGetShaderiv ||
+ NULL == fFunctions.fGetString ||
+ NULL == fFunctions.fGetUniformLocation ||
+ NULL == fFunctions.fLinkProgram ||
+ NULL == fFunctions.fLineWidth ||
+ NULL == fFunctions.fPixelStorei ||
+ NULL == fFunctions.fReadPixels ||
+ NULL == fFunctions.fScissor ||
+ NULL == fFunctions.fShaderSource ||
+ NULL == fFunctions.fStencilFunc ||
+ NULL == fFunctions.fStencilMask ||
+ NULL == fFunctions.fStencilOp ||
+ NULL == fFunctions.fTexImage2D ||
+ NULL == fFunctions.fTexParameteri ||
+ NULL == fFunctions.fTexParameteriv ||
+ NULL == fFunctions.fTexSubImage2D ||
+ NULL == fFunctions.fUniform1f ||
+ NULL == fFunctions.fUniform1i ||
+ NULL == fFunctions.fUniform1fv ||
+ NULL == fFunctions.fUniform1iv ||
+ NULL == fFunctions.fUniform2f ||
+ NULL == fFunctions.fUniform2i ||
+ NULL == fFunctions.fUniform2fv ||
+ NULL == fFunctions.fUniform2iv ||
+ NULL == fFunctions.fUniform3f ||
+ NULL == fFunctions.fUniform3i ||
+ NULL == fFunctions.fUniform3fv ||
+ NULL == fFunctions.fUniform3iv ||
+ NULL == fFunctions.fUniform4f ||
+ NULL == fFunctions.fUniform4i ||
+ NULL == fFunctions.fUniform4fv ||
+ NULL == fFunctions.fUniform4iv ||
+ NULL == fFunctions.fUniformMatrix2fv ||
+ NULL == fFunctions.fUniformMatrix3fv ||
+ NULL == fFunctions.fUniformMatrix4fv ||
+ NULL == fFunctions.fUseProgram ||
+ NULL == fFunctions.fVertexAttrib4fv ||
+ NULL == fFunctions.fVertexAttribPointer ||
+ NULL == fFunctions.fViewport ||
+ NULL == fFunctions.fBindFramebuffer ||
+ NULL == fFunctions.fBindRenderbuffer ||
+ NULL == fFunctions.fCheckFramebufferStatus ||
+ NULL == fFunctions.fDeleteFramebuffers ||
+ NULL == fFunctions.fDeleteRenderbuffers ||
+ NULL == fFunctions.fFinish ||
+ NULL == fFunctions.fFlush ||
+ NULL == fFunctions.fFramebufferRenderbuffer ||
+ NULL == fFunctions.fFramebufferTexture2D ||
+ NULL == fFunctions.fGetFramebufferAttachmentParameteriv ||
+ NULL == fFunctions.fGetRenderbufferParameteriv ||
+ NULL == fFunctions.fGenFramebuffers ||
+ NULL == fFunctions.fGenRenderbuffers ||
+ NULL == fFunctions.fRenderbufferStorage) {
+ RETURN_FALSE_INTERFACE
}
GrGLVersion glVer = GrGLGetVersion(this);
-
- bool isCoreProfile = false;
- if (kDesktop_GrGLBinding == binding && glVer >= GR_GL_VER(3,2)) {
- GrGLint profileMask;
- GR_GL_GetIntegerv(this, GR_GL_CONTEXT_PROFILE_MASK, &profileMask);
- isCoreProfile = SkToBool(profileMask & GR_GL_CONTEXT_CORE_PROFILE_BIT);
+ if (GR_GL_INVALID_VER == glVer) {
+ RETURN_FALSE_INTERFACE
}
// Now check that baseline ES/Desktop fns not covered above are present
- // and that we have fn pointers for any advertised extensions that we will
+ // and that we have fn pointers for any advertised fExtensions that we will
// try to use.
// these functions are part of ES2, we assume they are available
// On the desktop we assume they are available if the extension
// is present or GL version is high enough.
- if (kES_GrGLBinding == binding) {
- if (NULL == fStencilFuncSeparate ||
- NULL == fStencilMaskSeparate ||
- NULL == fStencilOpSeparate) {
- return false;
+ if (kGLES_GrGLStandard == fStandard) {
+ if (NULL == fFunctions.fStencilFuncSeparate ||
+ NULL == fFunctions.fStencilMaskSeparate ||
+ NULL == fFunctions.fStencilOpSeparate) {
+ RETURN_FALSE_INTERFACE
}
- } else if (kDesktop_GrGLBinding == binding) {
+ } else if (kGL_GrGLStandard == fStandard) {
if (glVer >= GR_GL_VER(2,0)) {
- if (NULL == fStencilFuncSeparate ||
- NULL == fStencilMaskSeparate ||
- NULL == fStencilOpSeparate) {
- return false;
+ if (NULL == fFunctions.fStencilFuncSeparate ||
+ NULL == fFunctions.fStencilMaskSeparate ||
+ NULL == fFunctions.fStencilOpSeparate) {
+ RETURN_FALSE_INTERFACE
}
}
- if (glVer >= GR_GL_VER(3,0) && NULL == fBindFragDataLocation) {
- return false;
+ if (glVer >= GR_GL_VER(3,0) && NULL == fFunctions.fBindFragDataLocation) {
+ RETURN_FALSE_INTERFACE
}
- if (glVer >= GR_GL_VER(2,0) || extensions.has("GL_ARB_draw_buffers")) {
- if (NULL == fDrawBuffers) {
- return false;
+ if (glVer >= GR_GL_VER(2,0) || fExtensions.has("GL_ARB_draw_buffers")) {
+ if (NULL == fFunctions.fDrawBuffers) {
+ RETURN_FALSE_INTERFACE
}
}
- if (glVer >= GR_GL_VER(1,5) || extensions.has("GL_ARB_occlusion_query")) {
- if (NULL == fGenQueries ||
- NULL == fDeleteQueries ||
- NULL == fBeginQuery ||
- NULL == fEndQuery ||
- NULL == fGetQueryiv ||
- NULL == fGetQueryObjectiv ||
- NULL == fGetQueryObjectuiv) {
- return false;
+ if (glVer >= GR_GL_VER(1,5) || fExtensions.has("GL_ARB_occlusion_query")) {
+ if (NULL == fFunctions.fGenQueries ||
+ NULL == fFunctions.fDeleteQueries ||
+ NULL == fFunctions.fBeginQuery ||
+ NULL == fFunctions.fEndQuery ||
+ NULL == fFunctions.fGetQueryiv ||
+ NULL == fFunctions.fGetQueryObjectiv ||
+ NULL == fFunctions.fGetQueryObjectuiv) {
+ RETURN_FALSE_INTERFACE
}
}
if (glVer >= GR_GL_VER(3,3) ||
- extensions.has("GL_ARB_timer_query") ||
- extensions.has("GL_EXT_timer_query")) {
- if (NULL == fGetQueryObjecti64v ||
- NULL == fGetQueryObjectui64v) {
- return false;
+ fExtensions.has("GL_ARB_timer_query") ||
+ fExtensions.has("GL_EXT_timer_query")) {
+ if (NULL == fFunctions.fGetQueryObjecti64v ||
+ NULL == fFunctions.fGetQueryObjectui64v) {
+ RETURN_FALSE_INTERFACE
}
}
- if (glVer >= GR_GL_VER(3,3) || extensions.has("GL_ARB_timer_query")) {
- if (NULL == fQueryCounter) {
- return false;
+ if (glVer >= GR_GL_VER(3,3) || fExtensions.has("GL_ARB_timer_query")) {
+ if (NULL == fFunctions.fQueryCounter) {
+ RETURN_FALSE_INTERFACE
}
}
- if (!isCoreProfile) {
- if (NULL == fClientActiveTexture ||
- NULL == fDisableClientState ||
- NULL == fEnableClientState ||
- NULL == fLoadIdentity ||
- NULL == fLoadMatrixf ||
- NULL == fMatrixMode ||
- NULL == fTexGenf ||
- NULL == fTexGenfv ||
- NULL == fTexGeni ||
- NULL == fVertexPointer) {
- return false;
+ if (fExtensions.has("GL_EXT_direct_state_access")) {
+ if (NULL == fFunctions.fMatrixLoadf ||
+ NULL == fFunctions.fMatrixLoadIdentity) {
+ RETURN_FALSE_INTERFACE
}
}
- if (false && extensions.has("GL_NV_path_rendering")) {
- if (NULL == fPathCommands ||
- NULL == fPathCoords ||
- NULL == fPathSubCommands ||
- NULL == fPathSubCoords ||
- NULL == fPathString ||
- NULL == fPathGlyphs ||
- NULL == fPathGlyphRange ||
- NULL == fWeightPaths ||
- NULL == fCopyPath ||
- NULL == fInterpolatePaths ||
- NULL == fTransformPath ||
- NULL == fPathParameteriv ||
- NULL == fPathParameteri ||
- NULL == fPathParameterfv ||
- NULL == fPathParameterf ||
- NULL == fPathDashArray ||
- NULL == fGenPaths ||
- NULL == fDeletePaths ||
- NULL == fIsPath ||
- NULL == fPathStencilFunc ||
- NULL == fPathStencilDepthOffset ||
- NULL == fStencilFillPath ||
- NULL == fStencilStrokePath ||
- NULL == fStencilFillPathInstanced ||
- NULL == fStencilStrokePathInstanced ||
- NULL == fPathCoverDepthFunc ||
- NULL == fPathColorGen ||
- NULL == fPathTexGen ||
- NULL == fPathFogGen ||
- NULL == fCoverFillPath ||
- NULL == fCoverStrokePath ||
- NULL == fCoverFillPathInstanced ||
- NULL == fCoverStrokePathInstanced ||
- NULL == fGetPathParameteriv ||
- NULL == fGetPathParameterfv ||
- NULL == fGetPathCommands ||
- NULL == fGetPathCoords ||
- NULL == fGetPathDashArray ||
- NULL == fGetPathMetrics ||
- NULL == fGetPathMetricRange ||
- NULL == fGetPathSpacing ||
- NULL == fGetPathColorGeniv ||
- NULL == fGetPathColorGenfv ||
- NULL == fGetPathTexGeniv ||
- NULL == fGetPathTexGenfv ||
- NULL == fIsPointInFillPath ||
- NULL == fIsPointInStrokePath ||
- NULL == fGetPathLength ||
- NULL == fPointAlongPath) {
- return false;
+ if (fExtensions.has("GL_NV_path_rendering")) {
+ if (NULL == fFunctions.fPathCommands ||
+ NULL == fFunctions.fPathCoords ||
+ NULL == fFunctions.fPathSubCommands ||
+ NULL == fFunctions.fPathSubCoords ||
+ NULL == fFunctions.fPathString ||
+ NULL == fFunctions.fPathGlyphs ||
+ NULL == fFunctions.fPathGlyphRange ||
+ NULL == fFunctions.fWeightPaths ||
+ NULL == fFunctions.fCopyPath ||
+ NULL == fFunctions.fInterpolatePaths ||
+ NULL == fFunctions.fTransformPath ||
+ NULL == fFunctions.fPathParameteriv ||
+ NULL == fFunctions.fPathParameteri ||
+ NULL == fFunctions.fPathParameterfv ||
+ NULL == fFunctions.fPathParameterf ||
+ NULL == fFunctions.fPathDashArray ||
+ NULL == fFunctions.fGenPaths ||
+ NULL == fFunctions.fDeletePaths ||
+ NULL == fFunctions.fIsPath ||
+ NULL == fFunctions.fPathStencilFunc ||
+ NULL == fFunctions.fPathStencilDepthOffset ||
+ NULL == fFunctions.fStencilFillPath ||
+ NULL == fFunctions.fStencilStrokePath ||
+ NULL == fFunctions.fStencilFillPathInstanced ||
+ NULL == fFunctions.fStencilStrokePathInstanced ||
+ NULL == fFunctions.fPathCoverDepthFunc ||
+ NULL == fFunctions.fPathColorGen ||
+ NULL == fFunctions.fPathTexGen ||
+ NULL == fFunctions.fPathFogGen ||
+ NULL == fFunctions.fCoverFillPath ||
+ NULL == fFunctions.fCoverStrokePath ||
+ NULL == fFunctions.fCoverFillPathInstanced ||
+ NULL == fFunctions.fCoverStrokePathInstanced ||
+ NULL == fFunctions.fGetPathParameteriv ||
+ NULL == fFunctions.fGetPathParameterfv ||
+ NULL == fFunctions.fGetPathCommands ||
+ NULL == fFunctions.fGetPathCoords ||
+ NULL == fFunctions.fGetPathDashArray ||
+ NULL == fFunctions.fGetPathMetrics ||
+ NULL == fFunctions.fGetPathMetricRange ||
+ NULL == fFunctions.fGetPathSpacing ||
+ NULL == fFunctions.fGetPathColorGeniv ||
+ NULL == fFunctions.fGetPathColorGenfv ||
+ NULL == fFunctions.fGetPathTexGeniv ||
+ NULL == fFunctions.fGetPathTexGenfv ||
+ NULL == fFunctions.fIsPointInFillPath ||
+ NULL == fFunctions.fIsPointInStrokePath ||
+ NULL == fFunctions.fGetPathLength ||
+ NULL == fFunctions.fPointAlongPath) {
+ RETURN_FALSE_INTERFACE
}
}
}
// optional function on desktop before 1.3
- if (kDesktop_GrGLBinding != binding ||
+ if (kGL_GrGLStandard != fStandard ||
(glVer >= GR_GL_VER(1,3)) ||
- extensions.has("GL_ARB_texture_compression")) {
- if (NULL == fCompressedTexImage2D) {
- return false;
+ fExtensions.has("GL_ARB_texture_compression")) {
+ if (NULL == fFunctions.fCompressedTexImage2D
+#if 0
+ || NULL == fFunctions.fCompressedTexSubImage2D
+#endif
+ ) {
+ RETURN_FALSE_INTERFACE
}
}
// part of desktop GL, but not ES
- if (kDesktop_GrGLBinding == binding &&
- (NULL == fGetTexLevelParameteriv ||
- NULL == fDrawBuffer ||
- NULL == fReadBuffer)) {
- return false;
+ if (kGL_GrGLStandard == fStandard &&
+ (NULL == fFunctions.fGetTexLevelParameteriv ||
+ NULL == fFunctions.fDrawBuffer ||
+ NULL == fFunctions.fReadBuffer)) {
+ RETURN_FALSE_INTERFACE
}
// GL_EXT_texture_storage is part of desktop 4.2
// There is a desktop ARB extension and an ES+desktop EXT extension
- if (kDesktop_GrGLBinding == binding) {
+ if (kGL_GrGLStandard == fStandard) {
if (glVer >= GR_GL_VER(4,2) ||
- extensions.has("GL_ARB_texture_storage") ||
- extensions.has("GL_EXT_texture_storage")) {
- if (NULL == fTexStorage2D) {
- return false;
+ fExtensions.has("GL_ARB_texture_storage") ||
+ fExtensions.has("GL_EXT_texture_storage")) {
+ if (NULL == fFunctions.fTexStorage2D) {
+ RETURN_FALSE_INTERFACE
}
}
- } else if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_EXT_texture_storage")) {
- if (NULL == fTexStorage2D) {
- return false;
+ } else if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_EXT_texture_storage")) {
+ if (NULL == fFunctions.fTexStorage2D) {
+ RETURN_FALSE_INTERFACE
}
}
- if (extensions.has("GL_EXT_discard_framebuffer")) {
+ if (fExtensions.has("GL_EXT_discard_framebuffer")) {
// FIXME: Remove this once Chromium is updated to provide this function
#if 0
- if (NULL == fDiscardFramebuffer) {
- return false;
+ if (NULL == fFunctions.fDiscardFramebuffer) {
+ RETURN_FALSE_INTERFACE
}
#endif
}
// FBO MSAA
- if (kDesktop_GrGLBinding == binding) {
+ if (kGL_GrGLStandard == fStandard) {
// GL 3.0 and the ARB extension have multisample + blit
- if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_ARB_framebuffer_object")) {
- if (NULL == fRenderbufferStorageMultisample ||
- NULL == fBlitFramebuffer) {
- return false;
+ if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_ARB_framebuffer_object")) {
+ if (NULL == fFunctions.fRenderbufferStorageMultisample ||
+ NULL == fFunctions.fBlitFramebuffer) {
+ RETURN_FALSE_INTERFACE
}
} else {
- if (extensions.has("GL_EXT_framebuffer_blit") &&
- NULL == fBlitFramebuffer) {
- return false;
+ if (fExtensions.has("GL_EXT_framebuffer_blit") &&
+ NULL == fFunctions.fBlitFramebuffer) {
+ RETURN_FALSE_INTERFACE
}
- if (extensions.has("GL_EXT_framebuffer_multisample") &&
- NULL == fRenderbufferStorageMultisample) {
- return false;
+ if (fExtensions.has("GL_EXT_framebuffer_multisample") &&
+ NULL == fFunctions.fRenderbufferStorageMultisample) {
+ RETURN_FALSE_INTERFACE
}
}
} else {
-#if GR_GL_IGNORE_ES3_MSAA
- if (extensions.has("GL_CHROMIUM_framebuffer_multisample")) {
- if (NULL == fRenderbufferStorageMultisample ||
- NULL == fBlitFramebuffer) {
- return false;
- }
- } else if (extensions.has("GL_APPLE_framebuffer_multisample")) {
- if (NULL == fRenderbufferStorageMultisample ||
- NULL == fResolveMultisampleFramebuffer) {
- return false;
- }
- } else if (extensions.has("GL_IMG_multisampled_render_to_texture") ||
- extensions.has("GL_EXT_multisampled_render_to_texture")) {
- if (NULL == fRenderbufferStorageMultisample ||
- NULL == fFramebufferTexture2DMultisample) {
- return false;
- }
- }
-#else
- if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_CHROMIUM_framebuffer_multisample")) {
- if (NULL == fRenderbufferStorageMultisample ||
- NULL == fBlitFramebuffer) {
- return false;
+ if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_CHROMIUM_framebuffer_multisample")) {
+ if (NULL == fFunctions.fRenderbufferStorageMultisample ||
+ NULL == fFunctions.fBlitFramebuffer) {
+ RETURN_FALSE_INTERFACE
}
}
- if (extensions.has("GL_APPLE_framebuffer_multisample")) {
- if (NULL == fRenderbufferStorageMultisampleES2APPLE ||
- NULL == fResolveMultisampleFramebuffer) {
- return false;
+ if (fExtensions.has("GL_APPLE_framebuffer_multisample")) {
+ if (NULL == fFunctions.fRenderbufferStorageMultisampleES2APPLE ||
+ NULL == fFunctions.fResolveMultisampleFramebuffer) {
+ RETURN_FALSE_INTERFACE
}
}
- if (extensions.has("GL_IMG_multisampled_render_to_texture") ||
- extensions.has("GL_EXT_multisampled_render_to_texture")) {
- if (NULL == fRenderbufferStorageMultisampleES2EXT ||
- NULL == fFramebufferTexture2DMultisample) {
- return false;
+ if (fExtensions.has("GL_IMG_multisampled_render_to_texture") ||
+ fExtensions.has("GL_EXT_multisampled_render_to_texture")) {
+ if (NULL == fFunctions.fRenderbufferStorageMultisampleES2EXT ||
+ NULL == fFunctions.fFramebufferTexture2DMultisample) {
+ RETURN_FALSE_INTERFACE
}
}
-#endif
}
// On ES buffer mapping is an extension. On Desktop
// buffer mapping was part of original VBO extension
// which we require.
- if (kDesktop_GrGLBinding == binding || extensions.has("GL_OES_mapbuffer")) {
- if (NULL == fMapBuffer ||
- NULL == fUnmapBuffer) {
- return false;
+ if (kGL_GrGLStandard == fStandard || fExtensions.has("GL_OES_mapbuffer")) {
+ if (NULL == fFunctions.fMapBuffer ||
+ NULL == fFunctions.fUnmapBuffer) {
+ RETURN_FALSE_INTERFACE
}
}
// Dual source blending
- if (kDesktop_GrGLBinding == binding &&
- (glVer >= GR_GL_VER(3,3) || extensions.has("GL_ARB_blend_func_extended"))) {
- if (NULL == fBindFragDataLocationIndexed) {
- return false;
+ if (kGL_GrGLStandard == fStandard &&
+ (glVer >= GR_GL_VER(3,3) || fExtensions.has("GL_ARB_blend_func_extended"))) {
+ if (NULL == fFunctions.fBindFragDataLocationIndexed) {
+ RETURN_FALSE_INTERFACE
}
}
// glGetStringi was added in version 3.0 of both desktop and ES.
if (glVer >= GR_GL_VER(3, 0)) {
- if (NULL == fGetStringi) {
- return false;
+ if (NULL == fFunctions.fGetStringi) {
+ RETURN_FALSE_INTERFACE
}
}
- if (kDesktop_GrGLBinding == binding) {
- if (glVer >= GR_GL_VER(3, 0) || extensions.has("GL_ARB_vertex_array_object")) {
- if (NULL == fBindVertexArray ||
- NULL == fDeleteVertexArrays ||
- NULL == fGenVertexArrays) {
- return false;
+ if (kGL_GrGLStandard == fStandard) {
+ if (glVer >= GR_GL_VER(3, 0) || fExtensions.has("GL_ARB_vertex_array_object")) {
+ if (NULL == fFunctions.fBindVertexArray ||
+ NULL == fFunctions.fDeleteVertexArrays ||
+ NULL == fFunctions.fGenVertexArrays) {
+ RETURN_FALSE_INTERFACE
}
}
} else {
- if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_OES_vertex_array_object")) {
- if (NULL == fBindVertexArray ||
- NULL == fDeleteVertexArrays ||
- NULL == fGenVertexArrays) {
- return false;
+ if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_OES_vertex_array_object")) {
+ if (NULL == fFunctions.fBindVertexArray ||
+ NULL == fFunctions.fDeleteVertexArrays ||
+ NULL == fFunctions.fGenVertexArrays) {
+ RETURN_FALSE_INTERFACE
}
}
}
+ if (fExtensions.has("GL_EXT_debug_marker")) {
+ if (NULL == fFunctions.fInsertEventMarker ||
+ NULL == fFunctions.fPushGroupMarker ||
+ NULL == fFunctions.fPopGroupMarker) {
+ RETURN_FALSE_INTERFACE
+ }
+ }
+
+ if ((kGL_GrGLStandard == fStandard && glVer >= GR_GL_VER(4,3)) ||
+ fExtensions.has("GL_ARB_invalidate_subdata")) {
+ if (NULL == fFunctions.fInvalidateBufferData ||
+ NULL == fFunctions.fInvalidateBufferSubData ||
+ NULL == fFunctions.fInvalidateFramebuffer ||
+ NULL == fFunctions.fInvalidateSubFramebuffer ||
+ NULL == fFunctions.fInvalidateTexImage ||
+ NULL == fFunctions.fInvalidateTexSubImage) {
+ RETURN_FALSE_INTERFACE;
+ }
+ } else if (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,0)) {
+ // ES 3.0 adds the framebuffer functions but not the others.
+ if (NULL == fFunctions.fInvalidateFramebuffer ||
+ NULL == fFunctions.fInvalidateSubFramebuffer) {
+ RETURN_FALSE_INTERFACE;
+ }
+ }
+
+ if (kGLES_GrGLStandard == fStandard && fExtensions.has("GL_CHROMIUM_map_sub")) {
+ if (NULL == fFunctions.fMapBufferSubData ||
+ NULL == fFunctions.fMapTexSubImage2D ||
+ NULL == fFunctions.fUnmapBufferSubData ||
+ NULL == fFunctions.fUnmapTexSubImage2D) {
+ RETURN_FALSE_INTERFACE;
+ }
+ }
+
+ // These functions are added to the 3.0 version of both GLES and GL.
+ if (glVer >= GR_GL_VER(3,0) ||
+ (kGLES_GrGLStandard == fStandard && fExtensions.has("GL_EXT_map_buffer_range")) ||
+ (kGL_GrGLStandard == fStandard && fExtensions.has("GL_ARB_map_buffer_range"))) {
+ if (NULL == fFunctions.fMapBufferRange ||
+ NULL == fFunctions.fFlushMappedBufferRange) {
+ RETURN_FALSE_INTERFACE;
+ }
+ }
return true;
}
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLNameAllocator.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLNameAllocator.cpp
new file mode 100644
index 00000000000..f2c37edbeb2
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLNameAllocator.cpp
@@ -0,0 +1,370 @@
+
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrGLNameAllocator.h"
+
+/**
+ * This is the abstract base class for a nonempty AVL tree that tracks allocated
+ * names within the half-open range [fFirst, fEnd). The inner nodes can be
+ * sparse (meaning not every name within the range is necessarily allocated),
+ * but the bounds are tight, so fFirst *is* guaranteed to be allocated, and so
+ * is fEnd - 1.
+ */
+class GrGLNameAllocator::SparseNameRange : public SkRefCnt {
+public:
+ virtual ~SparseNameRange() {}
+
+ /**
+ * Return the beginning of the range. first() is guaranteed to be allocated.
+ *
+ * @return The first name in the range.
+ */
+ GrGLuint first() const { return fFirst; }
+
+ /**
+ * Return the end of the range. end() - 1 is guaranteed to be allocated.
+ *
+ * @return One plus the final name in the range.
+ */
+ GrGLuint end() const { return fEnd; }
+
+ /**
+ * Return the height of the tree. This can only be nonzero at an inner node.
+ *
+ * @return 0 if the implementation is a leaf node,
+ * The nonzero height of the tree otherwise.
+ */
+ GrGLuint height() const { return fHeight; }
+
+ /**
+ * Allocate a name from strictly inside this range. The call will fail if
+ * there is not a free name within.
+ *
+ * @param outName A pointer that receives the allocated name. outName will
+ * be set to zero if there were no free names within the
+ * range [fFirst, fEnd).
+ * @return The resulting SparseNameRange after the allocation. Note that
+ * this call is destructive, so the original SparseNameRange will no
+ * longer be valid afterward. The caller must always update its
+ * pointer with the new SparseNameRange.
+ */
+ virtual SparseNameRange* SK_WARN_UNUSED_RESULT internalAllocate(GrGLuint* outName) = 0;
+
+ /**
+ * Remove the leftmost leaf node from this range (or the entire thing if it
+ * *is* a leaf node). This is an internal helper method that is used after
+ * an allocation if one contiguous range became adjacent to another. (The
+ * range gets removed so the one immediately before can be extended,
+ * collapsing the two into one.)
+ *
+ * @param removedCount A pointer that receives the size of the contiguous
+ range that was removed.
+ * @return The resulting SparseNameRange after the removal (or NULL if it
+ * became empty). Note that this call is destructive, so the
+ * original SparseNameRange will no longer be valid afterward. The
+ * caller must always update its pointer with the new
+ * SparseNameRange.
+ */
+ virtual SparseNameRange* SK_WARN_UNUSED_RESULT removeLeftmostContiguousRange(GrGLuint* removedCount) = 0;
+
+ /**
+ * Append adjacent allocated names to the end of this range. This operation
+ * does not affect the structure of the tree. The caller is responsible for
+ * ensuring the new names won't overlap sibling ranges, if any.
+ *
+ * @param count The number of adjacent names to append.
+ * @return The first name appended.
+ */
+ virtual GrGLuint appendNames(GrGLuint count) = 0;
+
+ /**
+ * Prepend adjacent allocated names behind the beginning of this range. This
+ * operation does not affect the structure of the tree. The caller is
+ * responsible for ensuring the new names won't overlap sibling ranges, if
+ * any.
+ *
+ * @param count The number of adjacent names to prepend.
+ * @return The final name prepended (the one with the lowest value).
+ */
+ virtual GrGLuint prependNames(GrGLuint count) = 0;
+
+ /**
+ * Free a name so it is no longer tracked as allocated. If the name is at
+ * the very beginning or very end of the range, the boundaries [fFirst, fEnd)
+ * will be tightened.
+ *
+ * @param name The name to free. Not-allocated names are silently ignored
+ * the same way they are in the OpenGL spec.
+ * @return The resulting SparseNameRange after the free (or NULL if it
+ * became empty). Note that this call is destructive, so the
+ * original SparseNameRange will no longer be valid afterward. The
+ * caller must always update its pointer with the new
+ * SparseNameRange.
+ */
+ virtual SparseNameRange* SK_WARN_UNUSED_RESULT free(GrGLuint name) = 0;
+
+protected:
+ SparseNameRange* takeRef() {
+ this->ref();
+ return this;
+ }
+
+ GrGLuint fFirst;
+ GrGLuint fEnd;
+ GrGLuint fHeight;
+};
+
+/**
+ * This class is the SparseNameRange implementation for an inner node. It is an
+ * AVL tree with non-null, non-adjacent left and right children.
+ */
+class GrGLNameAllocator::SparseNameTree : public SparseNameRange {
+public:
+ SparseNameTree(SparseNameRange* left, SparseNameRange* right)
+ : fLeft(left),
+ fRight(right) {
+ SkASSERT(fLeft.get());
+ SkASSERT(fRight.get());
+ this->updateStats();
+ }
+
+ virtual SparseNameRange* SK_WARN_UNUSED_RESULT internalAllocate(GrGLuint* outName) SK_OVERRIDE {
+ // Try allocating the range inside fLeft's internal gaps.
+ fLeft.reset(fLeft->internalAllocate(outName));
+ if (0 != *outName) {
+ this->updateStats();
+ return this->rebalance();
+ }
+
+ if (fLeft->end() + 1 == fRight->first()) {
+ // It closed the gap between fLeft and fRight; merge.
+ GrGLuint removedCount;
+ fRight.reset(fRight->removeLeftmostContiguousRange(&removedCount));
+ *outName = fLeft->appendNames(1 + removedCount);
+ if (NULL == fRight.get()) {
+ return fLeft.detach();
+ }
+ this->updateStats();
+ return this->rebalance();
+ }
+
+ // There is guaranteed to be a gap between fLeft and fRight, and the
+ // "size 1" case has already been covered.
+ SkASSERT(fLeft->end() + 1 < fRight->first());
+ *outName = fLeft->appendNames(1);
+ return this->takeRef();
+ }
+
+ virtual SparseNameRange* SK_WARN_UNUSED_RESULT removeLeftmostContiguousRange(GrGLuint* removedCount) SK_OVERRIDE {
+ fLeft.reset(fLeft->removeLeftmostContiguousRange(removedCount));
+ if (NULL == fLeft) {
+ return fRight.detach();
+ }
+ this->updateStats();
+ return this->rebalance();
+ }
+
+ virtual GrGLuint appendNames(GrGLuint count) SK_OVERRIDE {
+ SkASSERT(fEnd + count > fEnd); // Check for integer wrap.
+ GrGLuint name = fRight->appendNames(count);
+ SkASSERT(fRight->end() == fEnd + count);
+ this->updateStats();
+ return name;
+ }
+
+ virtual GrGLuint prependNames(GrGLuint count) SK_OVERRIDE {
+ SkASSERT(fFirst > count); // We can't allocate at or below 0.
+ GrGLuint name = fLeft->prependNames(count);
+ SkASSERT(fLeft->first() == fFirst - count);
+ this->updateStats();
+ return name;
+ }
+
+ virtual SparseNameRange* SK_WARN_UNUSED_RESULT free(GrGLuint name) SK_OVERRIDE {
+ if (name < fLeft->end()) {
+ fLeft.reset(fLeft->free(name));
+ if (NULL == fLeft) {
+ // fLeft became empty after the free.
+ return fRight.detach();
+ }
+ this->updateStats();
+ return this->rebalance();
+ } else {
+ fRight.reset(fRight->free(name));
+ if (NULL == fRight) {
+ // fRight became empty after the free.
+ return fLeft.detach();
+ }
+ this->updateStats();
+ return this->rebalance();
+ }
+ }
+
+private:
+ typedef SkAutoTUnref<SparseNameRange> SparseNameTree::* ChildRange;
+
+ SparseNameRange* SK_WARN_UNUSED_RESULT rebalance() {
+ if (fLeft->height() > fRight->height() + 1) {
+ return this->rebalanceImpl<&SparseNameTree::fLeft, &SparseNameTree::fRight>();
+ }
+ if (fRight->height() > fLeft->height() + 1) {
+ return this->rebalanceImpl<&SparseNameTree::fRight, &SparseNameTree::fLeft>();
+ }
+ return this->takeRef();
+ }
+
+ /**
+ * Rebalance the tree using rotations, as described in the AVL algorithm:
+ * http://en.wikipedia.org/wiki/AVL_tree#Insertion
+ */
+ template<ChildRange Tall, ChildRange Short>
+ SparseNameRange* SK_WARN_UNUSED_RESULT rebalanceImpl() {
+ // We should be calling rebalance() enough that the tree never gets more
+ // than one rotation off balance.
+ SkASSERT(2 == (this->*Tall)->height() - (this->*Short)->height());
+
+ // Ensure we are in the 'Left Left' or 'Right Right' case:
+ // http://en.wikipedia.org/wiki/AVL_tree#Insertion
+ SparseNameTree* tallChild = static_cast<SparseNameTree*>((this->*Tall).get());
+ if ((tallChild->*Tall)->height() < (tallChild->*Short)->height()) {
+ (this->*Tall).reset(tallChild->rotate<Short, Tall>());
+ }
+
+ // Perform a rotation to balance the tree.
+ return this->rotate<Tall, Short>();
+ }
+
+ /**
+ * Perform a node rotation, as described in the AVL algorithm:
+ * http://en.wikipedia.org/wiki/AVL_tree#Insertion
+ */
+ template<ChildRange Tall, ChildRange Short>
+ SparseNameRange* SK_WARN_UNUSED_RESULT rotate() {
+ SparseNameTree* newRoot = static_cast<SparseNameTree*>((this->*Tall).detach());
+
+ (this->*Tall).reset((newRoot->*Short).detach());
+ this->updateStats();
+
+ (newRoot->*Short).reset(this->takeRef());
+ newRoot->updateStats();
+
+ return newRoot;
+ }
+
+ void updateStats() {
+ SkASSERT(fLeft->end() < fRight->first()); // There must be a gap between left and right.
+ fFirst = fLeft->first();
+ fEnd = fRight->end();
+ fHeight = 1 + SkMax32(fLeft->height(), fRight->height());
+ }
+
+ SkAutoTUnref<SparseNameRange> fLeft;
+ SkAutoTUnref<SparseNameRange> fRight;
+};
+
+/**
+ * This class is the SparseNameRange implementation for a leaf node. It just a
+ * contiguous range of allocated names.
+ */
+class GrGLNameAllocator::ContiguousNameRange : public SparseNameRange {
+public:
+ ContiguousNameRange(GrGLuint first, GrGLuint end) {
+ SkASSERT(first < end);
+ fFirst = first;
+ fEnd = end;
+ fHeight = 0;
+ }
+
+ virtual SparseNameRange* SK_WARN_UNUSED_RESULT internalAllocate(GrGLuint* outName) SK_OVERRIDE {
+ *outName = 0; // No internal gaps, we are contiguous.
+ return this->takeRef();
+ }
+
+ virtual SparseNameRange* SK_WARN_UNUSED_RESULT removeLeftmostContiguousRange(GrGLuint* removedCount) SK_OVERRIDE {
+ *removedCount = fEnd - fFirst;
+ return NULL;
+ }
+
+ virtual GrGLuint appendNames(GrGLuint count) SK_OVERRIDE {
+ SkASSERT(fEnd + count > fEnd); // Check for integer wrap.
+ GrGLuint name = fEnd;
+ fEnd += count;
+ return name;
+ }
+
+ virtual GrGLuint prependNames(GrGLuint count) SK_OVERRIDE {
+ SkASSERT(fFirst > count); // We can't allocate at or below 0.
+ fFirst -= count;
+ return fFirst;
+ }
+
+ virtual SparseNameRange* SK_WARN_UNUSED_RESULT free(GrGLuint name) SK_OVERRIDE {
+ if (name < fFirst || name >= fEnd) {
+ // Not-allocated names are silently ignored.
+ return this->takeRef();
+ }
+
+ if (fFirst == name) {
+ ++fFirst;
+ return (fEnd == fFirst) ? NULL : this->takeRef();
+ }
+
+ if (fEnd == name + 1) {
+ --fEnd;
+ return this->takeRef();
+ }
+
+ SparseNameRange* left = SkNEW_ARGS(ContiguousNameRange, (fFirst, name));
+ SparseNameRange* right = this->takeRef();
+ fFirst = name + 1;
+ return SkNEW_ARGS(SparseNameTree, (left, right));
+ }
+};
+
+GrGLNameAllocator::GrGLNameAllocator(GrGLuint firstName, GrGLuint endName)
+ : fFirstName(firstName),
+ fEndName(endName) {
+ SkASSERT(firstName > 0);
+ SkASSERT(endName > firstName);
+}
+
+GrGLNameAllocator::~GrGLNameAllocator() {
+}
+
+GrGLuint GrGLNameAllocator::allocateName() {
+ if (NULL == fAllocatedNames.get()) {
+ fAllocatedNames.reset(SkNEW_ARGS(ContiguousNameRange, (fFirstName, fFirstName + 1)));
+ return fFirstName;
+ }
+
+ if (fAllocatedNames->first() > fFirstName) {
+ return fAllocatedNames->prependNames(1);
+ }
+
+ GrGLuint name;
+ fAllocatedNames.reset(fAllocatedNames->internalAllocate(&name));
+ if (0 != name) {
+ return name;
+ }
+
+ if (fAllocatedNames->end() < fEndName) {
+ return fAllocatedNames->appendNames(1);
+ }
+
+ // Out of names.
+ return 0;
+}
+
+void GrGLNameAllocator::free(GrGLuint name) {
+ if (!fAllocatedNames.get()) {
+ // Not-allocated names are silently ignored.
+ return;
+ }
+
+ fAllocatedNames.reset(fAllocatedNames->free(name));
+}
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLNameAllocator.h b/chromium/third_party/skia/src/gpu/gl/GrGLNameAllocator.h
new file mode 100644
index 00000000000..1c2c26e59f6
--- /dev/null
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLNameAllocator.h
@@ -0,0 +1,86 @@
+
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrGLNameAllocator_DEFINED
+#define GrGLNameAllocator_DEFINED
+
+#include "SkRefCnt.h"
+#include "gl/GrGLFunctions.h"
+
+/**
+ * This class assumes ownership of an explicit range of OpenGL object names and
+ * manages allocations within that range. This allows the app to generate new
+ * objects on the client side without making round trips to the GL server.
+ */
+class GrGLNameAllocator {
+public:
+ /**
+ * Constructs a name allocator that produces names within the explicit
+ * half-open range [firstName, end). Note that the caller will most likely
+ * need to call glGen* beforehand to reserve a range within the GL driver,
+ * and then invoke this constructor with that range.
+ *
+ * @param firstName The first name in the range owned by this class. Must be
+ greater than zero.
+ * @param endName The first past-the-end name beyond the range owned by
+ this class. Must be >= firstName.
+ */
+ GrGLNameAllocator(GrGLuint firstName, GrGLuint endName);
+
+ /**
+ * Destructs the name allocator. The caller is responsible for calling the
+ * appropriate glDelete* on the range if necessary.
+ */
+ ~GrGLNameAllocator();
+
+ /**
+ * Return the beginning of this class's range.
+ *
+ * @return The first name in the range owned by this class.
+ */
+ GrGLuint firstName() const { return fFirstName; }
+
+ /**
+ * Return the end of this class's range. Note that endName() is not owned by
+ * this class.
+ *
+ * @return One plus the final name in the range owned by this class.
+ */
+ GrGLuint endName() const { return fEndName; }
+
+ /**
+ * Allocate an OpenGL object name from within this class's range.
+ *
+ * @return The name if one was available,
+ 0 if all the names in the range were already in use.
+ */
+ GrGLuint allocateName();
+
+ /**
+ * Free an OpenGL object name, allowing it to be returned by a future call
+ * to allocateName(). Note that the caller should most likely redefine the
+ * object as empty to deallocate any underlying GPU memory before calling
+ * this method (but not call glDelete*, since that would free up the name
+ * within the driver itself).
+ *
+ * @param name The object name to free. Not-allocated names are silently
+ * ignored the same way they are in the OpenGL spec.
+ */
+ void free(GrGLuint name);
+
+private:
+ class SparseNameRange;
+ class SparseNameTree;
+ class ContiguousNameRange;
+
+ const GrGLuint fFirstName;
+ const GrGLuint fEndName;
+ SkAutoTUnref<SparseNameRange> fAllocatedNames;
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLNoOpInterface.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLNoOpInterface.cpp
index 0641af85d73..df32d2a7cfc 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLNoOpInterface.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLNoOpInterface.cpp
@@ -37,11 +37,11 @@ const GrGLubyte* combined_extensions_string() {
static SkMutex gMutex;
gMutex.acquire();
if (0 == gExtString.size()) {
- for (size_t i = 0; i < GR_ARRAY_COUNT(kExtensions) - 1; ++i) {
+ for (size_t i = 0; i < SK_ARRAY_COUNT(kExtensions) - 1; ++i) {
gExtString.append(kExtensions[i]);
gExtString.append(" ");
}
- gExtString.append(kExtensions[GR_ARRAY_COUNT(kExtensions) - 1]);
+ gExtString.append(kExtensions[SK_ARRAY_COUNT(kExtensions) - 1]);
}
gMutex.release();
return (const GrGLubyte*) gExtString.c_str();
@@ -100,6 +100,17 @@ GrGLvoid GR_GL_FUNCTION_TYPE noOpGLCompressedTexImage2D(GrGLenum target,
const GrGLvoid* data) {
}
+GrGLvoid GR_GL_FUNCTION_TYPE noOpGLCompressedTexSubImage2D(GrGLenum target,
+ GrGLint level,
+ GrGLint xoffset,
+ GrGLint yoffset,
+ GrGLsizei width,
+ GrGLsizei height,
+ GrGLenum format,
+ GrGLsizei imageSize,
+ const GrGLvoid* data) {
+}
+
GrGLvoid GR_GL_FUNCTION_TYPE noOpGLCopyTexSubImage2D(GrGLenum target,
GrGLint level,
GrGLint xoffset,
@@ -119,9 +130,6 @@ GrGLvoid GR_GL_FUNCTION_TYPE noOpGLDepthMask(GrGLboolean flag) {
GrGLvoid GR_GL_FUNCTION_TYPE noOpGLDisable(GrGLenum cap) {
}
-GrGLvoid GR_GL_FUNCTION_TYPE noOpGLDisableClientState(GrGLenum) {
-}
-
GrGLvoid GR_GL_FUNCTION_TYPE noOpGLDisableVertexAttribArray(GrGLuint index) {
}
@@ -146,9 +154,6 @@ GrGLvoid GR_GL_FUNCTION_TYPE noOpGLDrawElements(GrGLenum mode,
GrGLvoid GR_GL_FUNCTION_TYPE noOpGLEnable(GrGLenum cap) {
}
-GrGLvoid GR_GL_FUNCTION_TYPE noOpGLEnableClientState(GrGLenum cap) {
-}
-
GrGLvoid GR_GL_FUNCTION_TYPE noOpGLEnableVertexAttribArray(GrGLuint index) {
}
@@ -170,13 +175,10 @@ GrGLvoid GR_GL_FUNCTION_TYPE noOpGLLineWidth(GrGLfloat width) {
GrGLvoid GR_GL_FUNCTION_TYPE noOpGLLinkProgram(GrGLuint program) {
}
-GrGLvoid GR_GL_FUNCTION_TYPE noOpGLLoadIdentity() {
-}
-
-GrGLvoid GR_GL_FUNCTION_TYPE noOpGLLoadMatrixf(const GrGLfloat*) {
+GrGLvoid GR_GL_FUNCTION_TYPE noOpGLMatrixLoadf(GrGLenum, const GrGLfloat*) {
}
-GrGLvoid GR_GL_FUNCTION_TYPE noOpGLMatrixMode(GrGLenum) {
+GrGLvoid GR_GL_FUNCTION_TYPE noOpGLMatrixLoadIdentity(GrGLenum) {
}
GrGLvoid GR_GL_FUNCTION_TYPE noOpGLQueryCounter(GrGLuint id, GrGLenum target) {
@@ -225,15 +227,6 @@ GrGLvoid GR_GL_FUNCTION_TYPE noOpGLStencilOpSeparate(GrGLenum face,
GrGLenum zpass) {
}
-GrGLvoid GR_GL_FUNCTION_TYPE noOpGLTexGenf(GrGLenum, GrGLenum, float) {
-}
-
-GrGLvoid GR_GL_FUNCTION_TYPE noOpGLTexGenfv(GrGLenum, GrGLenum, const float*) {
-}
-
-GrGLvoid GR_GL_FUNCTION_TYPE noOpGLTexGeni(GrGLenum, GrGLenum, GrGLint) {
-}
-
GrGLvoid GR_GL_FUNCTION_TYPE noOpGLTexImage2D(GrGLenum target,
GrGLint level,
GrGLint internalformat,
@@ -385,9 +378,6 @@ GrGLvoid GR_GL_FUNCTION_TYPE noOpGLVertexAttribPointer(GrGLuint indx,
const GrGLvoid* ptr) {
}
-GrGLvoid GR_GL_FUNCTION_TYPE noOpGLVertexPointer(GrGLint, GrGLenum, GrGLsizei, const GrGLvoid*) {
-}
-
GrGLvoid GR_GL_FUNCTION_TYPE noOpGLViewport(GrGLint x,
GrGLint y,
GrGLsizei width,
@@ -518,10 +508,10 @@ GrGLvoid GR_GL_FUNCTION_TYPE noOpGLGetIntegerv(GrGLenum pname, GrGLint* params)
*params = kDefaultMaxVaryingVectors;
break;
case GR_GL_NUM_EXTENSIONS:
- *params = GR_ARRAY_COUNT(kExtensions);
+ *params = SK_ARRAY_COUNT(kExtensions);
break;
default:
- GrCrash("Unexpected pname to GetIntegerv");
+ SkFAIL("Unexpected pname to GetIntegerv");
}
}
@@ -550,7 +540,7 @@ GrGLvoid GR_GL_FUNCTION_TYPE noOpGLGetShaderOrProgramiv(GrGLuint program,
break;
// we don't expect any other pnames
default:
- GrCrash("Unexpected pname to GetProgramiv");
+ SkFAIL("Unexpected pname to GetProgramiv");
break;
}
}
@@ -566,7 +556,7 @@ void query_result(GrGLenum GLtarget, GrGLenum pname, T *params) {
*params = 0;
break;
default:
- GrCrash("Unexpected pname passed to GetQueryObject.");
+ SkFAIL("Unexpected pname passed to GetQueryObject.");
break;
}
}
@@ -583,7 +573,7 @@ GrGLvoid GR_GL_FUNCTION_TYPE noOpGLGetQueryiv(GrGLenum GLtarget,
*params = 32;
break;
default:
- GrCrash("Unexpected pname passed GetQueryiv.");
+ SkFAIL("Unexpected pname passed GetQueryiv.");
}
}
@@ -624,7 +614,7 @@ const GrGLubyte* GR_GL_FUNCTION_TYPE noOpGLGetString(GrGLenum name) {
case GR_GL_RENDERER:
return (const GrGLubyte*)"The Debug (Non-)Renderer";
default:
- GrCrash("Unexpected name passed to GetString");
+ SkFAIL("Unexpected name passed to GetString");
return NULL;
}
}
@@ -632,13 +622,13 @@ const GrGLubyte* GR_GL_FUNCTION_TYPE noOpGLGetString(GrGLenum name) {
const GrGLubyte* GR_GL_FUNCTION_TYPE noOpGLGetStringi(GrGLenum name, GrGLuint i) {
switch (name) {
case GR_GL_EXTENSIONS:
- if (static_cast<size_t>(i) <= GR_ARRAY_COUNT(kExtensions)) {
+ if (static_cast<size_t>(i) <= SK_ARRAY_COUNT(kExtensions)) {
return (const GrGLubyte*) kExtensions[i];
} else {
return NULL;
}
default:
- GrCrash("Unexpected name passed to GetStringi");
+ SkFAIL("Unexpected name passed to GetStringi");
return NULL;
}
}
@@ -649,10 +639,17 @@ GrGLvoid GR_GL_FUNCTION_TYPE noOpGLGetTexLevelParameteriv(GrGLenum target,
GrGLint* params) {
// we used to use this to query stuff about externally created textures,
// now we just require clients to tell us everything about the texture.
- GrCrash("Should never query texture parameters.");
+ SkFAIL("Should never query texture parameters.");
}
GrGLint GR_GL_FUNCTION_TYPE noOpGLGetUniformLocation(GrGLuint program, const char* name) {
static int gUniLocation = 0;
return ++gUniLocation;
}
+
+GrGLvoid GR_GL_FUNCTION_TYPE noOpGLInsertEventMarker(GrGLsizei length, const char* marker) {
+}
+GrGLvoid GR_GL_FUNCTION_TYPE noOpGLPushGroupMarker(GrGLsizei length , const char* marker) {
+}
+GrGLvoid GR_GL_FUNCTION_TYPE noOpGLPopGroupMarker() {
+}
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLNoOpInterface.h b/chromium/third_party/skia/src/gpu/gl/GrGLNoOpInterface.h
index 8fe9b44ea2e..3e146d330b4 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLNoOpInterface.h
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLNoOpInterface.h
@@ -55,6 +55,16 @@ GrGLvoid GR_GL_FUNCTION_TYPE noOpGLCompressedTexImage2D(GrGLenum target,
GrGLsizei imageSize,
const GrGLvoid* data);
+GrGLvoid GR_GL_FUNCTION_TYPE noOpGLCompressedTexSubImage2D(GrGLenum target,
+ GrGLint level,
+ GrGLint xoffset,
+ GrGLint yoffset,
+ GrGLsizei width,
+ GrGLsizei height,
+ GrGLenum format,
+ GrGLsizei imageSize,
+ const GrGLvoid* data);
+
GrGLvoid GR_GL_FUNCTION_TYPE noOpGLCopyTexSubImage2D(GrGLenum target,
GrGLint level,
GrGLint xoffset,
@@ -70,8 +80,6 @@ GrGLvoid GR_GL_FUNCTION_TYPE noOpGLDepthMask(GrGLboolean flag);
GrGLvoid GR_GL_FUNCTION_TYPE noOpGLDisable(GrGLenum cap);
-GrGLvoid GR_GL_FUNCTION_TYPE noOpGLDisableClientState(GrGLenum);
-
GrGLvoid GR_GL_FUNCTION_TYPE noOpGLDisableVertexAttribArray(GrGLuint index);
GrGLvoid GR_GL_FUNCTION_TYPE noOpGLDrawArrays(GrGLenum mode, GrGLint first, GrGLsizei count);
@@ -88,8 +96,6 @@ GrGLvoid GR_GL_FUNCTION_TYPE noOpGLDrawElements(GrGLenum mode,
GrGLvoid GR_GL_FUNCTION_TYPE noOpGLEnable(GrGLenum cap);
-GrGLvoid GR_GL_FUNCTION_TYPE noOpGLEnableClientState(GrGLenum cap);
-
GrGLvoid GR_GL_FUNCTION_TYPE noOpGLEnableVertexAttribArray(GrGLuint index);
GrGLvoid GR_GL_FUNCTION_TYPE noOpGLEndQuery(GrGLenum target);
@@ -100,16 +106,14 @@ GrGLvoid GR_GL_FUNCTION_TYPE noOpGLFlush();
GrGLvoid GR_GL_FUNCTION_TYPE noOpGLFrontFace(GrGLenum mode);
-GrGLvoid GR_GL_FUNCTION_TYPE noOpGLLoadIdentity();
+GrGLvoid GR_GL_FUNCTION_TYPE noOpGLMatrixLoadf(GrGLenum, const GrGLfloat*);
-GrGLvoid GR_GL_FUNCTION_TYPE noOpGLLoadMatrixf(const GrGLfloat*);
+GrGLvoid GR_GL_FUNCTION_TYPE noOpGLMatrixLoadIdentity(GrGLenum);
GrGLvoid GR_GL_FUNCTION_TYPE noOpGLLineWidth(GrGLfloat width);
GrGLvoid GR_GL_FUNCTION_TYPE noOpGLLinkProgram(GrGLuint program);
-GrGLvoid GR_GL_FUNCTION_TYPE noOpGLMatrixMode(GrGLenum);
-
GrGLvoid GR_GL_FUNCTION_TYPE noOpGLQueryCounter(GrGLuint id,
GrGLenum target);
@@ -169,12 +173,6 @@ GrGLvoid GR_GL_FUNCTION_TYPE noOpGLTexStorage2D(GrGLenum target,
GrGLsizei width,
GrGLsizei height);
-GrGLvoid GR_GL_FUNCTION_TYPE noOpGLTexGenf(GrGLenum, GrGLenum, GrGLfloat);
-
-GrGLvoid GR_GL_FUNCTION_TYPE noOpGLTexGenfv(GrGLenum, GrGLenum, const GrGLfloat*);
-
-GrGLvoid GR_GL_FUNCTION_TYPE noOpGLTexGeni(GrGLenum, GrGLenum, GrGLint);
-
GrGLvoid GR_GL_FUNCTION_TYPE noOpGLDiscardFramebuffer(GrGLenum target,
GrGLsizei numAttachments,
const GrGLenum* attachments);
@@ -277,8 +275,6 @@ GrGLvoid GR_GL_FUNCTION_TYPE noOpGLVertexAttribPointer(GrGLuint indx,
GrGLsizei stride,
const GrGLvoid* ptr);
-GrGLvoid GR_GL_FUNCTION_TYPE noOpGLVertexPointer(GrGLint, GrGLenum, GrGLsizei, const GrGLvoid*);
-
GrGLvoid GR_GL_FUNCTION_TYPE noOpGLViewport(GrGLint x,
GrGLint y,
GrGLsizei width,
@@ -375,4 +371,8 @@ GrGLvoid GR_GL_FUNCTION_TYPE noOpGLGetTexLevelParameteriv(GrGLenum target,
GrGLint GR_GL_FUNCTION_TYPE noOpGLGetUniformLocation(GrGLuint program, const char* name);
+GrGLvoid GR_GL_FUNCTION_TYPE noOpGLInsertEventMarker(GrGLsizei length, const char* marker);
+GrGLvoid GR_GL_FUNCTION_TYPE noOpGLPushGroupMarker(GrGLsizei length , const char* marker);
+GrGLvoid GR_GL_FUNCTION_TYPE noOpGLPopGroupMarker();
+
#endif
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLPath.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLPath.cpp
index a749e410bd1..bb26b12c72c 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLPath.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLPath.cpp
@@ -30,7 +30,7 @@ inline GrGLubyte verb_to_gl_path_cmd(SkPath::Verb verb) {
GR_STATIC_ASSERT(4 == SkPath::kCubic_Verb);
GR_STATIC_ASSERT(5 == SkPath::kClose_Verb);
- SkASSERT(verb >= 0 && (size_t)verb < GR_ARRAY_COUNT(gTable));
+ SkASSERT(verb >= 0 && (size_t)verb < SK_ARRAY_COUNT(gTable));
return gTable[verb];
}
@@ -50,7 +50,7 @@ inline int num_pts(SkPath::Verb verb) {
GR_STATIC_ASSERT(4 == SkPath::kCubic_Verb);
GR_STATIC_ASSERT(5 == SkPath::kClose_Verb);
- SkASSERT(verb >= 0 && (size_t)verb < GR_ARRAY_COUNT(gTable));
+ SkASSERT(verb >= 0 && (size_t)verb < SK_ARRAY_COUNT(gTable));
return gTable[verb];
}
#endif
@@ -65,7 +65,7 @@ inline GrGLenum join_to_gl_join(SkPaint::Join join) {
GR_STATIC_ASSERT(0 == SkPaint::kMiter_Join);
GR_STATIC_ASSERT(1 == SkPaint::kRound_Join);
GR_STATIC_ASSERT(2 == SkPaint::kBevel_Join);
- GR_STATIC_ASSERT(GR_ARRAY_COUNT(gSkJoinsToGrGLJoins) == SkPaint::kJoinCount);
+ GR_STATIC_ASSERT(SK_ARRAY_COUNT(gSkJoinsToGrGLJoins) == SkPaint::kJoinCount);
}
inline GrGLenum cap_to_gl_cap(SkPaint::Cap cap) {
@@ -78,7 +78,7 @@ inline GrGLenum cap_to_gl_cap(SkPaint::Cap cap) {
GR_STATIC_ASSERT(0 == SkPaint::kButt_Cap);
GR_STATIC_ASSERT(1 == SkPaint::kRound_Cap);
GR_STATIC_ASSERT(2 == SkPaint::kSquare_Cap);
- GR_STATIC_ASSERT(GR_ARRAY_COUNT(gSkCapsToGrGLCaps) == SkPaint::kCapCount);
+ GR_STATIC_ASSERT(SK_ARRAY_COUNT(gSkCapsToGrGLCaps) == SkPaint::kCapCount);
}
}
@@ -87,12 +87,9 @@ static const bool kIsWrapped = false; // The constructor creates the GL path obj
GrGLPath::GrGLPath(GrGpuGL* gpu, const SkPath& path, const SkStrokeRec& stroke)
: INHERITED(gpu, kIsWrapped, path, stroke) {
-#ifndef SK_SCALAR_IS_FLOAT
- GrCrash("Assumes scalar is float.");
-#endif
SkASSERT(!path.isEmpty());
- GL_CALL_RET(fPathID, GenPaths(1));
+ fPathID = gpu->createGLPathObject();
SkSTArray<16, GrGLubyte, true> pathCommands;
SkSTArray<16, SkPoint, true> pathPoints;
@@ -138,7 +135,7 @@ GrGLPath::~GrGLPath() {
void GrGLPath::onRelease() {
if (0 != fPathID && !this->isWrapped()) {
- GL_CALL(DeletePaths(fPathID, 1));
+ static_cast<GrGpuGL*>(this->getGpu())->deleteGLPathObject(fPathID);
fPathID = 0;
}
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLPath.h b/chromium/third_party/skia/src/gpu/gl/GrGLPath.h
index 3647d4d6286..3409547b2b0 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLPath.h
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLPath.h
@@ -27,7 +27,7 @@ public:
GrGLuint pathID() const { return fPathID; }
// TODO: Figure out how to get an approximate size of the path in Gpu
// memory.
- virtual size_t sizeInBytes() const SK_OVERRIDE { return 100; }
+ virtual size_t gpuMemorySize() const SK_OVERRIDE { return 100; }
protected:
virtual void onRelease() SK_OVERRIDE;
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLProgram.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLProgram.cpp
index cac38b4bddc..435d0cdb02c 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLProgram.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLProgram.cpp
@@ -24,52 +24,38 @@ GrGLProgram* GrGLProgram::Create(GrGpuGL* gpu,
const GrGLProgramDesc& desc,
const GrEffectStage* colorStages[],
const GrEffectStage* coverageStages[]) {
- GrGLProgram* program = SkNEW_ARGS(GrGLProgram, (gpu, desc, colorStages, coverageStages));
- if (!program->succeeded()) {
- delete program;
- program = NULL;
+ GrGLShaderBuilder::GenProgramOutput output;
+ SkAutoTUnref<GrGLUniformManager> uman(SkNEW_ARGS(GrGLUniformManager, (gpu)));
+ if (GrGLShaderBuilder::GenProgram(gpu, uman, desc, colorStages, coverageStages,
+ &output)) {
+ SkASSERT(0 != output.fProgramID);
+ return SkNEW_ARGS(GrGLProgram, (gpu, desc, uman, output));
}
- return program;
+ return NULL;
}
GrGLProgram::GrGLProgram(GrGpuGL* gpu,
const GrGLProgramDesc& desc,
- const GrEffectStage* colorStages[],
- const GrEffectStage* coverageStages[])
-: fGpu(gpu)
-, fUniformManager(gpu)
-, fHasVertexShader(false)
-, fNumTexCoordSets(0) {
- fDesc = desc;
- fProgramID = 0;
-
- fDstCopyTexUnit = -1;
-
- fColor = GrColor_ILLEGAL;
-
- if (fDesc.getHeader().fHasVertexCode ||
- !fGpu->shouldUseFixedFunctionTexturing()) {
- GrGLFullShaderBuilder fullBuilder(fGpu, fUniformManager, fDesc);
- if (this->genProgram(&fullBuilder, colorStages, coverageStages)) {
- fUniformHandles.fViewMatrixUni = fullBuilder.getViewMatrixUniform();
- fHasVertexShader = true;
- }
- } else {
- GrGLFragmentOnlyShaderBuilder fragmentOnlyBuilder(fGpu, fUniformManager, fDesc);
- if (this->genProgram(&fragmentOnlyBuilder, colorStages, coverageStages)) {
- fNumTexCoordSets = fragmentOnlyBuilder.getNumTexCoordSets();
- }
- }
+ GrGLUniformManager* uman,
+ const GrGLShaderBuilder::GenProgramOutput& builderOutput)
+ : fColor(GrColor_ILLEGAL)
+ , fCoverage(GrColor_ILLEGAL)
+ , fDstCopyTexUnit(-1)
+ , fBuilderOutput(builderOutput)
+ , fDesc(desc)
+ , fGpu(gpu)
+ , fUniformManager(SkRef(uman)) {
+ this->initSamplerUniforms();
}
GrGLProgram::~GrGLProgram() {
- if (fProgramID) {
- GL_CALL(DeleteProgram(fProgramID));
+ if (fBuilderOutput.fProgramID) {
+ GL_CALL(DeleteProgram(fBuilderOutput.fProgramID));
}
}
void GrGLProgram::abandon() {
- fProgramID = 0;
+ fBuilderOutput.fProgramID = 0;
}
void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff,
@@ -89,104 +75,20 @@ void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff,
SkASSERT(kOne_GrBlendCoeff == *srcCoeff && kZero_GrBlendCoeff == *dstCoeff);
break;
default:
- GrCrash("Unexpected coverage output");
+ SkFAIL("Unexpected coverage output");
break;
}
}
-bool GrGLProgram::genProgram(GrGLShaderBuilder* builder,
- const GrEffectStage* colorStages[],
- const GrEffectStage* coverageStages[]) {
- SkASSERT(0 == fProgramID);
-
- const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
-
- // incoming color to current stage being processed.
- GrGLSLExpr4 inColor = builder->getInputColor();
-
- fColorEffects.reset(
- builder->createAndEmitEffects(colorStages,
- fDesc.effectKeys(),
- fDesc.numColorEffects(),
- &inColor));
-
- ///////////////////////////////////////////////////////////////////////////
- // compute the partial coverage
- GrGLSLExpr4 inCoverage = builder->getInputCoverage();
-
- fCoverageEffects.reset(
- builder->createAndEmitEffects(coverageStages,
- fDesc.getEffectKeys() + fDesc.numColorEffects(),
- fDesc.numCoverageEffects(),
- &inCoverage));
-
- // discard if coverage is zero
- if (header.fDiscardIfZeroCoverage && !inCoverage.isOnes()) {
- if (inCoverage.isZeros()) {
- // This is unfortunate.
- builder->fsCodeAppend("\tdiscard;\n");
- } else {
- builder->fsCodeAppendf("\tif (all(lessThanEqual(%s, vec4(0.0)))) {\n\t\tdiscard;\n\t}\n",
- inCoverage.c_str());
- }
- }
-
- if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(header.fCoverageOutput)) {
- const char* secondaryOutputName = builder->enableSecondaryOutput();
-
- // default coeff to ones for kCoverage_DualSrcOutput
- GrGLSLExpr4 coeff(1);
- if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == header.fCoverageOutput) {
- // Get (1-A) into coeff
- coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inColor.a());
- } else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput == header.fCoverageOutput) {
- // Get (1-RGBA) into coeff
- coeff = GrGLSLExpr4(1) - inColor;
- }
- // Get coeff * coverage into modulate and then write that to the dual source output.
- builder->fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inCoverage).c_str());
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // combine color and coverage as frag color
-
- // Get "color * coverage" into fragColor
- GrGLSLExpr4 fragColor = inColor * inCoverage;
- // Now tack on "+(1-coverage)dst onto the frag color if we were asked to do so.
- if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == header.fCoverageOutput) {
- GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inCoverage;
-
- GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(builder->dstColor());
-
- fragColor = fragColor + dstContribution;
- }
- builder->fsCodeAppendf("\t%s = %s;\n", builder->getColorOutputName(), fragColor.c_str());
-
- if (!builder->finish(&fProgramID)) {
- return false;
- }
-
- fUniformHandles.fRTHeightUni = builder->getRTHeightUniform();
- fUniformHandles.fDstCopyTopLeftUni = builder->getDstCopyTopLeftUniform();
- fUniformHandles.fDstCopyScaleUni = builder->getDstCopyScaleUniform();
- fUniformHandles.fColorUni = builder->getColorUniform();
- fUniformHandles.fCoverageUni = builder->getCoverageUniform();
- fUniformHandles.fDstCopySamplerUni = builder->getDstCopySamplerUniform();
- // This must be called after we set fDstCopySamplerUni above.
- this->initSamplerUniforms();
-
- return true;
-}
-
void GrGLProgram::initSamplerUniforms() {
- GL_CALL(UseProgram(fProgramID));
+ GL_CALL(UseProgram(fBuilderOutput.fProgramID));
GrGLint texUnitIdx = 0;
- if (fUniformHandles.fDstCopySamplerUni.isValid()) {
- fUniformManager.setSampler(fUniformHandles.fDstCopySamplerUni, texUnitIdx);
+ if (fBuilderOutput.fUniformHandles.fDstCopySamplerUni.isValid()) {
+ fUniformManager->setSampler(fBuilderOutput.fUniformHandles.fDstCopySamplerUni, texUnitIdx);
fDstCopyTexUnit = texUnitIdx++;
}
- fColorEffects->initSamplers(fUniformManager, &texUnitIdx);
- fCoverageEffects->initSamplers(fUniformManager, &texUnitIdx);
+ fBuilderOutput.fColorEffects->initSamplers(*fUniformManager, &texUnitIdx);
+ fBuilderOutput.fCoverageEffects->initSamplers(*fUniformManager, &texUnitIdx);
}
///////////////////////////////////////////////////////////////////////////////
@@ -216,34 +118,35 @@ void GrGLProgram::setData(GrDrawState::BlendOptFlags blendOpts,
this->setMatrixAndRenderTargetHeight(drawState);
if (NULL != dstCopy) {
- if (fUniformHandles.fDstCopyTopLeftUni.isValid()) {
- fUniformManager.set2f(fUniformHandles.fDstCopyTopLeftUni,
- static_cast<GrGLfloat>(dstCopy->offset().fX),
- static_cast<GrGLfloat>(dstCopy->offset().fY));
- fUniformManager.set2f(fUniformHandles.fDstCopyScaleUni,
- 1.f / dstCopy->texture()->width(),
- 1.f / dstCopy->texture()->height());
+ if (fBuilderOutput.fUniformHandles.fDstCopyTopLeftUni.isValid()) {
+ fUniformManager->set2f(fBuilderOutput.fUniformHandles.fDstCopyTopLeftUni,
+ static_cast<GrGLfloat>(dstCopy->offset().fX),
+ static_cast<GrGLfloat>(dstCopy->offset().fY));
+ fUniformManager->set2f(fBuilderOutput.fUniformHandles.fDstCopyScaleUni,
+ 1.f / dstCopy->texture()->width(),
+ 1.f / dstCopy->texture()->height());
GrGLTexture* texture = static_cast<GrGLTexture*>(dstCopy->texture());
static GrTextureParams kParams; // the default is clamp, nearest filtering.
fGpu->bindTexture(fDstCopyTexUnit, kParams, texture);
} else {
- SkASSERT(!fUniformHandles.fDstCopyScaleUni.isValid());
- SkASSERT(!fUniformHandles.fDstCopySamplerUni.isValid());
+ SkASSERT(!fBuilderOutput.fUniformHandles.fDstCopyScaleUni.isValid());
+ SkASSERT(!fBuilderOutput.fUniformHandles.fDstCopySamplerUni.isValid());
}
} else {
- SkASSERT(!fUniformHandles.fDstCopyTopLeftUni.isValid());
- SkASSERT(!fUniformHandles.fDstCopyScaleUni.isValid());
- SkASSERT(!fUniformHandles.fDstCopySamplerUni.isValid());
+ SkASSERT(!fBuilderOutput.fUniformHandles.fDstCopyTopLeftUni.isValid());
+ SkASSERT(!fBuilderOutput.fUniformHandles.fDstCopyScaleUni.isValid());
+ SkASSERT(!fBuilderOutput.fUniformHandles.fDstCopySamplerUni.isValid());
}
- fColorEffects->setData(fGpu, fUniformManager, colorStages);
- fCoverageEffects->setData(fGpu, fUniformManager, coverageStages);
+ fBuilderOutput.fColorEffects->setData(fGpu, *fUniformManager, colorStages);
+ fBuilderOutput.fCoverageEffects->setData(fGpu, *fUniformManager, coverageStages);
- // TexGen state applies to the the fixed function vertex shader. For custom shaders, it's
- // ignored, so we don't need to change the texgen settings in that case.
- if (!fHasVertexShader) {
- fGpu->flushTexGenSettings(fNumTexCoordSets);
+ // PathTexGen state applies to the the fixed function vertex shader. For
+ // custom shaders, it's ignored, so we don't need to change the texgen
+ // settings in that case.
+ if (!fBuilderOutput.fHasVertexShader) {
+ fGpu->flushPathTexGenSettings(fBuilderOutput.fTexCoordSetCnt);
}
}
@@ -266,11 +169,11 @@ void GrGLProgram::setColor(const GrDrawState& drawState,
}
break;
case GrGLProgramDesc::kUniform_ColorInput:
- if (fColor != color && fUniformHandles.fColorUni.isValid()) {
+ if (fColor != color && fBuilderOutput.fUniformHandles.fColorUni.isValid()) {
// OpenGL ES doesn't support unsigned byte varieties of glUniform
GrGLfloat c[4];
GrColorToRGBAFloat(color, c);
- fUniformManager.set4fv(fUniformHandles.fColorUni, 1, c);
+ fUniformManager->set4fv(fBuilderOutput.fUniformHandles.fColorUni, 1, c);
fColor = color;
}
sharedState->fConstAttribColorIndex = -1;
@@ -280,7 +183,7 @@ void GrGLProgram::setColor(const GrDrawState& drawState,
sharedState->fConstAttribColorIndex = -1;
break;
default:
- GrCrash("Unknown color type.");
+ SkFAIL("Unknown color type.");
}
} else {
sharedState->fConstAttribColorIndex = -1;
@@ -309,7 +212,7 @@ void GrGLProgram::setCoverage(const GrDrawState& drawState,
// OpenGL ES doesn't support unsigned byte varieties of glUniform
GrGLfloat c[4];
GrColorToRGBAFloat(coverage, c);
- fUniformManager.set4fv(fUniformHandles.fCoverageUni, 1, c);
+ fUniformManager->set4fv(fBuilderOutput.fUniformHandles.fCoverageUni, 1, c);
fCoverage = coverage;
}
sharedState->fConstAttribCoverageIndex = -1;
@@ -319,7 +222,7 @@ void GrGLProgram::setCoverage(const GrDrawState& drawState,
sharedState->fConstAttribCoverageIndex = -1;
break;
default:
- GrCrash("Unknown coverage type.");
+ SkFAIL("Unknown coverage type.");
}
} else {
sharedState->fConstAttribCoverageIndex = -1;
@@ -332,18 +235,20 @@ void GrGLProgram::setMatrixAndRenderTargetHeight(const GrDrawState& drawState) {
size.set(rt->width(), rt->height());
// Load the RT height uniform if it is needed to y-flip gl_FragCoord.
- if (fUniformHandles.fRTHeightUni.isValid() &&
+ if (fBuilderOutput.fUniformHandles.fRTHeightUni.isValid() &&
fMatrixState.fRenderTargetSize.fHeight != size.fHeight) {
- fUniformManager.set1f(fUniformHandles.fRTHeightUni, SkIntToScalar(size.fHeight));
+ fUniformManager->set1f(fBuilderOutput.fUniformHandles.fRTHeightUni,
+ SkIntToScalar(size.fHeight));
}
- if (!fHasVertexShader) {
- SkASSERT(!fUniformHandles.fViewMatrixUni.isValid());
+ if (!fBuilderOutput.fHasVertexShader) {
+ SkASSERT(!fBuilderOutput.fUniformHandles.fViewMatrixUni.isValid());
+ SkASSERT(!fBuilderOutput.fUniformHandles.fRTAdjustmentUni.isValid());
fGpu->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin());
} else if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
fMatrixState.fRenderTargetSize != size ||
!fMatrixState.fViewMatrix.cheapEqualTo(drawState.getViewMatrix())) {
- SkASSERT(fUniformHandles.fViewMatrixUni.isValid());
+ SkASSERT(fBuilderOutput.fUniformHandles.fViewMatrixUni.isValid());
fMatrixState.fViewMatrix = drawState.getViewMatrix();
fMatrixState.fRenderTargetSize = size;
@@ -351,6 +256,10 @@ void GrGLProgram::setMatrixAndRenderTargetHeight(const GrDrawState& drawState) {
GrGLfloat viewMatrix[3 * 3];
fMatrixState.getGLMatrix<3>(viewMatrix);
- fUniformManager.setMatrix3f(fUniformHandles.fViewMatrixUni, viewMatrix);
+ fUniformManager->setMatrix3f(fBuilderOutput.fUniformHandles.fViewMatrixUni, viewMatrix);
+
+ GrGLfloat rtAdjustmentVec[4];
+ fMatrixState.getRTAdjustmentVec(rtAdjustmentVec);
+ fUniformManager->set4fv(fBuilderOutput.fUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
}
}
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLProgram.h b/chromium/third_party/skia/src/gpu/gl/GrGLProgram.h
index 8e2ae74aab9..73a32395a29 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLProgram.h
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLProgram.h
@@ -60,9 +60,9 @@ public:
/**
* Gets the GL program ID for this program.
*/
- GrGLuint programID() const { return fProgramID; }
+ GrGLuint programID() const { return fBuilderOutput.fProgramID; }
- bool hasVertexShader() const { return fHasVertexShader; }
+ bool hasVertexShader() const { return fBuilderOutput.fHasVertexShader; }
/**
* Some GL state that is relevant to programs is not stored per-program. In particular color
@@ -103,20 +103,50 @@ public:
fRenderTargetSize.fHeight = -1;
fRenderTargetOrigin = (GrSurfaceOrigin) -1;
}
+
+ /**
+ * Gets a matrix that goes from local coords to Skia's device coordinates.
+ */
template<int Size> void getGLMatrix(GrGLfloat* destMatrix) {
+ GrGLGetMatrix<Size>(destMatrix, fViewMatrix);
+ }
+
+ /**
+ * Gets a matrix that goes from local coordinates to GL normalized device coords.
+ */
+ template<int Size> void getRTAdjustedGLMatrix(GrGLfloat* destMatrix) {
SkMatrix combined;
if (kBottomLeft_GrSurfaceOrigin == fRenderTargetOrigin) {
combined.setAll(SkIntToScalar(2) / fRenderTargetSize.fWidth, 0, -SK_Scalar1,
0, -SkIntToScalar(2) / fRenderTargetSize.fHeight, SK_Scalar1,
- 0, 0, SkMatrix::I()[8]);
+ 0, 0, 1);
} else {
combined.setAll(SkIntToScalar(2) / fRenderTargetSize.fWidth, 0, -SK_Scalar1,
0, SkIntToScalar(2) / fRenderTargetSize.fHeight, -SK_Scalar1,
- 0, 0, SkMatrix::I()[8]);
+ 0, 0, 1);
}
- combined.setConcat(combined, fViewMatrix);
+ combined.preConcat(fViewMatrix);
GrGLGetMatrix<Size>(destMatrix, combined);
}
+
+ /**
+ * Gets a vec4 that adjusts the position from Skia device coords to GL's normalized device
+ * coords. Assuming the transformed position, pos, is a homogeneous vec3, the vec, v, is
+ * applied as such:
+ * pos.x = dot(v.xy, pos.xz)
+ * pos.y = dot(v.zq, pos.yz)
+ */
+ void getRTAdjustmentVec(GrGLfloat* destVec) {
+ destVec[0] = 2.f / fRenderTargetSize.fWidth;
+ destVec[1] = -1.f;
+ if (kBottomLeft_GrSurfaceOrigin == fRenderTargetOrigin) {
+ destVec[2] = -2.f / fRenderTargetSize.fHeight;
+ destVec[3] = 1.f;
+ } else {
+ destVec[2] = 2.f / fRenderTargetSize.fHeight;
+ destVec[3] = -1.f;
+ }
+ }
};
/**
@@ -134,38 +164,12 @@ public:
private:
typedef GrGLUniformManager::UniformHandle UniformHandle;
- // handles for uniforms (aside from per-effect samplers)
- struct UniformHandles {
- UniformHandle fViewMatrixUni;
- UniformHandle fColorUni;
- UniformHandle fCoverageUni;
-
- // We use the render target height to provide a y-down frag coord when specifying
- // origin_upper_left is not supported.
- UniformHandle fRTHeightUni;
+ GrGLProgram(GrGpuGL*,
+ const GrGLProgramDesc&,
+ GrGLUniformManager*,
+ const GrGLShaderBuilder::GenProgramOutput&);
- // Uniforms for computing texture coords to do the dst-copy lookup
- UniformHandle fDstCopyTopLeftUni;
- UniformHandle fDstCopyScaleUni;
- UniformHandle fDstCopySamplerUni;
- };
-
- GrGLProgram(GrGpuGL* gpu,
- const GrGLProgramDesc& desc,
- const GrEffectStage* colorStages[],
- const GrEffectStage* coverageStages[]);
-
- bool succeeded() const { return 0 != fProgramID; }
-
- /**
- * This is the heavy initialization routine for building a GLProgram. colorStages and
- * coverageStages correspond to the output of GrGLProgramDesc::Build().
- */
- bool genProgram(GrGLShaderBuilder* builder,
- const GrEffectStage* colorStages[],
- const GrEffectStage* coverageStages[]);
-
- // Sets the texture units for samplers
+ // Sets the texture units for samplers.
void initSamplerUniforms();
// Helper for setData(). Makes GL calls to specify the initial color when there is not
@@ -179,26 +183,18 @@ private:
// Helper for setData() that sets the view matrix and loads the render target height uniform
void setMatrixAndRenderTargetHeight(const GrDrawState&);
- // GL program ID
- GrGLuint fProgramID;
-
// these reflect the current values of uniforms (GL uniform values travel with program)
- MatrixState fMatrixState;
- GrColor fColor;
- GrColor fCoverage;
- int fDstCopyTexUnit;
-
- SkAutoTDelete<GrGLProgramEffects> fColorEffects;
- SkAutoTDelete<GrGLProgramEffects> fCoverageEffects;
+ MatrixState fMatrixState;
+ GrColor fColor;
+ GrColor fCoverage;
+ int fDstCopyTexUnit;
- GrGLProgramDesc fDesc;
- GrGpuGL* fGpu;
+ GrGLShaderBuilder::GenProgramOutput fBuilderOutput;
- GrGLUniformManager fUniformManager;
- UniformHandles fUniformHandles;
+ GrGLProgramDesc fDesc;
+ GrGpuGL* fGpu;
- bool fHasVertexShader;
- int fNumTexCoordSets;
+ SkAutoTUnref<GrGLUniformManager> fUniformManager;
typedef SkRefCnt INHERITED;
};
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLProgramDesc.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLProgramDesc.cpp
index 381461a03b6..4039eaf95cd 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLProgramDesc.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLProgramDesc.cpp
@@ -37,7 +37,7 @@ inline GrGLEffect::EffectKey get_key_and_update_stats(const GrEffectStage& stage
}
}
void GrGLProgramDesc::Build(const GrDrawState& drawState,
- bool isPoints,
+ GrGpu::DrawType drawType,
GrDrawState::BlendOptFlags blendOpts,
GrBlendCoeff srcCoeff,
GrBlendCoeff dstCoeff,
@@ -113,7 +113,10 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
int currEffectKey = 0;
bool readsDst = false;
bool readFragPosition = false;
- bool hasVertexCode = false;
+ // We use vertexshader-less shader programs only when drawing paths.
+ bool hasVertexCode = !(GrGpu::kDrawPath_DrawType == drawType ||
+ GrGpu::kDrawPaths_DrawType == drawType);
+
if (!skipColor) {
for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) {
effectKeys[currEffectKey++] =
@@ -132,7 +135,7 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
}
header->fHasVertexCode = hasVertexCode || requiresLocalCoordAttrib;
- header->fEmitsPointSize = isPoints;
+ header->fEmitsPointSize = GrGpu::kDrawPoints_DrawType == drawType;
// Currently the experimental GS will only work with triangle prims (and it doesn't do anything
// other than pass through values from the VS to the FS anyway).
@@ -215,8 +218,7 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
// Here we deal with whether/how we handle color and coverage separately.
- // Set these defaults and then possibly change our mind if there is coverage.
- header->fDiscardIfZeroCoverage = false;
+ // Set this default and then possibly change our mind if there is coverage.
header->fCoverageOutput = kModulate_CoverageOutput;
// If we do have coverage determine whether it matters.
@@ -224,12 +226,6 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
if (!drawState.isCoverageDrawing() && !skipCoverage &&
(drawState.numCoverageStages() > 0 || requiresCoverageAttrib)) {
- // If we're stenciling then we want to discard samples that have zero coverage
- if (drawState.getStencil().doesWrite()) {
- header->fDiscardIfZeroCoverage = true;
- separateCoverageFromColor = true;
- }
-
if (gpu->caps()->dualSourceBlendingSupport() &&
!(blendOpts & (GrDrawState::kEmitCoverage_BlendOptFlag |
GrDrawState::kCoverageAsAlpha_BlendOptFlag))) {
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLProgramDesc.h b/chromium/third_party/skia/src/gpu/gl/GrGLProgramDesc.h
index ec3f0979068..9165f4eb8b1 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLProgramDesc.h
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLProgramDesc.h
@@ -11,6 +11,7 @@
#include "GrGLEffect.h"
#include "GrDrawState.h"
#include "GrGLShaderBuilder.h"
+#include "GrGpu.h"
class GrGpuGL;
@@ -64,7 +65,7 @@ public:
* be treated as color stages in the output.
*/
static void Build(const GrDrawState&,
- bool isPoints,
+ GrGpu::DrawType drawType,
GrDrawState::BlendOptFlags,
GrBlendCoeff srcCoeff,
GrBlendCoeff dstCoeff,
@@ -151,9 +152,6 @@ private:
// effects that read the fragment position.
// Otherwise, 0.
- // should the FS discard if the coverage is zero (to avoid stencil manipulation)
- SkBool8 fDiscardIfZeroCoverage;
-
ColorInput fColorInput : 8;
ColorInput fCoverageInput : 8;
CoverageOutput fCoverageOutput : 8;
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLProgramEffects.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLProgramEffects.cpp
index 17c666a015b..04cebf85196 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLProgramEffects.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLProgramEffects.cpp
@@ -341,7 +341,7 @@ void GrGLVertexProgramEffects::emitTransforms(GrGLFullShaderBuilder* builder,
varyingType = kVec3f_GrSLType;
break;
default:
- GrCrash("Unexpected key.");
+ SkFAIL("Unexpected key.");
}
SkString suffixedUniName;
if (kVoid_GrSLType != transforms[t].fType) {
@@ -393,7 +393,7 @@ void GrGLVertexProgramEffects::emitTransforms(GrGLFullShaderBuilder* builder,
break;
}
default:
- GrCrash("Unexpected uniform type.");
+ SkFAIL("Unexpected uniform type.");
}
SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords,
(SkString(fsVaryingName), varyingType));
@@ -425,7 +425,7 @@ void GrGLVertexProgramEffects::setTransformData(const GrGLUniformManager& unifor
switch (transforms[t].fType) {
case kVoid_GrSLType:
SkASSERT(get_transform_matrix(drawEffect, t).isIdentity());
- return;
+ break;
case kVec2f_GrSLType: {
GrGLfloat tx, ty;
get_transform_translation(drawEffect, t, &tx, &ty);
@@ -446,7 +446,7 @@ void GrGLVertexProgramEffects::setTransformData(const GrGLUniformManager& unifor
break;
}
default:
- GrCrash("Unexpected uniform type.");
+ SkFAIL("Unexpected uniform type.");
}
}
}
@@ -469,7 +469,7 @@ void GrGLVertexProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
////////////////////////////////////////////////////////////////////////////////
-void GrGLTexGenProgramEffects::emitEffect(GrGLFragmentOnlyShaderBuilder* builder,
+void GrGLPathTexGenProgramEffects::emitEffect(GrGLFragmentOnlyShaderBuilder* builder,
const GrEffectStage& stage,
EffectKey key,
const char* outColor,
@@ -481,7 +481,7 @@ void GrGLTexGenProgramEffects::emitEffect(GrGLFragmentOnlyShaderBuilder* builder
SkSTArray<4, TextureSampler> samplers(effect->numTextures());
SkASSERT(0 == stage.getVertexAttribIndexCount());
- this->setupTexGen(builder, effect, key, &coords);
+ this->setupPathTexGen(builder, effect, key, &coords);
this->emitSamplers(builder, effect, &samplers);
GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect);
@@ -498,7 +498,7 @@ void GrGLTexGenProgramEffects::emitEffect(GrGLFragmentOnlyShaderBuilder* builder
builder->fsCodeAppend("\t}\n");
}
-void GrGLTexGenProgramEffects::setupTexGen(GrGLFragmentOnlyShaderBuilder* builder,
+void GrGLPathTexGenProgramEffects::setupPathTexGen(GrGLFragmentOnlyShaderBuilder* builder,
const GrEffectRef& effect,
EffectKey effectKey,
TransformedCoordsArray* outCoords) {
@@ -516,7 +516,7 @@ void GrGLTexGenProgramEffects::setupTexGen(GrGLFragmentOnlyShaderBuilder* builde
}
}
-void GrGLTexGenProgramEffects::setData(GrGpuGL* gpu,
+void GrGLPathTexGenProgramEffects::setData(GrGpuGL* gpu,
const GrGLUniformManager& uniformManager,
const GrEffectStage* effectStages[]) {
int numEffects = fGLEffects.count();
@@ -525,12 +525,12 @@ void GrGLTexGenProgramEffects::setData(GrGpuGL* gpu,
for (int e = 0; e < numEffects; ++e) {
GrDrawEffect drawEffect(*effectStages[e], false);
fGLEffects[e]->setData(uniformManager, drawEffect);
- this->setTexGenState(gpu, drawEffect, e);
+ this->setPathTexGenState(gpu, drawEffect, e);
this->bindTextures(gpu, *drawEffect.effect(), e);
}
}
-void GrGLTexGenProgramEffects::setTexGenState(GrGpuGL* gpu,
+void GrGLPathTexGenProgramEffects::setPathTexGenState(GrGpuGL* gpu,
const GrDrawEffect& drawEffect,
int effectIdx) {
EffectKey totalKey = fTransforms[effectIdx].fTransformKey;
@@ -542,7 +542,9 @@ void GrGLTexGenProgramEffects::setTexGenState(GrGpuGL* gpu,
SkASSERT(get_transform_matrix(drawEffect, t).isIdentity());
GrGLfloat identity[] = {1, 0, 0,
0, 1, 0};
- gpu->enableTexGen(texCoordIndex++, GrGpuGL::kST_TexGenComponents, identity);
+ gpu->enablePathTexGen(texCoordIndex++,
+ GrGpuGL::kST_PathTexGenComponents,
+ identity);
break;
}
case kTrans_MatrixType: {
@@ -550,37 +552,43 @@ void GrGLTexGenProgramEffects::setTexGenState(GrGpuGL* gpu,
get_transform_translation(drawEffect, t, &tx, &ty);
GrGLfloat translate[] = {1, 0, tx,
0, 1, ty};
- gpu->enableTexGen(texCoordIndex++, GrGpuGL::kST_TexGenComponents, translate);
+ gpu->enablePathTexGen(texCoordIndex++,
+ GrGpuGL::kST_PathTexGenComponents,
+ translate);
break;
}
case kNoPersp_MatrixType: {
const SkMatrix& transform = get_transform_matrix(drawEffect, t);
- gpu->enableTexGen(texCoordIndex++, GrGpuGL::kST_TexGenComponents, transform);
+ gpu->enablePathTexGen(texCoordIndex++,
+ GrGpuGL::kST_PathTexGenComponents,
+ transform);
break;
}
case kGeneral_MatrixType: {
const SkMatrix& transform = get_transform_matrix(drawEffect, t);
- gpu->enableTexGen(texCoordIndex++, GrGpuGL::kSTR_TexGenComponents, transform);
+ gpu->enablePathTexGen(texCoordIndex++,
+ GrGpuGL::kSTR_PathTexGenComponents,
+ transform);
break;
}
default:
- GrCrash("Unexpected matrixs type.");
+ SkFAIL("Unexpected matrixs type.");
}
}
}
-GrGLTexGenProgramEffectsBuilder::GrGLTexGenProgramEffectsBuilder(
+GrGLPathTexGenProgramEffectsBuilder::GrGLPathTexGenProgramEffectsBuilder(
GrGLFragmentOnlyShaderBuilder* builder,
int reserveCount)
: fBuilder(builder)
- , fProgramEffects(SkNEW_ARGS(GrGLTexGenProgramEffects, (reserveCount))) {
+ , fProgramEffects(SkNEW_ARGS(GrGLPathTexGenProgramEffects, (reserveCount))) {
}
-void GrGLTexGenProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
- GrGLProgramEffects::EffectKey key,
- const char* outColor,
- const char* inColor,
- int stageIndex) {
+void GrGLPathTexGenProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
+ GrGLProgramEffects::EffectKey key,
+ const char* outColor,
+ const char* inColor,
+ int stageIndex) {
SkASSERT(NULL != fProgramEffects.get());
fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex);
}
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLProgramEffects.h b/chromium/third_party/skia/src/gpu/gl/GrGLProgramEffects.h
index 3320891b379..48d01c8ad7c 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLProgramEffects.h
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLProgramEffects.h
@@ -24,7 +24,7 @@ class GrGLFragmentOnlyShaderBuilder;
* and textures). It is built with GrGLProgramEffectsBuilder, then used to manage the necessary GL
* state and shader uniforms.
*/
-class GrGLProgramEffects {
+class GrGLProgramEffects : public SkRefCnt {
public:
typedef GrBackendEffectFactory::EffectKey EffectKey;
typedef GrGLUniformManager::UniformHandle UniformHandle;
@@ -122,6 +122,9 @@ protected:
SkTArray<GrGLEffect*> fGLEffects;
SkTArray<SkSTArray<4, Sampler, true> > fSamplers;
+
+private:
+ typedef SkRefCnt INHERITED;
};
/**
@@ -237,19 +240,19 @@ private:
////////////////////////////////////////////////////////////////////////////////
/**
- * This is a GrGLProgramEffects implementation that does coord transforms with the the built-in GL
- * TexGen functionality.
+ * This is a GrGLProgramEffects implementation that does coord transforms with
+ * the the NV_path_rendering PathTexGen functionality.
*/
-class GrGLTexGenProgramEffects : public GrGLProgramEffects {
+class GrGLPathTexGenProgramEffects : public GrGLProgramEffects {
public:
virtual void setData(GrGpuGL*,
const GrGLUniformManager&,
const GrEffectStage* effectStages[]) SK_OVERRIDE;
private:
- friend class GrGLTexGenProgramEffectsBuilder;
+ friend class GrGLPathTexGenProgramEffectsBuilder;
- GrGLTexGenProgramEffects(int reserveCount)
+ GrGLPathTexGenProgramEffects(int reserveCount)
: INHERITED(reserveCount)
, fTransforms(reserveCount) {
}
@@ -273,15 +276,15 @@ private:
* types are appended to the TransformedCoordsArray* object, which is in turn passed to the
* effect's emitCode() function.
*/
- void setupTexGen(GrGLFragmentOnlyShaderBuilder*,
- const GrEffectRef&,
- EffectKey,
- TransformedCoordsArray*);
+ void setupPathTexGen(GrGLFragmentOnlyShaderBuilder*,
+ const GrEffectRef&,
+ EffectKey,
+ TransformedCoordsArray*);
/**
- * Helper for setData(). Sets the TexGen state for each transform in an effect.
+ * Helper for setData(). Sets the PathTexGen state for each transform in an effect.
*/
- void setTexGenState(GrGpuGL*, const GrDrawEffect&, int effectIdx);
+ void setPathTexGenState(GrGpuGL*, const GrDrawEffect&, int effectIdx);
struct Transforms {
Transforms(EffectKey transformKey, int texCoordIndex)
@@ -296,12 +299,12 @@ private:
};
/**
- * This class is used to construct a GrGLTexGenProgramEffects* object.
+ * This class is used to construct a GrGLPathTexGenProgramEffects* object.
*/
-class GrGLTexGenProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
+class GrGLPathTexGenProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
public:
- GrGLTexGenProgramEffectsBuilder(GrGLFragmentOnlyShaderBuilder*, int reserveCount);
- virtual ~GrGLTexGenProgramEffectsBuilder() { }
+ GrGLPathTexGenProgramEffectsBuilder(GrGLFragmentOnlyShaderBuilder*, int reserveCount);
+ virtual ~GrGLPathTexGenProgramEffectsBuilder() { }
virtual void emitEffect(const GrEffectStage&,
GrGLProgramEffects::EffectKey,
@@ -317,7 +320,7 @@ public:
private:
GrGLFragmentOnlyShaderBuilder* fBuilder;
- SkAutoTDelete<GrGLTexGenProgramEffects> fProgramEffects;
+ SkAutoTDelete<GrGLPathTexGenProgramEffects> fProgramEffects;
typedef GrGLProgramEffectsBuilder INHERITED;
};
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLSL.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLSL.cpp
index dce44f3aff6..468b13b138d 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLSL.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLSL.cpp
@@ -9,56 +9,62 @@
#include "GrGLShaderVar.h"
#include "SkString.h"
-GrGLSLGeneration GrGetGLSLGeneration(GrGLBinding binding, const GrGLInterface* gl) {
+bool GrGetGLSLGeneration(const GrGLInterface* gl, GrGLSLGeneration* generation) {
+ SkASSERT(NULL != generation);
GrGLSLVersion ver = GrGLGetGLSLVersion(gl);
- switch (binding) {
- case kDesktop_GrGLBinding:
+ if (GR_GLSL_INVALID_VER == ver) {
+ return false;
+ }
+ switch (gl->fStandard) {
+ case kGL_GrGLStandard:
SkASSERT(ver >= GR_GLSL_VER(1,10));
if (ver >= GR_GLSL_VER(1,50)) {
- return k150_GrGLSLGeneration;
+ *generation = k150_GrGLSLGeneration;
} else if (ver >= GR_GLSL_VER(1,40)) {
- return k140_GrGLSLGeneration;
+ *generation = k140_GrGLSLGeneration;
} else if (ver >= GR_GLSL_VER(1,30)) {
- return k130_GrGLSLGeneration;
+ *generation = k130_GrGLSLGeneration;
} else {
- return k110_GrGLSLGeneration;
+ *generation = k110_GrGLSLGeneration;
}
- case kES_GrGLBinding:
+ return true;
+ case kGLES_GrGLStandard:
// version 1.00 of ES GLSL based on ver 1.20 of desktop GLSL
SkASSERT(ver >= GR_GL_VER(1,00));
- return k110_GrGLSLGeneration;
+ *generation = k110_GrGLSLGeneration;
+ return true;
default:
- GrCrash("Unknown GL Binding");
- return k110_GrGLSLGeneration; // suppress warning
+ SkFAIL("Unknown GL Standard");
+ return false;
}
}
const char* GrGetGLSLVersionDecl(const GrGLContextInfo& info) {
switch (info.glslGeneration()) {
case k110_GrGLSLGeneration:
- if (kES_GrGLBinding == info.binding()) {
+ if (kGLES_GrGLStandard == info.standard()) {
// ES2s shader language is based on version 1.20 but is version
// 1.00 of the ES language.
return "#version 100\n";
} else {
- SkASSERT(kDesktop_GrGLBinding == info.binding());
+ SkASSERT(kGL_GrGLStandard == info.standard());
return "#version 110\n";
}
case k130_GrGLSLGeneration:
- SkASSERT(kDesktop_GrGLBinding == info.binding());
+ SkASSERT(kGL_GrGLStandard == info.standard());
return "#version 130\n";
case k140_GrGLSLGeneration:
- SkASSERT(kDesktop_GrGLBinding == info.binding());
+ SkASSERT(kGL_GrGLStandard == info.standard());
return "#version 140\n";
case k150_GrGLSLGeneration:
- SkASSERT(kDesktop_GrGLBinding == info.binding());
+ SkASSERT(kGL_GrGLStandard == info.standard());
if (info.caps()->isCoreProfile()) {
return "#version 150\n";
} else {
return "#version 150 compatibility\n";
}
default:
- GrCrash("Unknown GL version.");
+ SkFAIL("Unknown GL version.");
return ""; // suppress warning
}
}
@@ -67,7 +73,7 @@ namespace {
void append_tabs(SkString* outAppend, int tabCnt) {
static const char kTabs[] = "\t\t\t\t\t\t\t\t";
while (tabCnt) {
- int cnt = GrMin((int)GR_ARRAY_COUNT(kTabs), tabCnt);
+ int cnt = SkTMin((int)SK_ARRAY_COUNT(kTabs), tabCnt);
outAppend->append(kTabs, cnt);
tabCnt -= cnt;
}
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLSL.h b/chromium/third_party/skia/src/gpu/gl/GrGLSL.h
index 8c5da51bde0..ff39c2b6800 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLSL.h
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLSL.h
@@ -40,8 +40,7 @@ enum GrGLSLGeneration {
/**
* Gets the most recent GLSL Generation compatible with the OpenGL context.
*/
-GrGLSLGeneration GrGetGLSLGeneration(GrGLBinding binding,
- const GrGLInterface* gl);
+bool GrGetGLSLGeneration(const GrGLInterface* gl, GrGLSLGeneration* generation);
/**
* Returns a string to include at the beginning of a shader to declare the GLSL
@@ -71,7 +70,7 @@ static inline const char* GrGLSLTypeString(GrSLType t) {
case kSampler2D_GrSLType:
return "sampler2D";
default:
- GrCrash("Unknown shader var type.");
+ SkFAIL("Unknown shader var type.");
return ""; // suppress warning
}
}
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLShaderBuilder.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLShaderBuilder.cpp
index 961cad798fc..4b2778c5030 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLShaderBuilder.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLShaderBuilder.cpp
@@ -13,7 +13,7 @@
#include "GrGpuGL.h"
#include "GrTexture.h"
#include "SkRTConf.h"
-#include "SkTrace.h"
+#include "SkTraceEvent.h"
#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
@@ -89,45 +89,52 @@ static const char kDstCopyColorName[] = "_dstColor";
///////////////////////////////////////////////////////////////////////////////
-GrGLShaderBuilder::GrGLShaderBuilder(GrGpuGL* gpu,
- GrGLUniformManager& uniformManager,
- const GrGLProgramDesc& desc)
- : fGpu(gpu)
- , fUniformManager(uniformManager)
- , fFSFeaturesAddedMask(0)
- , fFSInputs(kVarsPerBlock)
- , fFSOutputs(kMaxFSOutputs)
- , fUniforms(kVarsPerBlock)
- , fSetupFragPosition(false)
- , fHasCustomColorOutput(false)
- , fHasSecondaryOutput(false)
- , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey) {
+bool GrGLShaderBuilder::GenProgram(GrGpuGL* gpu,
+ GrGLUniformManager* uman,
+ const GrGLProgramDesc& desc,
+ const GrEffectStage* inColorStages[],
+ const GrEffectStage* inCoverageStages[],
+ GenProgramOutput* output) {
+ SkAutoTDelete<GrGLShaderBuilder> builder;
+ if (desc.getHeader().fHasVertexCode ||!gpu->shouldUseFixedFunctionTexturing()) {
+ builder.reset(SkNEW_ARGS(GrGLFullShaderBuilder, (gpu, uman, desc)));
+ } else {
+ builder.reset(SkNEW_ARGS(GrGLFragmentOnlyShaderBuilder, (gpu, uman, desc)));
+ }
+ if (builder->genProgram(inColorStages, inCoverageStages)) {
+ *output = builder->getOutput();
+ return true;
+ }
+ return false;
+}
- const GrGLProgramDesc::KeyHeader& header = desc.getHeader();
+bool GrGLShaderBuilder::genProgram(const GrEffectStage* colorStages[],
+ const GrEffectStage* coverageStages[]) {
+ const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader();
- // Emit code to read the dst copy textue if necessary.
+ ///////////////////////////////////////////////////////////////////////////
+ // emit code to read the dst copy texture, if necessary
if (kNoDstRead_DstReadKey != header.fDstReadKey &&
GrGLCaps::kNone_FBFetchType == fGpu->glCaps().fbFetchType()) {
bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKey);
const char* dstCopyTopLeftName;
const char* dstCopyCoordScaleName;
+ const char* dstCopySamplerName;
uint32_t configMask;
if (SkToBool(kUseAlphaConfig_DstReadKeyBit & header.fDstReadKey)) {
configMask = kA_GrColorComponentFlag;
} else {
configMask = kRGBA_GrColorComponentFlags;
}
- fDstCopySamplerUniform = this->addUniform(kFragment_Visibility,
- kSampler2D_GrSLType,
- "DstCopySampler");
- fDstCopyTopLeftUniform = this->addUniform(kFragment_Visibility,
- kVec2f_GrSLType,
- "DstCopyUpperLeft",
- &dstCopyTopLeftName);
- fDstCopyScaleUniform = this->addUniform(kFragment_Visibility,
- kVec2f_GrSLType,
- "DstCopyCoordScale",
- &dstCopyCoordScaleName);
+ fOutput.fUniformHandles.fDstCopySamplerUni =
+ this->addUniform(kFragment_Visibility, kSampler2D_GrSLType, "DstCopySampler",
+ &dstCopySamplerName);
+ fOutput.fUniformHandles.fDstCopyTopLeftUni =
+ this->addUniform(kFragment_Visibility, kVec2f_GrSLType, "DstCopyUpperLeft",
+ &dstCopyTopLeftName);
+ fOutput.fUniformHandles.fDstCopyScaleUni =
+ this->addUniform(kFragment_Visibility, kVec2f_GrSLType, "DstCopyCoordScale",
+ &dstCopyCoordScaleName);
const char* fragPos = this->fragmentPosition();
this->fsCodeAppend("\t// Read color from copy of the destination.\n");
this->fsCodeAppendf("\tvec2 _dstTexCoord = (%s.xy - %s) * %s;\n",
@@ -138,33 +145,41 @@ GrGLShaderBuilder::GrGLShaderBuilder(GrGpuGL* gpu,
this->fsCodeAppendf("\tvec4 %s = ", kDstCopyColorName);
append_texture_lookup(&fFSCode,
fGpu,
- this->getUniformCStr(fDstCopySamplerUniform),
+ dstCopySamplerName,
"_dstTexCoord",
configMask,
"rgba");
this->fsCodeAppend(";\n\n");
}
+ ///////////////////////////////////////////////////////////////////////////
+ // get the initial color and coverage to feed into the first effect in each effect chain
+
+ GrGLSLExpr4 inputColor;
+ GrGLSLExpr4 inputCoverage;
+
if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) {
const char* name;
- fColorUniform = this->addUniform(GrGLShaderBuilder::kFragment_Visibility,
- kVec4f_GrSLType, "Color", &name);
- fInputColor = GrGLSLExpr4(name);
+ fOutput.fUniformHandles.fColorUni =
+ this->addUniform(GrGLShaderBuilder::kFragment_Visibility, kVec4f_GrSLType, "Color",
+ &name);
+ inputColor = GrGLSLExpr4(name);
} else if (GrGLProgramDesc::kSolidWhite_ColorInput == header.fColorInput) {
- fInputColor = GrGLSLExpr4(1);
+ inputColor = GrGLSLExpr4(1);
} else if (GrGLProgramDesc::kTransBlack_ColorInput == header.fColorInput) {
- fInputColor = GrGLSLExpr4(0);
+ inputColor = GrGLSLExpr4(0);
}
if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) {
const char* name;
- fCoverageUniform = this->addUniform(GrGLShaderBuilder::kFragment_Visibility,
- kVec4f_GrSLType, "Coverage", &name);
- fInputCoverage = GrGLSLExpr4(name);
+ fOutput.fUniformHandles.fCoverageUni =
+ this->addUniform(GrGLShaderBuilder::kFragment_Visibility, kVec4f_GrSLType, "Coverage",
+ &name);
+ inputCoverage = GrGLSLExpr4(name);
} else if (GrGLProgramDesc::kSolidWhite_ColorInput == header.fCoverageInput) {
- fInputCoverage = GrGLSLExpr4(1);
+ inputCoverage = GrGLSLExpr4(1);
} else if (GrGLProgramDesc::kTransBlack_ColorInput == header.fCoverageInput) {
- fInputCoverage = GrGLSLExpr4(0);
+ inputCoverage = GrGLSLExpr4(0);
}
if (k110_GrGLSLGeneration != fGpu->glslGeneration()) {
@@ -173,6 +188,81 @@ GrGLShaderBuilder::GrGLShaderBuilder(GrGpuGL* gpu,
declared_color_output_name());
fHasCustomColorOutput = true;
}
+
+ this->emitCodeBeforeEffects(&inputColor, &inputCoverage);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // emit the per-effect code for both color and coverage effects
+
+ fOutput.fColorEffects.reset(this->createAndEmitEffects(colorStages,
+ this->desc().getEffectKeys(),
+ this->desc().numColorEffects(),
+ &inputColor));
+
+ fOutput.fCoverageEffects.reset(this->createAndEmitEffects(coverageStages,
+ this->desc().getEffectKeys() + this->desc().numColorEffects(),
+ this->desc().numCoverageEffects(),
+ &inputCoverage));
+
+ this->emitCodeAfterEffects();
+
+ ///////////////////////////////////////////////////////////////////////////
+ // write the secondary color output if necessary
+ if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(header.fCoverageOutput)) {
+ const char* secondaryOutputName = this->enableSecondaryOutput();
+
+ // default coeff to ones for kCoverage_DualSrcOutput
+ GrGLSLExpr4 coeff(1);
+ if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == header.fCoverageOutput) {
+ // Get (1-A) into coeff
+ coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inputColor.a());
+ } else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput ==
+ header.fCoverageOutput){
+ // Get (1-RGBA) into coeff
+ coeff = GrGLSLExpr4(1) - inputColor;
+ }
+ // Get coeff * coverage into modulate and then write that to the dual source output.
+ this->fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inputCoverage).c_str());
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // combine color and coverage as frag color
+
+ // Get "color * coverage" into fragColor
+ GrGLSLExpr4 fragColor = inputColor * inputCoverage;
+ // Now tack on "+(1-coverage)dst onto the frag color if we were asked to do so.
+ if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == header.fCoverageOutput) {
+ GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inputCoverage;
+
+ GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(this->dstColor());
+
+ fragColor = fragColor + dstContribution;
+ }
+ this->fsCodeAppendf("\t%s = %s;\n", this->getColorOutputName(), fragColor.c_str());
+
+ if (!this->finish()) {
+ return false;
+ }
+
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+GrGLShaderBuilder::GrGLShaderBuilder(GrGpuGL* gpu,
+ GrGLUniformManager* uniformManager,
+ const GrGLProgramDesc& desc)
+ : fDesc(desc)
+ , fGpu(gpu)
+ , fUniformManager(SkRef(uniformManager))
+ , fFSFeaturesAddedMask(0)
+ , fFSInputs(kVarsPerBlock)
+ , fFSOutputs(kMaxFSOutputs)
+ , fUniforms(kVarsPerBlock)
+ , fSetupFragPosition(false)
+ , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey)
+ , fHasCustomColorOutput(false)
+ , fHasSecondaryOutput(false) {
}
bool GrGLShaderBuilder::enableFeature(GLSLFeature feature) {
@@ -181,13 +271,13 @@ bool GrGLShaderBuilder::enableFeature(GLSLFeature feature) {
if (!fGpu->glCaps().shaderDerivativeSupport()) {
return false;
}
- if (kES_GrGLBinding == fGpu->glBinding()) {
+ if (kGLES_GrGLStandard == fGpu->glStandard()) {
this->addFSFeature(1 << kStandardDerivatives_GLSLFeature,
"GL_OES_standard_derivatives");
}
return true;
default:
- GrCrash("Unexpected GLSLFeature requested.");
+ SkFAIL("Unexpected GLSLFeature requested.");
return false;
}
}
@@ -218,7 +308,7 @@ bool GrGLShaderBuilder::enablePrivateFeature(GLSLPrivateFeature feature) {
"GL_NV_shader_framebuffer_fetch");
return true;
default:
- GrCrash("Unexpected GLSLPrivateFeature requested.");
+ SkFAIL("Unexpected GLSLPrivateFeature requested.");
return false;
}
}
@@ -249,7 +339,7 @@ const char* GrGLShaderBuilder::dstColor() {
if (fCodeStage.inStageCode()) {
const GrEffectRef& effect = *fCodeStage.effectStage()->getEffect();
if (!effect->willReadDstColor()) {
- GrDebugCrash("GrGLEffect asked for dst color but its generating GrEffect "
+ SkDEBUGFAIL("GrGLEffect asked for dst color but its generating GrEffect "
"did not request access.");
return "";
}
@@ -262,7 +352,7 @@ const char* GrGLShaderBuilder::dstColor() {
} else if (GrGLCaps::kNV_FBFetchType == fetchType) {
SkAssertResult(this->enablePrivateFeature(kNVShaderFramebufferFetch_GLSLPrivateFeature));
return kFBFetchColorName;
- } else if (fDstCopySamplerUniform.isValid()) {
+ } else if (fOutput.fUniformHandles.fDstCopySamplerUni.isValid()) {
return kDstCopyColorName;
} else {
return "";
@@ -355,7 +445,7 @@ GrGLUniformManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t vi
BuilderUniform& uni = fUniforms.push_back();
UniformHandle h = GrGLUniformManager::UniformHandle::CreateFromUniformIndex(fUniforms.count() - 1);
SkDEBUGCODE(UniformHandle h2 =)
- fUniformManager.appendUniform(type, count);
+ fUniformManager->appendUniform(type, count);
// We expect the uniform manager to initially have no uniforms and that all uniforms are added
// by this function. Therefore, the handles should match.
SkASSERT(h2 == h);
@@ -399,19 +489,16 @@ const char* GrGLShaderBuilder::fragmentPosition() {
if (fCodeStage.inStageCode()) {
const GrEffectRef& effect = *fCodeStage.effectStage()->getEffect();
if (!effect->willReadFragmentPosition()) {
- GrDebugCrash("GrGLEffect asked for frag position but its generating GrEffect "
+ SkDEBUGFAIL("GrGLEffect asked for frag position but its generating GrEffect "
"did not request access.");
return "";
}
}
+ // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers
+ // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the
+ // declaration varies in earlier GLSL specs. So it is simpler to omit it.
if (fTopLeftFragPosRead) {
- if (!fSetupFragPosition) {
- fFSInputs.push_back().set(kVec4f_GrSLType,
- GrGLShaderVar::kIn_TypeModifier,
- "gl_FragCoord",
- GrGLShaderVar::kDefault_Precision);
- fSetupFragPosition = true;
- }
+ fSetupFragPosition = true;
return "gl_FragCoord";
} else if (fGpu->glCaps().fragCoordConventionsSupport()) {
if (!fSetupFragPosition) {
@@ -430,19 +517,17 @@ const char* GrGLShaderBuilder::fragmentPosition() {
// temporarily change the stage index because we're inserting non-stage code.
CodeStage::AutoStageRestore csar(&fCodeStage, NULL);
- SkASSERT(!fRTHeightUniform.isValid());
+ SkASSERT(!fOutput.fUniformHandles.fRTHeightUni.isValid());
const char* rtHeightName;
- fRTHeightUniform = this->addUniform(kFragment_Visibility,
- kFloat_GrSLType,
- "RTHeight",
- &rtHeightName);
+ fOutput.fUniformHandles.fRTHeightUni =
+ this->addUniform(kFragment_Visibility, kFloat_GrSLType, "RTHeight", &rtHeightName);
this->fFSCode.prependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, gl_FragCoord.zw);\n",
kCoordName, rtHeightName);
fSetupFragPosition = true;
}
- SkASSERT(fRTHeightUniform.isValid());
+ SkASSERT(fOutput.fUniformHandles.fRTHeightUni.isValid());
return kCoordName;
}
}
@@ -471,10 +556,10 @@ void GrGLShaderBuilder::fsEmitFunction(GrSLType returnType,
namespace {
inline void append_default_precision_qualifier(GrGLShaderVar::Precision p,
- GrGLBinding binding,
+ GrGLStandard standard,
SkString* str) {
// Desktop GLSL has added precision qualifiers but they don't do anything.
- if (kES_GrGLBinding == binding) {
+ if (kGLES_GrGLStandard == standard) {
switch (p) {
case GrGLShaderVar::kHigh_Precision:
str->append("precision highp float;\n");
@@ -486,9 +571,9 @@ inline void append_default_precision_qualifier(GrGLShaderVar::Precision p,
str->append("precision lowp float;\n");
break;
case GrGLShaderVar::kDefault_Precision:
- GrCrash("Default precision now allowed.");
+ SkFAIL("Default precision now allowed.");
default:
- GrCrash("Unknown precision value.");
+ SkFAIL("Unknown precision value.");
}
}
}
@@ -572,27 +657,26 @@ const char* GrGLShaderBuilder::enableSecondaryOutput() {
return dual_source_output_name();
}
-
-bool GrGLShaderBuilder::finish(GrGLuint* outProgramId) {
- SK_TRACE_EVENT0("GrGLShaderBuilder::finish");
-
- GrGLuint programId = 0;
- GL_CALL_RET(programId, CreateProgram());
- if (!programId) {
+bool GrGLShaderBuilder::finish() {
+ SkASSERT(0 == fOutput.fProgramID);
+ GL_CALL_RET(fOutput.fProgramID, CreateProgram());
+ if (!fOutput.fProgramID) {
return false;
}
- if (!this->compileAndAttachShaders(programId)) {
- GL_CALL(DeleteProgram(programId));
+ SkTDArray<GrGLuint> shadersToDelete;
+
+ if (!this->compileAndAttachShaders(fOutput.fProgramID, &shadersToDelete)) {
+ GL_CALL(DeleteProgram(fOutput.fProgramID));
return false;
}
- this->bindProgramLocations(programId);
- if (fUniformManager.isUsingBindUniform()) {
- fUniformManager.getUniformLocations(programId, fUniforms);
+ this->bindProgramLocations(fOutput.fProgramID);
+ if (fUniformManager->isUsingBindUniform()) {
+ fUniformManager->getUniformLocations(fOutput.fProgramID, fUniforms);
}
- GL_CALL(LinkProgram(programId));
+ GL_CALL(LinkProgram(fOutput.fProgramID));
// Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
bool checkLinked = !fGpu->ctxInfo().isChromium();
@@ -601,46 +685,51 @@ bool GrGLShaderBuilder::finish(GrGLuint* outProgramId) {
#endif
if (checkLinked) {
GrGLint linked = GR_GL_INIT_ZERO;
- GL_CALL(GetProgramiv(programId, GR_GL_LINK_STATUS, &linked));
+ GL_CALL(GetProgramiv(fOutput.fProgramID, GR_GL_LINK_STATUS, &linked));
if (!linked) {
GrGLint infoLen = GR_GL_INIT_ZERO;
- GL_CALL(GetProgramiv(programId, GR_GL_INFO_LOG_LENGTH, &infoLen));
+ GL_CALL(GetProgramiv(fOutput.fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen));
SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
if (infoLen > 0) {
// retrieve length even though we don't need it to workaround
// bug in chrome cmd buffer param validation.
GrGLsizei length = GR_GL_INIT_ZERO;
- GL_CALL(GetProgramInfoLog(programId,
+ GL_CALL(GetProgramInfoLog(fOutput.fProgramID,
infoLen+1,
&length,
(char*)log.get()));
GrPrintf((char*)log.get());
}
SkDEBUGFAIL("Error linking program");
- GL_CALL(DeleteProgram(programId));
+ GL_CALL(DeleteProgram(fOutput.fProgramID));
+ fOutput.fProgramID = 0;
return false;
}
}
- if (!fUniformManager.isUsingBindUniform()) {
- fUniformManager.getUniformLocations(programId, fUniforms);
+ if (!fUniformManager->isUsingBindUniform()) {
+ fUniformManager->getUniformLocations(fOutput.fProgramID, fUniforms);
}
- *outProgramId = programId;
+
+ for (int i = 0; i < shadersToDelete.count(); ++i) {
+ GL_CALL(DeleteShader(shadersToDelete[i]));
+ }
+
return true;
}
-// Compiles a GL shader, attaches it to a program, and releases the shader's reference.
-// (That way there's no need to hang on to the GL shader id and delete it later.)
-static bool attach_shader(const GrGLContext& glCtx,
- GrGLuint programId,
- GrGLenum type,
- const SkString& shaderSrc) {
+// Compiles a GL shader and attaches it to a program. Returns the shader ID if
+// successful, or 0 if not.
+static GrGLuint attach_shader(const GrGLContext& glCtx,
+ GrGLuint programId,
+ GrGLenum type,
+ const SkString& shaderSrc) {
const GrGLInterface* gli = glCtx.interface();
GrGLuint shaderId;
GR_GL_CALL_RET(gli, shaderId, CreateShader(type));
if (0 == shaderId) {
- return false;
+ return 0;
}
const GrGLchar* sourceStr = shaderSrc.c_str();
@@ -649,7 +738,7 @@ static bool attach_shader(const GrGLContext& glCtx,
GR_GL_CALL(gli, CompileShader(shaderId));
// Calling GetShaderiv in Chromium is quite expensive. Assume success in release builds.
- bool checkCompiled = !glCtx.info().isChromium();
+ bool checkCompiled = !glCtx.isChromium();
#ifdef SK_DEBUG
checkCompiled = true;
#endif
@@ -672,7 +761,7 @@ static bool attach_shader(const GrGLContext& glCtx,
}
SkDEBUGFAIL("Shader compilation failed!");
GR_GL_CALL(gli, DeleteShader(shaderId));
- return false;
+ return 0;
}
}
if (c_PrintShaders) {
@@ -680,16 +769,20 @@ static bool attach_shader(const GrGLContext& glCtx,
GrPrintf("\n");
}
+ // Attach the shader, but defer deletion until after we have linked the program.
+ // This works around a bug in the Android emulator's GLES2 wrapper which
+ // will immediately delete the shader object and free its memory even though it's
+ // attached to a program, which then causes glLinkProgram to fail.
GR_GL_CALL(gli, AttachShader(programId, shaderId));
- GR_GL_CALL(gli, DeleteShader(shaderId));
- return true;
+
+ return shaderId;
}
-bool GrGLShaderBuilder::compileAndAttachShaders(GrGLuint programId) const {
+bool GrGLShaderBuilder::compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const {
SkString fragShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo()));
fragShaderSrc.append(fFSExtensions);
append_default_precision_qualifier(kDefaultFragmentPrecision,
- fGpu->glBinding(),
+ fGpu->glStandard(),
&fragShaderSrc);
this->appendUniformDecls(kFragment_Visibility, &fragShaderSrc);
this->appendDecls(fFSInputs, &fragShaderSrc);
@@ -700,10 +793,14 @@ bool GrGLShaderBuilder::compileAndAttachShaders(GrGLuint programId) const {
fragShaderSrc.append("void main() {\n");
fragShaderSrc.append(fFSCode);
fragShaderSrc.append("}\n");
- if (!attach_shader(fGpu->glContext(), programId, GR_GL_FRAGMENT_SHADER, fragShaderSrc)) {
+
+ GrGLuint fragShaderId = attach_shader(fGpu->glContext(), programId, GR_GL_FRAGMENT_SHADER, fragShaderSrc);
+ if (!fragShaderId) {
return false;
}
+ *shaderIds->append() = fragShaderId;
+
return true;
}
@@ -723,16 +820,19 @@ const GrGLContextInfo& GrGLShaderBuilder::ctxInfo() const {
////////////////////////////////////////////////////////////////////////////////
GrGLFullShaderBuilder::GrGLFullShaderBuilder(GrGpuGL* gpu,
- GrGLUniformManager& uniformManager,
+ GrGLUniformManager* uniformManager,
const GrGLProgramDesc& desc)
: INHERITED(gpu, uniformManager, desc)
- , fDesc(desc)
, fVSAttrs(kVarsPerBlock)
, fVSOutputs(kVarsPerBlock)
, fGSInputs(kVarsPerBlock)
, fGSOutputs(kVarsPerBlock) {
+}
+
+void GrGLFullShaderBuilder::emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) {
+ const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader();
- const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
+ fOutput.fHasVertexShader = true;
fPositionVar = &fVSAttrs.push_back();
fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition");
@@ -746,11 +846,12 @@ GrGLFullShaderBuilder::GrGLFullShaderBuilder(GrGpuGL* gpu,
}
const char* viewMName;
- fViewMatrixUniform = this->addUniform(GrGLShaderBuilder::kVertex_Visibility,
- kMat33f_GrSLType, "ViewM", &viewMName);
+ fOutput.fUniformHandles.fViewMatrixUni =
+ this->addUniform(GrGLShaderBuilder::kVertex_Visibility, kMat33f_GrSLType, "ViewM",
+ &viewMName);
- this->vsCodeAppendf("\tvec3 pos3 = %s * vec3(%s, 1);\n"
- "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n",
+ // Transform the position into Skia's device coords.
+ this->vsCodeAppendf("\tvec3 pos3 = %s * vec3(%s, 1);\n",
viewMName, fPositionVar->c_str());
// we output point size in the GS if present
@@ -767,7 +868,7 @@ GrGLFullShaderBuilder::GrGLFullShaderBuilder(GrGpuGL* gpu,
const char *vsName, *fsName;
this->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName);
this->vsCodeAppendf("\t%s = %s;\n", vsName, color_attribute_name());
- this->setInputColor(fsName);
+ *color = fsName;
}
if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) {
@@ -775,10 +876,22 @@ GrGLFullShaderBuilder::GrGLFullShaderBuilder(GrGpuGL* gpu,
const char *vsName, *fsName;
this->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName);
this->vsCodeAppendf("\t%s = %s;\n", vsName, coverage_attribute_name());
- this->setInputCoverage(fsName);
+ *coverage = fsName;
}
}
+void GrGLFullShaderBuilder::emitCodeAfterEffects() {
+ const char* rtAdjustName;
+ fOutput.fUniformHandles.fRTAdjustmentUni =
+ this->addUniform(GrGLShaderBuilder::kVertex_Visibility, kVec4f_GrSLType, "rtAdjustment",
+ &rtAdjustName);
+
+ // Transform from Skia's device coords to GL's normalized device coords.
+ this->vsCodeAppendf(
+ "\tgl_Position = vec4(dot(pos3.xz, %s.xy), dot(pos3.yz, %s.zw), 0, pos3.z);\n",
+ rtAdjustName, rtAdjustName);
+}
+
bool GrGLFullShaderBuilder::addAttribute(GrSLType type, const char* name) {
for (int i = 0; i < fVSAttrs.count(); ++i) {
const GrGLShaderVar& attr = fVSAttrs[i];
@@ -820,7 +933,7 @@ void GrGLFullShaderBuilder::addVarying(GrSLType type,
// input to FS comes either from VS or GS
const SkString* fsName;
#if GR_GL_EXPERIMENTAL_GS
- if (fDesc.getHeader().fExperimentalGS) {
+ if (this->desc().getHeader().fExperimentalGS) {
// if we have a GS take each varying in as an array
// and output as non-array.
fGSInputs.push_back();
@@ -870,7 +983,8 @@ GrGLProgramEffects* GrGLFullShaderBuilder::createAndEmitEffects(
return programEffectsBuilder.finish();
}
-bool GrGLFullShaderBuilder::compileAndAttachShaders(GrGLuint programId) const {
+bool GrGLFullShaderBuilder::compileAndAttachShaders(GrGLuint programId,
+ SkTDArray<GrGLuint>* shaderIds) const {
const GrGLContext& glCtx = this->gpu()->glContext();
SkString vertShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo()));
this->appendUniformDecls(kVertex_Visibility, &vertShaderSrc);
@@ -879,12 +993,14 @@ bool GrGLFullShaderBuilder::compileAndAttachShaders(GrGLuint programId) const {
vertShaderSrc.append("void main() {\n");
vertShaderSrc.append(fVSCode);
vertShaderSrc.append("}\n");
- if (!attach_shader(glCtx, programId, GR_GL_VERTEX_SHADER, vertShaderSrc)) {
+ GrGLuint vertShaderId = attach_shader(glCtx, programId, GR_GL_VERTEX_SHADER, vertShaderSrc);
+ if (!vertShaderId) {
return false;
}
+ *shaderIds->append() = vertShaderId;
#if GR_GL_EXPERIMENTAL_GS
- if (fDesc.getHeader().fExperimentalGS) {
+ if (this->desc().getHeader().fExperimentalGS) {
SkASSERT(this->ctxInfo().glslGeneration() >= k150_GrGLSLGeneration);
SkString geomShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo()));
geomShaderSrc.append("layout(triangles) in;\n"
@@ -894,7 +1010,7 @@ bool GrGLFullShaderBuilder::compileAndAttachShaders(GrGLuint programId) const {
geomShaderSrc.append("void main() {\n");
geomShaderSrc.append("\tfor (int i = 0; i < 3; ++i) {\n"
"\t\tgl_Position = gl_in[i].gl_Position;\n");
- if (fDesc.getHeader().fEmitsPointSize) {
+ if (this->desc().getHeader().fEmitsPointSize) {
geomShaderSrc.append("\t\tgl_PointSize = 1.0;\n");
}
SkASSERT(fGSInputs.count() == fGSOutputs.count());
@@ -907,19 +1023,21 @@ bool GrGLFullShaderBuilder::compileAndAttachShaders(GrGLuint programId) const {
"\t}\n"
"\tEndPrimitive();\n");
geomShaderSrc.append("}\n");
- if (!attach_shader(glCtx, programId, GR_GL_GEOMETRY_SHADER, geomShaderSrc)) {
+ GrGLuint geomShaderId = attach_shader(glCtx, programId, GR_GL_GEOMETRY_SHADER, geomShaderSrc);
+ if (!geomShaderId) {
return false;
}
+ *shaderIds->append() = geomShaderId;
}
#endif
- return this->INHERITED::compileAndAttachShaders(programId);
+ return this->INHERITED::compileAndAttachShaders(programId, shaderIds);
}
void GrGLFullShaderBuilder::bindProgramLocations(GrGLuint programId) const {
this->INHERITED::bindProgramLocations(programId);
- const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
+ const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader();
// Bind the attrib locations to same values for all shaders
SkASSERT(-1 != header.fPositionAttributeIndex);
@@ -951,22 +1069,19 @@ void GrGLFullShaderBuilder::bindProgramLocations(GrGLuint programId) const {
////////////////////////////////////////////////////////////////////////////////
GrGLFragmentOnlyShaderBuilder::GrGLFragmentOnlyShaderBuilder(GrGpuGL* gpu,
- GrGLUniformManager& uniformManager,
+ GrGLUniformManager* uniformManager,
const GrGLProgramDesc& desc)
- : INHERITED(gpu, uniformManager, desc)
- , fNumTexCoordSets(0) {
-
+ : INHERITED(gpu, uniformManager, desc) {
SkASSERT(!desc.getHeader().fHasVertexCode);
- SkASSERT(gpu->glCaps().fixedFunctionSupport());
SkASSERT(gpu->glCaps().pathRenderingSupport());
SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fColorInput);
SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fCoverageInput);
}
int GrGLFragmentOnlyShaderBuilder::addTexCoordSets(int count) {
- int firstFreeCoordSet = fNumTexCoordSets;
- fNumTexCoordSets += count;
- SkASSERT(gpu()->glCaps().maxFixedFunctionTextureCoords() >= fNumTexCoordSets);
+ int firstFreeCoordSet = fOutput.fTexCoordSetCnt;
+ fOutput.fTexCoordSetCnt += count;
+ SkASSERT(gpu()->glCaps().maxFixedFunctionTextureCoords() >= fOutput.fTexCoordSetCnt);
return firstFreeCoordSet;
}
@@ -976,11 +1091,12 @@ GrGLProgramEffects* GrGLFragmentOnlyShaderBuilder::createAndEmitEffects(
int effectCnt,
GrGLSLExpr4* inOutFSColor) {
- GrGLTexGenProgramEffectsBuilder texGenEffectsBuilder(this, effectCnt);
- this->INHERITED::createAndEmitEffects(&texGenEffectsBuilder,
+ GrGLPathTexGenProgramEffectsBuilder pathTexGenEffectsBuilder(this,
+ effectCnt);
+ this->INHERITED::createAndEmitEffects(&pathTexGenEffectsBuilder,
effectStages,
effectKeys,
effectCnt,
inOutFSColor);
- return texGenEffectsBuilder.finish();
+ return pathTexGenEffectsBuilder.finish();
}
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLShaderBuilder.h b/chromium/third_party/skia/src/gpu/gl/GrGLShaderBuilder.h
index 103efa5aabc..7e71acf901f 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLShaderBuilder.h
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLShaderBuilder.h
@@ -41,7 +41,62 @@ public:
kFragment_Visibility = 0x4,
};
- GrGLShaderBuilder(GrGpuGL*, GrGLUniformManager&, const GrGLProgramDesc&);
+ typedef GrGLUniformManager::UniformHandle UniformHandle;
+
+ // Handles for program uniforms (other than per-effect uniforms)
+ struct UniformHandles {
+ UniformHandle fViewMatrixUni;
+ UniformHandle fRTAdjustmentUni;
+ UniformHandle fColorUni;
+ UniformHandle fCoverageUni;
+
+ // We use the render target height to provide a y-down frag coord when specifying
+ // origin_upper_left is not supported.
+ UniformHandle fRTHeightUni;
+
+ // Uniforms for computing texture coords to do the dst-copy lookup
+ UniformHandle fDstCopyTopLeftUni;
+ UniformHandle fDstCopyScaleUni;
+ UniformHandle fDstCopySamplerUni;
+ };
+
+ struct GenProgramOutput {
+ GenProgramOutput()
+ : fColorEffects(NULL)
+ , fCoverageEffects(NULL)
+ , fHasVertexShader(false)
+ , fTexCoordSetCnt(0)
+ , fProgramID(0) {}
+
+ GenProgramOutput(const GenProgramOutput& other) {
+ *this = other;
+ }
+
+ GenProgramOutput& operator=(const GenProgramOutput& other) {
+ fColorEffects.reset(SkRef(other.fColorEffects.get()));
+ fCoverageEffects.reset(SkRef(other.fCoverageEffects.get()));
+ fUniformHandles = other.fUniformHandles;
+ fHasVertexShader = other.fHasVertexShader;
+ fTexCoordSetCnt = other.fTexCoordSetCnt;
+ fProgramID = other.fProgramID;
+ return *this;
+ }
+
+ SkAutoTUnref<GrGLProgramEffects> fColorEffects;
+ SkAutoTUnref<GrGLProgramEffects> fCoverageEffects;
+ UniformHandles fUniformHandles;
+ bool fHasVertexShader;
+ int fTexCoordSetCnt;
+ GrGLuint fProgramID;
+ };
+
+ static bool GenProgram(GrGpuGL* gpu,
+ GrGLUniformManager* uman,
+ const GrGLProgramDesc& desc,
+ const GrEffectStage* inColorStages[],
+ const GrEffectStage* inCoverageStages[],
+ GenProgramOutput* output);
+
virtual ~GrGLShaderBuilder() {}
/**
@@ -125,8 +180,7 @@ public:
uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
supported at this time. The actual uniform name will be mangled. If outName is not NULL then
it will refer to the final uniform name after return. Use the addUniformArray variant to add
- an array of uniforms.
- */
+ an array of uniforms. */
GrGLUniformManager::UniformHandle addUniform(uint32_t visibility,
GrSLType type,
const char* name,
@@ -140,7 +194,7 @@ public:
const char** outName = NULL);
const GrGLShaderVar& getUniformVariable(GrGLUniformManager::UniformHandle u) const {
- return fUniformManager.getBuilderUniform(fUniforms, u).fVariable;
+ return fUniformManager->getBuilderUniform(fUniforms, u).fVariable;
}
/**
@@ -161,51 +215,10 @@ public:
is in device space (e.g. 0,0 is the top left and pixel centers are at half-integers). */
const char* fragmentPosition();
- /** Returns the color of the destination pixel. This may be NULL if no effect advertised
- that it will read the destination. */
+ /** Returns the variable name that holds the color of the destination pixel. This may be NULL if
+ no effect advertised that it will read the destination. */
const char* dstColor();
- /**
- * Interfaces used by GrGLProgram.
- */
- const GrGLSLExpr4& getInputColor() const {
- return fInputColor;
- }
- const GrGLSLExpr4& getInputCoverage() const {
- return fInputCoverage;
- }
-
- /**
- * Adds code for effects and returns a GrGLProgramEffects* object. The caller is responsible for
- * deleting it when finished. effectStages contains the effects to add. effectKeys[i] is the key
- * generated from effectStages[i]. inOutFSColor specifies the input color to the first stage and
- * is updated to be the output color of the last stage.
- * The handles to texture samplers for effectStage[i] are added to
- * effectSamplerHandles[i].
- */
- virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
- const EffectKey effectKeys[],
- int effectCnt,
- GrGLSLExpr4* inOutFSColor) = 0;
-
- const char* getColorOutputName() const;
- const char* enableSecondaryOutput();
-
- GrGLUniformManager::UniformHandle getRTHeightUniform() const { return fRTHeightUniform; }
- GrGLUniformManager::UniformHandle getDstCopyTopLeftUniform() const {
- return fDstCopyTopLeftUniform;
- }
- GrGLUniformManager::UniformHandle getDstCopyScaleUniform() const {
- return fDstCopyScaleUniform;
- }
- GrGLUniformManager::UniformHandle getColorUniform() const { return fColorUniform; }
- GrGLUniformManager::UniformHandle getCoverageUniform() const { return fCoverageUniform; }
- GrGLUniformManager::UniformHandle getDstCopySamplerUniform() const {
- return fDstCopySamplerUniform;
- }
-
- bool finish(GrGLuint* outProgramId);
-
const GrGLContextInfo& ctxInfo() const;
/**
@@ -228,19 +241,15 @@ public:
};
protected:
+ GrGLShaderBuilder(GrGpuGL*, GrGLUniformManager*, const GrGLProgramDesc&);
+
GrGpuGL* gpu() const { return fGpu; }
- void setInputColor(const GrGLSLExpr4& inputColor) { fInputColor = inputColor; }
- void setInputCoverage(const GrGLSLExpr4& inputCoverage) { fInputCoverage = inputCoverage; }
+ const GrGLProgramDesc& desc() const { return fDesc; }
/** Add input/output variable declarations (i.e. 'varying') to the fragment shader. */
GrGLShaderVar& fsInputAppend() { return fFSInputs.push_back(); }
- // Generates a name for a variable. The generated string will be name prefixed by the prefix
- // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
- // generating stage code.
- void nameVariable(SkString* out, char prefix, const char* name);
-
// Helper for emitEffects().
void createAndEmitEffects(GrGLProgramEffectsBuilder*,
const GrEffectStage* effectStages[],
@@ -248,14 +257,24 @@ protected:
int effectCnt,
GrGLSLExpr4* inOutFSColor);
- virtual bool compileAndAttachShaders(GrGLuint programId) const;
+ // Generates a name for a variable. The generated string will be name prefixed by the prefix
+ // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
+ // generating stage code.
+ void nameVariable(SkString* out, char prefix, const char* name);
+
+ virtual bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
+
virtual void bindProgramLocations(GrGLuint programId) const;
void appendDecls(const VarArray&, SkString*) const;
void appendUniformDecls(ShaderVisibility, SkString*) const;
+ const GenProgramOutput& getOutput() const { return fOutput; }
+
+ GenProgramOutput fOutput;
+
private:
- class CodeStage : public SkNoncopyable {
+ class CodeStage : SkNoncopyable {
public:
CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffectStage(NULL) {}
@@ -274,7 +293,7 @@ private:
return fCurrentIndex;
}
- class AutoStageRestore : public SkNoncopyable {
+ class AutoStageRestore : SkNoncopyable {
public:
AutoStageRestore(CodeStage* codeStage, const GrEffectStage* newStage) {
SkASSERT(NULL != codeStage);
@@ -306,6 +325,47 @@ private:
const GrEffectStage* fEffectStage;
} fCodeStage;
+ bool genProgram(const GrEffectStage* colorStages[], const GrEffectStage* coverageStages[]);
+
+ /**
+ * The base class will emit the fragment code that precedes the per-effect code and then call
+ * this function. The subclass can use it to insert additional fragment code that should
+ * execute before the effects' code and/or emit other shaders (e.g. geometry, vertex).
+ *
+ * The subclass can modify the initial color or coverage
+ */
+ virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) = 0;
+
+ /**
+ * Adds code for effects and returns a GrGLProgramEffects* object. The caller is responsible for
+ * deleting it when finished. effectStages contains the effects to add. effectKeys[i] is the key
+ * generated from effectStages[i]. inOutFSColor specifies the input color to the first stage and
+ * is updated to be the output color of the last stage.
+ * The handles to texture samplers for effectStage[i] are added to
+ * effectSamplerHandles[i].
+ */
+ virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
+ const EffectKey effectKeys[],
+ int effectCnt,
+ GrGLSLExpr4* inOutFSColor) = 0;
+
+ /**
+ * Similar to emitCodeBeforeEffects() but called after per-effect code is emitted.
+ */
+ virtual void emitCodeAfterEffects() = 0;
+
+ /** Enables using the secondary color output and returns the name of the var in which it is
+ to be stored */
+ const char* enableSecondaryOutput();
+ /** Gets the name of the primary color output. */
+ const char* getColorOutputName() const;
+
+ /**
+ * Compiles all the shaders, links them into a program, and writes the program id to the output
+ * struct.
+ **/
+ bool finish();
+
/**
* Features that should only be enabled by GrGLShaderBuilder itself.
*/
@@ -322,10 +382,10 @@ private:
// Interpretation of DstReadKey when generating code
enum {
- kNoDstRead_DstReadKey = 0,
- kYesDstRead_DstReadKeyBit = 0x1, // Set if we do a dst-copy-read.
- kUseAlphaConfig_DstReadKeyBit = 0x2, // Set if dst-copy config is alpha only.
- kTopLeftOrigin_DstReadKeyBit = 0x4, // Set if dst-copy origin is top-left.
+ kNoDstRead_DstReadKey = 0,
+ kYesDstRead_DstReadKeyBit = 0x1, // Set if we do a dst-copy-read.
+ kUseAlphaConfig_DstReadKeyBit = 0x2, // Set if dst-copy config is alpha only.
+ kTopLeftOrigin_DstReadKeyBit = 0x4, // Set if dst-copy origin is top-left.
};
enum {
@@ -334,8 +394,9 @@ private:
kBottomLeftFragPosRead_FragPosKey = 0x2,// Read frag pos relative to bottom-left.
};
+ const GrGLProgramDesc& fDesc;
GrGpuGL* fGpu;
- GrGLUniformManager& fUniformManager;
+ SkAutoTUnref<GrGLUniformManager> fUniformManager;
uint32_t fFSFeaturesAddedMask;
SkString fFSFunctions;
SkString fFSExtensions;
@@ -346,28 +407,17 @@ private:
SkString fFSCode;
bool fSetupFragPosition;
- GrGLUniformManager::UniformHandle fDstCopySamplerUniform;
-
- GrGLSLExpr4 fInputColor;
- GrGLSLExpr4 fInputCoverage;
+ bool fTopLeftFragPosRead;
bool fHasCustomColorOutput;
bool fHasSecondaryOutput;
-
- GrGLUniformManager::UniformHandle fRTHeightUniform;
- GrGLUniformManager::UniformHandle fDstCopyTopLeftUniform;
- GrGLUniformManager::UniformHandle fDstCopyScaleUniform;
- GrGLUniformManager::UniformHandle fColorUniform;
- GrGLUniformManager::UniformHandle fCoverageUniform;
-
- bool fTopLeftFragPosRead;
};
////////////////////////////////////////////////////////////////////////////////
class GrGLFullShaderBuilder : public GrGLShaderBuilder {
public:
- GrGLFullShaderBuilder(GrGpuGL*, GrGLUniformManager&, const GrGLProgramDesc&);
+ GrGLFullShaderBuilder(GrGpuGL*, GrGLUniformManager*, const GrGLProgramDesc&);
/**
* Called by GrGLEffects to add code to one of the shaders.
@@ -411,22 +461,21 @@ public:
bool addEffectAttribute(int attributeIndex, GrSLType type, const SkString& name);
const SkString* getEffectAttributeName(int attributeIndex) const;
- virtual GrGLProgramEffects* createAndEmitEffects(
- const GrEffectStage* effectStages[],
- const EffectKey effectKeys[],
- int effectCnt,
- GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
+private:
+ virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) SK_OVERRIDE;
- GrGLUniformManager::UniformHandle getViewMatrixUniform() const {
- return fViewMatrixUniform;
- }
+ virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
+ const EffectKey effectKeys[],
+ int effectCnt,
+ GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
+
+ virtual void emitCodeAfterEffects() SK_OVERRIDE;
+
+ virtual bool compileAndAttachShaders(GrGLuint programId,
+ SkTDArray<GrGLuint>* shaderIds) const SK_OVERRIDE;
-protected:
- virtual bool compileAndAttachShaders(GrGLuint programId) const SK_OVERRIDE;
virtual void bindProgramLocations(GrGLuint programId) const SK_OVERRIDE;
-private:
- const GrGLProgramDesc& fDesc;
VarArray fVSAttrs;
VarArray fVSOutputs;
VarArray fGSInputs;
@@ -443,8 +492,6 @@ private:
};
SkSTArray<10, AttributePair, true> fEffectAttributes;
- GrGLUniformManager::UniformHandle fViewMatrixUniform;
-
GrGLShaderVar* fPositionVar;
GrGLShaderVar* fLocalCoordsVar;
@@ -455,19 +502,19 @@ private:
class GrGLFragmentOnlyShaderBuilder : public GrGLShaderBuilder {
public:
- GrGLFragmentOnlyShaderBuilder(GrGpuGL*, GrGLUniformManager&, const GrGLProgramDesc&);
+ GrGLFragmentOnlyShaderBuilder(GrGpuGL*, GrGLUniformManager*, const GrGLProgramDesc&);
- int getNumTexCoordSets() const { return fNumTexCoordSets; }
int addTexCoordSets(int count);
- virtual GrGLProgramEffects* createAndEmitEffects(
- const GrEffectStage* effectStages[],
- const EffectKey effectKeys[],
- int effectCnt,
- GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
-
private:
- int fNumTexCoordSets;
+ virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) SK_OVERRIDE {}
+
+ virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
+ const EffectKey effectKeys[],
+ int effectCnt,
+ GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
+
+ virtual void emitCodeAfterEffects() SK_OVERRIDE {}
typedef GrGLShaderBuilder INHERITED;
};
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLShaderVar.h b/chromium/third_party/skia/src/gpu/gl/GrGLShaderVar.h
index acbcef3c45d..68c4bbd23a3 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLShaderVar.h
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLShaderVar.h
@@ -267,7 +267,7 @@ public:
ctxInfo.glslGeneration()));
out->append(" ");
}
- out->append(PrecisionString(fPrecision, ctxInfo.binding()));
+ out->append(PrecisionString(fPrecision, ctxInfo.standard()));
GrSLType effectiveType = this->getType();
if (this->isArray()) {
if (this->isUnsizedArray()) {
@@ -302,9 +302,9 @@ public:
fUseUniformFloatArrays ? "" : ".x");
}
- static const char* PrecisionString(Precision p, GrGLBinding binding) {
+ static const char* PrecisionString(Precision p, GrGLStandard standard) {
// Desktop GLSL has added precision qualifiers but they don't do anything.
- if (kES_GrGLBinding == binding) {
+ if (kGLES_GrGLStandard == standard) {
switch (p) {
case kLow_Precision:
return "lowp ";
@@ -315,7 +315,7 @@ public:
case kDefault_Precision:
return "";
default:
- GrCrash("Unexpected precision type.");
+ SkFAIL("Unexpected precision type.");
}
}
return "";
@@ -341,7 +341,7 @@ private:
case kVaryingOut_TypeModifier:
return k110_GrGLSLGeneration == gen ? "varying" : "out";
default:
- GrCrash("Unknown shader variable type modifier.");
+ SkFAIL("Unknown shader variable type modifier.");
return ""; // suppress warning
}
}
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLStencilBuffer.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLStencilBuffer.cpp
index d9322c26dbd..abcb3c4ba01 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLStencilBuffer.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLStencilBuffer.cpp
@@ -13,11 +13,11 @@ GrGLStencilBuffer::~GrGLStencilBuffer() {
this->release();
}
-size_t GrGLStencilBuffer::sizeInBytes() const {
+size_t GrGLStencilBuffer::gpuMemorySize() const {
uint64_t size = this->width();
size *= this->height();
size *= fFormat.fTotalBits;
- size *= GrMax(1,this->numSamples());
+ size *= SkTMax(1,this->numSamples());
return static_cast<size_t>(size / 8);
}
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLStencilBuffer.h b/chromium/third_party/skia/src/gpu/gl/GrGLStencilBuffer.h
index 2bf33ef7b26..1cb0a3301ab 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLStencilBuffer.h
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLStencilBuffer.h
@@ -36,7 +36,7 @@ public:
virtual ~GrGLStencilBuffer();
- virtual size_t sizeInBytes() const SK_OVERRIDE;
+ virtual size_t gpuMemorySize() const SK_OVERRIDE;
GrGLuint renderbufferID() const {
return fRenderbufferID;
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLTexture.h b/chromium/third_party/skia/src/gpu/gl/GrGLTexture.h
index 62052fd16ab..a8800fab55b 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLTexture.h
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLTexture.h
@@ -45,7 +45,7 @@ private:
////////////////////////////////////////////////////////////////////////////////
-class GrGLTexture : public GrTexture {
+class GrGLTexture : public GrTextureImpl {
public:
struct TexParams {
@@ -75,7 +75,7 @@ public:
virtual GrBackendObject getTextureHandle() const SK_OVERRIDE;
- virtual void invalidateCachedState() SK_OVERRIDE { fTexParams.invalidate(); }
+ virtual void textureParamsModified() SK_OVERRIDE { fTexParams.invalidate(); }
// These functions are used to track the texture parameters associated with the texture.
const TexParams& getCachedTexParams(GrGpu::ResetTimestamp* timestamp) const {
@@ -105,7 +105,7 @@ private:
const Desc& textureDesc,
const GrGLRenderTarget::Desc* rtDesc);
- typedef GrTexture INHERITED;
+ typedef GrTextureImpl INHERITED;
};
#endif
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLUniformManager.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLUniformManager.cpp
index 2d0b48a2bed..29679aa409a 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLUniformManager.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLUniformManager.cpp
@@ -16,7 +16,8 @@
(1 == arrayCount && GrGLShaderVar::kNonArray == uni.fArrayCount))
GrGLUniformManager::GrGLUniformManager(GrGpuGL* gpu) : fGpu(gpu) {
- fUsingBindUniform = fGpu->glInterface()->fBindUniformLocation != NULL;
+ // skbug.com/2056
+ fUsingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
}
GrGLUniformManager::UniformHandle GrGLUniformManager::appendUniform(GrSLType type, int arrayCount) {
@@ -233,7 +234,6 @@ void GrGLUniformManager::setMatrix4fv(UniformHandle u,
}
void GrGLUniformManager::setSkMatrix(UniformHandle u, const SkMatrix& matrix) const {
-// GR_STATIC_ASSERT(SK_SCALAR_IS_FLOAT);
GrGLfloat mt[] = {
matrix.get(SkMatrix::kMScaleX),
matrix.get(SkMatrix::kMSkewY),
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLUniformManager.h b/chromium/third_party/skia/src/gpu/gl/GrGLUniformManager.h
index d7438f9ed79..6137bcd9cc8 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLUniformManager.h
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLUniformManager.h
@@ -19,7 +19,7 @@ class SkMatrix;
/** Manages a program's uniforms.
*/
-class GrGLUniformManager {
+class GrGLUniformManager : public SkRefCnt {
public:
// Opaque handle to a uniform
class UniformHandle {
@@ -113,6 +113,8 @@ private:
bool fUsingBindUniform;
SkTArray<Uniform, true> fUniforms;
GrGpuGL* fGpu;
+
+ typedef SkRefCnt INHERITED;
};
#endif
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLUtil.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLUtil.cpp
index 96679fcfd5c..0fa2d2ce188 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLUtil.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLUtil.cpp
@@ -11,7 +11,7 @@
#include <stdio.h>
void GrGLClearErr(const GrGLInterface* gl) {
- while (GR_GL_NO_ERROR != gl->fGetError()) {}
+ while (GR_GL_NO_ERROR != gl->fFunctions.fGetError()) {}
}
namespace {
@@ -75,6 +75,10 @@ bool get_gl_version_for_mesa(int mesaMajorVersion, int* major, int* minor) {
*major = 3;
*minor = 1;
return true;
+ case 10:
+ *major = 3;
+ *minor = 3;
+ return true;
default:
return false;
}
@@ -93,10 +97,10 @@ bool get_gl_version_for_mesa(int mesaMajorVersion, int* major, int* minor) {
///////////////////////////////////////////////////////////////////////////////
-GrGLBinding GrGLGetBindingInUseFromString(const char* versionString) {
+GrGLStandard GrGLGetStandardInUseFromString(const char* versionString) {
if (NULL == versionString) {
- SkDEBUGFAIL("NULL GL version string.");
- return kNone_GrGLBinding;
+ SkDebugf("NULL GL version string.");
+ return kNone_GrGLStandard;
}
int major, minor;
@@ -104,7 +108,7 @@ GrGLBinding GrGLGetBindingInUseFromString(const char* versionString) {
// check for desktop
int n = sscanf(versionString, "%d.%d", &major, &minor);
if (2 == n) {
- return kDesktop_GrGLBinding;
+ return kGL_GrGLStandard;
}
// check for ES 1
@@ -112,15 +116,15 @@ GrGLBinding GrGLGetBindingInUseFromString(const char* versionString) {
n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1, &major, &minor);
if (4 == n) {
// we no longer support ES1.
- return kNone_GrGLBinding;
+ return kNone_GrGLStandard;
}
// check for ES2
n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor);
if (2 == n) {
- return kES_GrGLBinding;
+ return kGLES_GrGLStandard;
}
- return kNone_GrGLBinding;
+ return kNone_GrGLStandard;
}
bool GrGLIsMesaFromVersionString(const char* versionString) {
@@ -135,8 +139,8 @@ bool GrGLIsChromiumFromRendererString(const char* rendererString) {
GrGLVersion GrGLGetVersionFromString(const char* versionString) {
if (NULL == versionString) {
- SkDEBUGFAIL("NULL GL version string.");
- return 0;
+ SkDebugf("NULL GL version string.");
+ return GR_GL_INVALID_VER;
}
int major, minor;
@@ -148,7 +152,7 @@ GrGLVersion GrGLGetVersionFromString(const char* versionString) {
if (get_gl_version_for_mesa(mesaMajor, &major, &minor)) {
return GR_GL_VER(major, minor);
} else {
- return 0;
+ return GR_GL_INVALID_VER;
}
}
@@ -169,13 +173,13 @@ GrGLVersion GrGLGetVersionFromString(const char* versionString) {
return GR_GL_VER(major, minor);
}
- return 0;
+ return GR_GL_INVALID_VER;
}
GrGLSLVersion GrGLGetGLSLVersionFromString(const char* versionString) {
if (NULL == versionString) {
- SkDEBUGFAIL("NULL GLSL version string.");
- return 0;
+ SkDebugf("NULL GLSL version string.");
+ return GR_GLSL_INVALID_VER;
}
int major, minor;
@@ -198,7 +202,7 @@ GrGLSLVersion GrGLGetGLSLVersionFromString(const char* versionString) {
}
#endif
- return 0;
+ return GR_GLSL_INVALID_VER;
}
GrGLVendor GrGLGetVendorFromString(const char* vendorString) {
@@ -209,7 +213,7 @@ GrGLVendor GrGLGetVendorFromString(const char* vendorString) {
if (0 == strcmp(vendorString, "Imagination Technologies")) {
return kImagination_GrGLVendor;
}
- if (0 == strcmp(vendorString, "Intel")) {
+ if (0 == strncmp(vendorString, "Intel ", 6) || 0 == strcmp(vendorString, "Intel")) {
return kIntel_GrGLVendor;
}
if (0 == strcmp(vendorString, "Qualcomm")) {
@@ -223,17 +227,13 @@ GrGLRenderer GrGLGetRendererFromString(const char* rendererString) {
if (NULL != rendererString) {
if (0 == strcmp(rendererString, "NVIDIA Tegra 3")) {
return kTegra3_GrGLRenderer;
+ } else if (0 == strcmp(rendererString, "NVIDIA Tegra")) {
+ return kTegra2_GrGLRenderer;
}
}
return kOther_GrGLRenderer;
}
-GrGLBinding GrGLGetBindingInUse(const GrGLInterface* gl) {
- const GrGLubyte* v;
- GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION));
- return GrGLGetBindingInUseFromString((const char*) v);
-}
-
GrGLVersion GrGLGetVersion(const GrGLInterface* gl) {
const GrGLubyte* v;
GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION));
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLUtil.h b/chromium/third_party/skia/src/gpu/gl/GrGLUtil.h
index a4fb0e5dba7..73fcec11770 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLUtil.h
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLUtil.h
@@ -18,6 +18,14 @@ class SkMatrix;
typedef uint32_t GrGLVersion;
typedef uint32_t GrGLSLVersion;
+#define GR_GL_VER(major, minor) ((static_cast<int>(major) << 16) | \
+ static_cast<int>(minor))
+#define GR_GLSL_VER(major, minor) ((static_cast<int>(major) << 16) | \
+ static_cast<int>(minor))
+
+#define GR_GL_INVALID_VER GR_GL_VER(0, 0)
+#define GR_GLSL_INVALID_VER GR_GL_VER(0, 0)
+
/**
* The Vendor and Renderer enum values are lazily updated as required.
*/
@@ -31,16 +39,12 @@ enum GrGLVendor {
};
enum GrGLRenderer {
+ kTegra2_GrGLRenderer,
kTegra3_GrGLRenderer,
kOther_GrGLRenderer
};
-#define GR_GL_VER(major, minor) ((static_cast<int>(major) << 16) | \
- static_cast<int>(minor))
-#define GR_GLSL_VER(major, minor) ((static_cast<int>(major) << 16) | \
- static_cast<int>(minor))
-
////////////////////////////////////////////////////////////////////////////////
/**
@@ -78,7 +82,7 @@ enum GrGLRenderer {
// these variants assume caller already has a string from glGetString()
GrGLVersion GrGLGetVersionFromString(const char* versionString);
-GrGLBinding GrGLGetBindingInUseFromString(const char* versionString);
+GrGLStandard GrGLGetStandardInUseFromString(const char* versionString);
GrGLSLVersion GrGLGetGLSLVersionFromString(const char* versionString);
bool GrGLIsMesaFromVersionString(const char* versionString);
GrGLVendor GrGLGetVendorFromString(const char* vendorString);
@@ -86,7 +90,6 @@ GrGLRenderer GrGLGetRendererFromString(const char* rendererString);
bool GrGLIsChromiumFromRendererString(const char* rendererString);
// these variants call glGetString()
-GrGLBinding GrGLGetBindingInUse(const GrGLInterface*);
GrGLVersion GrGLGetVersion(const GrGLInterface*);
GrGLSLVersion GrGLGetGLSLVersion(const GrGLInterface*);
GrGLVendor GrGLGetVendor(const GrGLInterface*);
@@ -155,7 +158,7 @@ template<int MatrixSize> void GrGLGetMatrix(GrGLfloat* dest, const SkMatrix& src
#define GR_GL_CALL_NOERRCHECK(IFACE, X) \
do { \
GR_GL_CALLBACK_IMPL(IFACE); \
- (IFACE)->f##X; \
+ (IFACE)->fFunctions.f##X; \
GR_GL_LOG_CALLS_IMPL(X); \
} while (false)
@@ -170,11 +173,11 @@ template<int MatrixSize> void GrGLGetMatrix(GrGLfloat* dest, const SkMatrix& src
#define GR_GL_CALL_RET_NOERRCHECK(IFACE, RET, X) \
do { \
GR_GL_CALLBACK_IMPL(IFACE); \
- (RET) = (IFACE)->f##X; \
+ (RET) = (IFACE)->fFunctions.f##X; \
GR_GL_LOG_CALLS_IMPL(X); \
} while (false)
// call glGetError without doing a redundant error check or logging.
-#define GR_GL_GET_ERROR(IFACE) (IFACE)->fGetError()
+#define GR_GL_GET_ERROR(IFACE) (IFACE)->fFunctions.fGetError()
#endif
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLVertexArray.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLVertexArray.cpp
index 605ec3327b3..66feb820530 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLVertexArray.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLVertexArray.cpp
@@ -49,39 +49,7 @@ void GrGLAttribArrayState::set(const GrGpuGL* gpu,
}
}
-void GrGLAttribArrayState::setFixedFunctionVertexArray(const GrGpuGL* gpu,
- GrGLVertexBuffer* buffer,
- GrGLint size,
- GrGLenum type,
- GrGLsizei stride,
- GrGLvoid* offset) {
- SkASSERT(gpu->glCaps().fixedFunctionSupport());
- AttribArrayState* array = &fFixedFunctionVertexArray;
- if (!array->fEnableIsValid || !array->fEnabled) {
- GR_GL_CALL(gpu->glInterface(), EnableClientState(GR_GL_VERTEX_ARRAY));
- array->fEnableIsValid = true;
- array->fEnabled = true;
- }
- if (!array->fAttribPointerIsValid ||
- array->fVertexBufferID != buffer->bufferID() ||
- array->fSize != size ||
- array->fStride != stride ||
- array->fOffset != offset) {
-
- buffer->bind();
- GR_GL_CALL(gpu->glInterface(), VertexPointer(size,
- type,
- stride,
- offset));
- array->fAttribPointerIsValid = true;
- array->fVertexBufferID = buffer->bufferID();
- array->fSize = size;
- array->fStride = stride;
- array->fOffset = offset;
- }
-}
-
-void GrGLAttribArrayState::disableUnusedArrays(const GrGpuGL* gpu, uint64_t usedMask, bool usingFFVertexArray) {
+void GrGLAttribArrayState::disableUnusedArrays(const GrGpuGL* gpu, uint64_t usedMask) {
int count = fAttribArrayStates.count();
for (int i = 0; i < count; ++i) {
if (!(usedMask & 0x1)) {
@@ -96,41 +64,12 @@ void GrGLAttribArrayState::disableUnusedArrays(const GrGpuGL* gpu, uint64_t used
// if the count is greater than 64 then this will become 0 and we will disable arrays 64+.
usedMask >>= 1;
}
-
- // Deal with fixed-function vertex arrays.
- if (gpu->glCaps().fixedFunctionSupport()) {
- if (!usingFFVertexArray) {
- if (!fFixedFunctionVertexArray.fEnableIsValid || fFixedFunctionVertexArray.fEnabled) {
- GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_VERTEX_ARRAY));
- fFixedFunctionVertexArray.fEnableIsValid = true;
- fFixedFunctionVertexArray.fEnabled = false;
- }
- } else {
- SkASSERT(fFixedFunctionVertexArray.fEnableIsValid && fFixedFunctionVertexArray.fEnabled);
- }
- // When we use fixed function vertex processing we always use the vertex array and none of
- // the other arrays.
- if (!fUnusedFixedFunctionArraysDisabled) {
- GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_NORMAL_ARRAY));
- GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_COLOR_ARRAY));
- GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_SECONDARY_COLOR_ARRAY));
- GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_INDEX_ARRAY));
- GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_EDGE_FLAG_ARRAY));
- for (int i = 0; i < gpu->glCaps().maxFixedFunctionTextureCoords(); ++i) {
- GR_GL_CALL(gpu->glInterface(), ClientActiveTexture(GR_GL_TEXTURE0 + i));
- GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_TEXTURE_COORD_ARRAY));
- }
- fUnusedFixedFunctionArraysDisabled = true;
- }
- } else {
- SkASSERT(!usingFFVertexArray);
- }
}
///////////////////////////////////////////////////////////////////////////////////////////////////
GrGLVertexArray::GrGLVertexArray(GrGpuGL* gpu, GrGLint id, int attribCount)
- : GrResource(gpu, false)
+ : INHERITED(gpu, false)
, fID(id)
, fAttribArrays(attribCount)
, fIndexBufferIDIsValid(false) {
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLVertexArray.h b/chromium/third_party/skia/src/gpu/gl/GrGLVertexArray.h
index 5cc7b5fd5be..0e5bffe4c1f 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLVertexArray.h
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLVertexArray.h
@@ -8,7 +8,7 @@
#ifndef GrGLVertexArray_DEFINED
#define GrGLVertexArray_DEFINED
-#include "GrResource.h"
+#include "GrGpuObject.h"
#include "GrTypesPriv.h"
#include "gl/GrGLDefines.h"
#include "gl/GrGLFunctions.h"
@@ -51,9 +51,6 @@ class GrGLAttribArrayState {
public:
explicit GrGLAttribArrayState(int arrayCount = 0) {
this->resize(arrayCount);
- // glVertexPointer doesn't have a normalization param.
- fFixedFunctionVertexArray.fNormalized = false;
- fUnusedFixedFunctionArraysDisabled = false;
}
void resize(int newCount) {
@@ -77,26 +74,17 @@ public:
GrGLsizei stride,
GrGLvoid* offset);
- void setFixedFunctionVertexArray(const GrGpuGL*,
- GrGLVertexBuffer*,
- GrGLint size,
- GrGLenum type,
- GrGLsizei stride,
- GrGLvoid* offset);
-
/**
* This function disables vertex attribs not present in the mask. It is assumed that the
* GrGLAttribArrayState is tracking the state of the currently bound vertex array object.
*/
- void disableUnusedArrays(const GrGpuGL*, uint64_t usedAttribArrayMask, bool usingFFVertexArray);
+ void disableUnusedArrays(const GrGpuGL*, uint64_t usedAttribArrayMask);
void invalidate() {
int count = fAttribArrayStates.count();
for (int i = 0; i < count; ++i) {
fAttribArrayStates[i].invalidate();
}
- fFixedFunctionVertexArray.invalidate();
- fUnusedFixedFunctionArraysDisabled = false;
}
void notifyVertexBufferDelete(GrGLuint id) {
@@ -107,10 +95,6 @@ public:
fAttribArrayStates[i].invalidate();
}
}
- if (fFixedFunctionVertexArray.fAttribPointerIsValid &&
- id == fFixedFunctionVertexArray.fVertexBufferID) {
- fFixedFunctionVertexArray.invalidate();
- }
}
/**
@@ -140,20 +124,13 @@ private:
};
SkSTArray<16, AttribArrayState, true> fAttribArrayStates;
-
- // Tracks the array specified by glVertexPointer.
- AttribArrayState fFixedFunctionVertexArray;
-
- // Tracks whether we've disabled the other fixed function arrays that we don't
- // use (e.g. glNormalPointer).
- bool fUnusedFixedFunctionArraysDisabled;
};
/**
* This class represents an OpenGL vertex array object. It manages the lifetime of the vertex array
* and is used to track the state of the vertex array to avoid redundant GL calls.
*/
-class GrGLVertexArray : public GrResource {
+class GrGLVertexArray : public GrGpuObject {
public:
GrGLVertexArray(GrGpuGL* gpu, GrGLint id, int attribCount);
@@ -180,7 +157,7 @@ public:
void invalidateCachedState();
- virtual size_t sizeInBytes() const SK_OVERRIDE { return 0; }
+ virtual size_t gpuMemorySize() const SK_OVERRIDE { return 0; }
protected:
virtual void onAbandon() SK_OVERRIDE;
@@ -193,7 +170,7 @@ private:
GrGLuint fIndexBufferID;
bool fIndexBufferIDIsValid;
- typedef GrResource INHERITED;
+ typedef GrGpuObject INHERITED;
};
#endif
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLVertexBuffer.cpp b/chromium/third_party/skia/src/gpu/gl/GrGLVertexBuffer.cpp
index 685166c90b6..a13ad126ecc 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLVertexBuffer.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLVertexBuffer.cpp
@@ -14,43 +14,34 @@ GrGLVertexBuffer::GrGLVertexBuffer(GrGpuGL* gpu, const Desc& desc)
}
void GrGLVertexBuffer::onRelease() {
- if (this->isValid()) {
+ if (!this->wasDestroyed()) {
fImpl.release(this->getGpuGL());
}
INHERITED::onRelease();
}
-
void GrGLVertexBuffer::onAbandon() {
fImpl.abandon();
INHERITED::onAbandon();
}
-void* GrGLVertexBuffer::lock() {
- if (this->isValid()) {
- return fImpl.lock(this->getGpuGL());
+void* GrGLVertexBuffer::onMap() {
+ if (!this->wasDestroyed()) {
+ return fImpl.map(this->getGpuGL());
} else {
return NULL;
}
}
-void* GrGLVertexBuffer::lockPtr() const {
- return fImpl.lockPtr();
-}
-
-void GrGLVertexBuffer::unlock() {
- if (this->isValid()) {
- fImpl.unlock(this->getGpuGL());
+void GrGLVertexBuffer::onUnmap() {
+ if (!this->wasDestroyed()) {
+ fImpl.unmap(this->getGpuGL());
}
}
-bool GrGLVertexBuffer::isLocked() const {
- return fImpl.isLocked();
-}
-
-bool GrGLVertexBuffer::updateData(const void* src, size_t srcSizeInBytes) {
- if (this->isValid()) {
+bool GrGLVertexBuffer::onUpdateData(const void* src, size_t srcSizeInBytes) {
+ if (!this->wasDestroyed()) {
return fImpl.updateData(this->getGpuGL(), src, srcSizeInBytes);
} else {
return false;
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLVertexBuffer.h b/chromium/third_party/skia/src/gpu/gl/GrGLVertexBuffer.h
index 1741adc23d8..db413ac9909 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLVertexBuffer.h
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLVertexBuffer.h
@@ -26,26 +26,22 @@ public:
size_t baseOffset() const { return fImpl.baseOffset(); }
void bind() const {
- if (this->isValid()) {
+ if (!this->wasDestroyed()) {
fImpl.bind(this->getGpuGL());
}
}
- // overrides of GrVertexBuffer
- virtual void* lock();
- virtual void* lockPtr() const;
- virtual void unlock();
- virtual bool isLocked() const;
- virtual bool updateData(const void* src, size_t srcSizeInBytes);
-
protected:
- // overrides of GrResource
virtual void onAbandon() SK_OVERRIDE;
virtual void onRelease() SK_OVERRIDE;
private:
+ virtual void* onMap() SK_OVERRIDE;
+ virtual void onUnmap() SK_OVERRIDE;
+ virtual bool onUpdateData(const void* src, size_t srcSizeInBytes) SK_OVERRIDE;
+
GrGpuGL* getGpuGL() const {
- SkASSERT(this->isValid());
+ SkASSERT(!this->wasDestroyed());
return (GrGpuGL*)(this->getGpu());
}
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGLVertexEffect.h b/chromium/third_party/skia/src/gpu/gl/GrGLVertexEffect.h
index 1b4c7444b40..40b4b34004d 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGLVertexEffect.h
+++ b/chromium/third_party/skia/src/gpu/gl/GrGLVertexEffect.h
@@ -42,7 +42,7 @@ public:
const char* inputColor,
const TransformedCoordsArray& coords,
const TextureSamplerArray& samplers) SK_OVERRIDE {
- GrCrash("GrGLVertexEffect requires GrGLFullShaderBuilder* overload for emitCode().");
+ SkFAIL("GrGLVertexEffect requires GrGLFullShaderBuilder* overload for emitCode().");
}
private:
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGpuGL.cpp b/chromium/third_party/skia/src/gpu/gl/GrGpuGL.cpp
index 4b5221c31b5..f1b6da82613 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGpuGL.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGpuGL.cpp
@@ -7,6 +7,7 @@
#include "GrGpuGL.h"
+#include "GrGLNameAllocator.h"
#include "GrGLStencilBuffer.h"
#include "GrGLPath.h"
#include "GrGLShaderBuilder.h"
@@ -81,7 +82,7 @@ bool GrGpuGL::BlendCoeffReferencesConstant(GrBlendCoeff coeff) {
};
return gCoeffReferencesBlendConst[coeff];
GR_STATIC_ASSERT(kTotalGrBlendCoeffCount ==
- GR_ARRAY_COUNT(gCoeffReferencesBlendConst));
+ SK_ARRAY_COUNT(gCoeffReferencesBlendConst));
GR_STATIC_ASSERT(0 == kZero_GrBlendCoeff);
GR_STATIC_ASSERT(1 == kOne_GrBlendCoeff);
@@ -105,7 +106,7 @@ bool GrGpuGL::BlendCoeffReferencesConstant(GrBlendCoeff coeff) {
// assertion for gXfermodeCoeff2Blend have to be in GrGpu scope
GR_STATIC_ASSERT(kTotalGrBlendCoeffCount ==
- GR_ARRAY_COUNT(gXfermodeCoeff2Blend));
+ SK_ARRAY_COUNT(gXfermodeCoeff2Blend));
}
///////////////////////////////////////////////////////////////////////////////
@@ -117,14 +118,12 @@ GrGpuGL::GrGpuGL(const GrGLContext& ctx, GrContext* context)
, fGLContext(ctx) {
SkASSERT(ctx.isInitialized());
+ fCaps.reset(SkRef(ctx.caps()));
- fCaps.reset(SkRef(ctx.info().caps()));
-
- fHWBoundTextures.reset(ctx.info().caps()->maxFragmentTextureUnits());
- fHWTexGenSettings.reset(ctx.info().caps()->maxFixedFunctionTextureCoords());
+ fHWBoundTextures.reset(this->glCaps().maxFragmentTextureUnits());
+ fHWPathTexGenSettings.reset(this->glCaps().maxFixedFunctionTextureCoords());
GrGLClearErr(fGLContext.interface());
-
if (gPrintStartupSpew) {
const GrGLubyte* vendor;
const GrGLubyte* renderer;
@@ -138,9 +137,11 @@ GrGpuGL::GrGpuGL(const GrGLContext& ctx, GrContext* context)
GrPrintf("------ RENDERER %s\n", renderer);
GrPrintf("------ VERSION %s\n", version);
GrPrintf("------ EXTENSIONS\n");
- ctx.info().extensions().print();
+#if 0 // TODO: Reenable this after GrGLInterface's extensions can be accessed safely.
+ ctx.extensions().print();
+#endif
GrPrintf("\n");
- GrPrintf(ctx.info().caps()->dump().c_str());
+ GrPrintf(this->glCaps().dump().c_str());
}
fProgramCache = SkNEW_ARGS(ProgramCache, (this));
@@ -175,7 +176,7 @@ GrPixelConfig GrGpuGL::preferredReadPixelsConfig(GrPixelConfig readConfig,
GrPixelConfig surfaceConfig) const {
if (GR_GL_RGBA_8888_PIXEL_OPS_SLOW && kRGBA_8888_GrPixelConfig == readConfig) {
return kBGRA_8888_GrPixelConfig;
- } else if (fGLContext.info().isMesa() &&
+ } else if (this->glContext().isMesa() &&
GrBytesPerPixel(readConfig) == 4 &&
GrPixelConfigSwapRAndB(readConfig) == surfaceConfig) {
// Mesa 3D takes a slow path on when reading back BGRA from an RGBA surface and vice-versa.
@@ -203,13 +204,13 @@ bool GrGpuGL::canWriteTexturePixels(const GrTexture* texture, GrPixelConfig srcC
if (kIndex_8_GrPixelConfig == srcConfig || kIndex_8_GrPixelConfig == texture->config()) {
return false;
}
- if (srcConfig != texture->config() && kES_GrGLBinding == this->glBinding()) {
+ if (srcConfig != texture->config() && kGLES_GrGLStandard == this->glStandard()) {
// In general ES2 requires the internal format of the texture and the format of the src
// pixels to match. However, It may or may not be possible to upload BGRA data to a RGBA
// texture. It depends upon which extension added BGRA. The Apple extension allows it
// (BGRA's internal format is RGBA) while the EXT extension does not (BGRA is its own
// internal format).
- if (this->glCaps().bgraFormatSupport() &&
+ if (this->glCaps().isConfigTexturable(kBGRA_8888_GrPixelConfig) &&
!this->glCaps().bgraIsInternalFormat() &&
kBGRA_8888_GrPixelConfig == srcConfig &&
kRGBA_8888_GrPixelConfig == texture->config()) {
@@ -235,7 +236,7 @@ void GrGpuGL::onResetContext(uint32_t resetBits) {
fHWDrawFace = GrDrawState::kInvalid_DrawFace;
fHWDitherEnabled = kUnknown_TriState;
- if (kDesktop_GrGLBinding == this->glBinding()) {
+ if (kGL_GrGLStandard == this->glStandard()) {
// Desktop-only state that we never change
if (!this->glCaps().isCoreProfile()) {
GL_CALL(Disable(GR_GL_POINT_SMOOTH));
@@ -300,30 +301,20 @@ void GrGpuGL::onResetContext(uint32_t resetBits) {
fHWBoundRenderTarget = NULL;
}
- if (resetBits & (kFixedFunction_GrGLBackendState | kPathRendering_GrGLBackendState)) {
- if (this->glCaps().fixedFunctionSupport()) {
+ if (resetBits & kPathRendering_GrGLBackendState) {
+ if (this->caps()->pathRenderingSupport()) {
fHWProjectionMatrixState.invalidate();
// we don't use the model view matrix.
- GL_CALL(MatrixMode(GR_GL_MODELVIEW));
- GL_CALL(LoadIdentity());
+ GL_CALL(MatrixLoadIdentity(GR_GL_MODELVIEW));
for (int i = 0; i < this->glCaps().maxFixedFunctionTextureCoords(); ++i) {
- GL_CALL(ActiveTexture(GR_GL_TEXTURE0 + i));
- GL_CALL(Disable(GR_GL_TEXTURE_GEN_S));
- GL_CALL(Disable(GR_GL_TEXTURE_GEN_T));
- GL_CALL(Disable(GR_GL_TEXTURE_GEN_Q));
- GL_CALL(Disable(GR_GL_TEXTURE_GEN_R));
- if (this->caps()->pathRenderingSupport()) {
- GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL));
- }
- fHWTexGenSettings[i].fMode = GR_GL_NONE;
- fHWTexGenSettings[i].fNumComponents = 0;
+ GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL));
+ fHWPathTexGenSettings[i].fMode = GR_GL_NONE;
+ fHWPathTexGenSettings[i].fNumComponents = 0;
}
- fHWActiveTexGenSets = 0;
- }
- if (this->caps()->pathRenderingSupport()) {
- fHWPathStencilSettings.invalidate();
+ fHWActivePathTexGenSets = 0;
}
+ fHWPathStencilSettings.invalidate();
}
// we assume these values
@@ -486,14 +477,24 @@ bool GrGpuGL::onWriteTexturePixels(GrTexture* texture,
desc.fTextureID = glTex->textureID();
desc.fOrigin = glTex->origin();
- if (this->uploadTexData(desc, false,
- left, top, width, height,
- config, buffer, rowBytes)) {
- texture->dirtyMipMaps(true);
- return true;
+ bool success = false;
+ if (GrPixelConfigIsCompressed(desc.fConfig)) {
+ // We check that config == desc.fConfig in GrGpuGL::canWriteTexturePixels()
+ SkASSERT(config == desc.fConfig);
+ success = this->uploadCompressedTexData(desc, buffer, false,
+ left, top, width, height);
} else {
- return false;
+ success = this->uploadTexData(desc, false,
+ left, top, width, height,
+ config, buffer, rowBytes);
}
+
+ if (success) {
+ texture->impl()->dirtyMipMaps(true);
+ return true;
+ }
+
+ return false;
}
namespace {
@@ -541,6 +542,9 @@ bool GrGpuGL::uploadTexData(const GrGLTexture::Desc& desc,
size_t rowBytes) {
SkASSERT(NULL != data || isNewTexture);
+ // If we're uploading compressed data then we should be using uploadCompressedTexData
+ SkASSERT(!GrPixelConfigIsCompressed(dataConfig));
+
size_t bpp = GrBytesPerPixel(dataConfig);
if (!adjust_pixel_ops_params(desc.fWidth, desc.fHeight, bpp, &left, &top,
&width, &height, &data, &rowBytes)) {
@@ -558,10 +562,10 @@ bool GrGpuGL::uploadTexData(const GrGLTexture::Desc& desc,
// texture storage.
bool useTexStorage = false &&
isNewTexture &&
- desc.fConfig != kIndex_8_GrPixelConfig &&
+ kIndex_8_GrPixelConfig != desc.fConfig &&
this->glCaps().texStorageSupport();
- if (useTexStorage && kDesktop_GrGLBinding == this->glBinding()) {
+ if (useTexStorage && kGL_GrGLStandard == this->glStandard()) {
// 565 is not a sized internal format on desktop GL. So on desktop with
// 565 we always use an unsized internal format to let the system pick
// the best sized format to convert the 565 data to. Since TexStorage
@@ -708,20 +712,85 @@ bool GrGpuGL::uploadTexData(const GrGLTexture::Desc& desc,
return succeeded;
}
+// TODO: This function is using a lot of wonky semantics like, if width == -1
+// then set width = desc.fWdith ... blah. A better way to do it might be to
+// create a CompressedTexData struct that takes a desc/ptr and figures out
+// the proper upload semantics. Then users can construct this function how they
+// see fit if they want to go against the "standard" way to do it.
+bool GrGpuGL::uploadCompressedTexData(const GrGLTexture::Desc& desc,
+ const void* data,
+ bool isNewTexture,
+ int left, int top, int width, int height) {
+ SkASSERT(NULL != data || isNewTexture);
+
+ // No support for software flip y, yet...
+ SkASSERT(kBottomLeft_GrSurfaceOrigin != desc.fOrigin);
+
+ if (-1 == width) {
+ width = desc.fWidth;
+ }
+#ifdef SK_DEBUG
+ else {
+ SkASSERT(width <= desc.fWidth);
+ }
+#endif
+
+ if (-1 == height) {
+ height = desc.fHeight;
+ }
+#ifdef SK_DEBUG
+ else {
+ SkASSERT(height <= desc.fHeight);
+ }
+#endif
+
+ // Make sure that the width and height that we pass to OpenGL
+ // is a multiple of the block size.
+ int dataSize = GrCompressedFormatDataSize(desc.fConfig, width, height);
+
+ // We only need the internal format for compressed 2D textures.
+ GrGLenum internalFormat = 0;
+ if (!this->configToGLFormats(desc.fConfig, false, &internalFormat, NULL, NULL)) {
+ return false;
+ }
+
+ bool succeeded = true;
+ CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
+
+ if (isNewTexture) {
+ GL_ALLOC_CALL(this->glInterface(),
+ CompressedTexImage2D(GR_GL_TEXTURE_2D,
+ 0, // level
+ internalFormat,
+ width, height,
+ 0, // border
+ dataSize,
+ data));
+ } else {
+ GL_ALLOC_CALL(this->glInterface(),
+ CompressedTexSubImage2D(GR_GL_TEXTURE_2D,
+ 0, // level
+ left, top,
+ width, height,
+ internalFormat,
+ dataSize,
+ data));
+ }
+
+ GrGLenum error = check_alloc_error(desc, this->glInterface());
+ if (error != GR_GL_NO_ERROR) {
+ succeeded = false;
+ }
+ return succeeded;
+}
+
static bool renderbuffer_storage_msaa(GrGLContext& ctx,
int sampleCount,
GrGLenum format,
int width, int height) {
CLEAR_ERROR_BEFORE_ALLOC(ctx.interface());
- SkASSERT(GrGLCaps::kNone_MSFBOType != ctx.info().caps()->msFBOType());
-#if GR_GL_IGNORE_ES3_MSAA
- GL_ALLOC_CALL(ctx.interface(),
- RenderbufferStorageMultisample(GR_GL_RENDERBUFFER,
- sampleCount,
- format,
- width, height));
-#else
- switch (ctx.info().caps()->msFBOType()) {
+ SkASSERT(GrGLCaps::kNone_MSFBOType != ctx.caps()->msFBOType());
+ switch (ctx.caps()->msFBOType()) {
case GrGLCaps::kDesktop_ARB_MSFBOType:
case GrGLCaps::kDesktop_EXT_MSFBOType:
case GrGLCaps::kES_3_0_MSFBOType:
@@ -747,10 +816,9 @@ static bool renderbuffer_storage_msaa(GrGLContext& ctx,
width, height));
break;
case GrGLCaps::kNone_MSFBOType:
- GrCrash("Shouldn't be here if we don't support multisampled renderbuffers.");
+ SkFAIL("Shouldn't be here if we don't support multisampled renderbuffers.");
break;
}
-#endif
return (GR_GL_NO_ERROR == CHECK_ALLOC_ERROR(ctx.interface()));;
}
@@ -787,7 +855,7 @@ bool GrGpuGL::createRenderTargetObjects(int width, int height,
!desc->fMSColorRenderbufferID ||
!this->configToGLFormats(desc->fConfig,
// ES2 and ES3 require sized internal formats for rb storage.
- kES_GrGLBinding == this->glBinding(),
+ kGLES_GrGLStandard == this->glStandard(),
&msColorFormat,
NULL,
NULL)) {
@@ -820,7 +888,7 @@ bool GrGpuGL::createRenderTargetObjects(int width, int height,
if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
goto FAILED;
}
- fGLContext.info().caps()->markConfigAsValidColorAttachment(desc->fConfig);
+ fGLContext.caps()->markConfigAsValidColorAttachment(desc->fConfig);
}
}
GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, desc->fTexFBOID));
@@ -842,7 +910,7 @@ bool GrGpuGL::createRenderTargetObjects(int width, int height,
if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
goto FAILED;
}
- fGLContext.info().caps()->markConfigAsValidColorAttachment(desc->fConfig);
+ fGLContext.caps()->markConfigAsValidColorAttachment(desc->fConfig);
}
return true;
@@ -887,7 +955,7 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
return return_null_texture();
}
// If the sample count exceeds the max then we clamp it.
- glTexDesc.fSampleCnt = GrMin(desc.fSampleCnt, this->caps()->maxSampleCount());
+ glTexDesc.fSampleCnt = SkTMin(desc.fSampleCnt, this->caps()->maxSampleCount());
glTexDesc.fFlags = desc.fFlags;
glTexDesc.fWidth = desc.fWidth;
@@ -995,6 +1063,80 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
return tex;
}
+GrTexture* GrGpuGL::onCreateCompressedTexture(const GrTextureDesc& desc,
+ const void* srcData) {
+
+ if(SkToBool(desc.fFlags & kRenderTarget_GrTextureFlagBit)) {
+ return return_null_texture();
+ }
+
+ // Make sure that we're not flipping Y.
+ GrSurfaceOrigin texOrigin = resolve_origin(desc.fOrigin, false);
+ if (kBottomLeft_GrSurfaceOrigin == texOrigin) {
+ return return_null_texture();
+ }
+
+ GrGLTexture::Desc glTexDesc;
+
+ glTexDesc.fFlags = desc.fFlags;
+ glTexDesc.fWidth = desc.fWidth;
+ glTexDesc.fHeight = desc.fHeight;
+ glTexDesc.fConfig = desc.fConfig;
+ glTexDesc.fIsWrapped = false;
+ glTexDesc.fOrigin = texOrigin;
+
+ int maxSize = this->caps()->maxTextureSize();
+ if (glTexDesc.fWidth > maxSize || glTexDesc.fHeight > maxSize) {
+ return return_null_texture();
+ }
+
+ GL_CALL(GenTextures(1, &glTexDesc.fTextureID));
+
+ if (!glTexDesc.fTextureID) {
+ return return_null_texture();
+ }
+
+ this->setScratchTextureUnit();
+ GL_CALL(BindTexture(GR_GL_TEXTURE_2D, glTexDesc.fTextureID));
+
+ // Some drivers like to know filter/wrap before seeing glTexImage2D. Some
+ // drivers have a bug where an FBO won't be complete if it includes a
+ // texture that is not mipmap complete (considering the filter in use).
+ GrGLTexture::TexParams initialTexParams;
+ // we only set a subset here so invalidate first
+ initialTexParams.invalidate();
+ initialTexParams.fMinFilter = GR_GL_NEAREST;
+ initialTexParams.fMagFilter = GR_GL_NEAREST;
+ initialTexParams.fWrapS = GR_GL_CLAMP_TO_EDGE;
+ initialTexParams.fWrapT = GR_GL_CLAMP_TO_EDGE;
+ GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
+ GR_GL_TEXTURE_MAG_FILTER,
+ initialTexParams.fMagFilter));
+ GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
+ GR_GL_TEXTURE_MIN_FILTER,
+ initialTexParams.fMinFilter));
+ GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
+ GR_GL_TEXTURE_WRAP_S,
+ initialTexParams.fWrapS));
+ GL_CALL(TexParameteri(GR_GL_TEXTURE_2D,
+ GR_GL_TEXTURE_WRAP_T,
+ initialTexParams.fWrapT));
+
+ if (!this->uploadCompressedTexData(glTexDesc, srcData)) {
+ GL_CALL(DeleteTextures(1, &glTexDesc.fTextureID));
+ return return_null_texture();
+ }
+
+ GrGLTexture* tex;
+ tex = SkNEW_ARGS(GrGLTexture, (this, glTexDesc));
+ tex->setCachedTexParams(initialTexParams, this->getResetTimestamp());
+#ifdef TRACE_TEXTURE_CREATION
+ GrPrintf("--- new compressed texture [%d] size=(%d %d) config=%d\n",
+ glTexDesc.fTextureID, desc.fWidth, desc.fHeight, desc.fConfig);
+#endif
+ return tex;
+}
+
namespace {
const GrGLuint kUnknownBitCount = GrGLStencilBuffer::kUnknownBitCount;
@@ -1138,7 +1280,7 @@ bool GrGpuGL::attachStencilBufferToRenderTarget(GrStencilBuffer* sb, GrRenderTar
}
return false;
} else {
- fGLContext.info().caps()->markColorConfigAndStencilFormatAsVerified(
+ fGLContext.caps()->markColorConfigAndStencilFormatAsVerified(
rt->config(),
glsb->format());
}
@@ -1303,6 +1445,60 @@ void GrGpuGL::onClear(const SkIRect* rect, GrColor color, bool canIgnoreRect) {
GL_CALL(Clear(GR_GL_COLOR_BUFFER_BIT));
}
+void GrGpuGL::discard(GrRenderTarget* renderTarget) {
+ if (!this->caps()->discardRenderTargetSupport()) {
+ return;
+ }
+ if (NULL == renderTarget) {
+ renderTarget = this->drawState()->getRenderTarget();
+ if (NULL == renderTarget) {
+ return;
+ }
+ }
+
+ GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(renderTarget);
+ if (renderTarget != fHWBoundRenderTarget) {
+ fHWBoundRenderTarget = NULL;
+ GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, glRT->renderFBOID()));
+ }
+ switch (this->glCaps().invalidateFBType()) {
+ case GrGLCaps::kNone_FBFetchType:
+ SkFAIL("Should never get here.");
+ break;
+ case GrGLCaps::kInvalidate_InvalidateFBType:
+ if (0 == glRT->renderFBOID()) {
+ // When rendering to the default framebuffer the legal values for attachments
+ // are GL_COLOR, GL_DEPTH, GL_STENCIL, ... rather than the various FBO attachment
+ // types.
+ static const GrGLenum attachments[] = { GR_GL_COLOR };
+ GL_CALL(InvalidateFramebuffer(GR_GL_FRAMEBUFFER, SK_ARRAY_COUNT(attachments),
+ attachments));
+ } else {
+ static const GrGLenum attachments[] = { GR_GL_COLOR_ATTACHMENT0 };
+ GL_CALL(InvalidateFramebuffer(GR_GL_FRAMEBUFFER, SK_ARRAY_COUNT(attachments),
+ attachments));
+ }
+ break;
+ case GrGLCaps::kDiscard_InvalidateFBType: {
+ if (0 == glRT->renderFBOID()) {
+ // When rendering to the default framebuffer the legal values for attachments
+ // are GL_COLOR, GL_DEPTH, GL_STENCIL, ... rather than the various FBO attachment
+ // types. See glDiscardFramebuffer() spec.
+ static const GrGLenum attachments[] = { GR_GL_COLOR };
+ GL_CALL(DiscardFramebuffer(GR_GL_FRAMEBUFFER, SK_ARRAY_COUNT(attachments),
+ attachments));
+ } else {
+ static const GrGLenum attachments[] = { GR_GL_COLOR_ATTACHMENT0 };
+ GL_CALL(DiscardFramebuffer(GR_GL_FRAMEBUFFER, SK_ARRAY_COUNT(attachments),
+ attachments));
+ }
+ break;
+ }
+ }
+ renderTarget->flagAsResolved();
+}
+
+
void GrGpuGL::clearStencil() {
if (NULL == this->getDrawState().getRenderTarget()) {
return;
@@ -1359,10 +1555,6 @@ void GrGpuGL::clearStencilClip(const SkIRect& rect, bool insideClip) {
fHWStencilSettings.invalidate();
}
-void GrGpuGL::onForceRenderTargetFlush() {
- this->flushRenderTarget(&SkIRect::EmptyIRect());
-}
-
bool GrGpuGL::readPixelsWillPayForYFlip(GrRenderTarget* renderTarget,
int left, int top,
int width, int height,
@@ -1400,8 +1592,13 @@ bool GrGpuGL::onReadPixels(GrRenderTarget* target,
GrPixelConfig config,
void* buffer,
size_t rowBytes) {
- GrGLenum format;
- GrGLenum type;
+ // We cannot read pixels into a compressed buffer
+ if (GrPixelConfigIsCompressed(config)) {
+ return false;
+ }
+
+ GrGLenum format = 0;
+ GrGLenum type = 0;
bool flipY = kBottomLeft_GrSurfaceOrigin == target->origin();
if (!this->configToGLFormats(config, false, NULL, &format, &type)) {
return false;
@@ -1431,7 +1628,7 @@ bool GrGpuGL::onReadPixels(GrRenderTarget* target,
tgt->textureFBOID()));
break;
default:
- GrCrash("Unknown resolve type");
+ SkFAIL("Unknown resolve type");
}
const GrGLIRect& glvp = tgt->getViewport();
@@ -1531,7 +1728,7 @@ void GrGpuGL::flushRenderTarget(const SkIRect* bound) {
// lots of repeated command buffer flushes when the compositor is
// rendering with Ganesh, which is really slow; even too slow for
// Debug mode.
- if (!this->glContext().info().isChromium()) {
+ if (!this->glContext().isChromium()) {
GrGLenum status;
GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
@@ -1551,8 +1748,8 @@ void GrGpuGL::flushRenderTarget(const SkIRect* bound) {
}
GrTexture *texture = rt->asTexture();
- if (texture) {
- texture->dirtyMipMaps(true);
+ if (NULL != texture) {
+ texture->impl()->dirtyMipMaps(true);
}
}
@@ -1591,7 +1788,7 @@ void GrGpuGL::onGpuDraw(const DrawInfo& info) {
size_t indexOffsetInBytes;
this->setupGeometry(info, &indexOffsetInBytes);
- SkASSERT((size_t)info.primitiveType() < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
+ SkASSERT((size_t)info.primitiveType() < SK_ARRAY_COUNT(gPrimitiveType2GLMode));
if (info.isIndexed()) {
GrGLvoid* indices =
@@ -1624,7 +1821,7 @@ void GrGpuGL::onGpuDraw(const DrawInfo& info) {
static GrGLenum gr_stencil_op_to_gl_path_rendering_fill_mode(GrStencilOp op) {
switch (op) {
default:
- GrCrash("Unexpected path fill.");
+ SkFAIL("Unexpected path fill.");
/* fallthrough */;
case kIncClamp_StencilOp:
return GR_GL_COUNT_UP;
@@ -1693,7 +1890,100 @@ void GrGpuGL::onGpuDrawPath(const GrPath* path, SkPath::FillType fill) {
vmi.mapRect(&bounds);
// theoretically could set bloat = 0, instead leave it because of matrix inversion
// precision.
- SkScalar bloat = drawState->getViewMatrix().getMaxStretch() * SK_ScalarHalf;
+ SkScalar bloat = drawState->getViewMatrix().getMaxScale() * SK_ScalarHalf;
+ bounds.outset(bloat, bloat);
+ } else {
+ avmr.setIdentity(drawState);
+ }
+
+ this->drawSimpleRect(bounds, NULL);
+ }
+}
+
+void GrGpuGL::onGpuDrawPaths(int pathCount, const GrPath** paths,
+ const SkMatrix* transforms,
+ SkPath::FillType fill,
+ SkStrokeRec::Style stroke) {
+ SkASSERT(this->caps()->pathRenderingSupport());
+ SkASSERT(NULL != this->drawState()->getRenderTarget());
+ SkASSERT(NULL != this->drawState()->getRenderTarget()->getStencilBuffer());
+ SkASSERT(!fCurrentProgram->hasVertexShader());
+ SkASSERT(stroke != SkStrokeRec::kHairline_Style);
+
+ SkAutoMalloc pathData(pathCount * sizeof(GrGLuint));
+ SkAutoMalloc transformData(pathCount * sizeof(GrGLfloat) * 6);
+ GrGLfloat* transformValues =
+ reinterpret_cast<GrGLfloat*>(transformData.get());
+ GrGLuint* pathIDs = reinterpret_cast<GrGLuint*>(pathData.get());
+
+ for (int i = 0; i < pathCount; ++i) {
+ SkASSERT(transforms[i].asAffine(NULL));
+ const SkMatrix& m = transforms[i];
+ transformValues[i * 6] = m.getScaleX();
+ transformValues[i * 6 + 1] = m.getSkewY();
+ transformValues[i * 6 + 2] = m.getSkewX();
+ transformValues[i * 6 + 3] = m.getScaleY();
+ transformValues[i * 6 + 4] = m.getTranslateX();
+ transformValues[i * 6 + 5] = m.getTranslateY();
+ pathIDs[i] = static_cast<const GrGLPath*>(paths[i])->pathID();
+ }
+
+ flushPathStencilSettings(fill);
+
+ SkPath::FillType nonInvertedFill =
+ SkPath::ConvertToNonInverseFillType(fill);
+
+ SkASSERT(!fHWPathStencilSettings.isTwoSided());
+ GrGLenum fillMode =
+ gr_stencil_op_to_gl_path_rendering_fill_mode(
+ fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
+ GrGLint writeMask =
+ fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
+
+ bool doFill = stroke == SkStrokeRec::kFill_Style
+ || stroke == SkStrokeRec::kStrokeAndFill_Style;
+ bool doStroke = stroke == SkStrokeRec::kStroke_Style
+ || stroke == SkStrokeRec::kStrokeAndFill_Style;
+
+ if (doFill) {
+ GL_CALL(StencilFillPathInstanced(pathCount, GR_GL_UNSIGNED_INT,
+ pathIDs, 0,
+ fillMode, writeMask,
+ GR_GL_AFFINE_2D, transformValues));
+ }
+ if (doStroke) {
+ GL_CALL(StencilStrokePathInstanced(pathCount, GR_GL_UNSIGNED_INT,
+ pathIDs, 0,
+ 0xffff, writeMask,
+ GR_GL_AFFINE_2D, transformValues));
+ }
+
+ if (nonInvertedFill == fill) {
+ if (doStroke) {
+ GL_CALL(CoverStrokePathInstanced(
+ pathCount, GR_GL_UNSIGNED_INT, pathIDs, 0,
+ GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
+ GR_GL_AFFINE_2D, transformValues));
+ } else {
+ GL_CALL(CoverFillPathInstanced(
+ pathCount, GR_GL_UNSIGNED_INT, pathIDs, 0,
+ GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
+ GR_GL_AFFINE_2D, transformValues));
+
+ }
+ } else {
+ GrDrawState* drawState = this->drawState();
+ GrDrawState::AutoViewMatrixRestore avmr;
+ SkRect bounds = SkRect::MakeLTRB(0, 0,
+ SkIntToScalar(drawState->getRenderTarget()->width()),
+ SkIntToScalar(drawState->getRenderTarget()->height()));
+ SkMatrix vmi;
+ // mapRect through persp matrix may not be correct
+ if (!drawState->getViewMatrix().hasPerspective() && drawState->getViewInverse(&vmi)) {
+ vmi.mapRect(&bounds);
+ // theoretically could set bloat = 0, instead leave it because of matrix inversion
+ // precision.
+ SkScalar bloat = drawState->getViewMatrix().getMaxScale() * SK_ScalarHalf;
bounds.outset(bloat, bloat);
} else {
avmr.setIdentity(drawState);
@@ -1759,7 +2049,7 @@ GrGLenum gr_to_gl_stencil_func(GrStencilFunc basicFunc) {
GR_GL_EQUAL, // kEqual_StencilFunc,
GR_GL_NOTEQUAL, // kNotEqual_StencilFunc,
};
- GR_STATIC_ASSERT(GR_ARRAY_COUNT(gTable) == kBasicStencilFuncCount);
+ GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kBasicStencilFuncCount);
GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
GR_STATIC_ASSERT(1 == kNever_StencilFunc);
GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
@@ -1784,7 +2074,7 @@ GrGLenum gr_to_gl_stencil_op(GrStencilOp op) {
GR_GL_ZERO, // kZero_StencilOp
GR_GL_INVERT, // kInvert_StencilOp
};
- GR_STATIC_ASSERT(GR_ARRAY_COUNT(gTable) == kStencilOpCount);
+ GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kStencilOpCount);
GR_STATIC_ASSERT(0 == kKeep_StencilOp);
GR_STATIC_ASSERT(1 == kReplace_StencilOp);
GR_STATIC_ASSERT(2 == kIncWrap_StencilOp);
@@ -1868,7 +2158,7 @@ void GrGpuGL::flushAAState(DrawType type) {
#endif
const GrRenderTarget* rt = this->getDrawState().getRenderTarget();
- if (kDesktop_GrGLBinding == this->glBinding()) {
+ if (kGL_GrGLStandard == this->glStandard()) {
// ES doesn't support toggling GL_MULTISAMPLE and doesn't have
// smooth lines.
// we prefer smooth lines over multisampled lines
@@ -2028,12 +2318,15 @@ void GrGpuGL::bindTexture(int unitIdx, const GrTextureParams& params, GrGLTextur
GR_GL_LINEAR,
GR_GL_LINEAR
};
- newTexParams.fMinFilter = glMinFilterModes[params.filterMode()];
- newTexParams.fMagFilter = glMagFilterModes[params.filterMode()];
+ GrTextureParams::FilterMode filterMode = params.filterMode();
+ if (!this->caps()->mipMapSupport() && GrTextureParams::kMipMap_FilterMode == filterMode) {
+ filterMode = GrTextureParams::kBilerp_FilterMode;
+ }
+ newTexParams.fMinFilter = glMinFilterModes[filterMode];
+ newTexParams.fMagFilter = glMagFilterModes[filterMode];
- if (params.filterMode() == GrTextureParams::kMipMap_FilterMode &&
- texture->mipMapsAreDirty()) {
-// GL_CALL(Hint(GR_GL_GENERATE_MIPMAP_HINT,GR_GL_NICEST));
+ if (GrTextureParams::kMipMap_FilterMode == filterMode &&
+ texture->mipMapsAreDirty() && !GrPixelConfigIsCompressed(texture->config())) {
GL_CALL(GenerateMipmap(GR_GL_TEXTURE_2D));
texture->dirtyMipMaps(false);
}
@@ -2072,7 +2365,7 @@ void GrGpuGL::bindTexture(int unitIdx, const GrTextureParams& params, GrGLTextur
oldTexParams.fSwizzleRGBA,
sizeof(newTexParams.fSwizzleRGBA)))) {
this->setTextureUnit(unitIdx);
- if (this->glBinding() == kES_GrGLBinding) {
+ if (this->glStandard() == kGLES_GrGLStandard) {
// ES3 added swizzle support but not GL_TEXTURE_SWIZZLE_RGBA.
const GrGLenum* swizzle = newTexParams.fSwizzleRGBA;
GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_SWIZZLE_R, swizzle[0]));
@@ -2092,7 +2385,7 @@ void GrGpuGL::setProjectionMatrix(const SkMatrix& matrix,
const SkISize& renderTargetSize,
GrSurfaceOrigin renderTargetOrigin) {
- SkASSERT(this->glCaps().fixedFunctionSupport());
+ SkASSERT(this->glCaps().pathRenderingSupport());
if (renderTargetOrigin == fHWProjectionMatrixState.fRenderTargetOrigin &&
renderTargetSize == fHWProjectionMatrixState.fRenderTargetSize &&
@@ -2105,114 +2398,85 @@ void GrGpuGL::setProjectionMatrix(const SkMatrix& matrix,
fHWProjectionMatrixState.fRenderTargetOrigin = renderTargetOrigin;
GrGLfloat glMatrix[4 * 4];
- fHWProjectionMatrixState.getGLMatrix<4>(glMatrix);
- GL_CALL(MatrixMode(GR_GL_PROJECTION));
- GL_CALL(LoadMatrixf(glMatrix));
+ fHWProjectionMatrixState.getRTAdjustedGLMatrix<4>(glMatrix);
+ GL_CALL(MatrixLoadf(GR_GL_PROJECTION, glMatrix));
}
-void GrGpuGL::enableTexGen(int unitIdx,
- TexGenComponents components,
- const GrGLfloat* coefficients) {
- SkASSERT(this->glCaps().fixedFunctionSupport());
- SkASSERT(components >= kS_TexGenComponents && components <= kSTR_TexGenComponents);
+void GrGpuGL::enablePathTexGen(int unitIdx,
+ PathTexGenComponents components,
+ const GrGLfloat* coefficients) {
+ SkASSERT(this->glCaps().pathRenderingSupport());
+ SkASSERT(components >= kS_PathTexGenComponents &&
+ components <= kSTR_PathTexGenComponents);
SkASSERT(this->glCaps().maxFixedFunctionTextureCoords() >= unitIdx);
- if (GR_GL_OBJECT_LINEAR == fHWTexGenSettings[unitIdx].fMode &&
- components == fHWTexGenSettings[unitIdx].fNumComponents &&
- !memcmp(coefficients, fHWTexGenSettings[unitIdx].fCoefficients,
+ if (GR_GL_OBJECT_LINEAR == fHWPathTexGenSettings[unitIdx].fMode &&
+ components == fHWPathTexGenSettings[unitIdx].fNumComponents &&
+ !memcmp(coefficients, fHWPathTexGenSettings[unitIdx].fCoefficients,
3 * components * sizeof(GrGLfloat))) {
return;
}
this->setTextureUnit(unitIdx);
- if (GR_GL_OBJECT_LINEAR != fHWTexGenSettings[unitIdx].fMode) {
- for (int i = 0; i < 4; i++) {
- GL_CALL(TexGeni(GR_GL_S + i, GR_GL_TEXTURE_GEN_MODE, GR_GL_OBJECT_LINEAR));
- }
- fHWTexGenSettings[unitIdx].fMode = GR_GL_OBJECT_LINEAR;
- }
+ fHWPathTexGenSettings[unitIdx].fNumComponents = components;
+ GL_CALL(PathTexGen(GR_GL_TEXTURE0 + unitIdx,
+ GR_GL_OBJECT_LINEAR,
+ components,
+ coefficients));
- for (int i = fHWTexGenSettings[unitIdx].fNumComponents; i < components; i++) {
- GL_CALL(Enable(GR_GL_TEXTURE_GEN_S + i));
- }
- for (int i = components; i < fHWTexGenSettings[unitIdx].fNumComponents; i++) {
- GL_CALL(Disable(GR_GL_TEXTURE_GEN_S + i));
- }
- fHWTexGenSettings[unitIdx].fNumComponents = components;
-
- for (int i = 0; i < components; i++) {
- GrGLfloat plane[] = {coefficients[0 + 3 * i],
- coefficients[1 + 3 * i],
- 0,
- coefficients[2 + 3 * i]};
- GL_CALL(TexGenfv(GR_GL_S + i, GR_GL_OBJECT_PLANE, plane));
- }
-
- if (this->caps()->pathRenderingSupport()) {
- GL_CALL(PathTexGen(GR_GL_TEXTURE0 + unitIdx,
- GR_GL_OBJECT_LINEAR,
- components,
- coefficients));
- }
-
- memcpy(fHWTexGenSettings[unitIdx].fCoefficients, coefficients,
+ memcpy(fHWPathTexGenSettings[unitIdx].fCoefficients, coefficients,
3 * components * sizeof(GrGLfloat));
}
-void GrGpuGL::enableTexGen(int unitIdx, TexGenComponents components, const SkMatrix& matrix) {
+void GrGpuGL::enablePathTexGen(int unitIdx, PathTexGenComponents components,
+ const SkMatrix& matrix) {
GrGLfloat coefficients[3 * 3];
- SkASSERT(this->glCaps().fixedFunctionSupport());
- SkASSERT(components >= kS_TexGenComponents && components <= kSTR_TexGenComponents);
+ SkASSERT(this->glCaps().pathRenderingSupport());
+ SkASSERT(components >= kS_PathTexGenComponents &&
+ components <= kSTR_PathTexGenComponents);
coefficients[0] = SkScalarToFloat(matrix[SkMatrix::kMScaleX]);
coefficients[1] = SkScalarToFloat(matrix[SkMatrix::kMSkewX]);
coefficients[2] = SkScalarToFloat(matrix[SkMatrix::kMTransX]);
- if (components >= kST_TexGenComponents) {
+ if (components >= kST_PathTexGenComponents) {
coefficients[3] = SkScalarToFloat(matrix[SkMatrix::kMSkewY]);
coefficients[4] = SkScalarToFloat(matrix[SkMatrix::kMScaleY]);
coefficients[5] = SkScalarToFloat(matrix[SkMatrix::kMTransY]);
}
- if (components >= kSTR_TexGenComponents) {
+ if (components >= kSTR_PathTexGenComponents) {
coefficients[6] = SkScalarToFloat(matrix[SkMatrix::kMPersp0]);
coefficients[7] = SkScalarToFloat(matrix[SkMatrix::kMPersp1]);
coefficients[8] = SkScalarToFloat(matrix[SkMatrix::kMPersp2]);
}
- enableTexGen(unitIdx, components, coefficients);
+ enablePathTexGen(unitIdx, components, coefficients);
}
-void GrGpuGL::flushTexGenSettings(int numUsedTexCoordSets) {
- SkASSERT(this->glCaps().fixedFunctionSupport());
+void GrGpuGL::flushPathTexGenSettings(int numUsedTexCoordSets) {
+ SkASSERT(this->glCaps().pathRenderingSupport());
SkASSERT(this->glCaps().maxFixedFunctionTextureCoords() >= numUsedTexCoordSets);
- // Only write the inactive tex gens, since active tex gens were written
- // when they were enabled.
+ // Only write the inactive path tex gens, since active path tex gens were
+ // written when they were enabled.
SkDEBUGCODE(
for (int i = 0; i < numUsedTexCoordSets; i++) {
- SkASSERT(0 != fHWTexGenSettings[i].fNumComponents);
+ SkASSERT(0 != fHWPathTexGenSettings[i].fNumComponents);
}
);
- for (int i = numUsedTexCoordSets; i < fHWActiveTexGenSets; i++) {
- SkASSERT(0 != fHWTexGenSettings[i].fNumComponents);
+ for (int i = numUsedTexCoordSets; i < fHWActivePathTexGenSets; i++) {
+ SkASSERT(0 != fHWPathTexGenSettings[i].fNumComponents);
this->setTextureUnit(i);
- for (int j = 0; j < fHWTexGenSettings[i].fNumComponents; j++) {
- GL_CALL(Disable(GR_GL_TEXTURE_GEN_S + j));
- }
-
- if (this->caps()->pathRenderingSupport()) {
- GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL));
- }
-
- fHWTexGenSettings[i].fNumComponents = 0;
+ GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL));
+ fHWPathTexGenSettings[i].fNumComponents = 0;
}
- fHWActiveTexGenSets = numUsedTexCoordSets;
+ fHWActivePathTexGenSets = numUsedTexCoordSets;
}
void GrGpuGL::flushMiscFixedFunctionState() {
@@ -2258,7 +2522,7 @@ void GrGpuGL::flushMiscFixedFunctionState() {
GL_CALL(Disable(GR_GL_CULL_FACE));
break;
default:
- GrCrash("Unknown draw face.");
+ SkFAIL("Unknown draw face.");
}
fHWDrawFace = drawState.getDrawFace();
}
@@ -2280,6 +2544,39 @@ void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
}
}
+
+GrGLuint GrGpuGL::createGLPathObject() {
+ if (NULL == fPathNameAllocator.get()) {
+ static const int range = 65536;
+ GrGLuint firstName;
+ GL_CALL_RET(firstName, GenPaths(range));
+ fPathNameAllocator.reset(SkNEW_ARGS(GrGLNameAllocator, (firstName, firstName + range)));
+ }
+
+ GrGLuint name = fPathNameAllocator->allocateName();
+ if (0 == name) {
+ // Our reserved path names are all in use. Fall back on GenPaths.
+ GL_CALL_RET(name, GenPaths(1));
+ }
+
+ return name;
+}
+
+void GrGpuGL::deleteGLPathObject(GrGLuint name) {
+ if (NULL == fPathNameAllocator.get() ||
+ name < fPathNameAllocator->firstName() ||
+ name >= fPathNameAllocator->endName()) {
+ // If we aren't inside fPathNameAllocator's range then this name was
+ // generated by the GenPaths fallback (or else the name is unallocated).
+ GL_CALL(DeletePaths(name, 1));
+ return;
+ }
+
+ // Make the path empty to save memory, but don't free the name in the driver.
+ GL_CALL(PathCommands(name, 0, NULL, 0, GR_GL_FLOAT, NULL));
+ fPathNameAllocator->free(name);
+}
+
bool GrGpuGL::configToGLFormats(GrPixelConfig config,
bool getSizedInternalFormat,
GrGLenum* internalFormat,
@@ -2296,6 +2593,10 @@ bool GrGpuGL::configToGLFormats(GrPixelConfig config,
externalType = &dontCare;
}
+ if(!this->glCaps().isConfigTexturable(config)) {
+ return false;
+ }
+
switch (config) {
case kRGBA_8888_GrPixelConfig:
*internalFormat = GR_GL_RGBA;
@@ -2308,9 +2609,6 @@ bool GrGpuGL::configToGLFormats(GrPixelConfig config,
*externalType = GR_GL_UNSIGNED_BYTE;
break;
case kBGRA_8888_GrPixelConfig:
- if (!this->glCaps().bgraFormatSupport()) {
- return false;
- }
if (this->glCaps().bgraIsInternalFormat()) {
if (getSizedInternalFormat) {
*internalFormat = GR_GL_BGRA8;
@@ -2331,7 +2629,7 @@ bool GrGpuGL::configToGLFormats(GrPixelConfig config,
*internalFormat = GR_GL_RGB;
*externalFormat = GR_GL_RGB;
if (getSizedInternalFormat) {
- if (this->glBinding() == kDesktop_GrGLBinding) {
+ if (this->glStandard() == kGL_GrGLStandard) {
return false;
} else {
*internalFormat = GR_GL_RGB565;
@@ -2352,17 +2650,12 @@ bool GrGpuGL::configToGLFormats(GrPixelConfig config,
*externalType = GR_GL_UNSIGNED_SHORT_4_4_4_4;
break;
case kIndex_8_GrPixelConfig:
- if (this->caps()->eightBitPaletteSupport()) {
- *internalFormat = GR_GL_PALETTE8_RGBA8;
- // glCompressedTexImage doesn't take external params
- *externalFormat = GR_GL_PALETTE8_RGBA8;
- // no sized/unsized internal format distinction here
- *internalFormat = GR_GL_PALETTE8_RGBA8;
- // unused with CompressedTexImage
- *externalType = GR_GL_UNSIGNED_BYTE;
- } else {
- return false;
- }
+ // glCompressedTexImage doesn't take external params
+ *externalFormat = GR_GL_PALETTE8_RGBA8;
+ // no sized/unsized internal format distinction here
+ *internalFormat = GR_GL_PALETTE8_RGBA8;
+ // unused with CompressedTexImage
+ *externalType = GR_GL_UNSIGNED_BYTE;
break;
case kAlpha_8_GrPixelConfig:
if (this->glCaps().textureRedSupport()) {
@@ -2385,6 +2678,22 @@ bool GrGpuGL::configToGLFormats(GrPixelConfig config,
*externalType = GR_GL_UNSIGNED_BYTE;
}
break;
+ case kETC1_GrPixelConfig:
+ *internalFormat = GR_GL_COMPRESSED_RGB8_ETC1;
+ break;
+ case kLATC_GrPixelConfig:
+ switch(this->glCaps().latcAlias()) {
+ case GrGLCaps::kLATC_LATCAlias:
+ *internalFormat = GR_GL_COMPRESSED_LUMINANCE_LATC1;
+ break;
+ case GrGLCaps::kRGTC_LATCAlias:
+ *internalFormat = GR_GL_COMPRESSED_RED_RGTC1;
+ break;
+ case GrGLCaps::k3DC_LATCAlias:
+ *internalFormat = GR_GL_COMPRESSED_3DC_X;
+ break;
+ }
+ break;
default:
return false;
}
@@ -2442,7 +2751,7 @@ inline bool can_copy_texsubimage(const GrSurface* dst,
// Table 3.9 of the ES2 spec indicates the supported formats with CopyTexSubImage
// and BGRA isn't in the spec. There doesn't appear to be any extension that adds it. Perhaps
// many drivers would allow it to work, but ANGLE does not.
- if (kES_GrGLBinding == gpu->glBinding() && gpu->glCaps().bgraIsInternalFormat() &&
+ if (kGLES_GrGLStandard == gpu->glStandard() && gpu->glCaps().bgraIsInternalFormat() &&
(kBGRA_8888_GrPixelConfig == dst->config() || kBGRA_8888_GrPixelConfig == src->config())) {
return false;
}
@@ -2461,7 +2770,8 @@ inline bool can_copy_texsubimage(const GrSurface* dst,
if (gpu->glCaps().isConfigRenderable(src->config(), src->desc().fSampleCnt > 0) &&
NULL != dst->asTexture() &&
dst->origin() == src->origin() &&
- kIndex_8_GrPixelConfig != src->config()) {
+ kIndex_8_GrPixelConfig != src->config() &&
+ !GrPixelConfigIsCompressed(src->config())) {
if (NULL != wouldNeedTempFBO) {
*wouldNeedTempFBO = NULL == src->asRenderTarget();
}
@@ -2505,7 +2815,7 @@ inline GrGLuint bind_surface_as_fbo(const GrGLInterface* gl,
void GrGpuGL::initCopySurfaceDstDesc(const GrSurface* src, GrTextureDesc* desc) {
// Check for format issues with glCopyTexSubImage2D
- if (kES_GrGLBinding == this->glBinding() && this->glCaps().bgraIsInternalFormat() &&
+ if (kGLES_GrGLStandard == this->glStandard() && this->glCaps().bgraIsInternalFormat() &&
kBGRA_8888_GrPixelConfig == src->config()) {
// glCopyTexSubImage2D doesn't work with this config. We'll want to make it a render target
// in order to call glBlitFramebuffer or to copy to it by rendering.
@@ -2666,7 +2976,19 @@ bool GrGpuGL::onCanCopySurface(GrSurface* dst,
return INHERITED::onCanCopySurface(dst, src, srcRect, dstPoint);
}
+void GrGpuGL::didAddGpuTraceMarker() {
+ if (this->caps()->gpuTracingSupport()) {
+ const GrTraceMarkerSet& markerArray = this->getActiveTraceMarkers();
+ SkString markerString = markerArray.toString();
+ GL_CALL(PushGroupMarker(0, markerString.c_str()));
+ }
+}
+void GrGpuGL::didRemoveGpuTraceMarker() {
+ if (this->caps()->gpuTracingSupport()) {
+ GL_CALL(PopGroupMarker());
+ }
+}
///////////////////////////////////////////////////////////////////////////////
GrGLAttribArrayState* GrGpuGL::HWGeometryState::bindArrayAndBuffersToDraw(
@@ -2678,7 +3000,7 @@ GrGLAttribArrayState* GrGpuGL::HWGeometryState::bindArrayAndBuffersToDraw(
// We use a vertex array if we're on a core profile and the verts are in a VBO.
if (gpu->glCaps().isCoreProfile() && !vbuffer->isCPUBacked()) {
- if (NULL == fVBOVertexArray || !fVBOVertexArray->isValid()) {
+ if (NULL == fVBOVertexArray || fVBOVertexArray->wasDestroyed()) {
SkSafeUnref(fVBOVertexArray);
GrGLuint arrayID;
GR_GL_CALL(gpu->glInterface(), GenVertexArrays(1, &arrayID));
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGpuGL.h b/chromium/third_party/skia/src/gpu/gl/GrGpuGL.h
index 1a3f1a29f35..a2c636d2aad 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGpuGL.h
+++ b/chromium/third_party/skia/src/gpu/gl/GrGpuGL.h
@@ -26,6 +26,8 @@
#define PROGRAM_CACHE_STATS
#endif
+class GrGLNameAllocator;
+
class GrGpuGL : public GrGpu {
public:
GrGpuGL(const GrGLContext& ctx, GrContext* context);
@@ -34,27 +36,30 @@ public:
const GrGLContext& glContext() const { return fGLContext; }
const GrGLInterface* glInterface() const { return fGLContext.interface(); }
- const GrGLContextInfo& ctxInfo() const { return fGLContext.info(); }
- GrGLBinding glBinding() const { return fGLContext.info().binding(); }
- GrGLVersion glVersion() const { return fGLContext.info().version(); }
- GrGLSLGeneration glslGeneration() const { return fGLContext.info().glslGeneration(); }
+ const GrGLContextInfo& ctxInfo() const { return fGLContext; }
+ GrGLStandard glStandard() const { return fGLContext.standard(); }
+ GrGLVersion glVersion() const { return fGLContext.version(); }
+ GrGLSLGeneration glslGeneration() const { return fGLContext.glslGeneration(); }
+ const GrGLCaps& glCaps() const { return *fGLContext.caps(); }
+
+ virtual void discard(GrRenderTarget*) SK_OVERRIDE;
- // Used by GrGLProgram and GrGLTexGenProgramEffects to configure OpenGL state.
+ // Used by GrGLProgram and GrGLPathTexGenProgramEffects to configure OpenGL
+ // state.
void bindTexture(int unitIdx, const GrTextureParams& params, GrGLTexture* texture);
void setProjectionMatrix(const SkMatrix& matrix,
const SkISize& renderTargetSize,
GrSurfaceOrigin renderTargetOrigin);
- enum TexGenComponents {
- kS_TexGenComponents = 1,
- kST_TexGenComponents = 2,
- kSTR_TexGenComponents = 3
+ enum PathTexGenComponents {
+ kS_PathTexGenComponents = 1,
+ kST_PathTexGenComponents = 2,
+ kSTR_PathTexGenComponents = 3
};
- void enableTexGen(int unitIdx, TexGenComponents, const GrGLfloat* coefficients);
- void enableTexGen(int unitIdx, TexGenComponents, const SkMatrix& matrix);
- void flushTexGenSettings(int numUsedTexCoordSets);
+ void enablePathTexGen(int unitIdx, PathTexGenComponents, const GrGLfloat* coefficients);
+ void enablePathTexGen(int unitIdx, PathTexGenComponents, const SkMatrix& matrix);
+ void flushPathTexGenSettings(int numUsedTexCoordSets);
bool shouldUseFixedFunctionTexturing() const {
- return this->glCaps().fixedFunctionSupport() &&
- this->glCaps().pathRenderingSupport();
+ return this->glCaps().pathRenderingSupport();
}
bool programUnitTest(int maxStages);
@@ -77,8 +82,6 @@ public:
virtual void abandonResources() SK_OVERRIDE;
- const GrGLCaps& glCaps() const { return *fGLContext.info().caps(); }
-
// These functions should be used to bind GL objects. They track the GL state and skip redundant
// bindings. Making the equivalent glBind calls directly will confuse the state tracking.
void bindVertexArray(GrGLuint id) {
@@ -105,6 +108,11 @@ public:
void notifyTextureDelete(GrGLTexture* texture);
void notifyRenderTargetDelete(GrRenderTarget* renderTarget);
+ // These functions should be used to generate and delete GL path names. They have their own
+ // allocator that runs on the client side, so they are much faster than going through GenPaths.
+ GrGLuint createGLPathObject();
+ void deleteGLPathObject(GrGLuint);
+
protected:
virtual bool onCopySurface(GrSurface* dst,
GrSurface* src,
@@ -123,6 +131,8 @@ private:
virtual GrTexture* onCreateTexture(const GrTextureDesc& desc,
const void* srcData,
size_t rowBytes) SK_OVERRIDE;
+ virtual GrTexture* onCreateCompressedTexture(const GrTextureDesc& desc,
+ const void* srcData) SK_OVERRIDE;
virtual GrVertexBuffer* onCreateVertexBuffer(size_t size, bool dynamic) SK_OVERRIDE;
virtual GrIndexBuffer* onCreateIndexBuffer(size_t size, bool dynamic) SK_OVERRIDE;
virtual GrPath* onCreatePath(const SkPath&, const SkStrokeRec&) SK_OVERRIDE;
@@ -137,8 +147,6 @@ private:
virtual void onClear(const SkIRect* rect, GrColor color, bool canIgnoreRect) SK_OVERRIDE;
- virtual void onForceRenderTargetFlush() SK_OVERRIDE;
-
virtual bool onReadPixels(GrRenderTarget* target,
int left, int top,
int width, int height,
@@ -157,12 +165,19 @@ private:
virtual void onGpuStencilPath(const GrPath*, SkPath::FillType) SK_OVERRIDE;
virtual void onGpuDrawPath(const GrPath*, SkPath::FillType) SK_OVERRIDE;
+ virtual void onGpuDrawPaths(int, const GrPath**, const SkMatrix*,
+ SkPath::FillType,
+ SkStrokeRec::Style) SK_OVERRIDE;
virtual void clearStencil() SK_OVERRIDE;
virtual void clearStencilClip(const SkIRect& rect,
bool insideClip) SK_OVERRIDE;
virtual bool flushGraphicsState(DrawType, const GrDeviceCoordTexture* dstCopy) SK_OVERRIDE;
+ // GrDrawTarget ovverides
+ virtual void didAddGpuTraceMarker() SK_OVERRIDE;
+ virtual void didRemoveGpuTraceMarker() SK_OVERRIDE;
+
// binds texture unit in GL
void setTextureUnit(int unitIdx);
@@ -177,7 +192,7 @@ private:
// have been accounted for).
void flushBlend(bool isLines, GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff);
- bool hasExtension(const char* ext) const { return fGLContext.info().hasExtension(ext); }
+ bool hasExtension(const char* ext) const { return fGLContext.hasExtension(ext); }
static bool BlendCoeffReferencesConstant(GrBlendCoeff coeff);
@@ -195,7 +210,7 @@ private:
enum {
// We may actually have kMaxEntries+1 shaders in the GL context because we create a new
// shader before evicting from the cache.
- kMaxEntries = 32,
+ kMaxEntries = 128,
kHashBits = 6,
};
@@ -259,6 +274,18 @@ private:
const void* data,
size_t rowBytes);
+ // helper for onCreateCompressedTexture. If width and height are
+ // set to -1, then this function will use desc.fWidth and desc.fHeight
+ // for the size of the data. The isNewTexture flag should be set to true
+ // whenever a new texture needs to be created. Otherwise, we assume that
+ // the texture is already in GPU memory and that it's going to be updated
+ // with new data.
+ bool uploadCompressedTexData(const GrGLTexture::Desc& desc,
+ const void* data,
+ bool isNewTexture = true,
+ int left = 0, int top = 0,
+ int width = -1, int height = -1);
+
bool createRenderTargetObjects(int width, int height,
GrGLuint texID,
GrGLRenderTarget::Desc* desc);
@@ -440,19 +467,21 @@ private:
GrRenderTarget* fHWBoundRenderTarget;
SkTArray<GrTexture*, true> fHWBoundTextures;
- struct TexGenData {
+ struct PathTexGenData {
GrGLenum fMode;
GrGLint fNumComponents;
GrGLfloat fCoefficients[3 * 3];
};
- int fHWActiveTexGenSets;
- SkTArray<TexGenData, true> fHWTexGenSettings;
+ int fHWActivePathTexGenSets;
+ SkTArray<PathTexGenData, true> fHWPathTexGenSettings;
///@}
// we record what stencil format worked last time to hopefully exit early
// from our loop that tries stencil formats and calls check fb status.
int fLastSuccessfulStencilFmtIdx;
+ SkAutoTDelete<GrGLNameAllocator> fPathNameAllocator;
+
typedef GrGpu INHERITED;
};
diff --git a/chromium/third_party/skia/src/gpu/gl/GrGpuGL_program.cpp b/chromium/third_party/skia/src/gpu/gl/GrGpuGL_program.cpp
index a3beab1a599..bd4758c8563 100644
--- a/chromium/third_party/skia/src/gpu/gl/GrGpuGL_program.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/GrGpuGL_program.cpp
@@ -10,6 +10,7 @@
#include "GrEffect.h"
#include "GrGLEffect.h"
#include "SkRTConf.h"
+#include "GrGLNameAllocator.h"
#include "SkTSearch.h"
#ifdef PROGRAM_CACHE_STATS
@@ -202,6 +203,7 @@ void GrGpuGL::abandonResources(){
INHERITED::abandonResources();
fProgramCache->abandon();
fHWProgramID = 0;
+ fPathNameAllocator.reset(NULL);
}
////////////////////////////////////////////////////////////////////////////////
@@ -233,7 +235,7 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
SkSTArray<8, const GrEffectStage*, true> coverageStages;
GrGLProgramDesc desc;
GrGLProgramDesc::Build(this->getDrawState(),
- kDrawPoints_DrawType == type,
+ type,
blendOpts,
srcCoeff,
dstCoeff,
@@ -251,7 +253,8 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
return false;
}
- SkASSERT(kDrawPath_DrawType != type || !fCurrentProgram->hasVertexShader());
+ SkASSERT((kDrawPath_DrawType != type && kDrawPaths_DrawType != type)
+ || !fCurrentProgram->hasVertexShader());
fCurrentProgram.get()->ref();
@@ -308,11 +311,11 @@ void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) {
break;
default:
vbuf = NULL; // suppress warning
- GrCrash("Unknown geometry src type!");
+ SkFAIL("Unknown geometry src type!");
}
SkASSERT(NULL != vbuf);
- SkASSERT(!vbuf->isLocked());
+ SkASSERT(!vbuf->isMapped());
vertexOffsetInBytes += vbuf->baseOffset();
GrGLIndexBuffer* ibuf = NULL;
@@ -332,34 +335,21 @@ void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) {
break;
default:
ibuf = NULL; // suppress warning
- GrCrash("Unknown geometry src type!");
+ SkFAIL("Unknown geometry src type!");
}
SkASSERT(NULL != ibuf);
- SkASSERT(!ibuf->isLocked());
+ SkASSERT(!ibuf->isMapped());
*indexOffsetInBytes += ibuf->baseOffset();
}
GrGLAttribArrayState* attribState =
fHWGeometryState.bindArrayAndBuffersToDraw(this, vbuf, ibuf);
- if (!fCurrentProgram->hasVertexShader()) {
- int posIdx = this->getDrawState().positionAttributeIndex();
- const GrVertexAttrib* vertexArray = this->getDrawState().getVertexAttribs() + posIdx;
- GrVertexAttribType vertexArrayType = vertexArray->fType;
- SkASSERT(!GrGLAttribTypeToLayout(vertexArrayType).fNormalized);
- SkASSERT(GrGLAttribTypeToLayout(vertexArrayType).fCount == 2);
- attribState->setFixedFunctionVertexArray(this,
- vbuf,
- 2,
- GrGLAttribTypeToLayout(vertexArrayType).fType,
- stride,
- reinterpret_cast<GrGLvoid*>(
- vertexOffsetInBytes + vertexArray->fOffset));
- attribState->disableUnusedArrays(this, 0, true);
- } else {
+ if (fCurrentProgram->hasVertexShader()) {
+ int vertexAttribCount = this->getDrawState().getVertexAttribCount();
uint32_t usedAttribArraysMask = 0;
const GrVertexAttrib* vertexAttrib = this->getDrawState().getVertexAttribs();
- int vertexAttribCount = this->getDrawState().getVertexAttribCount();
+
for (int vertexAttribIndex = 0; vertexAttribIndex < vertexAttribCount;
++vertexAttribIndex, ++vertexAttrib) {
@@ -373,9 +363,8 @@ void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) {
GrGLAttribTypeToLayout(attribType).fNormalized,
stride,
reinterpret_cast<GrGLvoid*>(
- vertexOffsetInBytes + vertexAttrib->fOffset));
+ vertexOffsetInBytes + vertexAttrib->fOffset));
}
-
- attribState->disableUnusedArrays(this, usedAttribArraysMask, false);
+ attribState->disableUnusedArrays(this, usedAttribArraysMask);
}
}
diff --git a/chromium/third_party/skia/src/gpu/gl/SkGLContextHelper.cpp b/chromium/third_party/skia/src/gpu/gl/SkGLContextHelper.cpp
index da446be0b09..b06f755f677 100644
--- a/chromium/third_party/skia/src/gpu/gl/SkGLContextHelper.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/SkGLContextHelper.cpp
@@ -37,9 +37,7 @@ bool SkGLContextHelper::init(int width, int height) {
if (fGL) {
const GrGLubyte* temp;
- GrGLBinding bindingInUse = GrGLGetBindingInUse(this->gl());
-
- if (!fGL->validate(bindingInUse) || !fExtensions.init(bindingInUse, fGL)) {
+ if (!fGL->validate()) {
fGL = NULL;
this->destroyGLContext();
return false;
@@ -59,7 +57,7 @@ bool SkGLContextHelper::init(int width, int height) {
SK_GL(*this, BindFramebuffer(GR_GL_FRAMEBUFFER, fFBO));
SK_GL(*this, GenRenderbuffers(1, &fColorBufferID));
SK_GL(*this, BindRenderbuffer(GR_GL_RENDERBUFFER, fColorBufferID));
- if (kES_GrGLBinding == bindingInUse) {
+ if (kGLES_GrGLStandard == this->gl()->fStandard) {
SK_GL(*this, RenderbufferStorage(GR_GL_RENDERBUFFER,
GR_GL_RGBA8,
width, height));
@@ -79,7 +77,7 @@ bool SkGLContextHelper::init(int width, int height) {
// in binding a packed format an FBO. However, we can't rely on packed
// depth stencil being available.
bool supportsPackedDepthStencil;
- if (kES_GrGLBinding == bindingInUse) {
+ if (kGLES_GrGLStandard == this->gl()->fStandard) {
supportsPackedDepthStencil = version >= GR_GL_VER(3,0) ||
this->hasExtension("GL_OES_packed_depth_stencil");
} else {
@@ -91,7 +89,7 @@ bool SkGLContextHelper::init(int width, int height) {
if (supportsPackedDepthStencil) {
// ES2 requires sized internal formats for RenderbufferStorage
// On Desktop we let the driver decide.
- GrGLenum format = kES_GrGLBinding == bindingInUse ?
+ GrGLenum format = kGLES_GrGLStandard == this->gl()->fStandard ?
GR_GL_DEPTH24_STENCIL8 :
GR_GL_DEPTH_STENCIL;
SK_GL(*this, RenderbufferStorage(GR_GL_RENDERBUFFER,
@@ -102,9 +100,8 @@ bool SkGLContextHelper::init(int width, int height) {
GR_GL_RENDERBUFFER,
fDepthStencilBufferID));
} else {
- GrGLenum format = kES_GrGLBinding == bindingInUse ?
- GR_GL_STENCIL_INDEX8 :
- GR_GL_STENCIL_INDEX;
+ GrGLenum format = kGLES_GrGLStandard == this->gl()->fStandard ? GR_GL_STENCIL_INDEX8 :
+ GR_GL_STENCIL_INDEX;
SK_GL(*this, RenderbufferStorage(GR_GL_RENDERBUFFER,
format,
width, height));
diff --git a/chromium/third_party/skia/src/gpu/gl/android/GrGLCreateNativeInterface_android.cpp b/chromium/third_party/skia/src/gpu/gl/android/GrGLCreateNativeInterface_android.cpp
index ed1c8349023..781e29bc9df 100644
--- a/chromium/third_party/skia/src/gpu/gl/android/GrGLCreateNativeInterface_android.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/android/GrGLCreateNativeInterface_android.cpp
@@ -4,8 +4,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "gl/GrGLExtensions.h"
#include "gl/GrGLInterface.h"
+#include "gl/GrGLAssembleInterface.h"
+#include "gl/GrGLExtensions.h"
#include "gl/GrGLUtil.h"
#ifndef GL_GLEXT_PROTOTYPES
@@ -17,418 +18,259 @@
#include <EGL/egl.h>
-static const GrGLInterface* create_es_interface(GrGLVersion version,
- const GrGLExtensions& extensions) {
+static GrGLInterface* create_es_interface(GrGLVersion version,
+ GrGLExtensions* extensions) {
if (version < GR_GL_VER(2,0)) {
return NULL;
}
GrGLInterface* interface = SkNEW(GrGLInterface);
- interface->fBindingsExported = kES_GrGLBinding;
+ interface->fStandard = kGLES_GrGLStandard;
+ GrGLInterface::Functions* functions = &interface->fFunctions;
- interface->fActiveTexture = glActiveTexture;
- interface->fAttachShader = glAttachShader;
- interface->fBindAttribLocation = glBindAttribLocation;
- interface->fBindBuffer = glBindBuffer;
- interface->fBindTexture = glBindTexture;
- interface->fBindVertexArray = glBindVertexArrayOES;
- interface->fBlendColor = glBlendColor;
- interface->fBlendFunc = glBlendFunc;
- interface->fBufferData = glBufferData;
- interface->fBufferSubData = glBufferSubData;
- interface->fClear = glClear;
- interface->fClearColor = glClearColor;
- interface->fClearStencil = glClearStencil;
- interface->fColorMask = glColorMask;
- interface->fCompileShader = glCompileShader;
- interface->fCompressedTexImage2D = glCompressedTexImage2D;
- interface->fCopyTexSubImage2D = glCopyTexSubImage2D;
- interface->fCreateProgram = glCreateProgram;
- interface->fCreateShader = glCreateShader;
- interface->fCullFace = glCullFace;
- interface->fDeleteBuffers = glDeleteBuffers;
- interface->fDeleteProgram = glDeleteProgram;
- interface->fDeleteShader = glDeleteShader;
- interface->fDeleteTextures = glDeleteTextures;
- interface->fDeleteVertexArrays = glDeleteVertexArraysOES;
- interface->fDepthMask = glDepthMask;
- interface->fDisable = glDisable;
- interface->fDisableVertexAttribArray = glDisableVertexAttribArray;
- interface->fDrawArrays = glDrawArrays;
- interface->fDrawElements = glDrawElements;
- interface->fEnable = glEnable;
- interface->fEnableVertexAttribArray = glEnableVertexAttribArray;
- interface->fFinish = glFinish;
- interface->fFlush = glFlush;
- interface->fFrontFace = glFrontFace;
- interface->fGenBuffers = glGenBuffers;
- interface->fGenerateMipmap = glGenerateMipmap;
- interface->fGenTextures = glGenTextures;
- interface->fGenVertexArrays = glGenVertexArraysOES;
- interface->fGetBufferParameteriv = glGetBufferParameteriv;
- interface->fGetError = glGetError;
- interface->fGetIntegerv = glGetIntegerv;
- interface->fGetProgramInfoLog = glGetProgramInfoLog;
- interface->fGetProgramiv = glGetProgramiv;
- interface->fGetShaderInfoLog = glGetShaderInfoLog;
- interface->fGetShaderiv = glGetShaderiv;
- interface->fGetString = glGetString;
-#if GL_ES_VERSION_30
- interface->fGetStringi = glGetStringi;
+ functions->fActiveTexture = glActiveTexture;
+ functions->fAttachShader = glAttachShader;
+ functions->fBindAttribLocation = glBindAttribLocation;
+ functions->fBindBuffer = glBindBuffer;
+ functions->fBindTexture = glBindTexture;
+ functions->fBindVertexArray = glBindVertexArrayOES;
+ functions->fBlendColor = glBlendColor;
+ functions->fBlendFunc = glBlendFunc;
+ functions->fBufferData = glBufferData;
+ functions->fBufferSubData = glBufferSubData;
+ functions->fClear = glClear;
+ functions->fClearColor = glClearColor;
+ functions->fClearStencil = glClearStencil;
+ functions->fColorMask = glColorMask;
+ functions->fCompileShader = glCompileShader;
+ functions->fCompressedTexImage2D = glCompressedTexImage2D;
+ functions->fCompressedTexSubImage2D = glCompressedTexSubImage2D;
+ functions->fCopyTexSubImage2D = glCopyTexSubImage2D;
+ functions->fCreateProgram = glCreateProgram;
+ functions->fCreateShader = glCreateShader;
+ functions->fCullFace = glCullFace;
+ functions->fDeleteBuffers = glDeleteBuffers;
+ functions->fDeleteProgram = glDeleteProgram;
+ functions->fDeleteShader = glDeleteShader;
+ functions->fDeleteTextures = glDeleteTextures;
+ functions->fDeleteVertexArrays = glDeleteVertexArraysOES;
+ functions->fDepthMask = glDepthMask;
+ functions->fDisable = glDisable;
+ functions->fDisableVertexAttribArray = glDisableVertexAttribArray;
+ functions->fDrawArrays = glDrawArrays;
+ functions->fDrawElements = glDrawElements;
+ functions->fEnable = glEnable;
+ functions->fEnableVertexAttribArray = glEnableVertexAttribArray;
+ functions->fFinish = glFinish;
+ functions->fFlush = glFlush;
+ functions->fFrontFace = glFrontFace;
+ functions->fGenBuffers = glGenBuffers;
+ functions->fGenerateMipmap = glGenerateMipmap;
+ functions->fGenTextures = glGenTextures;
+ functions->fGenVertexArrays = glGenVertexArraysOES;
+ functions->fGetBufferParameteriv = glGetBufferParameteriv;
+ functions->fGetError = glGetError;
+ functions->fGetIntegerv = glGetIntegerv;
+ functions->fGetProgramInfoLog = glGetProgramInfoLog;
+ functions->fGetProgramiv = glGetProgramiv;
+ functions->fGetShaderInfoLog = glGetShaderInfoLog;
+ functions->fGetShaderiv = glGetShaderiv;
+ functions->fGetString = glGetString;
+#if GL_ES_VERSION_3_0
+ functions->fGetStringi = glGetStringi;
#else
- interface->fGetStringi = (GrGLGetStringiProc) eglGetProcAddress("glGetStringi");
+ functions->fGetStringi = (GrGLGetStringiProc) eglGetProcAddress("glGetStringi");
#endif
- interface->fGetUniformLocation = glGetUniformLocation;
- interface->fLineWidth = glLineWidth;
- interface->fLinkProgram = glLinkProgram;
- interface->fPixelStorei = glPixelStorei;
- interface->fReadPixels = glReadPixels;
- interface->fScissor = glScissor;
+ functions->fGetUniformLocation = glGetUniformLocation;
+ functions->fLineWidth = glLineWidth;
+ functions->fLinkProgram = glLinkProgram;
+ functions->fPixelStorei = glPixelStorei;
+ functions->fReadPixels = glReadPixels;
+ functions->fScissor = glScissor;
#if GR_GL_USE_NEW_SHADER_SOURCE_SIGNATURE
- interface->fShaderSource = (GrGLShaderSourceProc) glShaderSource;
+ functions->fShaderSource = (GrGLShaderSourceProc) glShaderSource;
#else
- interface->fShaderSource = glShaderSource;
+ functions->fShaderSource = glShaderSource;
#endif
- interface->fStencilFunc = glStencilFunc;
- interface->fStencilFuncSeparate = glStencilFuncSeparate;
- interface->fStencilMask = glStencilMask;
- interface->fStencilMaskSeparate = glStencilMaskSeparate;
- interface->fStencilOp = glStencilOp;
- interface->fStencilOpSeparate = glStencilOpSeparate;
- interface->fTexImage2D = glTexImage2D;
- interface->fTexParameteri = glTexParameteri;
- interface->fTexParameteriv = glTexParameteriv;
- interface->fTexSubImage2D = glTexSubImage2D;
+ functions->fStencilFunc = glStencilFunc;
+ functions->fStencilFuncSeparate = glStencilFuncSeparate;
+ functions->fStencilMask = glStencilMask;
+ functions->fStencilMaskSeparate = glStencilMaskSeparate;
+ functions->fStencilOp = glStencilOp;
+ functions->fStencilOpSeparate = glStencilOpSeparate;
+ functions->fTexImage2D = glTexImage2D;
+ functions->fTexParameteri = glTexParameteri;
+ functions->fTexParameteriv = glTexParameteriv;
+ functions->fTexSubImage2D = glTexSubImage2D;
if (version >= GR_GL_VER(3,0)) {
#if GL_ES_VERSION_3_0
- interface->fTexStorage2D = glTexStorage2D;
+ functions->fTexStorage2D = glTexStorage2D;
#else
- interface->fTexStorage2D = (GrGLTexStorage2DProc) eglGetProcAddress("glTexStorage2D");
+ functions->fTexStorage2D = (GrGLTexStorage2DProc) eglGetProcAddress("glTexStorage2D");
#endif
} else {
#if GL_EXT_texture_storage
- interface->fTexStorage2D = glTexStorage2DEXT;
+ functions->fTexStorage2D = glTexStorage2DEXT;
#else
- interface->fTexStorage2D = (GrGLTexStorage2DProc) eglGetProcAddress("glTexStorage2DEXT");
+ functions->fTexStorage2D = (GrGLTexStorage2DProc) eglGetProcAddress("glTexStorage2DEXT");
#endif
}
#if GL_EXT_discard_framebuffer
- interface->fDiscardFramebuffer = glDiscardFramebufferEXT;
+ functions->fDiscardFramebuffer = glDiscardFramebufferEXT;
#endif
- interface->fUniform1f = glUniform1f;
- interface->fUniform1i = glUniform1i;
- interface->fUniform1fv = glUniform1fv;
- interface->fUniform1iv = glUniform1iv;
- interface->fUniform2f = glUniform2f;
- interface->fUniform2i = glUniform2i;
- interface->fUniform2fv = glUniform2fv;
- interface->fUniform2iv = glUniform2iv;
- interface->fUniform3f = glUniform3f;
- interface->fUniform3i = glUniform3i;
- interface->fUniform3fv = glUniform3fv;
- interface->fUniform3iv = glUniform3iv;
- interface->fUniform4f = glUniform4f;
- interface->fUniform4i = glUniform4i;
- interface->fUniform4fv = glUniform4fv;
- interface->fUniform4iv = glUniform4iv;
- interface->fUniformMatrix2fv = glUniformMatrix2fv;
- interface->fUniformMatrix3fv = glUniformMatrix3fv;
- interface->fUniformMatrix4fv = glUniformMatrix4fv;
- interface->fUseProgram = glUseProgram;
- interface->fVertexAttrib4fv = glVertexAttrib4fv;
- interface->fVertexAttribPointer = glVertexAttribPointer;
- interface->fViewport = glViewport;
- interface->fBindFramebuffer = glBindFramebuffer;
- interface->fBindRenderbuffer = glBindRenderbuffer;
- interface->fCheckFramebufferStatus = glCheckFramebufferStatus;
- interface->fDeleteFramebuffers = glDeleteFramebuffers;
- interface->fDeleteRenderbuffers = glDeleteRenderbuffers;
- interface->fFramebufferRenderbuffer = glFramebufferRenderbuffer;
- interface->fFramebufferTexture2D = glFramebufferTexture2D;
-#if GR_GL_IGNORE_ES3_MSAA
+ functions->fUniform1f = glUniform1f;
+ functions->fUniform1i = glUniform1i;
+ functions->fUniform1fv = glUniform1fv;
+ functions->fUniform1iv = glUniform1iv;
+ functions->fUniform2f = glUniform2f;
+ functions->fUniform2i = glUniform2i;
+ functions->fUniform2fv = glUniform2fv;
+ functions->fUniform2iv = glUniform2iv;
+ functions->fUniform3f = glUniform3f;
+ functions->fUniform3i = glUniform3i;
+ functions->fUniform3fv = glUniform3fv;
+ functions->fUniform3iv = glUniform3iv;
+ functions->fUniform4f = glUniform4f;
+ functions->fUniform4i = glUniform4i;
+ functions->fUniform4fv = glUniform4fv;
+ functions->fUniform4iv = glUniform4iv;
+ functions->fUniformMatrix2fv = glUniformMatrix2fv;
+ functions->fUniformMatrix3fv = glUniformMatrix3fv;
+ functions->fUniformMatrix4fv = glUniformMatrix4fv;
+ functions->fUseProgram = glUseProgram;
+ functions->fVertexAttrib4fv = glVertexAttrib4fv;
+ functions->fVertexAttribPointer = glVertexAttribPointer;
+ functions->fViewport = glViewport;
+ functions->fBindFramebuffer = glBindFramebuffer;
+ functions->fBindRenderbuffer = glBindRenderbuffer;
+ functions->fCheckFramebufferStatus = glCheckFramebufferStatus;
+ functions->fDeleteFramebuffers = glDeleteFramebuffers;
+ functions->fDeleteRenderbuffers = glDeleteRenderbuffers;
+ functions->fFramebufferRenderbuffer = glFramebufferRenderbuffer;
+ functions->fFramebufferTexture2D = glFramebufferTexture2D;
- if (extensions.has("GL_EXT_multisampled_render_to_texture")) {
+ if (version >= GR_GL_VER(3,0)) {
+#if GL_ES_VERSION_3_0
+ functions->fRenderbufferStorageMultisample = glRenderbufferStorageMultisample;
+ functions->fBlitFramebuffer = glBlitFramebuffer;
+#else
+ functions->fRenderbufferStorageMultisample = (GrGLRenderbufferStorageMultisampleProc) eglGetProcAddress("glRenderbufferStorageMultisample");
+ functions->fBlitFramebuffer = (GrGLBlitFramebufferProc) eglGetProcAddress("glBlitFramebuffer");
+#endif
+ }
+
+ if (extensions->has("GL_EXT_multisampled_render_to_texture")) {
#if GL_EXT_multisampled_render_to_texture
- interface->fFramebufferTexture2DMultisample = glFramebufferTexture2DMultisampleEXT;
- interface->fRenderbufferStorageMultisample = glRenderbufferStorageMultisampleEXT;
+ functions->fFramebufferTexture2DMultisample = glFramebufferTexture2DMultisampleEXT;
+ functions->fRenderbufferStorageMultisampleES2EXT = glRenderbufferStorageMultisampleEXT;
#else
- interface->fFramebufferTexture2DMultisample = (GrGLFramebufferTexture2DMultisampleProc) eglGetProcAddress("glFramebufferTexture2DMultisampleEXT");
- interface->fRenderbufferStorageMultisample = (GrGLRenderbufferStorageMultisampleProc) eglGetProcAddress("glRenderbufferStorageMultisampleEXT");
+ functions->fFramebufferTexture2DMultisample = (GrGLFramebufferTexture2DMultisampleProc) eglGetProcAddress("glFramebufferTexture2DMultisampleEXT");
+ functions->fRenderbufferStorageMultisampleES2EXT = (GrGLRenderbufferStorageMultisampleProc) eglGetProcAddress("glRenderbufferStorageMultisampleEXT");
#endif
- } else if (extensions.has("GL_IMG_multisampled_render_to_texture")) {
+ } else if (extensions->has("GL_IMG_multisampled_render_to_texture")) {
#if GL_IMG_multisampled_render_to_texture
- interface->fFramebufferTexture2DMultisample = glFramebufferTexture2DMultisampleIMG;
- interface->fRenderbufferStorageMultisample = glRenderbufferStorageMultisampleIMG;
+ functions->fFramebufferTexture2DMultisample = glFramebufferTexture2DMultisampleIMG;
+ functions->fRenderbufferStorageMultisampleES2EXT = glRenderbufferStorageMultisampleIMG;
#else
- interface->fFramebufferTexture2DMultisample = (GrGLFramebufferTexture2DMultisampleProc) eglGetProcAddress("glFramebufferTexture2DMultisampleIMG");
- interface->fRenderbufferStorageMultisample = (GrGLRenderbufferStorageMultisampleProc) eglGetProcAddress("glRenderbufferStorageMultisampleIMG");
+ functions->fFramebufferTexture2DMultisample = (GrGLFramebufferTexture2DMultisampleProc) eglGetProcAddress("glFramebufferTexture2DMultisampleIMG");
+ functions->fRenderbufferStorageMultisampleES2EXT = (GrGLRenderbufferStorageMultisampleProc) eglGetProcAddress("glRenderbufferStorageMultisampleIMG");
#endif
}
-#else // GR_GL_IGNORE_ES3_MSAA
+ functions->fGenFramebuffers = glGenFramebuffers;
+ functions->fGenRenderbuffers = glGenRenderbuffers;
+ functions->fGetFramebufferAttachmentParameteriv = glGetFramebufferAttachmentParameteriv;
+ functions->fGetRenderbufferParameteriv = glGetRenderbufferParameteriv;
+ functions->fRenderbufferStorage = glRenderbufferStorage;
- if (version >= GR_GL_VER(3,0)) {
-#if GL_ES_VERSION_3_0
- interface->fRenderbufferStorageMultisample = glRenderbufferStorageMultisample;
- interface->fBlitFramebuffer = glBlitFramebuffer;
+#if GL_OES_mapbuffer
+ functions->fMapBuffer = glMapBufferOES;
+ functions->fUnmapBuffer = glUnmapBufferOES;
#else
- interface->fRenderbufferStorageMultisample = (GrGLRenderbufferStorageMultisampleProc) eglGetProcAddress("glRenderbufferStorageMultisample");
- interface->fBlitFramebuffer = (GrGLBlitFramebufferProc) eglGetProcAddress("glBlitFramebuffer");
+ functions->fMapBuffer = (GrGLMapBufferProc) eglGetProcAddress("glMapBufferOES");
+ functions->fUnmapBuffer = (GrGLUnmapBufferProc) eglGetProcAddress("glUnmapBufferOES");
+
#endif
- }
- if (extensions.has("GL_EXT_multisampled_render_to_texture")) {
-#if GL_EXT_multisampled_render_to_texture
- interface->fFramebufferTexture2DMultisample = glFramebufferTexture2DMultisampleEXT;
- interface->fRenderbufferStorageMultisampleES2EXT = glRenderbufferStorageMultisampleEXT;
+
+ if (version >= GR_GL_VER(3,0)) {
+#if GL_ES_VERSION_3_0
+ functions->fMapBufferRange = glMapBufferRange;
+ functions->fFlushMappedBufferRange = glFlushMappedBufferRange;
#else
- interface->fFramebufferTexture2DMultisample = (GrGLFramebufferTexture2DMultisampleProc) eglGetProcAddress("glFramebufferTexture2DMultisampleEXT");
- interface->fRenderbufferStorageMultisampleES2EXT = (GrGLRenderbufferStorageMultisampleProc) eglGetProcAddress("glRenderbufferStorageMultisampleEXT");
+ functions->fMapBufferRange = (GrGLMapBufferRangeProc) eglGetProcAddress("glMapBufferRange");
+ functions->fFlushMappedBufferRange = (GrGLFlushMappedBufferRangeProc) eglGetProcAddress("glFlushMappedBufferRange");
#endif
- } else if (extensions.has("GL_IMG_multisampled_render_to_texture")) {
-#if GL_IMG_multisampled_render_to_texture
- interface->fFramebufferTexture2DMultisample = glFramebufferTexture2DMultisampleIMG;
- interface->fRenderbufferStorageMultisampleES2EXT = glRenderbufferStorageMultisampleIMG;
+ } else if (extensions->has("GL_EXT_map_buffer_range")) {
+#if GL_EXT_map_buffer_range
+ functions->fMapBufferRange = glMapBufferRangeEXT;
+ functions->fFlushMappedBufferRange = glFlushMappedBufferRangeEXT;
#else
- interface->fFramebufferTexture2DMultisample = (GrGLFramebufferTexture2DMultisampleProc) eglGetProcAddress("glFramebufferTexture2DMultisampleIMG");
- interface->fRenderbufferStorageMultisampleES2EXT = (GrGLRenderbufferStorageMultisampleProc) eglGetProcAddress("glRenderbufferStorageMultisampleIMG");
+ functions->fMapBufferRange = (GrGLMapBufferRangeProc) eglGetProcAddress("glMapBufferRangeEXT");
+ functions->fFlushMappedBufferRange = (GrGLFlushMappedBufferRangeProc) eglGetProcAddress("glFlushMappedBufferRangeEXT");
#endif
+ }
+
+ if (extensions->has("GL_EXT_debug_marker")) {
+ functions->fInsertEventMarker = (GrGLInsertEventMarkerProc) eglGetProcAddress("glInsertEventMarker");
+ functions->fPushGroupMarker = (GrGLInsertEventMarkerProc) eglGetProcAddress("glPushGroupMarker");
+ functions->fPopGroupMarker = (GrGLPopGroupMarkerProc) eglGetProcAddress("glPopGroupMarker");
+ // The below check is here because a device has been found that has the extension string but
+ // returns NULL from the eglGetProcAddress for the functions
+ if (NULL == functions->fInsertEventMarker ||
+ NULL == functions->fPushGroupMarker ||
+ NULL == functions->fPopGroupMarker) {
+ extensions->remove("GL_EXT_debug_marker");
}
+ }
-#endif // GR_GL_IGNORE_ES3_MSAA
- interface->fGenFramebuffers = glGenFramebuffers;
- interface->fGenRenderbuffers = glGenRenderbuffers;
- interface->fGetFramebufferAttachmentParameteriv = glGetFramebufferAttachmentParameteriv;
- interface->fGetRenderbufferParameteriv = glGetRenderbufferParameteriv;
- interface->fRenderbufferStorage = glRenderbufferStorage;
-#if GL_OES_mapbuffer
- interface->fMapBuffer = glMapBufferOES;
- interface->fUnmapBuffer = glUnmapBufferOES;
+#if GL_ES_VERSION_3_0
+ functions->fInvalidateFramebuffer = glInvalidateFramebuffer;
+ functions->fInvalidateSubFramebuffer = glInvalidateSubFramebuffer;
#else
- interface->fMapBuffer = (GrGLMapBufferProc) eglGetProcAddress("glMapBufferOES");
- interface->fUnmapBuffer = (GrGLUnmapBufferProc) eglGetProcAddress("glUnmapBufferOES");
+ functions->fInvalidateFramebuffer = (GrGLInvalidateFramebufferProc) eglGetProcAddress("glInvalidateFramebuffer");
+ functions->fInvalidateSubFramebuffer = (GrGLInvalidateSubFramebufferProc) eglGetProcAddress("glInvalidateSubFramebuffer");
#endif
+ functions->fInvalidateBufferData = (GrGLInvalidateBufferDataProc) eglGetProcAddress("glInvalidateBufferData");
+ functions->fInvalidateBufferSubData = (GrGLInvalidateBufferSubDataProc) eglGetProcAddress("glInvalidateBufferSubData");
+ functions->fInvalidateTexImage = (GrGLInvalidateTexImageProc) eglGetProcAddress("glInvalidateTexImage");
+ functions->fInvalidateTexSubImage = (GrGLInvalidateTexSubImageProc) eglGetProcAddress("glInvalidateTexSubImage");
return interface;
}
-static const GrGLInterface* create_desktop_interface(GrGLVersion version,
- const GrGLExtensions& extensions) {
- // Currently this assumes a 4.4 context or later. Supporting lower GL versions would require
- // getting suffixed versions of pointers for supported extensions.
- if (version < GR_GL_VER(4,4)) {
- return NULL;
- }
-
- GrGLInterface* interface = SkNEW(GrGLInterface);
- interface->fBindingsExported = kDesktop_GrGLBinding;
-
- interface->fActiveTexture = (GrGLActiveTextureProc) eglGetProcAddress("glActiveTexture");
- interface->fAttachShader = (GrGLAttachShaderProc) eglGetProcAddress("glAttachShader");
- interface->fBeginQuery = (GrGLBeginQueryProc) eglGetProcAddress("glBeginQuery");
- interface->fBindAttribLocation = (GrGLBindAttribLocationProc) eglGetProcAddress("glBindAttribLocation");
- interface->fBindBuffer = (GrGLBindBufferProc) eglGetProcAddress("glBindBuffer");
- interface->fBindFragDataLocation = (GrGLBindFragDataLocationProc) eglGetProcAddress("glBindFragDataLocation");
- interface->fBindFragDataLocationIndexed = (GrGLBindFragDataLocationIndexedProc) eglGetProcAddress("glBindFragDataLocationIndexed");
- interface->fBindFramebuffer = (GrGLBindFramebufferProc) eglGetProcAddress("glBindFramebuffer");
- interface->fBindRenderbuffer = (GrGLBindRenderbufferProc) eglGetProcAddress("glBindRenderbuffer");
- interface->fBindTexture = (GrGLBindTextureProc) eglGetProcAddress("glBindTexture");
- interface->fBindVertexArray = (GrGLBindVertexArrayProc) eglGetProcAddress("glBindVertexArray");
- interface->fBlendColor = (GrGLBlendColorProc) eglGetProcAddress("glBlendColor");
- interface->fBlendFunc = (GrGLBlendFuncProc) eglGetProcAddress("glBlendFunc");
- interface->fBlitFramebuffer = (GrGLBlitFramebufferProc) eglGetProcAddress("glBlitFramebuffer");
- interface->fBufferData = (GrGLBufferDataProc) eglGetProcAddress("glBufferData");
- interface->fBufferSubData = (GrGLBufferSubDataProc) eglGetProcAddress("glBufferSubData");
- interface->fCheckFramebufferStatus = (GrGLCheckFramebufferStatusProc) eglGetProcAddress("glCheckFramebufferStatus");
- interface->fClear = (GrGLClearProc) eglGetProcAddress("glClear");
- interface->fClearColor = (GrGLClearColorProc) eglGetProcAddress("glClearColor");
- interface->fClearStencil = (GrGLClearStencilProc) eglGetProcAddress("glClearStencil");
- interface->fClientActiveTexture = (GrGLClientActiveTextureProc) eglGetProcAddress("glClientActiveTexture");
- interface->fColorMask = (GrGLColorMaskProc) eglGetProcAddress("glColorMask");
- interface->fCompileShader = (GrGLCompileShaderProc) eglGetProcAddress("glCompileShader");
- interface->fCompressedTexImage2D = (GrGLCompressedTexImage2DProc) eglGetProcAddress("glCompressedTexImage2D");
- interface->fCopyTexSubImage2D = (GrGLCopyTexSubImage2DProc) eglGetProcAddress("glCopyTexSubImage2D");
- interface->fCreateProgram = (GrGLCreateProgramProc) eglGetProcAddress("glCreateProgram");
- interface->fCreateShader = (GrGLCreateShaderProc) eglGetProcAddress("glCreateShader");
- interface->fCullFace = (GrGLCullFaceProc) eglGetProcAddress("glCullFace");
- interface->fDeleteBuffers = (GrGLDeleteBuffersProc) eglGetProcAddress("glDeleteBuffers");
- interface->fDeleteFramebuffers = (GrGLDeleteFramebuffersProc) eglGetProcAddress("glDeleteFramebuffers");
- interface->fDeleteProgram = (GrGLDeleteProgramProc) eglGetProcAddress("glDeleteProgram");
- interface->fDeleteQueries = (GrGLDeleteQueriesProc) eglGetProcAddress("glDeleteQueries");
- interface->fDeleteRenderbuffers = (GrGLDeleteRenderbuffersProc) eglGetProcAddress("glDeleteRenderbuffers");
- interface->fDeleteShader = (GrGLDeleteShaderProc) eglGetProcAddress("glDeleteShader");
- interface->fDeleteTextures = (GrGLDeleteTexturesProc) eglGetProcAddress("glDeleteTextures");
- interface->fDeleteVertexArrays = (GrGLDeleteVertexArraysProc) eglGetProcAddress("glDeleteVertexArrays");
- interface->fDepthMask = (GrGLDepthMaskProc) eglGetProcAddress("glDepthMask");
- interface->fDisable = (GrGLDisableProc) eglGetProcAddress("glDisable");
- interface->fDisableClientState = (GrGLDisableClientStateProc) eglGetProcAddress("glDisableClientState");
- interface->fDisableVertexAttribArray = (GrGLDisableVertexAttribArrayProc) eglGetProcAddress("glDisableVertexAttribArray");
- interface->fDrawArrays = (GrGLDrawArraysProc) eglGetProcAddress("glDrawArrays");
- interface->fDrawBuffer = (GrGLDrawBufferProc) eglGetProcAddress("glDrawBuffer");
- interface->fDrawBuffers = (GrGLDrawBuffersProc) eglGetProcAddress("glDrawBuffers");
- interface->fDrawElements = (GrGLDrawElementsProc) eglGetProcAddress("glDrawElements");
- interface->fEnable = (GrGLEnableProc) eglGetProcAddress("glEnable");
- interface->fEnableClientState = (GrGLEnableClientStateProc) eglGetProcAddress("glEnableClientState");
- interface->fEnableVertexAttribArray = (GrGLEnableVertexAttribArrayProc) eglGetProcAddress("glEnableVertexAttribArray");
- interface->fEndQuery = (GrGLEndQueryProc) eglGetProcAddress("glEndQuery");
- interface->fFinish = (GrGLFinishProc) eglGetProcAddress("glFinish");
- interface->fFlush = (GrGLFlushProc) eglGetProcAddress("glFlush");
- interface->fFramebufferRenderbuffer = (GrGLFramebufferRenderbufferProc) eglGetProcAddress("glFramebufferRenderbuffer");
- interface->fFramebufferTexture2D = (GrGLFramebufferTexture2DProc) eglGetProcAddress("glFramebufferTexture2D");
- interface->fFrontFace = (GrGLFrontFaceProc) eglGetProcAddress("glFrontFace");
- interface->fGenBuffers = (GrGLGenBuffersProc) eglGetProcAddress("glGenBuffers");
- interface->fGenFramebuffers = (GrGLGenFramebuffersProc) eglGetProcAddress("glGenFramebuffers");
- interface->fGenerateMipmap = (GrGLGenerateMipmapProc) eglGetProcAddress("glGenerateMipmap");
- interface->fGenQueries = (GrGLGenQueriesProc) eglGetProcAddress("glGenQueries");
- interface->fGenRenderbuffers = (GrGLGenRenderbuffersProc) eglGetProcAddress("glGenRenderbuffers");
- interface->fGenTextures = (GrGLGenTexturesProc) eglGetProcAddress("glGenTextures");
- interface->fGenVertexArrays = (GrGLGenVertexArraysProc) eglGetProcAddress("glGenVertexArrays");
- interface->fGetBufferParameteriv = (GrGLGetBufferParameterivProc) eglGetProcAddress("glGetBufferParameteriv");
- interface->fGetError = (GrGLGetErrorProc) eglGetProcAddress("glGetError");
- interface->fGetFramebufferAttachmentParameteriv = (GrGLGetFramebufferAttachmentParameterivProc) eglGetProcAddress("glGetFramebufferAttachmentParameteriv");
- interface->fGetIntegerv = (GrGLGetIntegervProc) eglGetProcAddress("glGetIntegerv");
- interface->fGetQueryObjecti64v = (GrGLGetQueryObjecti64vProc) eglGetProcAddress("glGetQueryObjecti64v");
- interface->fGetQueryObjectiv = (GrGLGetQueryObjectivProc) eglGetProcAddress("glGetQueryObjectiv");
- interface->fGetQueryObjectui64v = (GrGLGetQueryObjectui64vProc) eglGetProcAddress("glGetQueryObjectui64v");
- interface->fGetQueryObjectuiv = (GrGLGetQueryObjectuivProc) eglGetProcAddress("glGetQueryObjectuiv");
- interface->fGetQueryiv = (GrGLGetQueryivProc) eglGetProcAddress("glGetQueryiv");
- interface->fGetProgramInfoLog = (GrGLGetProgramInfoLogProc) eglGetProcAddress("glGetProgramInfoLog");
- interface->fGetProgramiv = (GrGLGetProgramivProc) eglGetProcAddress("glGetProgramiv");
- interface->fGetRenderbufferParameteriv = (GrGLGetRenderbufferParameterivProc) eglGetProcAddress("glGetRenderbufferParameteriv");
- interface->fGetShaderInfoLog = (GrGLGetShaderInfoLogProc) eglGetProcAddress("glGetShaderInfoLog");
- interface->fGetShaderiv = (GrGLGetShaderivProc) eglGetProcAddress("glGetShaderiv");
- interface->fGetString = (GrGLGetStringProc) eglGetProcAddress("glGetString");
- interface->fGetStringi = (GrGLGetStringiProc) eglGetProcAddress("glGetStringi");
- interface->fGetTexLevelParameteriv = (GrGLGetTexLevelParameterivProc) eglGetProcAddress("glGetTexLevelParameteriv");
- interface->fGetUniformLocation = (GrGLGetUniformLocationProc) eglGetProcAddress("glGetUniformLocation");
- interface->fLineWidth = (GrGLLineWidthProc) eglGetProcAddress("glLineWidth");
- interface->fLinkProgram = (GrGLLinkProgramProc) eglGetProcAddress("glLinkProgram");
- interface->fLoadIdentity = (GrGLLoadIdentityProc) eglGetProcAddress("glLoadIdentity");
- interface->fLoadMatrixf = (GrGLLoadMatrixfProc) eglGetProcAddress("glLoadMatrixf");
- interface->fMapBuffer = (GrGLMapBufferProc) eglGetProcAddress("glMapBuffer");
- interface->fMatrixMode = (GrGLMatrixModeProc) eglGetProcAddress("glMatrixMode");
- interface->fPixelStorei = (GrGLPixelStoreiProc) eglGetProcAddress("glPixelStorei");
- interface->fQueryCounter = (GrGLQueryCounterProc) eglGetProcAddress("glQueryCounter");
- interface->fReadBuffer = (GrGLReadBufferProc) eglGetProcAddress("glReadBuffer");
- interface->fReadPixels = (GrGLReadPixelsProc) eglGetProcAddress("glReadPixels");
- interface->fRenderbufferStorage = (GrGLRenderbufferStorageProc) eglGetProcAddress("glRenderbufferStorage");
- interface->fRenderbufferStorageMultisample = (GrGLRenderbufferStorageMultisampleProc) eglGetProcAddress("glRenderbufferStorageMultisample");
- interface->fScissor = (GrGLScissorProc) eglGetProcAddress("glScissor");
- interface->fShaderSource = (GrGLShaderSourceProc) eglGetProcAddress("glShaderSource");
- interface->fStencilFunc = (GrGLStencilFuncProc) eglGetProcAddress("glStencilFunc");
- interface->fStencilFuncSeparate = (GrGLStencilFuncSeparateProc) eglGetProcAddress("glStencilFuncSeparate");
- interface->fStencilMask = (GrGLStencilMaskProc) eglGetProcAddress("glStencilMask");
- interface->fStencilMaskSeparate = (GrGLStencilMaskSeparateProc) eglGetProcAddress("glStencilMaskSeparate");
- interface->fStencilOp = (GrGLStencilOpProc) eglGetProcAddress("glStencilOp");
- interface->fStencilOpSeparate = (GrGLStencilOpSeparateProc) eglGetProcAddress("glStencilOpSeparate");
- interface->fTexGenf = (GrGLTexGenfProc) eglGetProcAddress("glTexGenf");
- interface->fTexGenfv = (GrGLTexGenfvProc) eglGetProcAddress("glTexGenfv");
- interface->fTexGeni = (GrGLTexGeniProc) eglGetProcAddress("glTexGeni");
- interface->fTexImage2D = (GrGLTexImage2DProc) eglGetProcAddress("glTexImage2D");
- interface->fTexParameteri = (GrGLTexParameteriProc) eglGetProcAddress("glTexParameteri");
- interface->fTexParameteriv = (GrGLTexParameterivProc) eglGetProcAddress("glTexParameteriv");
- interface->fTexSubImage2D = (GrGLTexSubImage2DProc) eglGetProcAddress("glTexSubImage2D");
- interface->fTexStorage2D = (GrGLTexStorage2DProc) eglGetProcAddress("glTexStorage2D");
- interface->fUniform1f = (GrGLUniform1fProc) eglGetProcAddress("glUniform1f");
- interface->fUniform1i = (GrGLUniform1iProc) eglGetProcAddress("glUniform1i");
- interface->fUniform1fv = (GrGLUniform1fvProc) eglGetProcAddress("glUniform1fv");
- interface->fUniform1iv = (GrGLUniform1ivProc) eglGetProcAddress("glUniform1iv");
- interface->fUniform2f = (GrGLUniform2fProc) eglGetProcAddress("glUniform2f");
- interface->fUniform2i = (GrGLUniform2iProc) eglGetProcAddress("glUniform2i");
- interface->fUniform2fv = (GrGLUniform2fvProc) eglGetProcAddress("glUniform2fv");
- interface->fUniform2iv = (GrGLUniform2ivProc) eglGetProcAddress("glUniform2iv");
- interface->fUniform3f = (GrGLUniform3fProc) eglGetProcAddress("glUniform3f");
- interface->fUniform3i = (GrGLUniform3iProc) eglGetProcAddress("glUniform3i");
- interface->fUniform3fv = (GrGLUniform3fvProc) eglGetProcAddress("glUniform3fv");
- interface->fUniform3iv = (GrGLUniform3ivProc) eglGetProcAddress("glUniform3iv");
- interface->fUniform4f = (GrGLUniform4fProc) eglGetProcAddress("glUniform4f");
- interface->fUniform4i = (GrGLUniform4iProc) eglGetProcAddress("glUniform4i");
- interface->fUniform4fv = (GrGLUniform4fvProc) eglGetProcAddress("glUniform4fv");
- interface->fUniform4iv = (GrGLUniform4ivProc) eglGetProcAddress("glUniform4iv");
- interface->fUniformMatrix2fv = (GrGLUniformMatrix2fvProc) eglGetProcAddress("glUniformMatrix2fv");
- interface->fUniformMatrix3fv = (GrGLUniformMatrix3fvProc) eglGetProcAddress("glUniformMatrix3fv");
- interface->fUniformMatrix4fv = (GrGLUniformMatrix4fvProc) eglGetProcAddress("glUniformMatrix4fv");
- interface->fUnmapBuffer = (GrGLUnmapBufferProc) eglGetProcAddress("glUnmapBuffer");
- interface->fUseProgram = (GrGLUseProgramProc) eglGetProcAddress("glUseProgram");
- interface->fVertexAttrib4fv = (GrGLVertexAttrib4fvProc) eglGetProcAddress("glVertexAttrib4fv");
- interface->fVertexAttribPointer = (GrGLVertexAttribPointerProc) eglGetProcAddress("glVertexAttribPointer");
- interface->fVertexPointer = (GrGLVertexPointerProc) eglGetProcAddress("glVertexPointer");
- interface->fViewport = (GrGLViewportProc) eglGetProcAddress("glViewport");
-
- if (extensions.has("GL_NV_path_rendering")) {
- interface->fPathCommands = (GrGLPathCommandsProc) eglGetProcAddress("glPathCommandsNV");
- interface->fPathCoords = (GrGLPathCoordsProc) eglGetProcAddress("glPathCoordsNV");
- interface->fPathSubCommands = (GrGLPathSubCommandsProc) eglGetProcAddress("glPathSubCommandsNV");
- interface->fPathSubCoords = (GrGLPathSubCoordsProc) eglGetProcAddress("glPathSubCoordsNV");
- interface->fPathString = (GrGLPathStringProc) eglGetProcAddress("glPathStringNV");
- interface->fPathGlyphs = (GrGLPathGlyphsProc) eglGetProcAddress("glPathGlyphsNV");
- interface->fPathGlyphRange = (GrGLPathGlyphRangeProc) eglGetProcAddress("glPathGlyphRangeNV");
- interface->fWeightPaths = (GrGLWeightPathsProc) eglGetProcAddress("glWeightPathsNV");
- interface->fCopyPath = (GrGLCopyPathProc) eglGetProcAddress("glCopyPathNV");
- interface->fInterpolatePaths = (GrGLInterpolatePathsProc) eglGetProcAddress("glInterpolatePathsNV");
- interface->fTransformPath = (GrGLTransformPathProc) eglGetProcAddress("glTransformPathNV");
- interface->fPathParameteriv = (GrGLPathParameterivProc) eglGetProcAddress("glPathParameterivNV");
- interface->fPathParameteri = (GrGLPathParameteriProc) eglGetProcAddress("glPathParameteriNV");
- interface->fPathParameterfv = (GrGLPathParameterfvProc) eglGetProcAddress("glPathParameterfvNV");
- interface->fPathParameterf = (GrGLPathParameterfProc) eglGetProcAddress("glPathParameterfNV");
- interface->fPathDashArray = (GrGLPathDashArrayProc) eglGetProcAddress("glPathDashArrayNV");
- interface->fGenPaths = (GrGLGenPathsProc) eglGetProcAddress("glGenPathsNV");
- interface->fDeletePaths = (GrGLDeletePathsProc) eglGetProcAddress("glDeletePathsNV");
- interface->fIsPath = (GrGLIsPathProc) eglGetProcAddress("glIsPathNV");
- interface->fPathStencilFunc = (GrGLPathStencilFuncProc) eglGetProcAddress("glPathStencilFuncNV");
- interface->fPathStencilDepthOffset = (GrGLPathStencilDepthOffsetProc) eglGetProcAddress("glPathStencilDepthOffsetNV");
- interface->fStencilFillPath = (GrGLStencilFillPathProc) eglGetProcAddress("glStencilFillPathNV");
- interface->fStencilStrokePath = (GrGLStencilStrokePathProc) eglGetProcAddress("glStencilStrokePathNV");
- interface->fStencilFillPathInstanced = (GrGLStencilFillPathInstancedProc) eglGetProcAddress("glStencilFillPathInstancedNV");
- interface->fStencilStrokePathInstanced = (GrGLStencilStrokePathInstancedProc) eglGetProcAddress("glStencilStrokePathInstancedNV");
- interface->fPathCoverDepthFunc = (GrGLPathCoverDepthFuncProc) eglGetProcAddress("glPathCoverDepthFuncNV");
- interface->fPathColorGen = (GrGLPathColorGenProc) eglGetProcAddress("glPathColorGenNV");
- interface->fPathTexGen = (GrGLPathTexGenProc) eglGetProcAddress("glPathTexGenNV");
- interface->fPathFogGen = (GrGLPathFogGenProc) eglGetProcAddress("glPathFogGenNV");
- interface->fCoverFillPath = (GrGLCoverFillPathProc) eglGetProcAddress("glCoverFillPathNV");
- interface->fCoverStrokePath = (GrGLCoverStrokePathProc) eglGetProcAddress("glCoverStrokePathNV");
- interface->fCoverFillPathInstanced = (GrGLCoverFillPathInstancedProc) eglGetProcAddress("glCoverFillPathInstancedNV");
- interface->fCoverStrokePathInstanced = (GrGLCoverStrokePathInstancedProc) eglGetProcAddress("glCoverStrokePathInstancedNV");
- interface->fGetPathParameteriv = (GrGLGetPathParameterivProc) eglGetProcAddress("glGetPathParameterivNV");
- interface->fGetPathParameterfv = (GrGLGetPathParameterfvProc) eglGetProcAddress("glGetPathParameterfvNV");
- interface->fGetPathCommands = (GrGLGetPathCommandsProc) eglGetProcAddress("glGetPathCommandsNV");
- interface->fGetPathCoords = (GrGLGetPathCoordsProc) eglGetProcAddress("glGetPathCoordsNV");
- interface->fGetPathDashArray = (GrGLGetPathDashArrayProc) eglGetProcAddress("glGetPathDashArrayNV");
- interface->fGetPathMetrics = (GrGLGetPathMetricsProc) eglGetProcAddress("glGetPathMetricsNV");
- interface->fGetPathMetricRange = (GrGLGetPathMetricRangeProc) eglGetProcAddress("glGetPathMetricRangeNV");
- interface->fGetPathSpacing = (GrGLGetPathSpacingProc) eglGetProcAddress("glGetPathSpacingNV");
- interface->fGetPathColorGeniv = (GrGLGetPathColorGenivProc) eglGetProcAddress("glGetPathColorGenivNV");
- interface->fGetPathColorGenfv = (GrGLGetPathColorGenfvProc) eglGetProcAddress("glGetPathColorGenfvNV");
- interface->fGetPathTexGeniv = (GrGLGetPathTexGenivProc) eglGetProcAddress("glGetPathTexGenivNV");
- interface->fGetPathTexGenfv = (GrGLGetPathTexGenfvProc) eglGetProcAddress("glGetPathTexGenfvNV");
- interface->fIsPointInFillPath = (GrGLIsPointInFillPathProc) eglGetProcAddress("glIsPointInFillPathNV");
- interface->fIsPointInStrokePath = (GrGLIsPointInStrokePathProc) eglGetProcAddress("glIsPointInStrokePathNV");
- interface->fGetPathLength = (GrGLGetPathLengthProc) eglGetProcAddress("glGetPathLengthNV");
- interface->fPointAlongPath = (GrGLPointAlongPathProc) eglGetProcAddress("glPointAlongPathNV");
- }
+static GrGLFuncPtr android_get_gl_proc(void* ctx, const char name[]) {
+ SkASSERT(NULL == ctx);
+ return eglGetProcAddress(name);
+}
- return interface;
+static const GrGLInterface* create_desktop_interface() {
+ return GrGLAssembleGLInterface(NULL, android_get_gl_proc);
}
const GrGLInterface* GrGLCreateNativeInterface() {
- GrGLGetStringiProc getStringi = (GrGLGetStringiProc) eglGetProcAddress("glGetStringi");
-
const char* verStr = reinterpret_cast<const char*>(glGetString(GR_GL_VERSION));
- GrGLVersion version = GrGLGetVersionFromString(verStr);
- GrGLBinding binding = GrGLGetBindingInUseFromString(verStr);
+ GrGLStandard standard = GrGLGetStandardInUseFromString(verStr);
- GrGLExtensions extensions;
- if (!extensions.init(binding, glGetString, getStringi, glGetIntegerv)) {
- return NULL;
- }
+ if (kGLES_GrGLStandard == standard) {
+ GrGLVersion version = GrGLGetVersionFromString(verStr);
+ GrGLExtensions extensions;
+ GrGLGetStringiProc getStringi = (GrGLGetStringiProc) eglGetProcAddress("glGetStringi");
+ if (!extensions.init(standard, glGetString, getStringi, glGetIntegerv)) {
+ return NULL;
+ }
+ GrGLInterface* interface = create_es_interface(version, &extensions);
- if (kES_GrGLBinding == binding) {
- return create_es_interface(version, extensions);
- } else if (kDesktop_GrGLBinding == binding) {
- return create_desktop_interface(version, extensions);
- } else {
- return NULL;
+ if (NULL != interface) {
+ interface->fExtensions.swap(&extensions);
+ }
+
+ return interface;
+ } else if (kGL_GrGLStandard == standard) {
+ return create_desktop_interface();
}
+
+ return NULL;
}
diff --git a/chromium/third_party/skia/src/gpu/gl/android/SkNativeGLContext_android.cpp b/chromium/third_party/skia/src/gpu/gl/android/SkNativeGLContext_android.cpp
index dda7d9d3fa0..462109a6c48 100644
--- a/chromium/third_party/skia/src/gpu/gl/android/SkNativeGLContext_android.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/android/SkNativeGLContext_android.cpp
@@ -65,19 +65,19 @@ const GrGLInterface* SkNativeGLContext::createGLContext() {
const EGLint* fContextAttribs;
EGLenum fAPI;
EGLint fRenderableTypeBit;
- GrGLBinding fBinding;
+ GrGLStandard fStandard;
} kAPIs[] = {
{ // OpenGL
kEGLContextAttribsForOpenGL,
EGL_OPENGL_API,
EGL_OPENGL_BIT,
- kDesktop_GrGLBinding
+ kGL_GrGLStandard
},
{ // OpenGL ES. This seems to work for both ES2 and 3 (when available).
kEGLContextAttribsForOpenGLES,
EGL_OPENGL_ES_API,
EGL_OPENGL_ES2_BIT,
- kES_GrGLBinding
+ kGLES_GrGLStandard
},
};
@@ -150,7 +150,7 @@ const GrGLInterface* SkNativeGLContext::createGLContext() {
continue;
}
- if (!interface->validate(kAPIs[api].fBinding)) {
+ if (!interface->validate()) {
interface->unref();
interface = NULL;
this->destroyGLContext();
diff --git a/chromium/third_party/skia/src/gpu/gl/angle/GrGLCreateANGLEInterface.cpp b/chromium/third_party/skia/src/gpu/gl/angle/GrGLCreateANGLEInterface.cpp
index 19aee2bae33..6552f7c179f 100644
--- a/chromium/third_party/skia/src/gpu/gl/angle/GrGLCreateANGLEInterface.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/angle/GrGLCreateANGLEInterface.cpp
@@ -18,11 +18,10 @@
#include "EGL/egl.h"
#define GET_PROC(name) \
- interface->f ## name = (GrGL ## name ## Proc) GetProcAddress(ghANGLELib, "gl" #name);
+ interface->fFunctions.f ## name = (GrGL ## name ## Proc) GetProcAddress(ghANGLELib, "gl" #name);
const GrGLInterface* GrGLCreateANGLEInterface() {
- static SkAutoTUnref<GrGLInterface> glInterface;
static HMODULE ghANGLELib = NULL;
if (NULL == ghANGLELib) {
@@ -34,126 +33,155 @@ const GrGLInterface* GrGLCreateANGLEInterface() {
return NULL;
}
- if (!glInterface.get()) {
- GrGLInterface* interface = new GrGLInterface;
- glInterface.reset(interface);
- interface->fBindingsExported = kES_GrGLBinding;
-
- GET_PROC(ActiveTexture);
- GET_PROC(AttachShader);
- GET_PROC(BindAttribLocation);
- GET_PROC(BindBuffer);
- GET_PROC(BindTexture);
- interface->fBindVertexArray =
- (GrGLBindVertexArrayProc) eglGetProcAddress("glBindVertexArrayOES");
- GET_PROC(BlendColor);
- GET_PROC(BlendFunc);
- GET_PROC(BufferData);
- GET_PROC(BufferSubData);
- GET_PROC(Clear);
- GET_PROC(ClearColor);
- GET_PROC(ClearStencil);
- GET_PROC(ColorMask);
- GET_PROC(CompileShader);
- GET_PROC(CompressedTexImage2D);
- GET_PROC(CopyTexSubImage2D);
- GET_PROC(CreateProgram);
- GET_PROC(CreateShader);
- GET_PROC(CullFace);
- GET_PROC(DeleteBuffers);
- GET_PROC(DeleteProgram);
- GET_PROC(DeleteShader);
- GET_PROC(DeleteTextures);
- interface->fDeleteVertexArrays =
- (GrGLDeleteVertexArraysProc) eglGetProcAddress("glDeleteVertexArraysOES");
- GET_PROC(DepthMask);
- GET_PROC(Disable);
- GET_PROC(DisableVertexAttribArray);
- GET_PROC(DrawArrays);
- GET_PROC(DrawElements);
- GET_PROC(Enable);
- GET_PROC(EnableVertexAttribArray);
- GET_PROC(Finish);
- GET_PROC(Flush);
- GET_PROC(FrontFace);
- GET_PROC(GenBuffers);
- GET_PROC(GenerateMipmap);
- GET_PROC(GenTextures);
- interface->fGenVertexArrays =
- (GrGLGenVertexArraysProc) eglGetProcAddress("glGenVertexArraysOES");
- GET_PROC(GetBufferParameteriv);
- GET_PROC(GetError);
- GET_PROC(GetIntegerv);
- GET_PROC(GetProgramInfoLog);
- GET_PROC(GetProgramiv);
- GET_PROC(GetShaderInfoLog);
- GET_PROC(GetShaderiv);
- GET_PROC(GetString);
- GET_PROC(GetUniformLocation);
- GET_PROC(LineWidth);
- GET_PROC(LinkProgram);
- GET_PROC(PixelStorei);
- GET_PROC(ReadPixels);
- GET_PROC(Scissor);
- GET_PROC(ShaderSource);
- GET_PROC(StencilFunc);
- GET_PROC(StencilFuncSeparate);
- GET_PROC(StencilMask);
- GET_PROC(StencilMaskSeparate);
- GET_PROC(StencilOp);
- GET_PROC(StencilOpSeparate);
- GET_PROC(TexImage2D);
- GET_PROC(TexParameteri);
- GET_PROC(TexParameteriv);
- GET_PROC(TexSubImage2D);
+ GrGLInterface* interface = SkNEW(GrGLInterface);
+ interface->fStandard = kGLES_GrGLStandard;
+
+ GrGLInterface::Functions* functions = &interface->fFunctions;
+
+ GET_PROC(ActiveTexture);
+ GET_PROC(AttachShader);
+ GET_PROC(BindAttribLocation);
+ GET_PROC(BindBuffer);
+ GET_PROC(BindTexture);
+ functions->fBindVertexArray =
+ (GrGLBindVertexArrayProc) eglGetProcAddress("glBindVertexArrayOES");
+ GET_PROC(BlendColor);
+ GET_PROC(BlendFunc);
+ GET_PROC(BufferData);
+ GET_PROC(BufferSubData);
+ GET_PROC(Clear);
+ GET_PROC(ClearColor);
+ GET_PROC(ClearStencil);
+ GET_PROC(ColorMask);
+ GET_PROC(CompileShader);
+ GET_PROC(CompressedTexImage2D);
+ GET_PROC(CompressedTexSubImage2D);
+ GET_PROC(CopyTexSubImage2D);
+ GET_PROC(CreateProgram);
+ GET_PROC(CreateShader);
+ GET_PROC(CullFace);
+ GET_PROC(DeleteBuffers);
+ GET_PROC(DeleteProgram);
+ GET_PROC(DeleteShader);
+ GET_PROC(DeleteTextures);
+ functions->fDeleteVertexArrays =
+ (GrGLDeleteVertexArraysProc) eglGetProcAddress("glDeleteVertexArraysOES");
+ GET_PROC(DepthMask);
+ GET_PROC(Disable);
+ GET_PROC(DisableVertexAttribArray);
+ GET_PROC(DrawArrays);
+ GET_PROC(DrawElements);
+ GET_PROC(Enable);
+ GET_PROC(EnableVertexAttribArray);
+ GET_PROC(Finish);
+ GET_PROC(Flush);
+ GET_PROC(FrontFace);
+ GET_PROC(GenBuffers);
+ GET_PROC(GenerateMipmap);
+ GET_PROC(GenTextures);
+ functions->fGenVertexArrays =
+ (GrGLGenVertexArraysProc) eglGetProcAddress("glGenVertexArraysOES");
+ GET_PROC(GetBufferParameteriv);
+ GET_PROC(GetError);
+ GET_PROC(GetIntegerv);
+ GET_PROC(GetProgramInfoLog);
+ GET_PROC(GetProgramiv);
+ GET_PROC(GetShaderInfoLog);
+ GET_PROC(GetShaderiv);
+ GET_PROC(GetString);
+ GET_PROC(GetStringi);
+ GET_PROC(GetUniformLocation);
+ GET_PROC(LineWidth);
+ GET_PROC(LinkProgram);
+ GET_PROC(PixelStorei);
+ GET_PROC(ReadPixels);
+ GET_PROC(Scissor);
+ GET_PROC(ShaderSource);
+ GET_PROC(StencilFunc);
+ GET_PROC(StencilFuncSeparate);
+ GET_PROC(StencilMask);
+ GET_PROC(StencilMaskSeparate);
+ GET_PROC(StencilOp);
+ GET_PROC(StencilOpSeparate);
+ GET_PROC(TexImage2D);
+ GET_PROC(TexParameteri);
+ GET_PROC(TexParameteriv);
+ GET_PROC(TexSubImage2D);
#if GL_ARB_texture_storage
- GET_PROC(TexStorage2D);
+ GET_PROC(TexStorage2D);
#elif GL_EXT_texture_storage
- interface->fTexStorage2D = (GrGLTexStorage2DProc) eglGetProcAddress("glTexStorage2DEXT");
+ functions->fTexStorage2D = (GrGLTexStorage2DProc) eglGetProcAddress("glTexStorage2DEXT");
#endif
- GET_PROC(Uniform1f);
- GET_PROC(Uniform1i);
- GET_PROC(Uniform1fv);
- GET_PROC(Uniform1iv);
-
- GET_PROC(Uniform2f);
- GET_PROC(Uniform2i);
- GET_PROC(Uniform2fv);
- GET_PROC(Uniform2iv);
-
- GET_PROC(Uniform3f);
- GET_PROC(Uniform3i);
- GET_PROC(Uniform3fv);
- GET_PROC(Uniform3iv);
-
- GET_PROC(Uniform4f);
- GET_PROC(Uniform4i);
- GET_PROC(Uniform4fv);
- GET_PROC(Uniform4iv);
-
- GET_PROC(UniformMatrix2fv);
- GET_PROC(UniformMatrix3fv);
- GET_PROC(UniformMatrix4fv);
- GET_PROC(UseProgram);
- GET_PROC(VertexAttrib4fv);
- GET_PROC(VertexAttribPointer);
- GET_PROC(Viewport);
- GET_PROC(BindFramebuffer);
- GET_PROC(BindRenderbuffer);
- GET_PROC(CheckFramebufferStatus);
- GET_PROC(DeleteFramebuffers);
- GET_PROC(DeleteRenderbuffers);
- GET_PROC(FramebufferRenderbuffer);
- GET_PROC(FramebufferTexture2D);
- GET_PROC(GenFramebuffers);
- GET_PROC(GenRenderbuffers);
- GET_PROC(GetFramebufferAttachmentParameteriv);
- GET_PROC(GetRenderbufferParameteriv);
- GET_PROC(RenderbufferStorage);
-
- interface->fMapBuffer = (GrGLMapBufferProc) eglGetProcAddress("glMapBufferOES");
- interface->fUnmapBuffer = (GrGLUnmapBufferProc) eglGetProcAddress("glUnmapBufferOES");
- }
- glInterface.get()->ref();
- return glInterface.get();
+ GET_PROC(Uniform1f);
+ GET_PROC(Uniform1i);
+ GET_PROC(Uniform1fv);
+ GET_PROC(Uniform1iv);
+
+ GET_PROC(Uniform2f);
+ GET_PROC(Uniform2i);
+ GET_PROC(Uniform2fv);
+ GET_PROC(Uniform2iv);
+
+ GET_PROC(Uniform3f);
+ GET_PROC(Uniform3i);
+ GET_PROC(Uniform3fv);
+ GET_PROC(Uniform3iv);
+
+ GET_PROC(Uniform4f);
+ GET_PROC(Uniform4i);
+ GET_PROC(Uniform4fv);
+ GET_PROC(Uniform4iv);
+
+ GET_PROC(UniformMatrix2fv);
+ GET_PROC(UniformMatrix3fv);
+ GET_PROC(UniformMatrix4fv);
+ GET_PROC(UseProgram);
+ GET_PROC(VertexAttrib4fv);
+ GET_PROC(VertexAttribPointer);
+ GET_PROC(Viewport);
+ GET_PROC(BindFramebuffer);
+ GET_PROC(BindRenderbuffer);
+ GET_PROC(CheckFramebufferStatus);
+ GET_PROC(DeleteFramebuffers);
+ GET_PROC(DeleteRenderbuffers);
+ GET_PROC(FramebufferRenderbuffer);
+ GET_PROC(FramebufferTexture2D);
+ GET_PROC(GenFramebuffers);
+ GET_PROC(GenRenderbuffers);
+ GET_PROC(GetFramebufferAttachmentParameteriv);
+ GET_PROC(GetRenderbufferParameteriv);
+ GET_PROC(RenderbufferStorage);
+
+ functions->fMapBuffer = (GrGLMapBufferProc) eglGetProcAddress("glMapBufferOES");
+ functions->fUnmapBuffer = (GrGLUnmapBufferProc) eglGetProcAddress("glUnmapBufferOES");
+
+#if GL_ES_VERSION_3_0
+ functions->fMapBufferRange = GET_PROC(glMapBufferRange);
+ functions->fFlushMappedBufferRange = GET_PROC(glFlushMappedBufferRange);
+#else
+ functions->fMapBufferRange = (GrGLMapBufferRangeProc) eglGetProcAddress("glMapBufferRange");
+ functions->fFlushMappedBufferRange = (GrGLFlushMappedBufferRangeProc) eglGetProcAddress("glFlushMappedBufferRange");
+#endif
+
+ functions->fInsertEventMarker = (GrGLInsertEventMarkerProc) eglGetProcAddress("glInsertEventMarkerEXT");
+ functions->fPushGroupMarker = (GrGLInsertEventMarkerProc) eglGetProcAddress("glPushGroupMarkerEXT");
+ functions->fPopGroupMarker = (GrGLPopGroupMarkerProc) eglGetProcAddress("glPopGroupMarkerEXT");
+
+#if GL_ES_VERSION_3_0
+ GET_PROC(InvalidateFramebuffer);
+ GET_PROC(InvalidateSubFramebuffer);
+#else
+ functions->fInvalidateFramebuffer = (GrGLInvalidateFramebufferProc) eglGetProcAddress("glInvalidateFramebuffer");
+ functions->fInvalidateSubFramebuffer = (GrGLInvalidateSubFramebufferProc) eglGetProcAddress("glInvalidateSubFramebuffer");
+#endif
+ functions->fInvalidateBufferData = (GrGLInvalidateBufferDataProc) eglGetProcAddress("glInvalidateBufferData");
+ functions->fInvalidateBufferSubData = (GrGLInvalidateBufferSubDataProc) eglGetProcAddress("glInvalidateBufferSubData");
+ functions->fInvalidateTexImage = (GrGLInvalidateTexImageProc) eglGetProcAddress("glInvalidateTexImage");
+ functions->fInvalidateTexSubImage = (GrGLInvalidateTexSubImageProc) eglGetProcAddress("glInvalidateTexSubImage");
+
+ interface->fExtensions.init(kGLES_GrGLStandard,
+ functions->fGetString,
+ functions->fGetStringi,
+ functions->fGetIntegerv);
+ return interface;
}
diff --git a/chromium/third_party/skia/src/gpu/gl/debug/GrBufferObj.h b/chromium/third_party/skia/src/gpu/gl/debug/GrBufferObj.h
index fecfeb5e3ce..5c282eef31b 100644
--- a/chromium/third_party/skia/src/gpu/gl/debug/GrBufferObj.h
+++ b/chromium/third_party/skia/src/gpu/gl/debug/GrBufferObj.h
@@ -34,9 +34,15 @@ public:
GrAlwaysAssert(!fMapped);
}
- void setMapped() { fMapped = true; }
+ void setMapped(GrGLintptr offset, GrGLsizeiptr length) {
+ fMapped = true;
+ fMappedOffset = offset;
+ fMappedLength = length;
+ }
void resetMapped() { fMapped = false; }
bool getMapped() const { return fMapped; }
+ GrGLintptr getMappedOffset() const { return fMappedOffset; }
+ GrGLsizeiptr getMappedLength() const { return fMappedLength; }
void setBound() { fBound = true; }
void resetBound() { fBound = false; }
@@ -55,7 +61,9 @@ protected:
private:
GrGLchar* fDataPtr;
- bool fMapped; // is the buffer object mapped via "glMapBuffer"?
+ bool fMapped; // is the buffer object mapped via "glMapBuffer[Range]"?
+ GrGLintptr fMappedOffset; // the offset of the buffer range that is mapped
+ GrGLsizeiptr fMappedLength; // the size of the buffer range that is mapped
bool fBound; // is the buffer object bound via "glBindBuffer"?
GrGLsizeiptr fSize; // size in bytes
GrGLint fUsage; // one of: GL_STREAM_DRAW,
diff --git a/chromium/third_party/skia/src/gpu/gl/debug/GrFakeRefObj.h b/chromium/third_party/skia/src/gpu/gl/debug/GrFakeRefObj.h
index 47ec4ee4403..84ac499c758 100644
--- a/chromium/third_party/skia/src/gpu/gl/debug/GrFakeRefObj.h
+++ b/chromium/third_party/skia/src/gpu/gl/debug/GrFakeRefObj.h
@@ -18,7 +18,7 @@
// are tracking in this class are actually OpenGL's references to the objects
// not "ours"
// Each object also gets a unique globally identifying ID
-class GrFakeRefObj : public SkNoncopyable {
+class GrFakeRefObj : SkNoncopyable {
public:
GrFakeRefObj()
: fRef(0)
diff --git a/chromium/third_party/skia/src/gpu/gl/debug/GrGLCreateDebugInterface.cpp b/chromium/third_party/skia/src/gpu/gl/debug/GrGLCreateDebugInterface.cpp
index 1a0e7accf2c..788179cd845 100644
--- a/chromium/third_party/skia/src/gpu/gl/debug/GrGLCreateDebugInterface.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/debug/GrGLCreateDebugInterface.cpp
@@ -32,13 +32,6 @@ GrGLvoid GR_GL_FUNCTION_TYPE debugGLActiveTexture(GrGLenum texture) {
GrDebugGL::getInstance()->setCurTextureUnit(texture);
}
-GrGLvoid GR_GL_FUNCTION_TYPE debugGLClientActiveTexture(GrGLenum texture) {
-
- // Ganesh offsets the texture unit indices
- texture -= GR_GL_TEXTURE0;
- GrAlwaysAssert(texture < GrDebugGL::getInstance()->getMaxTextureUnits());
-}
-
////////////////////////////////////////////////////////////////////////////////
GrGLvoid GR_GL_FUNCTION_TYPE debugGLAttachShader(GrGLuint programID,
GrGLuint shaderID) {
@@ -100,7 +93,7 @@ GrGLvoid GR_GL_FUNCTION_TYPE debugGLBufferData(GrGLenum target,
buffer = GrDebugGL::getInstance()->getElementArrayBuffer();
break;
default:
- GrCrash("Unexpected target to glBufferData");
+ SkFAIL("Unexpected target to glBufferData");
break;
}
@@ -593,7 +586,7 @@ GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindBuffer(GrGLenum target, GrGLuint bufferI
GrDebugGL::getInstance()->setElementArrayBuffer(buffer);
break;
default:
- GrCrash("Unexpected target to glBindBuffer");
+ SkFAIL("Unexpected target to glBindBuffer");
break;
}
}
@@ -629,12 +622,14 @@ GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteBuffers(GrGLsizei n, const GrGLuint* i
}
// map a buffer to the caller's address space
-GrGLvoid* GR_GL_FUNCTION_TYPE debugGLMapBuffer(GrGLenum target, GrGLenum access) {
-
+GrGLvoid* GR_GL_FUNCTION_TYPE debugGLMapBufferRange(GrGLenum target, GrGLintptr offset,
+ GrGLsizeiptr length, GrGLbitfield access) {
GrAlwaysAssert(GR_GL_ARRAY_BUFFER == target ||
GR_GL_ELEMENT_ARRAY_BUFFER == target);
- // GR_GL_READ_ONLY == access || || GR_GL_READ_WRIT == access);
- GrAlwaysAssert(GR_GL_WRITE_ONLY == access);
+
+ // We only expect read access and we expect that the buffer or range is always invalidated.
+ GrAlwaysAssert(!SkToBool(GR_GL_MAP_READ_BIT & access));
+ GrAlwaysAssert((GR_GL_MAP_INVALIDATE_BUFFER_BIT | GR_GL_MAP_INVALIDATE_RANGE_BIT) & access);
GrBufferObj *buffer = NULL;
switch (target) {
@@ -645,20 +640,41 @@ GrGLvoid* GR_GL_FUNCTION_TYPE debugGLMapBuffer(GrGLenum target, GrGLenum access)
buffer = GrDebugGL::getInstance()->getElementArrayBuffer();
break;
default:
- GrCrash("Unexpected target to glMapBuffer");
+ SkFAIL("Unexpected target to glMapBufferRange");
break;
}
- if (buffer) {
+ if (NULL != buffer) {
+ GrAlwaysAssert(offset >= 0 && offset + length <= buffer->getSize());
GrAlwaysAssert(!buffer->getMapped());
- buffer->setMapped();
- return buffer->getDataPtr();
+ buffer->setMapped(offset, length);
+ return buffer->getDataPtr() + offset;
}
GrAlwaysAssert(false);
return NULL; // no buffer bound to the target
}
+GrGLvoid* GR_GL_FUNCTION_TYPE debugGLMapBuffer(GrGLenum target, GrGLenum access) {
+ GrAlwaysAssert(GR_GL_WRITE_ONLY == access);
+
+ GrBufferObj *buffer = NULL;
+ switch (target) {
+ case GR_GL_ARRAY_BUFFER:
+ buffer = GrDebugGL::getInstance()->getArrayBuffer();
+ break;
+ case GR_GL_ELEMENT_ARRAY_BUFFER:
+ buffer = GrDebugGL::getInstance()->getElementArrayBuffer();
+ break;
+ default:
+ SkFAIL("Unexpected target to glMapBuffer");
+ break;
+ }
+
+ return debugGLMapBufferRange(target, 0, buffer->getSize(),
+ GR_GL_MAP_WRITE_BIT | GR_GL_MAP_INVALIDATE_BUFFER_BIT);
+}
+
// remove a buffer from the caller's address space
// TODO: check if the "access" method from "glMapBuffer" was honored
GrGLboolean GR_GL_FUNCTION_TYPE debugGLUnmapBuffer(GrGLenum target) {
@@ -675,11 +691,11 @@ GrGLboolean GR_GL_FUNCTION_TYPE debugGLUnmapBuffer(GrGLenum target) {
buffer = GrDebugGL::getInstance()->getElementArrayBuffer();
break;
default:
- GrCrash("Unexpected target to glUnmapBuffer");
+ SkFAIL("Unexpected target to glUnmapBuffer");
break;
}
- if (buffer) {
+ if (NULL != buffer) {
GrAlwaysAssert(buffer->getMapped());
buffer->resetMapped();
return GR_GL_TRUE;
@@ -689,6 +705,34 @@ GrGLboolean GR_GL_FUNCTION_TYPE debugGLUnmapBuffer(GrGLenum target) {
return GR_GL_FALSE; // GR_GL_INVALID_OPERATION;
}
+GrGLvoid GR_GL_FUNCTION_TYPE debugGLFlushMappedBufferRange(GrGLenum target,
+ GrGLintptr offset,
+ GrGLsizeiptr length) {
+ GrAlwaysAssert(GR_GL_ARRAY_BUFFER == target ||
+ GR_GL_ELEMENT_ARRAY_BUFFER == target);
+
+ GrBufferObj *buffer = NULL;
+ switch (target) {
+ case GR_GL_ARRAY_BUFFER:
+ buffer = GrDebugGL::getInstance()->getArrayBuffer();
+ break;
+ case GR_GL_ELEMENT_ARRAY_BUFFER:
+ buffer = GrDebugGL::getInstance()->getElementArrayBuffer();
+ break;
+ default:
+ SkFAIL("Unexpected target to glUnmapBuffer");
+ break;
+ }
+
+ if (NULL != buffer) {
+ GrAlwaysAssert(buffer->getMapped());
+ GrAlwaysAssert(offset >= 0 && (offset + length) <= buffer->getMappedLength());
+ } else {
+ GrAlwaysAssert(false);
+ }
+}
+
+
GrGLvoid GR_GL_FUNCTION_TYPE debugGLGetBufferParameteriv(GrGLenum target,
GrGLenum value,
GrGLint* params) {
@@ -713,21 +757,21 @@ GrGLvoid GR_GL_FUNCTION_TYPE debugGLGetBufferParameteriv(GrGLenum target,
switch (value) {
case GR_GL_BUFFER_MAPPED:
*params = GR_GL_FALSE;
- if (buffer)
+ if (NULL != buffer)
*params = buffer->getMapped() ? GR_GL_TRUE : GR_GL_FALSE;
break;
case GR_GL_BUFFER_SIZE:
*params = 0;
- if (buffer)
- *params = buffer->getSize();
+ if (NULL != buffer)
+ *params = SkToInt(buffer->getSize());
break;
case GR_GL_BUFFER_USAGE:
*params = GR_GL_STATIC_DRAW;
- if (buffer)
+ if (NULL != buffer)
*params = buffer->getUsage();
break;
default:
- GrCrash("Unexpected value to glGetBufferParamateriv");
+ SkFAIL("Unexpected value to glGetBufferParamateriv");
break;
}
};
@@ -790,144 +834,145 @@ private:
const GrGLInterface* GrGLCreateDebugInterface() {
GrGLInterface* interface = SkNEW(GrDebugGLInterface);
- interface->fBindingsExported = kDesktop_GrGLBinding;
- interface->fActiveTexture = debugGLActiveTexture;
- interface->fAttachShader = debugGLAttachShader;
- interface->fBeginQuery = debugGLBeginQuery;
- interface->fBindAttribLocation = debugGLBindAttribLocation;
- interface->fBindBuffer = debugGLBindBuffer;
- interface->fBindFragDataLocation = noOpGLBindFragDataLocation;
- interface->fBindTexture = debugGLBindTexture;
- interface->fBindVertexArray = debugGLBindVertexArray;
- interface->fBlendColor = noOpGLBlendColor;
- interface->fBlendFunc = noOpGLBlendFunc;
- interface->fBufferData = debugGLBufferData;
- interface->fBufferSubData = noOpGLBufferSubData;
- interface->fClear = noOpGLClear;
- interface->fClearColor = noOpGLClearColor;
- interface->fClearStencil = noOpGLClearStencil;
- interface->fClientActiveTexture = debugGLClientActiveTexture;
- interface->fColorMask = noOpGLColorMask;
- interface->fCompileShader = noOpGLCompileShader;
- interface->fCompressedTexImage2D = noOpGLCompressedTexImage2D;
- interface->fCopyTexSubImage2D = noOpGLCopyTexSubImage2D;
- interface->fCreateProgram = debugGLCreateProgram;
- interface->fCreateShader = debugGLCreateShader;
- interface->fCullFace = noOpGLCullFace;
- interface->fDeleteBuffers = debugGLDeleteBuffers;
- interface->fDeleteProgram = debugGLDeleteProgram;
- interface->fDeleteQueries = noOpGLDeleteIds;
- interface->fDeleteShader = debugGLDeleteShader;
- interface->fDeleteTextures = debugGLDeleteTextures;
- interface->fDeleteVertexArrays = debugGLDeleteVertexArrays;
- interface->fDepthMask = noOpGLDepthMask;
- interface->fDisable = noOpGLDisable;
- interface->fDisableClientState = noOpGLDisableClientState;
- interface->fDisableVertexAttribArray = noOpGLDisableVertexAttribArray;
- interface->fDrawArrays = noOpGLDrawArrays;
- interface->fDrawBuffer = noOpGLDrawBuffer;
- interface->fDrawBuffers = noOpGLDrawBuffers;
- interface->fDrawElements = noOpGLDrawElements;
- interface->fEnable = noOpGLEnable;
- interface->fEnableClientState = noOpGLEnableClientState;
- interface->fEnableVertexAttribArray = noOpGLEnableVertexAttribArray;
- interface->fEndQuery = noOpGLEndQuery;
- interface->fFinish = noOpGLFinish;
- interface->fFlush = noOpGLFlush;
- interface->fFrontFace = noOpGLFrontFace;
- interface->fGenerateMipmap = debugGLGenerateMipmap;
- interface->fGenBuffers = debugGLGenBuffers;
- interface->fGenQueries = noOpGLGenIds;
- interface->fGenTextures = debugGLGenTextures;
- interface->fGetBufferParameteriv = debugGLGetBufferParameteriv;
- interface->fGetError = noOpGLGetError;
- interface->fGetIntegerv = noOpGLGetIntegerv;
- interface->fGetQueryObjecti64v = noOpGLGetQueryObjecti64v;
- interface->fGetQueryObjectiv = noOpGLGetQueryObjectiv;
- interface->fGetQueryObjectui64v = noOpGLGetQueryObjectui64v;
- interface->fGetQueryObjectuiv = noOpGLGetQueryObjectuiv;
- interface->fGetQueryiv = noOpGLGetQueryiv;
- interface->fGetProgramInfoLog = noOpGLGetInfoLog;
- interface->fGetProgramiv = noOpGLGetShaderOrProgramiv;
- interface->fGetShaderInfoLog = noOpGLGetInfoLog;
- interface->fGetShaderiv = noOpGLGetShaderOrProgramiv;
- interface->fGetString = noOpGLGetString;
- interface->fGetStringi = noOpGLGetStringi;
- interface->fGetTexLevelParameteriv = noOpGLGetTexLevelParameteriv;
- interface->fGetUniformLocation = noOpGLGetUniformLocation;
- interface->fGenVertexArrays = debugGLGenVertexArrays;
- interface->fLoadIdentity = noOpGLLoadIdentity;
- interface->fLoadMatrixf = noOpGLLoadMatrixf;
- interface->fLineWidth = noOpGLLineWidth;
- interface->fLinkProgram = noOpGLLinkProgram;
- interface->fMatrixMode = noOpGLMatrixMode;
- interface->fPixelStorei = debugGLPixelStorei;
- interface->fQueryCounter = noOpGLQueryCounter;
- interface->fReadBuffer = noOpGLReadBuffer;
- interface->fReadPixels = debugGLReadPixels;
- interface->fScissor = noOpGLScissor;
- interface->fShaderSource = noOpGLShaderSource;
- interface->fStencilFunc = noOpGLStencilFunc;
- interface->fStencilFuncSeparate = noOpGLStencilFuncSeparate;
- interface->fStencilMask = noOpGLStencilMask;
- interface->fStencilMaskSeparate = noOpGLStencilMaskSeparate;
- interface->fStencilOp = noOpGLStencilOp;
- interface->fStencilOpSeparate = noOpGLStencilOpSeparate;
- interface->fTexGenf = noOpGLTexGenf;
- interface->fTexGenfv = noOpGLTexGenfv;
- interface->fTexGeni = noOpGLTexGeni;
- interface->fTexImage2D = noOpGLTexImage2D;
- interface->fTexParameteri = noOpGLTexParameteri;
- interface->fTexParameteriv = noOpGLTexParameteriv;
- interface->fTexSubImage2D = noOpGLTexSubImage2D;
- interface->fTexStorage2D = noOpGLTexStorage2D;
- interface->fDiscardFramebuffer = noOpGLDiscardFramebuffer;
- interface->fUniform1f = noOpGLUniform1f;
- interface->fUniform1i = noOpGLUniform1i;
- interface->fUniform1fv = noOpGLUniform1fv;
- interface->fUniform1iv = noOpGLUniform1iv;
- interface->fUniform2f = noOpGLUniform2f;
- interface->fUniform2i = noOpGLUniform2i;
- interface->fUniform2fv = noOpGLUniform2fv;
- interface->fUniform2iv = noOpGLUniform2iv;
- interface->fUniform3f = noOpGLUniform3f;
- interface->fUniform3i = noOpGLUniform3i;
- interface->fUniform3fv = noOpGLUniform3fv;
- interface->fUniform3iv = noOpGLUniform3iv;
- interface->fUniform4f = noOpGLUniform4f;
- interface->fUniform4i = noOpGLUniform4i;
- interface->fUniform4fv = noOpGLUniform4fv;
- interface->fUniform4iv = noOpGLUniform4iv;
- interface->fUniformMatrix2fv = noOpGLUniformMatrix2fv;
- interface->fUniformMatrix3fv = noOpGLUniformMatrix3fv;
- interface->fUniformMatrix4fv = noOpGLUniformMatrix4fv;
- interface->fUseProgram = debugGLUseProgram;
- interface->fVertexAttrib4fv = noOpGLVertexAttrib4fv;
- interface->fVertexAttribPointer = noOpGLVertexAttribPointer;
- interface->fVertexPointer = noOpGLVertexPointer;
- interface->fViewport = noOpGLViewport;
- interface->fBindFramebuffer = debugGLBindFramebuffer;
- interface->fBindRenderbuffer = debugGLBindRenderbuffer;
- interface->fCheckFramebufferStatus = noOpGLCheckFramebufferStatus;
- interface->fDeleteFramebuffers = debugGLDeleteFramebuffers;
- interface->fDeleteRenderbuffers = debugGLDeleteRenderbuffers;
- interface->fFramebufferRenderbuffer = debugGLFramebufferRenderbuffer;
- interface->fFramebufferTexture2D = debugGLFramebufferTexture2D;
- interface->fGenFramebuffers = debugGLGenFramebuffers;
- interface->fGenRenderbuffers = debugGLGenRenderbuffers;
- interface->fGetFramebufferAttachmentParameteriv =
+ interface->fStandard = kGL_GrGLStandard;
+
+ GrGLInterface::Functions* functions = &interface->fFunctions;
+ functions->fActiveTexture = debugGLActiveTexture;
+ functions->fAttachShader = debugGLAttachShader;
+ functions->fBeginQuery = debugGLBeginQuery;
+ functions->fBindAttribLocation = debugGLBindAttribLocation;
+ functions->fBindBuffer = debugGLBindBuffer;
+ functions->fBindFragDataLocation = noOpGLBindFragDataLocation;
+ functions->fBindTexture = debugGLBindTexture;
+ functions->fBindVertexArray = debugGLBindVertexArray;
+ functions->fBlendColor = noOpGLBlendColor;
+ functions->fBlendFunc = noOpGLBlendFunc;
+ functions->fBufferData = debugGLBufferData;
+ functions->fBufferSubData = noOpGLBufferSubData;
+ functions->fClear = noOpGLClear;
+ functions->fClearColor = noOpGLClearColor;
+ functions->fClearStencil = noOpGLClearStencil;
+ functions->fColorMask = noOpGLColorMask;
+ functions->fCompileShader = noOpGLCompileShader;
+ functions->fCompressedTexImage2D = noOpGLCompressedTexImage2D;
+ functions->fCompressedTexSubImage2D = noOpGLCompressedTexSubImage2D;
+ functions->fCopyTexSubImage2D = noOpGLCopyTexSubImage2D;
+ functions->fCreateProgram = debugGLCreateProgram;
+ functions->fCreateShader = debugGLCreateShader;
+ functions->fCullFace = noOpGLCullFace;
+ functions->fDeleteBuffers = debugGLDeleteBuffers;
+ functions->fDeleteProgram = debugGLDeleteProgram;
+ functions->fDeleteQueries = noOpGLDeleteIds;
+ functions->fDeleteShader = debugGLDeleteShader;
+ functions->fDeleteTextures = debugGLDeleteTextures;
+ functions->fDeleteVertexArrays = debugGLDeleteVertexArrays;
+ functions->fDepthMask = noOpGLDepthMask;
+ functions->fDisable = noOpGLDisable;
+ functions->fDisableVertexAttribArray = noOpGLDisableVertexAttribArray;
+ functions->fDrawArrays = noOpGLDrawArrays;
+ functions->fDrawBuffer = noOpGLDrawBuffer;
+ functions->fDrawBuffers = noOpGLDrawBuffers;
+ functions->fDrawElements = noOpGLDrawElements;
+ functions->fEnable = noOpGLEnable;
+ functions->fEnableVertexAttribArray = noOpGLEnableVertexAttribArray;
+ functions->fEndQuery = noOpGLEndQuery;
+ functions->fFinish = noOpGLFinish;
+ functions->fFlush = noOpGLFlush;
+ functions->fFlushMappedBufferRange = debugGLFlushMappedBufferRange;
+ functions->fFrontFace = noOpGLFrontFace;
+ functions->fGenerateMipmap = debugGLGenerateMipmap;
+ functions->fGenBuffers = debugGLGenBuffers;
+ functions->fGenQueries = noOpGLGenIds;
+ functions->fGenTextures = debugGLGenTextures;
+ functions->fGetBufferParameteriv = debugGLGetBufferParameteriv;
+ functions->fGetError = noOpGLGetError;
+ functions->fGetIntegerv = noOpGLGetIntegerv;
+ functions->fGetQueryObjecti64v = noOpGLGetQueryObjecti64v;
+ functions->fGetQueryObjectiv = noOpGLGetQueryObjectiv;
+ functions->fGetQueryObjectui64v = noOpGLGetQueryObjectui64v;
+ functions->fGetQueryObjectuiv = noOpGLGetQueryObjectuiv;
+ functions->fGetQueryiv = noOpGLGetQueryiv;
+ functions->fGetProgramInfoLog = noOpGLGetInfoLog;
+ functions->fGetProgramiv = noOpGLGetShaderOrProgramiv;
+ functions->fGetShaderInfoLog = noOpGLGetInfoLog;
+ functions->fGetShaderiv = noOpGLGetShaderOrProgramiv;
+ functions->fGetString = noOpGLGetString;
+ functions->fGetStringi = noOpGLGetStringi;
+ functions->fGetTexLevelParameteriv = noOpGLGetTexLevelParameteriv;
+ functions->fGetUniformLocation = noOpGLGetUniformLocation;
+ functions->fGenVertexArrays = debugGLGenVertexArrays;
+ functions->fLineWidth = noOpGLLineWidth;
+ functions->fLinkProgram = noOpGLLinkProgram;
+ functions->fMapBuffer = debugGLMapBuffer;
+ functions->fMapBufferRange = debugGLMapBufferRange;
+ functions->fPixelStorei = debugGLPixelStorei;
+ functions->fQueryCounter = noOpGLQueryCounter;
+ functions->fReadBuffer = noOpGLReadBuffer;
+ functions->fReadPixels = debugGLReadPixels;
+ functions->fScissor = noOpGLScissor;
+ functions->fShaderSource = noOpGLShaderSource;
+ functions->fStencilFunc = noOpGLStencilFunc;
+ functions->fStencilFuncSeparate = noOpGLStencilFuncSeparate;
+ functions->fStencilMask = noOpGLStencilMask;
+ functions->fStencilMaskSeparate = noOpGLStencilMaskSeparate;
+ functions->fStencilOp = noOpGLStencilOp;
+ functions->fStencilOpSeparate = noOpGLStencilOpSeparate;
+ functions->fTexImage2D = noOpGLTexImage2D;
+ functions->fTexParameteri = noOpGLTexParameteri;
+ functions->fTexParameteriv = noOpGLTexParameteriv;
+ functions->fTexSubImage2D = noOpGLTexSubImage2D;
+ functions->fTexStorage2D = noOpGLTexStorage2D;
+ functions->fDiscardFramebuffer = noOpGLDiscardFramebuffer;
+ functions->fUniform1f = noOpGLUniform1f;
+ functions->fUniform1i = noOpGLUniform1i;
+ functions->fUniform1fv = noOpGLUniform1fv;
+ functions->fUniform1iv = noOpGLUniform1iv;
+ functions->fUniform2f = noOpGLUniform2f;
+ functions->fUniform2i = noOpGLUniform2i;
+ functions->fUniform2fv = noOpGLUniform2fv;
+ functions->fUniform2iv = noOpGLUniform2iv;
+ functions->fUniform3f = noOpGLUniform3f;
+ functions->fUniform3i = noOpGLUniform3i;
+ functions->fUniform3fv = noOpGLUniform3fv;
+ functions->fUniform3iv = noOpGLUniform3iv;
+ functions->fUniform4f = noOpGLUniform4f;
+ functions->fUniform4i = noOpGLUniform4i;
+ functions->fUniform4fv = noOpGLUniform4fv;
+ functions->fUniform4iv = noOpGLUniform4iv;
+ functions->fUniformMatrix2fv = noOpGLUniformMatrix2fv;
+ functions->fUniformMatrix3fv = noOpGLUniformMatrix3fv;
+ functions->fUniformMatrix4fv = noOpGLUniformMatrix4fv;
+ functions->fUnmapBuffer = debugGLUnmapBuffer;
+ functions->fUseProgram = debugGLUseProgram;
+ functions->fVertexAttrib4fv = noOpGLVertexAttrib4fv;
+ functions->fVertexAttribPointer = noOpGLVertexAttribPointer;
+ functions->fViewport = noOpGLViewport;
+ functions->fBindFramebuffer = debugGLBindFramebuffer;
+ functions->fBindRenderbuffer = debugGLBindRenderbuffer;
+ functions->fCheckFramebufferStatus = noOpGLCheckFramebufferStatus;
+ functions->fDeleteFramebuffers = debugGLDeleteFramebuffers;
+ functions->fDeleteRenderbuffers = debugGLDeleteRenderbuffers;
+ functions->fFramebufferRenderbuffer = debugGLFramebufferRenderbuffer;
+ functions->fFramebufferTexture2D = debugGLFramebufferTexture2D;
+ functions->fGenFramebuffers = debugGLGenFramebuffers;
+ functions->fGenRenderbuffers = debugGLGenRenderbuffers;
+ functions->fGetFramebufferAttachmentParameteriv =
noOpGLGetFramebufferAttachmentParameteriv;
- interface->fGetRenderbufferParameteriv = noOpGLGetRenderbufferParameteriv;
- interface->fRenderbufferStorage = noOpGLRenderbufferStorage;
- interface->fRenderbufferStorageMultisample =
+ functions->fGetRenderbufferParameteriv = noOpGLGetRenderbufferParameteriv;
+ functions->fRenderbufferStorage = noOpGLRenderbufferStorage;
+ functions->fRenderbufferStorageMultisample =
noOpGLRenderbufferStorageMultisample;
- interface->fBlitFramebuffer = noOpGLBlitFramebuffer;
- interface->fResolveMultisampleFramebuffer =
+ functions->fBlitFramebuffer = noOpGLBlitFramebuffer;
+ functions->fResolveMultisampleFramebuffer =
noOpGLResolveMultisampleFramebuffer;
- interface->fMapBuffer = debugGLMapBuffer;
- interface->fUnmapBuffer = debugGLUnmapBuffer;
- interface->fBindFragDataLocationIndexed =
+ functions->fMatrixLoadf = noOpGLMatrixLoadf;
+ functions->fMatrixLoadIdentity = noOpGLMatrixLoadIdentity;
+
+ functions->fBindFragDataLocationIndexed =
noOpGLBindFragDataLocationIndexed;
+ interface->fExtensions.init(kGL_GrGLStandard, functions->fGetString, functions->fGetStringi,
+ functions->fGetIntegerv);
+
return interface;
}
diff --git a/chromium/third_party/skia/src/gpu/gl/iOS/GrGLCreateNativeInterface_iOS.cpp b/chromium/third_party/skia/src/gpu/gl/iOS/GrGLCreateNativeInterface_iOS.cpp
index e8e9a2a4012..04089656946 100644
--- a/chromium/third_party/skia/src/gpu/gl/iOS/GrGLCreateNativeInterface_iOS.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/iOS/GrGLCreateNativeInterface_iOS.cpp
@@ -6,147 +6,169 @@
* found in the LICENSE file.
*/
-
#include "gl/GrGLInterface.h"
#import <OpenGLES/ES2/gl.h>
#import <OpenGLES/ES2/glext.h>
const GrGLInterface* GrGLCreateNativeInterface() {
- static SkAutoTUnref<GrGLInterface> glInterface;
- if (!glInterface.get()) {
- GrGLInterface* interface = SkNEW(GrGLInterface);
- glInterface.reset(interface);
+ GrGLInterface* interface = SkNEW(GrGLInterface);
+
+ GrGLInterface::Functions* functions = &interface->fFunctions;
- interface->fActiveTexture = glActiveTexture;
- interface->fAttachShader = glAttachShader;
- interface->fBindAttribLocation = glBindAttribLocation;
- interface->fBindBuffer = glBindBuffer;
- interface->fBindTexture = glBindTexture;
- interface->fBlendColor = glBlendColor;
- interface->fBlendFunc = glBlendFunc;
- interface->fBufferData = (GrGLBufferDataProc)glBufferData;
- interface->fBufferSubData = (GrGLBufferSubDataProc)glBufferSubData;
- interface->fClear = glClear;
- interface->fClearColor = glClearColor;
- interface->fClearStencil = glClearStencil;
- interface->fColorMask = glColorMask;
- interface->fCompileShader = glCompileShader;
- interface->fCompressedTexImage2D = glCompressedTexImage2D;
- interface->fCopyTexSubImage2D = glCopyTexSubImage2D;
- interface->fCreateProgram = glCreateProgram;
- interface->fCreateShader = glCreateShader;
- interface->fCullFace = glCullFace;
- interface->fDeleteBuffers = glDeleteBuffers;
- interface->fDeleteProgram = glDeleteProgram;
- interface->fDeleteShader = glDeleteShader;
- interface->fDeleteTextures = glDeleteTextures;
- interface->fDepthMask = glDepthMask;
- interface->fDisable = glDisable;
- interface->fDisableVertexAttribArray = glDisableVertexAttribArray;
- interface->fDrawArrays = glDrawArrays;
- interface->fDrawBuffer = NULL;
- interface->fDrawBuffers = NULL;
- interface->fDrawElements = glDrawElements;
- interface->fEnable = glEnable;
- interface->fEnableVertexAttribArray = glEnableVertexAttribArray;
- interface->fFinish = glFinish;
- interface->fFlush = glFlush;
- interface->fFrontFace = glFrontFace;
- interface->fGenBuffers = glGenBuffers;
- interface->fGenerateMipmap = glGenerateMipmap;
- interface->fGetBufferParameteriv = glGetBufferParameteriv;
- interface->fGetError = glGetError;
- interface->fGetIntegerv = glGetIntegerv;
- interface->fGetProgramInfoLog = glGetProgramInfoLog;
- interface->fGetProgramiv = glGetProgramiv;
- interface->fGetShaderInfoLog = glGetShaderInfoLog;
- interface->fGetShaderiv = glGetShaderiv;
- interface->fGetString = glGetString;
- interface->fGenTextures = glGenTextures;
- interface->fGetUniformLocation = glGetUniformLocation;
- interface->fLineWidth = glLineWidth;
- interface->fLinkProgram = glLinkProgram;
- interface->fPixelStorei = glPixelStorei;
- interface->fReadBuffer = NULL;
- interface->fReadPixels = glReadPixels;
- interface->fScissor = glScissor;
- interface->fShaderSource = glShaderSource;
- interface->fStencilFunc = glStencilFunc;
- interface->fStencilFuncSeparate = glStencilFuncSeparate;
- interface->fStencilMask = glStencilMask;
- interface->fStencilMaskSeparate = glStencilMaskSeparate;
- interface->fStencilOp = glStencilOp;
- interface->fStencilOpSeparate = glStencilOpSeparate;
- // mac uses GLenum for internalFormat param (non-standard)
- // amounts to int vs. uint.
- interface->fTexImage2D = (GrGLTexImage2DProc)glTexImage2D;
+ functions->fActiveTexture = glActiveTexture;
+ functions->fAttachShader = glAttachShader;
+ functions->fBindAttribLocation = glBindAttribLocation;
+ functions->fBindBuffer = glBindBuffer;
+ functions->fBindTexture = glBindTexture;
+ functions->fBlendColor = glBlendColor;
+ functions->fBlendFunc = glBlendFunc;
+ functions->fBufferData = (GrGLBufferDataProc)glBufferData;
+ functions->fBufferSubData = (GrGLBufferSubDataProc)glBufferSubData;
+ functions->fClear = glClear;
+ functions->fClearColor = glClearColor;
+ functions->fClearStencil = glClearStencil;
+ functions->fColorMask = glColorMask;
+ functions->fCompileShader = glCompileShader;
+ functions->fCompressedTexImage2D = glCompressedTexImage2D;
+ functions->fCompressedTexSubImage2D = glCompressedTexSubImage2D;
+ functions->fCopyTexSubImage2D = glCopyTexSubImage2D;
+ functions->fCreateProgram = glCreateProgram;
+ functions->fCreateShader = glCreateShader;
+ functions->fCullFace = glCullFace;
+ functions->fDeleteBuffers = glDeleteBuffers;
+ functions->fDeleteProgram = glDeleteProgram;
+ functions->fDeleteShader = glDeleteShader;
+ functions->fDeleteTextures = glDeleteTextures;
+ functions->fDepthMask = glDepthMask;
+ functions->fDisable = glDisable;
+ functions->fDisableVertexAttribArray = glDisableVertexAttribArray;
+ functions->fDrawArrays = glDrawArrays;
+ functions->fDrawBuffer = NULL;
+ functions->fDrawBuffers = NULL;
+ functions->fDrawElements = glDrawElements;
+ functions->fEnable = glEnable;
+ functions->fEnableVertexAttribArray = glEnableVertexAttribArray;
+ functions->fFinish = glFinish;
+ functions->fFlush = glFlush;
+ functions->fFrontFace = glFrontFace;
+ functions->fGenBuffers = glGenBuffers;
+ functions->fGenerateMipmap = glGenerateMipmap;
+ functions->fGetBufferParameteriv = glGetBufferParameteriv;
+ functions->fGetError = glGetError;
+ functions->fGetIntegerv = glGetIntegerv;
+ functions->fGetProgramInfoLog = glGetProgramInfoLog;
+ functions->fGetProgramiv = glGetProgramiv;
+ functions->fGetShaderInfoLog = glGetShaderInfoLog;
+ functions->fGetShaderiv = glGetShaderiv;
+ functions->fGetString = glGetString;
+ functions->fGenTextures = glGenTextures;
+ functions->fGetUniformLocation = glGetUniformLocation;
+ functions->fLineWidth = glLineWidth;
+ functions->fLinkProgram = glLinkProgram;
+ functions->fPixelStorei = glPixelStorei;
+ functions->fReadBuffer = NULL;
+ functions->fReadPixels = glReadPixels;
+ functions->fScissor = glScissor;
+ functions->fShaderSource = (GrGLShaderSourceProc) glShaderSource;
+ functions->fStencilFunc = glStencilFunc;
+ functions->fStencilFuncSeparate = glStencilFuncSeparate;
+ functions->fStencilMask = glStencilMask;
+ functions->fStencilMaskSeparate = glStencilMaskSeparate;
+ functions->fStencilOp = glStencilOp;
+ functions->fStencilOpSeparate = glStencilOpSeparate;
+ // mac uses GLenum for internalFormat param (non-standard)
+ // amounts to int vs. uint.
+ functions->fTexImage2D = (GrGLTexImage2DProc)glTexImage2D;
#if GL_ARB_texture_storage
- interface->fTexStorage2D = glTexStorage2D;
+ functions->fTexStorage2D = glTexStorage2D;
#elif GL_EXT_texture_storage
- interface->fTexStorage2D = glTexStorage2DEXT;
+ functions->fTexStorage2D = glTexStorage2DEXT;
#endif
#if GL_EXT_discard_framebuffer
- interface->fDiscardFramebuffer = glDiscardFramebufferEXT;
+ functions->fDiscardFramebuffer = glDiscardFramebufferEXT;
#endif
- interface->fTexParameteri = glTexParameteri;
- interface->fTexParameteriv = glTexParameteriv;
- interface->fTexSubImage2D = glTexSubImage2D;
- interface->fUniform1f = glUniform1f;
- interface->fUniform1i = glUniform1i;
- interface->fUniform1fv = glUniform1fv;
- interface->fUniform1iv = glUniform1iv;
- interface->fUniform2f = glUniform2f;
- interface->fUniform2i = glUniform2i;
- interface->fUniform2fv = glUniform2fv;
- interface->fUniform2iv = glUniform2iv;
- interface->fUniform3f = glUniform3f;
- interface->fUniform3i = glUniform3i;
- interface->fUniform3fv = glUniform3fv;
- interface->fUniform3iv = glUniform3iv;
- interface->fUniform4f = glUniform4f;
- interface->fUniform4i = glUniform4i;
- interface->fUniform4fv = glUniform4fv;
- interface->fUniform4iv = glUniform4iv;
- interface->fUniform4fv = glUniform4fv;
- interface->fUniformMatrix2fv = glUniformMatrix2fv;
- interface->fUniformMatrix3fv = glUniformMatrix3fv;
- interface->fUniformMatrix4fv = glUniformMatrix4fv;
- interface->fUseProgram = glUseProgram;
- interface->fVertexAttrib4fv = glVertexAttrib4fv;
- interface->fVertexAttribPointer = glVertexAttribPointer;
- interface->fViewport = glViewport;
- interface->fGenFramebuffers = glGenFramebuffers;
- interface->fGetFramebufferAttachmentParameteriv = glGetFramebufferAttachmentParameteriv;
- interface->fGetRenderbufferParameteriv = glGetRenderbufferParameteriv;
- interface->fBindFramebuffer = glBindFramebuffer;
- interface->fFramebufferTexture2D = glFramebufferTexture2D;
- interface->fCheckFramebufferStatus = glCheckFramebufferStatus;
- interface->fDeleteFramebuffers = glDeleteFramebuffers;
- interface->fRenderbufferStorage = glRenderbufferStorage;
- interface->fGenRenderbuffers = glGenRenderbuffers;
- interface->fDeleteRenderbuffers = glDeleteRenderbuffers;
- interface->fFramebufferRenderbuffer = glFramebufferRenderbuffer;
- interface->fBindRenderbuffer = glBindRenderbuffer;
+ functions->fTexParameteri = glTexParameteri;
+ functions->fTexParameteriv = glTexParameteriv;
+ functions->fTexSubImage2D = glTexSubImage2D;
+ functions->fUniform1f = glUniform1f;
+ functions->fUniform1i = glUniform1i;
+ functions->fUniform1fv = glUniform1fv;
+ functions->fUniform1iv = glUniform1iv;
+ functions->fUniform2f = glUniform2f;
+ functions->fUniform2i = glUniform2i;
+ functions->fUniform2fv = glUniform2fv;
+ functions->fUniform2iv = glUniform2iv;
+ functions->fUniform3f = glUniform3f;
+ functions->fUniform3i = glUniform3i;
+ functions->fUniform3fv = glUniform3fv;
+ functions->fUniform3iv = glUniform3iv;
+ functions->fUniform4f = glUniform4f;
+ functions->fUniform4i = glUniform4i;
+ functions->fUniform4fv = glUniform4fv;
+ functions->fUniform4iv = glUniform4iv;
+ functions->fUniform4fv = glUniform4fv;
+ functions->fUniformMatrix2fv = glUniformMatrix2fv;
+ functions->fUniformMatrix3fv = glUniformMatrix3fv;
+ functions->fUniformMatrix4fv = glUniformMatrix4fv;
+ functions->fUseProgram = glUseProgram;
+ functions->fVertexAttrib4fv = glVertexAttrib4fv;
+ functions->fVertexAttribPointer = glVertexAttribPointer;
+ functions->fViewport = glViewport;
+ functions->fGenFramebuffers = glGenFramebuffers;
+ functions->fGetFramebufferAttachmentParameteriv = glGetFramebufferAttachmentParameteriv;
+ functions->fGetRenderbufferParameteriv = glGetRenderbufferParameteriv;
+ functions->fBindFramebuffer = glBindFramebuffer;
+ functions->fFramebufferTexture2D = glFramebufferTexture2D;
+ functions->fCheckFramebufferStatus = glCheckFramebufferStatus;
+ functions->fDeleteFramebuffers = glDeleteFramebuffers;
+ functions->fRenderbufferStorage = glRenderbufferStorage;
+ functions->fGenRenderbuffers = glGenRenderbuffers;
+ functions->fDeleteRenderbuffers = glDeleteRenderbuffers;
+ functions->fFramebufferRenderbuffer = glFramebufferRenderbuffer;
+ functions->fBindRenderbuffer = glBindRenderbuffer;
#if GL_OES_mapbuffer
- interface->fMapBuffer = glMapBufferOES;
- interface->fUnmapBuffer = glUnmapBufferOES;
+ functions->fMapBuffer = glMapBufferOES;
+ functions->fUnmapBuffer = glUnmapBufferOES;
+#endif
+
+#if GL_EXT_map_buffer_range || GL_ES_VERSION_3_0
+ functions->fMapBufferRange = glMapBufferRangeEXT;
+ functions->fFlushMappedBufferRange = glFlushMappedBufferRangeEXT;
#endif
#if GL_APPLE_framebuffer_multisample
- interface->fRenderbufferStorageMultisample = glRenderbufferStorageMultisampleAPPLE;
- interface->fResolveMultisampleFramebuffer = glResolveMultisampleFramebufferAPPLE;
+ functions->fRenderbufferStorageMultisampleES2APPLE = glRenderbufferStorageMultisampleAPPLE;
+ functions->fResolveMultisampleFramebuffer = glResolveMultisampleFramebufferAPPLE;
#endif
#if GL_OES_vertex_array_object
- interface->fBindVertexArray = glBindVertexArrayOES;
- interface->fDeleteVertexArrays = glDeleteVertexArraysOES;
- interface->fGenVertexArrays = glGenVertexArraysOES;
+ functions->fBindVertexArray = glBindVertexArrayOES;
+ functions->fDeleteVertexArrays = glDeleteVertexArraysOES;
+ functions->fGenVertexArrays = glGenVertexArraysOES;
+#endif
+
+#if GL_EXT_debug_marker
+ functions->fInsertEventMarker = glInsertEventMarkerEXT;
+ functions->fPushGroupMarker = glPushGroupMarkerEXT;
+ functions->fPopGroupMarker = glPopGroupMarkerEXT;
#endif
- interface->fBindingsExported = kES_GrGLBinding;
- }
- glInterface.get()->ref();
- return glInterface.get();
+#if GL_ES_VERSION_3_0 || GL_ARB_invalidate_subdata
+ functions->fInvalidateFramebuffer = glInvalidateFramebuffer;
+ functions->fInvalidateSubFramebuffer = glInvalidateSubFramebuffer;
+#endif
+
+#if GL_ARB_invalidate_subdata
+ functions->fInvalidateBufferData = glInvalidateBufferData;
+ functions->fInvalidateBufferSubData = glInvalidateBufferSubData;
+ functions->fInvalidateTexImage = glInvalidateTexImage;
+ functions->fInvalidateTexSubImage = glInvalidateTexSubImage;
+#endif
+
+ interface->fStandard = kGLES_GrGLStandard;
+ interface->fExtensions.init(kGLES_GrGLStandard, glGetString, NULL, glGetIntegerv);
+
+ return interface;
}
diff --git a/chromium/third_party/skia/src/gpu/gl/mac/GrGLCreateNativeInterface_mac.cpp b/chromium/third_party/skia/src/gpu/gl/mac/GrGLCreateNativeInterface_mac.cpp
index 4f8ecac0710..ab3f0ad2417 100644
--- a/chromium/third_party/skia/src/gpu/gl/mac/GrGLCreateNativeInterface_mac.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/mac/GrGLCreateNativeInterface_mac.cpp
@@ -8,13 +8,10 @@
#include "gl/GrGLInterface.h"
-#include "gl/GrGLExtensions.h"
-#include "../GrGLUtil.h"
+#include "gl/GrGLAssembleInterface.h"
#include <dlfcn.h>
-// We get the proc addresss of all GL functions dynamically because we sometimes link against
-// alternative GL implementations (e.g. MESA) in addition to the native GL implementation.
class GLLoader {
public:
GLLoader() {
@@ -22,230 +19,40 @@ public:
"/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib",
RTLD_LAZY);
}
+
~GLLoader() {
if (NULL != fLibrary) {
dlclose(fLibrary);
}
}
- void* handle() {
+
+ void* handle() const {
return NULL == fLibrary ? RTLD_DEFAULT : fLibrary;
}
+
private:
void* fLibrary;
};
-static void* GetProcAddress(const char* name) {
- static GLLoader gLoader;
- return dlsym(gLoader.handle(), name);
-}
-
-#define GET_PROC(name) (interface->f ## name = ((GrGL ## name ## Proc) GetProcAddress("gl" #name)))
-#define GET_PROC_SUFFIX(name, suffix) (interface->f ## name = ((GrGL ## name ## Proc) GetProcAddress("gl" #name #suffix)))
-
-const GrGLInterface* GrGLCreateNativeInterface() {
- // The gl functions are not context-specific so we create one global interface
- static SkAutoTUnref<GrGLInterface> glInterface;
- if (!glInterface.get()) {
- GrGLInterface* interface = new GrGLInterface;
-
- GrGLGetStringProc glGetString = (GrGLGetStringProc) GetProcAddress("glGetString");
- GrGLGetStringiProc glGetStringi = (GrGLGetStringiProc) GetProcAddress("glGetStringi");
- GrGLGetIntegervProc glGetIntegerv = (GrGLGetIntegervProc) GetProcAddress("glGetIntegerv");
-
- glInterface.reset(interface);
- const char* verStr = (const char*) glGetString(GR_GL_VERSION);
- GrGLVersion ver = GrGLGetVersionFromString(verStr);
- GrGLExtensions extensions;
- if (!extensions.init(kDesktop_GrGLBinding, glGetString, glGetStringi, glGetIntegerv)) {
- glInterface.reset(NULL);
- return NULL;
- }
- interface->fBindingsExported = kDesktop_GrGLBinding;
-
- GET_PROC(ActiveTexture);
- GET_PROC(AttachShader);
- GET_PROC(BeginQuery);
- GET_PROC(BindAttribLocation);
- GET_PROC(BindBuffer);
- if (ver >= GR_GL_VER(3,0)) {
- GET_PROC(BindFragDataLocation);
- }
- GET_PROC(BindTexture);
- GET_PROC(BlendFunc);
-
- if (ver >= GR_GL_VER(1,4) ||
- extensions.has("GL_ARB_imaging") ||
- extensions.has("GL_EXT_blend_color")) {
- GET_PROC(BlendColor);
- }
+class GLProcGetter {
+public:
+ GLProcGetter() {}
- GET_PROC(BufferData);
- GET_PROC(BufferSubData);
- GET_PROC(Clear);
- GET_PROC(ClearColor);
- GET_PROC(ClearStencil);
- GET_PROC(ClientActiveTexture);
- GET_PROC(ColorMask);
- GET_PROC(CompileShader);
- GET_PROC(CompressedTexImage2D);
- GET_PROC(CopyTexSubImage2D);
- GET_PROC(CreateProgram);
- GET_PROC(CreateShader);
- GET_PROC(CullFace);
- GET_PROC(DeleteBuffers);
- GET_PROC(DeleteProgram);
- GET_PROC(DeleteQueries);
- GET_PROC(DeleteShader);
- GET_PROC(DeleteTextures);
- GET_PROC(DepthMask);
- GET_PROC(Disable);
- GET_PROC(DisableClientState);
- GET_PROC(DisableVertexAttribArray);
- GET_PROC(DrawArrays);
- GET_PROC(DrawBuffer);
- GET_PROC(DrawBuffers);
- GET_PROC(DrawElements);
- GET_PROC(Enable);
- GET_PROC(EnableClientState);
- GET_PROC(EnableVertexAttribArray);
- GET_PROC(EndQuery);
- GET_PROC(Finish);
- GET_PROC(Flush);
- GET_PROC(FrontFace);
- GET_PROC(GenBuffers);
- GET_PROC(GenerateMipmap);
- GET_PROC(GenQueries);
- GET_PROC(GetBufferParameteriv);
- GET_PROC(GetError);
- GET_PROC(GetIntegerv);
- GET_PROC(GetProgramInfoLog);
- GET_PROC(GetProgramiv);
- GET_PROC(GetQueryiv);
- GET_PROC(GetQueryObjectiv);
- GET_PROC(GetQueryObjectuiv);
- GET_PROC(GetShaderInfoLog);
- GET_PROC(GetShaderiv);
- GET_PROC(GetString);
- GET_PROC(GetStringi);
- GET_PROC(GetTexLevelParameteriv);
- GET_PROC(GenTextures);
- GET_PROC(GetUniformLocation);
- GET_PROC(LineWidth);
- GET_PROC(LinkProgram);
- GET_PROC(LoadIdentity);
- GET_PROC(LoadMatrixf);
- GET_PROC(MapBuffer);
- GET_PROC(MatrixMode);
- GET_PROC(PixelStorei);
- GET_PROC(ReadBuffer);
- GET_PROC(ReadPixels);
- GET_PROC(Scissor);
- GET_PROC(ShaderSource);
- GET_PROC(StencilFunc);
- GET_PROC(StencilFuncSeparate);
- GET_PROC(StencilMask);
- GET_PROC(StencilMaskSeparate);
- GET_PROC(StencilOp);
- GET_PROC(StencilOpSeparate);
- GET_PROC(TexGenf);
- GET_PROC(TexGenfv);
- GET_PROC(TexGeni);
- GET_PROC(TexImage2D);
- GET_PROC(TexParameteri);
- GET_PROC(TexParameteriv);
- if (ver >= GR_GL_VER(4,2) || extensions.has("GL_ARB_texture_storage")) {
- GET_PROC(TexStorage2D);
- } else if (extensions.has("GL_EXT_texture_storage")) {
- GET_PROC_SUFFIX(TexStorage2D, EXT);
- }
- GET_PROC(TexSubImage2D);
- GET_PROC(Uniform1f);
- GET_PROC(Uniform1i);
- GET_PROC(Uniform1fv);
- GET_PROC(Uniform1iv);
- GET_PROC(Uniform2f);
- GET_PROC(Uniform2i);
- GET_PROC(Uniform2fv);
- GET_PROC(Uniform2iv);
- GET_PROC(Uniform3f);
- GET_PROC(Uniform3i);
- GET_PROC(Uniform3fv);
- GET_PROC(Uniform3iv);
- GET_PROC(Uniform4f);
- GET_PROC(Uniform4i);
- GET_PROC(Uniform4fv);
- GET_PROC(Uniform4iv);
- GET_PROC(Uniform4fv);
- GET_PROC(UniformMatrix2fv);
- GET_PROC(UniformMatrix3fv);
- GET_PROC(UniformMatrix4fv);
- GET_PROC(UnmapBuffer);
- GET_PROC(UseProgram);
- GET_PROC(VertexAttrib4fv);
- GET_PROC(VertexAttribPointer);
- GET_PROC(VertexPointer);
- GET_PROC(Viewport);
+ GrGLFuncPtr getProc(const char name[]) const {
+ return (GrGLFuncPtr) dlsym(fLoader.handle(), name);
+ }
- if (ver >= GR_GL_VER(3,0) || extensions.has("GL_ARB_vertex_array_object")) {
- // no ARB suffix for GL_ARB_vertex_array_object
- GET_PROC(BindVertexArray);
- GET_PROC(DeleteVertexArrays);
- GET_PROC(GenVertexArrays);
- }
+private:
+ GLLoader fLoader;
+};
- if (ver >= GR_GL_VER(3,3) || extensions.has("GL_ARB_timer_query")) {
- // ARB extension doesn't use the ARB suffix on the function name
- GET_PROC(QueryCounter);
- GET_PROC(GetQueryObjecti64v);
- GET_PROC(GetQueryObjectui64v);
- } else if (extensions.has("GL_EXT_timer_query")) {
- GET_PROC_SUFFIX(GetQueryObjecti64v, EXT);
- GET_PROC_SUFFIX(GetQueryObjectui64v, EXT);
- }
+static GrGLFuncPtr mac_get_gl_proc(void* ctx, const char name[]) {
+ SkASSERT(NULL != ctx);
+ const GLProcGetter* getter = (const GLProcGetter*) ctx;
+ return getter->getProc(name);
+}
- if (ver >= GR_GL_VER(3,0) || extensions.has("GL_ARB_framebuffer_object")) {
- // ARB extension doesn't use the ARB suffix on the function names
- GET_PROC(GenFramebuffers);
- GET_PROC(GetFramebufferAttachmentParameteriv);
- GET_PROC(GetRenderbufferParameteriv);
- GET_PROC(BindFramebuffer);
- GET_PROC(FramebufferTexture2D);
- GET_PROC(CheckFramebufferStatus);
- GET_PROC(DeleteFramebuffers);
- GET_PROC(RenderbufferStorage);
- GET_PROC(GenRenderbuffers);
- GET_PROC(DeleteRenderbuffers);
- GET_PROC(FramebufferRenderbuffer);
- GET_PROC(BindRenderbuffer);
- GET_PROC(RenderbufferStorageMultisample);
- GET_PROC(BlitFramebuffer);
- } else {
- if (extensions.has("GL_EXT_framebuffer_object")) {
- GET_PROC_SUFFIX(GenFramebuffers, EXT);
- GET_PROC_SUFFIX(GetFramebufferAttachmentParameteriv, EXT);
- GET_PROC_SUFFIX(GetRenderbufferParameteriv, EXT);
- GET_PROC_SUFFIX(BindFramebuffer, EXT);
- GET_PROC_SUFFIX(FramebufferTexture2D, EXT);
- GET_PROC_SUFFIX(CheckFramebufferStatus, EXT);
- GET_PROC_SUFFIX(DeleteFramebuffers, EXT);
- GET_PROC_SUFFIX(RenderbufferStorage, EXT);
- GET_PROC_SUFFIX(GenRenderbuffers, EXT);
- GET_PROC_SUFFIX(DeleteRenderbuffers, EXT);
- GET_PROC_SUFFIX(FramebufferRenderbuffer, EXT);
- GET_PROC_SUFFIX(BindRenderbuffer, EXT);
- }
- if (extensions.has("GL_EXT_framebuffer_multisample")) {
- GET_PROC_SUFFIX(RenderbufferStorageMultisample, EXT);
- }
- if (extensions.has("GL_EXT_framebuffer_blit")) {
- GET_PROC_SUFFIX(BlitFramebuffer, EXT);
- }
- }
- if (ver >= GR_GL_VER(3,3) || extensions.has("GL_ARB_blend_func_extended")) {
- // ARB extension doesn't use the ARB suffix on the function name
- GET_PROC(BindFragDataLocationIndexed);
- }
- }
- glInterface.get()->ref();
- return glInterface.get();
+const GrGLInterface* GrGLCreateNativeInterface() {
+ GLProcGetter getter;
+ return GrGLAssembleGLInterface(&getter, mac_get_gl_proc);
}
diff --git a/chromium/third_party/skia/src/gpu/gl/mesa/GrGLCreateMesaInterface.cpp b/chromium/third_party/skia/src/gpu/gl/mesa/GrGLCreateMesaInterface.cpp
index 31f88d5e9e3..a95b6fc8695 100644
--- a/chromium/third_party/skia/src/gpu/gl/mesa/GrGLCreateMesaInterface.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/mesa/GrGLCreateMesaInterface.cpp
@@ -6,223 +6,20 @@
* found in the LICENSE file.
*/
-#include "gl/GrGLExtensions.h"
-#include "gl/GrGLInterface.h"
+#include "gl/GrGLAssembleInterface.h"
#include "../GrGLUtil.h"
-#define GL_GLEXT_PROTOTYPES
#include "osmesa_wrapper.h"
-#define GR_GL_GET_PROC(F) interface->f ## F = (GrGL ## F ## Proc) \
- OSMesaGetProcAddress("gl" #F);
-#define GR_GL_GET_PROC_SUFFIX(F, S) interface->f ## F = (GrGL ## F ## Proc) \
- OSMesaGetProcAddress("gl" #F #S);
-
-// We use OSMesaGetProcAddress for every gl function to avoid accidentally using
-// non-Mesa gl functions.
+static GrGLFuncPtr osmesa_get(void* ctx, const char name[]) {
+ SkASSERT(NULL == ctx);
+ SkASSERT(NULL != OSMesaGetCurrentContext());
+ return OSMesaGetProcAddress(name);
+}
const GrGLInterface* GrGLCreateMesaInterface() {
- if (NULL != OSMesaGetCurrentContext()) {
-
- GrGLGetStringProc getString = (GrGLGetStringProc) OSMesaGetProcAddress("glGetString");
- GrGLGetStringiProc getStringi = (GrGLGetStringiProc) OSMesaGetProcAddress("glGetStringi");
- GrGLGetIntegervProc getIntegerv =
- (GrGLGetIntegervProc) OSMesaGetProcAddress("glGetIntegerv");
-
- GrGLExtensions extensions;
- if (!extensions.init(kDesktop_GrGLBinding, getString, getStringi, getIntegerv)) {
- return NULL;
- }
-
- const char* versionString = (const char*) getString(GL_VERSION);
- GrGLVersion glVer = GrGLGetVersionFromString(versionString);
-
- if (glVer < GR_GL_VER(1,5)) {
- // We must have array and element_array buffer objects.
- return NULL;
- }
- GrGLInterface* interface = new GrGLInterface();
-
- GR_GL_GET_PROC(ActiveTexture);
- GR_GL_GET_PROC(BeginQuery);
- GR_GL_GET_PROC(AttachShader);
- GR_GL_GET_PROC(BindAttribLocation);
- GR_GL_GET_PROC(BindBuffer);
- GR_GL_GET_PROC(BindFragDataLocation);
- GR_GL_GET_PROC(BindTexture);
- GR_GL_GET_PROC(BlendFunc);
-
- if (glVer >= GR_GL_VER(1,4) ||
- extensions.has("GL_ARB_imaging") ||
- extensions.has("GL_EXT_blend_color")) {
- GR_GL_GET_PROC(BlendColor);
- }
-
- GR_GL_GET_PROC(BufferData);
- GR_GL_GET_PROC(BufferSubData);
- GR_GL_GET_PROC(Clear);
- GR_GL_GET_PROC(ClearColor);
- GR_GL_GET_PROC(ClearStencil);
- GR_GL_GET_PROC(ClientActiveTexture);
- GR_GL_GET_PROC(ColorMask);
- GR_GL_GET_PROC(CompileShader);
- GR_GL_GET_PROC(CompressedTexImage2D);
- GR_GL_GET_PROC(CopyTexSubImage2D);
- GR_GL_GET_PROC(CreateProgram);
- GR_GL_GET_PROC(CreateShader);
- GR_GL_GET_PROC(CullFace);
- GR_GL_GET_PROC(DeleteBuffers);
- GR_GL_GET_PROC(DeleteProgram);
- GR_GL_GET_PROC(DeleteQueries);
- GR_GL_GET_PROC(DeleteShader);
- GR_GL_GET_PROC(DeleteTextures);
- GR_GL_GET_PROC(DepthMask);
- GR_GL_GET_PROC(Disable);
- GR_GL_GET_PROC(DisableClientState);
- GR_GL_GET_PROC(DisableVertexAttribArray);
- GR_GL_GET_PROC(DrawArrays);
- GR_GL_GET_PROC(DrawBuffer);
- GR_GL_GET_PROC(DrawBuffers);
- GR_GL_GET_PROC(DrawElements);
- GR_GL_GET_PROC(Enable);
- GR_GL_GET_PROC(EnableClientState);
- GR_GL_GET_PROC(EnableVertexAttribArray);
- GR_GL_GET_PROC(EndQuery);
- GR_GL_GET_PROC(Finish);
- GR_GL_GET_PROC(Flush);
- GR_GL_GET_PROC(FrontFace);
- GR_GL_GET_PROC(GenBuffers);
- GR_GL_GET_PROC(GenerateMipmap);
- GR_GL_GET_PROC(GenQueries);
- GR_GL_GET_PROC(GetBufferParameteriv);
- GR_GL_GET_PROC(GetError);
- GR_GL_GET_PROC(GetIntegerv);
- GR_GL_GET_PROC(GetProgramInfoLog);
- GR_GL_GET_PROC(GetProgramiv);
- if (glVer >= GR_GL_VER(3,3) || extensions.has("GL_ARB_timer_query")) {
- GR_GL_GET_PROC(GetQueryObjecti64v);
- GR_GL_GET_PROC(GetQueryObjectui64v)
- GR_GL_GET_PROC(QueryCounter);
- } else if (extensions.has("GL_EXT_timer_query")) {
- GR_GL_GET_PROC_SUFFIX(GetQueryObjecti64v, EXT);
- GR_GL_GET_PROC_SUFFIX(GetQueryObjectui64v, EXT);
- }
- GR_GL_GET_PROC(GetQueryObjectiv);
- GR_GL_GET_PROC(GetQueryObjectuiv);
- GR_GL_GET_PROC(GetQueryiv);
- GR_GL_GET_PROC(GetShaderInfoLog);
- GR_GL_GET_PROC(GetShaderiv);
- GR_GL_GET_PROC(GetString);
- GR_GL_GET_PROC(GetStringi);
- GR_GL_GET_PROC(GetTexLevelParameteriv);
- GR_GL_GET_PROC(GenTextures);
- GR_GL_GET_PROC(GetUniformLocation);
- GR_GL_GET_PROC(LineWidth);
- GR_GL_GET_PROC(LinkProgram);
- GR_GL_GET_PROC(LoadIdentity);
- GR_GL_GET_PROC(LoadMatrixf);
- GR_GL_GET_PROC(MatrixMode);
- GR_GL_GET_PROC(MapBuffer);
- GR_GL_GET_PROC(PixelStorei);
- GR_GL_GET_PROC(ReadBuffer);
- GR_GL_GET_PROC(ReadPixels);
- GR_GL_GET_PROC(Scissor);
- GR_GL_GET_PROC(ShaderSource);
- GR_GL_GET_PROC(StencilFunc);
- GR_GL_GET_PROC(StencilFuncSeparate);
- GR_GL_GET_PROC(StencilMask);
- GR_GL_GET_PROC(StencilMaskSeparate);
- GR_GL_GET_PROC(StencilOp);
- GR_GL_GET_PROC(StencilOpSeparate);
- GR_GL_GET_PROC(TexGenf);
- GR_GL_GET_PROC(TexGenfv);
- GR_GL_GET_PROC(TexGeni);
- GR_GL_GET_PROC(TexImage2D)
- GR_GL_GET_PROC(TexParameteri);
- GR_GL_GET_PROC(TexParameteriv);
- GR_GL_GET_PROC(TexStorage2D);
- if (NULL == interface->fTexStorage2D) {
- GR_GL_GET_PROC_SUFFIX(TexStorage2D, EXT);
- }
- GR_GL_GET_PROC(TexSubImage2D);
- GR_GL_GET_PROC(Uniform1f);
- GR_GL_GET_PROC(Uniform1i);
- GR_GL_GET_PROC(Uniform1fv);
- GR_GL_GET_PROC(Uniform1iv);
- GR_GL_GET_PROC(Uniform2f);
- GR_GL_GET_PROC(Uniform2i);
- GR_GL_GET_PROC(Uniform2fv);
- GR_GL_GET_PROC(Uniform2iv);
- GR_GL_GET_PROC(Uniform3f);
- GR_GL_GET_PROC(Uniform3i);
- GR_GL_GET_PROC(Uniform3fv);
- GR_GL_GET_PROC(Uniform3iv);
- GR_GL_GET_PROC(Uniform4f);
- GR_GL_GET_PROC(Uniform4i);
- GR_GL_GET_PROC(Uniform4fv);
- GR_GL_GET_PROC(Uniform4iv);
- GR_GL_GET_PROC(UniformMatrix2fv);
- GR_GL_GET_PROC(UniformMatrix3fv);
- GR_GL_GET_PROC(UniformMatrix4fv);
- GR_GL_GET_PROC(UnmapBuffer);
- GR_GL_GET_PROC(UseProgram);
- GR_GL_GET_PROC(VertexAttrib4fv);
- GR_GL_GET_PROC(VertexAttribPointer);
- GR_GL_GET_PROC(VertexPointer);
- GR_GL_GET_PROC(Viewport);
-
- if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_ARB_vertex_array_object")) {
- // no ARB suffix for GL_ARB_vertex_array_object
- GR_GL_GET_PROC(BindVertexArray);
- GR_GL_GET_PROC(DeleteVertexArrays);
- GR_GL_GET_PROC(GenVertexArrays);
- }
-
- // First look for GL3.0 FBO or GL_ARB_framebuffer_object (same since
- // GL_ARB_framebuffer_object doesn't use ARB suffix.)
- if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_ARB_framebuffer_object")) {
- GR_GL_GET_PROC(GenFramebuffers);
- GR_GL_GET_PROC(GetFramebufferAttachmentParameteriv);
- GR_GL_GET_PROC(GetRenderbufferParameteriv);
- GR_GL_GET_PROC(BindFramebuffer);
- GR_GL_GET_PROC(FramebufferTexture2D);
- GR_GL_GET_PROC(CheckFramebufferStatus);
- GR_GL_GET_PROC(DeleteFramebuffers);
- GR_GL_GET_PROC(RenderbufferStorage);
- GR_GL_GET_PROC(GenRenderbuffers);
- GR_GL_GET_PROC(DeleteRenderbuffers);
- GR_GL_GET_PROC(FramebufferRenderbuffer);
- GR_GL_GET_PROC(BindRenderbuffer);
- GR_GL_GET_PROC(RenderbufferStorageMultisample);
- GR_GL_GET_PROC(BlitFramebuffer);
- } else if (extensions.has("GL_EXT_framebuffer_object")) {
- GR_GL_GET_PROC_SUFFIX(GenFramebuffers, EXT);
- GR_GL_GET_PROC_SUFFIX(GetFramebufferAttachmentParameteriv, EXT);
- GR_GL_GET_PROC_SUFFIX(GetRenderbufferParameteriv, EXT);
- GR_GL_GET_PROC_SUFFIX(BindFramebuffer, EXT);
- GR_GL_GET_PROC_SUFFIX(FramebufferTexture2D, EXT);
- GR_GL_GET_PROC_SUFFIX(CheckFramebufferStatus, EXT);
- GR_GL_GET_PROC_SUFFIX(DeleteFramebuffers, EXT);
- GR_GL_GET_PROC_SUFFIX(RenderbufferStorage, EXT);
- GR_GL_GET_PROC_SUFFIX(GenRenderbuffers, EXT);
- GR_GL_GET_PROC_SUFFIX(DeleteRenderbuffers, EXT);
- GR_GL_GET_PROC_SUFFIX(FramebufferRenderbuffer, EXT);
- GR_GL_GET_PROC_SUFFIX(BindRenderbuffer, EXT);
- if (extensions.has("GL_EXT_framebuffer_multisample")) {
- GR_GL_GET_PROC_SUFFIX(RenderbufferStorageMultisample, EXT);
- }
- if (extensions.has("GL_EXT_framebuffer_blit")) {
- GR_GL_GET_PROC_SUFFIX(BlitFramebuffer, EXT);
- }
- } else {
- // we must have FBOs
- delete interface;
- return NULL;
- }
- GR_GL_GET_PROC(BindFragDataLocationIndexed);
- interface->fBindingsExported = kDesktop_GrGLBinding;
- return interface;
- } else {
+ if (NULL == OSMesaGetCurrentContext()) {
return NULL;
}
+ return GrGLAssembleGLInterface(NULL, osmesa_get);
}
diff --git a/chromium/third_party/skia/src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp b/chromium/third_party/skia/src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp
index a71922e012a..ddbfe5de294 100644
--- a/chromium/third_party/skia/src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp
@@ -1,284 +1,25 @@
-
/*
- * Copyright 2011 Google Inc.
+ * Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
-#include "gl/GrGLExtensions.h"
#include "gl/GrGLInterface.h"
-#include "../GrGLUtil.h"
+#include "gl/GrGLAssembleInterface.h"
#include <GL/glx.h>
-#include <GL/gl.h>
-#include <GL/glext.h>
-#include <GL/glu.h>
-#define GR_GL_GET_PROC(F) interface->f ## F = (GrGL ## F ## Proc) \
- glXGetProcAddress(reinterpret_cast<const GLubyte*>("gl" #F));
-#define GR_GL_GET_PROC_SUFFIX(F, S) interface->f ## F = (GrGL ## F ## Proc) \
- glXGetProcAddress(reinterpret_cast<const GLubyte*>("gl" #F #S));
+static GrGLFuncPtr glx_get(void* ctx, const char name[]) {
+ SkASSERT(NULL == ctx);
+ SkASSERT(NULL != glXGetCurrentContext());
+ return glXGetProcAddress(reinterpret_cast<const GLubyte*>(name));
+}
const GrGLInterface* GrGLCreateNativeInterface() {
- if (NULL != glXGetCurrentContext()) {
-
- const char* versionString = (const char*) glGetString(GL_VERSION);
- GrGLVersion glVer = GrGLGetVersionFromString(versionString);
-
- // This may or may not succeed depending on the gl version.
- GrGLGetStringiProc glGetStringi =
- (GrGLGetStringiProc) glXGetProcAddress(reinterpret_cast<const GLubyte*>("glGetStringi"));
-
- GrGLExtensions extensions;
- if (!extensions.init(kDesktop_GrGLBinding, glGetString, glGetStringi, glGetIntegerv)) {
- return NULL;
- }
-
- if (glVer < GR_GL_VER(1,5)) {
- // We must have array and element_array buffer objects.
- return NULL;
- }
-
- GrGLInterface* interface = new GrGLInterface();
-
- interface->fActiveTexture = glActiveTexture;
- GR_GL_GET_PROC(AttachShader);
- GR_GL_GET_PROC(BindAttribLocation);
- GR_GL_GET_PROC(BindBuffer);
- GR_GL_GET_PROC(BindFragDataLocation);
- GR_GL_GET_PROC(BeginQuery);
- interface->fBindTexture = glBindTexture;
- interface->fBlendFunc = glBlendFunc;
-
- if (glVer >= GR_GL_VER(1,4) ||
- extensions.has("GL_ARB_imaging") ||
- extensions.has("GL_EXT_blend_color")) {
- GR_GL_GET_PROC(BlendColor);
- }
-
- GR_GL_GET_PROC(BufferData);
- GR_GL_GET_PROC(BufferSubData);
- interface->fClear = glClear;
- interface->fClearColor = glClearColor;
- interface->fClearStencil = glClearStencil;
- interface->fClientActiveTexture = glClientActiveTexture;
- interface->fColorMask = glColorMask;
- GR_GL_GET_PROC(CompileShader);
- interface->fCompressedTexImage2D = glCompressedTexImage2D;
- interface->fCopyTexSubImage2D = glCopyTexSubImage2D;
- GR_GL_GET_PROC(CreateProgram);
- GR_GL_GET_PROC(CreateShader);
- interface->fCullFace = glCullFace;
- GR_GL_GET_PROC(DeleteBuffers);
- GR_GL_GET_PROC(DeleteProgram);
- GR_GL_GET_PROC(DeleteQueries);
- GR_GL_GET_PROC(DeleteShader);
- interface->fDeleteTextures = glDeleteTextures;
- interface->fDepthMask = glDepthMask;
- interface->fDisable = glDisable;
- interface->fDisableClientState = glDisableClientState;
- GR_GL_GET_PROC(DisableVertexAttribArray);
- interface->fDrawArrays = glDrawArrays;
- interface->fDrawBuffer = glDrawBuffer;
- GR_GL_GET_PROC(DrawBuffers);
- interface->fDrawElements = glDrawElements;
- interface->fEnable = glEnable;
- interface->fEnableClientState = glEnableClientState;
- GR_GL_GET_PROC(EnableVertexAttribArray);
- GR_GL_GET_PROC(EndQuery);
- interface->fFinish = glFinish;
- interface->fFlush = glFlush;
- interface->fFrontFace = glFrontFace;
- GR_GL_GET_PROC(GenBuffers);
- GR_GL_GET_PROC(GenerateMipmap);
- GR_GL_GET_PROC(GetBufferParameteriv);
- interface->fGetError = glGetError;
- interface->fGetIntegerv = glGetIntegerv;
- GR_GL_GET_PROC(GetQueryObjectiv);
- GR_GL_GET_PROC(GetQueryObjectuiv);
- if (glVer >= GR_GL_VER(3,3) || extensions.has("GL_ARB_timer_query")) {
- GR_GL_GET_PROC(GetQueryObjecti64v);
- GR_GL_GET_PROC(GetQueryObjectui64v);
- GR_GL_GET_PROC(QueryCounter);
- } else if (extensions.has("GL_EXT_timer_query")) {
- GR_GL_GET_PROC_SUFFIX(GetQueryObjecti64v, EXT);
- GR_GL_GET_PROC_SUFFIX(GetQueryObjectui64v, EXT);
- }
- GR_GL_GET_PROC(GetQueryiv);
- GR_GL_GET_PROC(GetProgramInfoLog);
- GR_GL_GET_PROC(GetProgramiv);
- GR_GL_GET_PROC(GetShaderInfoLog);
- GR_GL_GET_PROC(GetShaderiv);
- interface->fGetString = glGetString;
- GR_GL_GET_PROC(GetStringi);
- interface->fGetTexLevelParameteriv = glGetTexLevelParameteriv;
- GR_GL_GET_PROC(GenQueries);
- interface->fGenTextures = glGenTextures;
- GR_GL_GET_PROC(GetUniformLocation);
- interface->fLineWidth = glLineWidth;
- GR_GL_GET_PROC(LinkProgram);
- GR_GL_GET_PROC(MapBuffer);
- interface->fPixelStorei = glPixelStorei;
- interface->fReadBuffer = glReadBuffer;
- interface->fReadPixels = glReadPixels;
- interface->fScissor = glScissor;
- GR_GL_GET_PROC(ShaderSource);
- interface->fStencilFunc = glStencilFunc;
- GR_GL_GET_PROC(StencilFuncSeparate);
- interface->fStencilMask = glStencilMask;
- GR_GL_GET_PROC(StencilMaskSeparate);
- interface->fStencilOp = glStencilOp;
- GR_GL_GET_PROC(StencilOpSeparate);
- interface->fTexImage2D = glTexImage2D;
- interface->fTexGenf = glTexGenf;
- interface->fTexGenfv = glTexGenfv;
- interface->fTexGeni = glTexGeni;
- interface->fTexParameteri = glTexParameteri;
- interface->fTexParameteriv = glTexParameteriv;
- if (glVer >= GR_GL_VER(4,2) || extensions.has("GL_ARB_texture_storage")) {
- GR_GL_GET_PROC(TexStorage2D);
- } else if (extensions.has("GL_EXT_texture_storage")) {
- GR_GL_GET_PROC_SUFFIX(TexStorage2D, EXT);
- }
- interface->fTexSubImage2D = glTexSubImage2D;
- GR_GL_GET_PROC(Uniform1f);
- GR_GL_GET_PROC(Uniform1i);
- GR_GL_GET_PROC(Uniform1fv);
- GR_GL_GET_PROC(Uniform1iv);
- GR_GL_GET_PROC(Uniform2f);
- GR_GL_GET_PROC(Uniform2i);
- GR_GL_GET_PROC(Uniform2fv);
- GR_GL_GET_PROC(Uniform2iv);
- GR_GL_GET_PROC(Uniform3f);
- GR_GL_GET_PROC(Uniform3i);
- GR_GL_GET_PROC(Uniform3fv);
- GR_GL_GET_PROC(Uniform3iv);
- GR_GL_GET_PROC(Uniform4f);
- GR_GL_GET_PROC(Uniform4i);
- GR_GL_GET_PROC(Uniform4fv);
- GR_GL_GET_PROC(Uniform4iv);
- GR_GL_GET_PROC(UniformMatrix2fv);
- GR_GL_GET_PROC(UniformMatrix3fv);
- GR_GL_GET_PROC(UniformMatrix4fv);
- GR_GL_GET_PROC(UnmapBuffer);
- GR_GL_GET_PROC(UseProgram);
- GR_GL_GET_PROC(VertexAttrib4fv);
- GR_GL_GET_PROC(VertexAttribPointer);
- GR_GL_GET_PROC(VertexPointer);
- interface->fViewport = glViewport;
- GR_GL_GET_PROC(BindFragDataLocationIndexed);
-
- if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_ARB_vertex_array_object")) {
- // no ARB suffix for GL_ARB_vertex_array_object
- GR_GL_GET_PROC(BindVertexArray);
- GR_GL_GET_PROC(GenVertexArrays);
- GR_GL_GET_PROC(DeleteVertexArrays);
- }
-
- // First look for GL3.0 FBO or GL_ARB_framebuffer_object (same since
- // GL_ARB_framebuffer_object doesn't use ARB suffix.)
- if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_ARB_framebuffer_object")) {
- GR_GL_GET_PROC(GenFramebuffers);
- GR_GL_GET_PROC(GetFramebufferAttachmentParameteriv);
- GR_GL_GET_PROC(GetRenderbufferParameteriv);
- GR_GL_GET_PROC(BindFramebuffer);
- GR_GL_GET_PROC(FramebufferTexture2D);
- GR_GL_GET_PROC(CheckFramebufferStatus);
- GR_GL_GET_PROC(DeleteFramebuffers);
- GR_GL_GET_PROC(RenderbufferStorage);
- GR_GL_GET_PROC(GenRenderbuffers);
- GR_GL_GET_PROC(DeleteRenderbuffers);
- GR_GL_GET_PROC(FramebufferRenderbuffer);
- GR_GL_GET_PROC(BindRenderbuffer);
- GR_GL_GET_PROC(RenderbufferStorageMultisample);
- GR_GL_GET_PROC(BlitFramebuffer);
- } else if (extensions.has("GL_EXT_framebuffer_object")) {
- GR_GL_GET_PROC_SUFFIX(GenFramebuffers, EXT);
- GR_GL_GET_PROC_SUFFIX(GetFramebufferAttachmentParameteriv, EXT);
- GR_GL_GET_PROC_SUFFIX(GetRenderbufferParameteriv, EXT);
- GR_GL_GET_PROC_SUFFIX(BindFramebuffer, EXT);
- GR_GL_GET_PROC_SUFFIX(FramebufferTexture2D, EXT);
- GR_GL_GET_PROC_SUFFIX(CheckFramebufferStatus, EXT);
- GR_GL_GET_PROC_SUFFIX(DeleteFramebuffers, EXT);
- GR_GL_GET_PROC_SUFFIX(RenderbufferStorage, EXT);
- GR_GL_GET_PROC_SUFFIX(GenRenderbuffers, EXT);
- GR_GL_GET_PROC_SUFFIX(DeleteRenderbuffers, EXT);
- GR_GL_GET_PROC_SUFFIX(FramebufferRenderbuffer, EXT);
- GR_GL_GET_PROC_SUFFIX(BindRenderbuffer, EXT);
- if (extensions.has("GL_EXT_framebuffer_multisample")) {
- GR_GL_GET_PROC_SUFFIX(RenderbufferStorageMultisample, EXT);
- }
- if (extensions.has("GL_EXT_framebuffer_blit")) {
- GR_GL_GET_PROC_SUFFIX(BlitFramebuffer, EXT);
- }
- } else {
- // we must have FBOs
- delete interface;
- return NULL;
- }
-
- GR_GL_GET_PROC(LoadIdentity);
- GR_GL_GET_PROC(LoadMatrixf);
- GR_GL_GET_PROC(MatrixMode);
-
- if (extensions.has("GL_NV_path_rendering")) {
- GR_GL_GET_PROC_SUFFIX(PathCommands, NV);
- GR_GL_GET_PROC_SUFFIX(PathCoords, NV);
- GR_GL_GET_PROC_SUFFIX(PathSubCommands, NV);
- GR_GL_GET_PROC_SUFFIX(PathSubCoords, NV);
- GR_GL_GET_PROC_SUFFIX(PathString, NV);
- GR_GL_GET_PROC_SUFFIX(PathGlyphs, NV);
- GR_GL_GET_PROC_SUFFIX(PathGlyphRange, NV);
- GR_GL_GET_PROC_SUFFIX(WeightPaths, NV);
- GR_GL_GET_PROC_SUFFIX(CopyPath, NV);
- GR_GL_GET_PROC_SUFFIX(InterpolatePaths, NV);
- GR_GL_GET_PROC_SUFFIX(TransformPath, NV);
- GR_GL_GET_PROC_SUFFIX(PathParameteriv, NV);
- GR_GL_GET_PROC_SUFFIX(PathParameteri, NV);
- GR_GL_GET_PROC_SUFFIX(PathParameterfv, NV);
- GR_GL_GET_PROC_SUFFIX(PathParameterf, NV);
- GR_GL_GET_PROC_SUFFIX(PathDashArray, NV);
- GR_GL_GET_PROC_SUFFIX(GenPaths, NV);
- GR_GL_GET_PROC_SUFFIX(DeletePaths, NV);
- GR_GL_GET_PROC_SUFFIX(IsPath, NV);
- GR_GL_GET_PROC_SUFFIX(PathStencilFunc, NV);
- GR_GL_GET_PROC_SUFFIX(PathStencilDepthOffset, NV);
- GR_GL_GET_PROC_SUFFIX(StencilFillPath, NV);
- GR_GL_GET_PROC_SUFFIX(StencilStrokePath, NV);
- GR_GL_GET_PROC_SUFFIX(StencilFillPathInstanced, NV);
- GR_GL_GET_PROC_SUFFIX(StencilStrokePathInstanced, NV);
- GR_GL_GET_PROC_SUFFIX(PathCoverDepthFunc, NV);
- GR_GL_GET_PROC_SUFFIX(PathColorGen, NV);
- GR_GL_GET_PROC_SUFFIX(PathTexGen, NV);
- GR_GL_GET_PROC_SUFFIX(PathFogGen, NV);
- GR_GL_GET_PROC_SUFFIX(CoverFillPath, NV);
- GR_GL_GET_PROC_SUFFIX(CoverStrokePath, NV);
- GR_GL_GET_PROC_SUFFIX(CoverFillPathInstanced, NV);
- GR_GL_GET_PROC_SUFFIX(CoverStrokePathInstanced, NV);
- GR_GL_GET_PROC_SUFFIX(GetPathParameteriv, NV);
- GR_GL_GET_PROC_SUFFIX(GetPathParameterfv, NV);
- GR_GL_GET_PROC_SUFFIX(GetPathCommands, NV);
- GR_GL_GET_PROC_SUFFIX(GetPathCoords, NV);
- GR_GL_GET_PROC_SUFFIX(GetPathDashArray, NV);
- GR_GL_GET_PROC_SUFFIX(GetPathMetrics, NV);
- GR_GL_GET_PROC_SUFFIX(GetPathMetricRange, NV);
- GR_GL_GET_PROC_SUFFIX(GetPathSpacing, NV);
- GR_GL_GET_PROC_SUFFIX(GetPathColorGeniv, NV);
- GR_GL_GET_PROC_SUFFIX(GetPathColorGenfv, NV);
- GR_GL_GET_PROC_SUFFIX(GetPathTexGeniv, NV);
- GR_GL_GET_PROC_SUFFIX(GetPathTexGenfv, NV);
- GR_GL_GET_PROC_SUFFIX(IsPointInFillPath, NV);
- GR_GL_GET_PROC_SUFFIX(IsPointInStrokePath, NV);
- GR_GL_GET_PROC_SUFFIX(GetPathLength, NV);
- GR_GL_GET_PROC_SUFFIX(PointAlongPath, NV);
- }
-
- interface->fBindingsExported = kDesktop_GrGLBinding;
-
- return interface;
- } else {
+ if (NULL == glXGetCurrentContext()) {
return NULL;
}
+ return GrGLAssembleGLInterface(NULL, glx_get);
}
diff --git a/chromium/third_party/skia/src/gpu/gl/win/GrGLCreateNativeInterface_win.cpp b/chromium/third_party/skia/src/gpu/gl/win/GrGLCreateNativeInterface_win.cpp
index 06e406f8597..6adaf1964fc 100644
--- a/chromium/third_party/skia/src/gpu/gl/win/GrGLCreateNativeInterface_win.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/win/GrGLCreateNativeInterface_win.cpp
@@ -6,24 +6,11 @@
* found in the LICENSE file.
*/
-
-#include "gl/GrGLExtensions.h"
#include "gl/GrGLInterface.h"
-#include "gl/GrGLUtil.h"
+#include "gl/GrGLAssembleInterface.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
-/*
- * Windows makes the GL funcs all be __stdcall instead of __cdecl :(
- * This implementation will only work if GR_GL_FUNCTION_TYPE is __stdcall.
- * Otherwise, a springboard would be needed that hides the calling convention.
- */
-
-#define SET_PROC(F) interface->f ## F = (GrGL ## F ## Proc) GetProcAddress(alu.get(), "gl" #F);
-#define WGL_SET_PROC(F) interface->f ## F = (GrGL ## F ## Proc) wglGetProcAddress("gl" #F);
-#define WGL_SET_PROC_SUFFIX(F, S) interface->f ## F = \
- (GrGL ## F ## Proc) wglGetProcAddress("gl" #F #S);
-
class AutoLibraryUnload {
public:
AutoLibraryUnload(const char* moduleName) {
@@ -40,281 +27,48 @@ private:
HMODULE fModule;
};
-const GrGLInterface* GrGLCreateNativeInterface() {
- // wglGetProcAddress requires a context.
- // GL Function pointers retrieved in one context may not be valid in another
- // context. For that reason we create a new GrGLInterface each time we're
- // called.
- AutoLibraryUnload alu("opengl32.dll");
- if (NULL == alu.get()) {
- return NULL;
- }
-
- if (NULL != wglGetCurrentContext()) {
-
- // These should always be present and don't require wglGetProcAddress
- GrGLGetStringProc glGetString =
- (GrGLGetStringProc) GetProcAddress(alu.get(), "glGetString");
- GrGLGetIntegervProc glGetIntegerv =
- (GrGLGetIntegervProc) GetProcAddress(alu.get(), "glGetIntegerv");
- if (NULL == glGetString || NULL == glGetIntegerv) {
- return NULL;
- }
-
- // This may or may not succeed depending on the gl version.
- GrGLGetStringiProc glGetStringi = (GrGLGetStringiProc) wglGetProcAddress("glGetStringi");
-
- GrGLExtensions extensions;
- if (!extensions.init(kDesktop_GrGLBinding, glGetString, glGetStringi, glGetIntegerv)) {
- return NULL;
- }
- const char* versionString = (const char*) glGetString(GR_GL_VERSION);
- GrGLVersion glVer = GrGLGetVersionFromString(versionString);
-
- if (glVer < GR_GL_VER(1,5)) {
- // We must have array and element_array buffer objects.
- return NULL;
- }
- GrGLInterface* interface = new GrGLInterface();
-
- // Functions that are part of GL 1.1 will return NULL in
- // wglGetProcAddress
- SET_PROC(BindTexture)
- SET_PROC(BlendFunc)
-
- if (glVer >= GR_GL_VER(1,4) ||
- extensions.has("GL_ARB_imaging") ||
- extensions.has("GL_EXT_blend_color")) {
- WGL_SET_PROC(BlendColor);
- }
+class GLProcGetter {
+public:
+ GLProcGetter() : fGLLib("opengl32.dll") {}
- SET_PROC(Clear)
- SET_PROC(ClearColor)
- SET_PROC(ClearStencil)
- SET_PROC(ColorMask)
- SET_PROC(CopyTexSubImage2D)
- SET_PROC(CullFace)
- SET_PROC(DeleteTextures)
- SET_PROC(DepthMask)
- SET_PROC(Disable)
- SET_PROC(DisableClientState)
- SET_PROC(DrawArrays)
- SET_PROC(DrawElements)
- SET_PROC(DrawBuffer)
- SET_PROC(Enable)
- SET_PROC(EnableClientState)
- SET_PROC(FrontFace)
- SET_PROC(Finish)
- SET_PROC(Flush)
- SET_PROC(GenTextures)
- SET_PROC(GetError)
- SET_PROC(GetIntegerv)
- SET_PROC(GetString)
- SET_PROC(GetTexLevelParameteriv)
- SET_PROC(LineWidth)
- SET_PROC(LoadIdentity)
- SET_PROC(LoadMatrixf)
- SET_PROC(MatrixMode)
- SET_PROC(PixelStorei)
- SET_PROC(ReadBuffer)
- SET_PROC(ReadPixels)
- SET_PROC(Scissor)
- SET_PROC(StencilFunc)
- SET_PROC(StencilMask)
- SET_PROC(StencilOp)
- SET_PROC(TexGenf)
- SET_PROC(TexGenfv)
- SET_PROC(TexGeni)
- SET_PROC(TexImage2D)
- SET_PROC(TexParameteri)
- SET_PROC(TexParameteriv)
- if (glVer >= GR_GL_VER(4,2) || extensions.has("GL_ARB_texture_storage")) {
- WGL_SET_PROC(TexStorage2D);
- } else if (extensions.has("GL_EXT_texture_storage")) {
- WGL_SET_PROC_SUFFIX(TexStorage2D, EXT);
- }
- SET_PROC(TexSubImage2D)
- SET_PROC(Viewport)
- SET_PROC(VertexPointer)
+ bool isInitialized() const { return NULL != fGLLib.get(); }
- WGL_SET_PROC(ActiveTexture);
- WGL_SET_PROC(AttachShader);
- WGL_SET_PROC(BeginQuery);
- WGL_SET_PROC(BindAttribLocation);
- WGL_SET_PROC(BindBuffer);
- WGL_SET_PROC(BindFragDataLocation);
- WGL_SET_PROC(BufferData);
- WGL_SET_PROC(BufferSubData);
- WGL_SET_PROC(ClientActiveTexture);
- WGL_SET_PROC(CompileShader);
- WGL_SET_PROC(CompressedTexImage2D);
- WGL_SET_PROC(CreateProgram);
- WGL_SET_PROC(CreateShader);
- WGL_SET_PROC(DeleteBuffers);
- WGL_SET_PROC(DeleteQueries);
- WGL_SET_PROC(DeleteProgram);
- WGL_SET_PROC(DeleteShader);
- WGL_SET_PROC(DisableVertexAttribArray);
- WGL_SET_PROC(DrawBuffers);
- WGL_SET_PROC(EnableVertexAttribArray);
- WGL_SET_PROC(EndQuery);
- WGL_SET_PROC(GenBuffers);
- WGL_SET_PROC(GenerateMipmap);
- WGL_SET_PROC(GenQueries);
- WGL_SET_PROC(GetBufferParameteriv);
- WGL_SET_PROC(GetQueryiv);
- WGL_SET_PROC(GetQueryObjectiv);
- WGL_SET_PROC(GetQueryObjectuiv);
- if (glVer > GR_GL_VER(3,3) || extensions.has("GL_ARB_timer_query")) {
- WGL_SET_PROC(GetQueryObjecti64v);
- WGL_SET_PROC(GetQueryObjectui64v);
- WGL_SET_PROC(QueryCounter);
- } else if (extensions.has("GL_EXT_timer_query")) {
- WGL_SET_PROC_SUFFIX(GetQueryObjecti64v, EXT);
- WGL_SET_PROC_SUFFIX(GetQueryObjectui64v, EXT);
+ GrGLFuncPtr getProc(const char name[]) const {
+ GrGLFuncPtr proc;
+ if (NULL != (proc = (GrGLFuncPtr) GetProcAddress(fGLLib.get(), name))) {
+ return proc;
}
- WGL_SET_PROC(GetProgramInfoLog);
- WGL_SET_PROC(GetProgramiv);
- WGL_SET_PROC(GetShaderInfoLog);
- WGL_SET_PROC(GetShaderiv);
- WGL_SET_PROC(GetStringi)
- WGL_SET_PROC(GetUniformLocation);
- WGL_SET_PROC(LinkProgram);
- WGL_SET_PROC(ShaderSource);
- WGL_SET_PROC(StencilFuncSeparate);
- WGL_SET_PROC(StencilMaskSeparate);
- WGL_SET_PROC(StencilOpSeparate);
- WGL_SET_PROC(Uniform1f);
- WGL_SET_PROC(Uniform1i);
- WGL_SET_PROC(Uniform1fv);
- WGL_SET_PROC(Uniform1iv);
- WGL_SET_PROC(Uniform2f);
- WGL_SET_PROC(Uniform2i);
- WGL_SET_PROC(Uniform2fv);
- WGL_SET_PROC(Uniform2iv);
- WGL_SET_PROC(Uniform3f);
- WGL_SET_PROC(Uniform3i);
- WGL_SET_PROC(Uniform3fv);
- WGL_SET_PROC(Uniform3iv);
- WGL_SET_PROC(Uniform4f);
- WGL_SET_PROC(Uniform4i);
- WGL_SET_PROC(Uniform4fv);
- WGL_SET_PROC(Uniform4iv);
- WGL_SET_PROC(UniformMatrix2fv);
- WGL_SET_PROC(UniformMatrix3fv);
- WGL_SET_PROC(UniformMatrix4fv);
- WGL_SET_PROC(UseProgram);
- WGL_SET_PROC(VertexAttrib4fv);
- WGL_SET_PROC(VertexAttribPointer);
- WGL_SET_PROC(BindFragDataLocationIndexed);
-
- if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_ARB_vertex_array_object")) {
- // no ARB suffix for GL_ARB_vertex_array_object
- WGL_SET_PROC(BindVertexArray);
- WGL_SET_PROC(DeleteVertexArrays);
- WGL_SET_PROC(GenVertexArrays);
+ if (NULL != (proc = (GrGLFuncPtr) wglGetProcAddress(name))) {
+ return proc;
}
+ return NULL;
+ }
- // First look for GL3.0 FBO or GL_ARB_framebuffer_object (same since
- // GL_ARB_framebuffer_object doesn't use ARB suffix.)
- if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_ARB_framebuffer_object")) {
- WGL_SET_PROC(GenFramebuffers);
- WGL_SET_PROC(GetFramebufferAttachmentParameteriv);
- WGL_SET_PROC(GetRenderbufferParameteriv);
- WGL_SET_PROC(BindFramebuffer);
- WGL_SET_PROC(FramebufferTexture2D);
- WGL_SET_PROC(CheckFramebufferStatus);
- WGL_SET_PROC(DeleteFramebuffers);
- WGL_SET_PROC(RenderbufferStorage);
- WGL_SET_PROC(GenRenderbuffers);
- WGL_SET_PROC(DeleteRenderbuffers);
- WGL_SET_PROC(FramebufferRenderbuffer);
- WGL_SET_PROC(BindRenderbuffer);
- WGL_SET_PROC(RenderbufferStorageMultisample);
- WGL_SET_PROC(BlitFramebuffer);
- } else if (extensions.has("GL_EXT_framebuffer_object")) {
- WGL_SET_PROC_SUFFIX(GenFramebuffers, EXT);
- WGL_SET_PROC_SUFFIX(GetFramebufferAttachmentParameteriv, EXT);
- WGL_SET_PROC_SUFFIX(GetRenderbufferParameteriv, EXT);
- WGL_SET_PROC_SUFFIX(BindFramebuffer, EXT);
- WGL_SET_PROC_SUFFIX(FramebufferTexture2D, EXT);
- WGL_SET_PROC_SUFFIX(CheckFramebufferStatus, EXT);
- WGL_SET_PROC_SUFFIX(DeleteFramebuffers, EXT);
- WGL_SET_PROC_SUFFIX(RenderbufferStorage, EXT);
- WGL_SET_PROC_SUFFIX(GenRenderbuffers, EXT);
- WGL_SET_PROC_SUFFIX(DeleteRenderbuffers, EXT);
- WGL_SET_PROC_SUFFIX(FramebufferRenderbuffer, EXT);
- WGL_SET_PROC_SUFFIX(BindRenderbuffer, EXT);
- if (extensions.has("GL_EXT_framebuffer_multisample")) {
- WGL_SET_PROC_SUFFIX(RenderbufferStorageMultisample, EXT);
- }
- if (extensions.has("GL_EXT_framebuffer_blit")) {
- WGL_SET_PROC_SUFFIX(BlitFramebuffer, EXT);
- }
- } else {
- // we must have FBOs
- delete interface;
- return NULL;
- }
- WGL_SET_PROC(MapBuffer);
- WGL_SET_PROC(UnmapBuffer);
+private:
+ AutoLibraryUnload fGLLib;
+};
- if (extensions.has("GL_NV_path_rendering")) {
- WGL_SET_PROC_SUFFIX(PathCommands, NV);
- WGL_SET_PROC_SUFFIX(PathCoords, NV);
- WGL_SET_PROC_SUFFIX(PathSubCommands, NV);
- WGL_SET_PROC_SUFFIX(PathSubCoords, NV);
- WGL_SET_PROC_SUFFIX(PathString, NV);
- WGL_SET_PROC_SUFFIX(PathGlyphs, NV);
- WGL_SET_PROC_SUFFIX(PathGlyphRange, NV);
- WGL_SET_PROC_SUFFIX(WeightPaths, NV);
- WGL_SET_PROC_SUFFIX(CopyPath, NV);
- WGL_SET_PROC_SUFFIX(InterpolatePaths, NV);
- WGL_SET_PROC_SUFFIX(TransformPath, NV);
- WGL_SET_PROC_SUFFIX(PathParameteriv, NV);
- WGL_SET_PROC_SUFFIX(PathParameteri, NV);
- WGL_SET_PROC_SUFFIX(PathParameterfv, NV);
- WGL_SET_PROC_SUFFIX(PathParameterf, NV);
- WGL_SET_PROC_SUFFIX(PathDashArray, NV);
- WGL_SET_PROC_SUFFIX(GenPaths, NV);
- WGL_SET_PROC_SUFFIX(DeletePaths, NV);
- WGL_SET_PROC_SUFFIX(IsPath, NV);
- WGL_SET_PROC_SUFFIX(PathStencilFunc, NV);
- WGL_SET_PROC_SUFFIX(PathStencilDepthOffset, NV);
- WGL_SET_PROC_SUFFIX(StencilFillPath, NV);
- WGL_SET_PROC_SUFFIX(StencilStrokePath, NV);
- WGL_SET_PROC_SUFFIX(StencilFillPathInstanced, NV);
- WGL_SET_PROC_SUFFIX(StencilStrokePathInstanced, NV);
- WGL_SET_PROC_SUFFIX(PathCoverDepthFunc, NV);
- WGL_SET_PROC_SUFFIX(PathColorGen, NV);
- WGL_SET_PROC_SUFFIX(PathTexGen, NV);
- WGL_SET_PROC_SUFFIX(PathFogGen, NV);
- WGL_SET_PROC_SUFFIX(CoverFillPath, NV);
- WGL_SET_PROC_SUFFIX(CoverStrokePath, NV);
- WGL_SET_PROC_SUFFIX(CoverFillPathInstanced, NV);
- WGL_SET_PROC_SUFFIX(CoverStrokePathInstanced, NV);
- WGL_SET_PROC_SUFFIX(GetPathParameteriv, NV);
- WGL_SET_PROC_SUFFIX(GetPathParameterfv, NV);
- WGL_SET_PROC_SUFFIX(GetPathCommands, NV);
- WGL_SET_PROC_SUFFIX(GetPathCoords, NV);
- WGL_SET_PROC_SUFFIX(GetPathDashArray, NV);
- WGL_SET_PROC_SUFFIX(GetPathMetrics, NV);
- WGL_SET_PROC_SUFFIX(GetPathMetricRange, NV);
- WGL_SET_PROC_SUFFIX(GetPathSpacing, NV);
- WGL_SET_PROC_SUFFIX(GetPathColorGeniv, NV);
- WGL_SET_PROC_SUFFIX(GetPathColorGenfv, NV);
- WGL_SET_PROC_SUFFIX(GetPathTexGeniv, NV);
- WGL_SET_PROC_SUFFIX(GetPathTexGenfv, NV);
- WGL_SET_PROC_SUFFIX(IsPointInFillPath, NV);
- WGL_SET_PROC_SUFFIX(IsPointInStrokePath, NV);
- WGL_SET_PROC_SUFFIX(GetPathLength, NV);
- WGL_SET_PROC_SUFFIX(PointAlongPath, NV);
- }
+static GrGLFuncPtr win_get_gl_proc(void* ctx, const char name[]) {
+ SkASSERT(NULL != ctx);
+ SkASSERT(NULL != wglGetCurrentContext());
+ const GLProcGetter* getter = (const GLProcGetter*) ctx;
+ return getter->getProc(name);
+}
- interface->fBindingsExported = kDesktop_GrGLBinding;
+/*
+ * Windows makes the GL funcs all be __stdcall instead of __cdecl :(
+ * This implementation will only work if GR_GL_FUNCTION_TYPE is __stdcall.
+ * Otherwise, a springboard would be needed that hides the calling convention.
+ */
+const GrGLInterface* GrGLCreateNativeInterface() {
+ if (NULL == wglGetCurrentContext()) {
+ return NULL;
+ }
- return interface;
- } else {
+ GLProcGetter getter;
+ if (!getter.isInitialized()) {
return NULL;
}
+
+ return GrGLAssembleGLInterface(&getter, win_get_gl_proc);
}
diff --git a/chromium/third_party/skia/src/gpu/gl/win/SkNativeGLContext_win.cpp b/chromium/third_party/skia/src/gpu/gl/win/SkNativeGLContext_win.cpp
index 392c2bc97d8..bae97a780c0 100644
--- a/chromium/third_party/skia/src/gpu/gl/win/SkNativeGLContext_win.cpp
+++ b/chromium/third_party/skia/src/gpu/gl/win/SkNativeGLContext_win.cpp
@@ -86,7 +86,8 @@ const GrGLInterface* SkNativeGLContext::createGLContext() {
return NULL;
}
- if (!(fGlRenderContext = SkCreateWGLContext(fDeviceContext, 0, true))) {
+ // Requesting a Core profile would bar us from using NVPR. So we pass false.
+ if (!(fGlRenderContext = SkCreateWGLContext(fDeviceContext, 0, false))) {
SkDebugf("Could not create rendering context.\n");
this->destroyGLContext();
return NULL;
diff --git a/chromium/third_party/skia/src/image/SkDataPixelRef.cpp b/chromium/third_party/skia/src/image/SkDataPixelRef.cpp
deleted file mode 100644
index c8bfe8083d1..00000000000
--- a/chromium/third_party/skia/src/image/SkDataPixelRef.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkDataPixelRef.h"
-#include "SkData.h"
-#include "SkFlattenableBuffers.h"
-
-SkDataPixelRef::SkDataPixelRef(const SkImageInfo& info, SkData* data)
- : INHERITED(info)
- , fData(data)
-{
- fData->ref();
- this->setPreLocked(const_cast<void*>(fData->data()), NULL);
-}
-
-SkDataPixelRef::~SkDataPixelRef() {
- fData->unref();
-}
-
-void* SkDataPixelRef::onLockPixels(SkColorTable** ct) {
- *ct = NULL;
- return const_cast<void*>(fData->data());
-}
-
-void SkDataPixelRef::onUnlockPixels() {
- // nothing to do
-}
-
-size_t SkDataPixelRef::getAllocatedSizeInBytes() const {
- return fData ? fData->size() : 0;
-}
-
-void SkDataPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
- this->INHERITED::flatten(buffer);
- buffer.writeDataAsByteArray(fData);
-}
-
-SkDataPixelRef::SkDataPixelRef(SkFlattenableReadBuffer& buffer)
- : INHERITED(buffer, NULL) {
- fData = buffer.readByteArrayAsData();
- this->setPreLocked(const_cast<void*>(fData->data()), NULL);
-}
diff --git a/chromium/third_party/skia/src/image/SkDataPixelRef.h b/chromium/third_party/skia/src/image/SkDataPixelRef.h
deleted file mode 100644
index 0f8269c80f3..00000000000
--- a/chromium/third_party/skia/src/image/SkDataPixelRef.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkDataPixelRef_DEFINED
-#define SkDataPixelRef_DEFINED
-
-#include "SkPixelRef.h"
-
-class SkData;
-
-class SkDataPixelRef : public SkPixelRef {
-public:
- SkDataPixelRef(const SkImageInfo&, SkData* data);
- virtual ~SkDataPixelRef();
-
- SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDataPixelRef)
-
-protected:
- virtual void* onLockPixels(SkColorTable**) SK_OVERRIDE;
- virtual void onUnlockPixels() SK_OVERRIDE;
- virtual size_t getAllocatedSizeInBytes() const SK_OVERRIDE;
-
- SkDataPixelRef(SkFlattenableReadBuffer& buffer);
- virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
-
-private:
- SkData* fData;
-
- typedef SkPixelRef INHERITED;
-};
-
-#endif
diff --git a/chromium/third_party/skia/src/image/SkImage.cpp b/chromium/third_party/skia/src/image/SkImage.cpp
index 620922f6450..e0a13f915bd 100644
--- a/chromium/third_party/skia/src/image/SkImage.cpp
+++ b/chromium/third_party/skia/src/image/SkImage.cpp
@@ -39,6 +39,41 @@ void SkImage::draw(SkCanvas* canvas, const SkRect* src, const SkRect& dst,
as_IB(this)->onDrawRectToRect(canvas, src, dst, paint);
}
+const void* SkImage::peekPixels(SkImageInfo* info, size_t* rowBytes) const {
+ SkImageInfo infoStorage;
+ size_t rowBytesStorage;
+ if (NULL == info) {
+ info = &infoStorage;
+ }
+ if (NULL == rowBytes) {
+ rowBytes = &rowBytesStorage;
+ }
+ return as_IB(this)->onPeekPixels(info, rowBytes);
+}
+
+bool SkImage::readPixels(SkBitmap* bitmap, const SkIRect* subset) const {
+ if (NULL == bitmap) {
+ return false;
+ }
+
+ SkIRect bounds = SkIRect::MakeWH(this->width(), this->height());
+
+ // trim against the bitmap, if its already been allocated
+ if (bitmap->pixelRef()) {
+ bounds.fRight = SkMin32(bounds.fRight, bitmap->width());
+ bounds.fBottom = SkMin32(bounds.fBottom, bitmap->height());
+ if (bounds.isEmpty()) {
+ return false;
+ }
+ }
+
+ if (subset && !bounds.intersect(*subset)) {
+ // perhaps we could return true + empty-bitmap?
+ return false;
+ }
+ return as_IB(this)->onReadPixels(bitmap, bounds);
+}
+
GrTexture* SkImage::getTexture() {
return as_IB(this)->onGetTexture();
}
@@ -50,3 +85,52 @@ SkData* SkImage::encode(SkImageEncoder::Type type, int quality) const {
}
return NULL;
}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static bool raster_canvas_supports(const SkImageInfo& info) {
+ switch (info.fColorType) {
+ case kN32_SkColorType:
+ return kUnpremul_SkAlphaType != info.fAlphaType;
+ case kRGB_565_SkColorType:
+ return true;
+ case kAlpha_8_SkColorType:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+bool SkImage_Base::onReadPixels(SkBitmap* bitmap, const SkIRect& subset) const {
+ if (bitmap->pixelRef()) {
+ const SkImageInfo info = bitmap->info();
+ if (kUnknown_SkColorType == info.colorType()) {
+ return false;
+ }
+ if (!raster_canvas_supports(info)) {
+ return false;
+ }
+ } else {
+ const SkImageInfo info = SkImageInfo::MakeN32Premul(subset.width(), subset.height());
+ SkBitmap tmp;
+ if (!tmp.allocPixels(info)) {
+ return false;
+ }
+ *bitmap = tmp;
+ }
+
+ SkRect srcR, dstR;
+ srcR.set(subset);
+ dstR = srcR;
+ dstR.offset(-dstR.left(), -dstR.top());
+
+ SkCanvas canvas(*bitmap);
+
+ SkPaint paint;
+ paint.setXfermodeMode(SkXfermode::kClear_Mode);
+ canvas.drawRect(dstR, paint);
+
+ const_cast<SkImage_Base*>(this)->onDrawRectToRect(&canvas, &srcR, dstR, NULL);
+ return true;
+}
diff --git a/chromium/third_party/skia/src/image/SkImagePriv.cpp b/chromium/third_party/skia/src/image/SkImagePriv.cpp
index 976a5b33335..f5b785877c7 100644
--- a/chromium/third_party/skia/src/image/SkImagePriv.cpp
+++ b/chromium/third_party/skia/src/image/SkImagePriv.cpp
@@ -9,8 +9,9 @@
#include "SkCanvas.h"
#include "SkPicture.h"
-SkBitmap::Config SkImageInfoToBitmapConfig(const SkImageInfo& info) {
- switch (info.fColorType) {
+#ifdef SK_SUPPORT_LEGACY_BITMAP_CONFIG
+SkBitmap::Config SkColorTypeToBitmapConfig(SkColorType colorType) {
+ switch (colorType) {
case kAlpha_8_SkColorType:
return SkBitmap::kA8_Config;
@@ -20,7 +21,7 @@ SkBitmap::Config SkImageInfoToBitmapConfig(const SkImageInfo& info) {
case kRGB_565_SkColorType:
return SkBitmap::kRGB_565_Config;
- case kPMColor_SkColorType:
+ case kN32_SkColorType:
return SkBitmap::kARGB_8888_Config;
case kIndex_8_SkColorType:
@@ -33,9 +34,23 @@ SkBitmap::Config SkImageInfoToBitmapConfig(const SkImageInfo& info) {
return SkBitmap::kNo_Config;
}
+SkColorType SkBitmapConfigToColorType(SkBitmap::Config config) {
+ static const SkColorType gCT[] = {
+ kUnknown_SkColorType, // kNo_Config
+ kAlpha_8_SkColorType, // kA8_Config
+ kIndex_8_SkColorType, // kIndex8_Config
+ kRGB_565_SkColorType, // kRGB_565_Config
+ kARGB_4444_SkColorType, // kARGB_4444_Config
+ kN32_SkColorType, // kARGB_8888_Config
+ };
+ SkASSERT((unsigned)config < SK_ARRAY_COUNT(gCT));
+ return gCT[config];
+}
+#endif
+
SkImage* SkNewImageFromBitmap(const SkBitmap& bm, bool canSharePixelRef) {
- SkImageInfo info;
- if (!bm.asImageInfo(&info)) {
+ const SkImageInfo info = bm.info();
+ if (kUnknown_SkColorType == info.colorType()) {
return NULL;
}
@@ -51,60 +66,3 @@ SkImage* SkNewImageFromBitmap(const SkBitmap& bm, bool canSharePixelRef) {
}
return image;
}
-
-static bool needs_layer(const SkPaint& paint) {
- return 0xFF != paint.getAlpha() ||
- paint.getColorFilter() ||
- paint.getImageFilter() ||
- SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode);
-}
-
-void SkImagePrivDrawPicture(SkCanvas* canvas, SkPicture* picture,
- SkScalar x, SkScalar y, const SkPaint* paint) {
- int saveCount = canvas->getSaveCount();
-
- if (paint && needs_layer(*paint)) {
- SkRect bounds;
- bounds.set(x, y,
- x + SkIntToScalar(picture->width()),
- y + SkIntToScalar(picture->height()));
- canvas->saveLayer(&bounds, paint);
- canvas->translate(x, y);
- } else if (x || y) {
- canvas->save();
- canvas->translate(x, y);
- }
-
- canvas->drawPicture(*picture);
- canvas->restoreToCount(saveCount);
-}
-
-void SkImagePrivDrawPicture(SkCanvas* canvas, SkPicture* picture,
- const SkRect* src, const SkRect& dst, const SkPaint* paint) {
- int saveCount = canvas->getSaveCount();
-
- SkMatrix matrix;
- SkRect tmpSrc;
-
- if (NULL != src) {
- tmpSrc = *src;
- } else {
- tmpSrc.set(0, 0,
- SkIntToScalar(picture->width()),
- SkIntToScalar(picture->height()));
- }
-
- matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
- if (paint && needs_layer(*paint)) {
- canvas->saveLayer(&dst, paint);
- } else {
- canvas->save();
- }
- canvas->concat(matrix);
- if (!paint || !needs_layer(*paint)) {
- canvas->clipRect(tmpSrc);
- }
-
- canvas->drawPicture(*picture);
- canvas->restoreToCount(saveCount);
-}
diff --git a/chromium/third_party/skia/src/image/SkImagePriv.h b/chromium/third_party/skia/src/image/SkImagePriv.h
index bf28f598c50..031832bd0d4 100644
--- a/chromium/third_party/skia/src/image/SkImagePriv.h
+++ b/chromium/third_party/skia/src/image/SkImagePriv.h
@@ -11,10 +11,6 @@
#include "SkBitmap.h"
#include "SkImage.h"
-class SkPicture;
-
-extern SkBitmap::Config SkImageInfoToBitmapConfig(const SkImageInfo&);
-
// Call this if you explicitly want to use/share this pixelRef in the image
extern SkImage* SkNewImageFromPixelRef(const SkImageInfo&, SkPixelRef*,
size_t rowBytes);
@@ -25,24 +21,12 @@ extern SkImage* SkNewImageFromPixelRef(const SkImageInfo&, SkPixelRef*,
* be shared if either the bitmap is marked as immutable, or canSharePixelRef
* is true.
*
- * If the bitmap's config cannot be converted into a corresponding
+ * If the bitmap's colortype cannot be converted into a corresponding
* SkImageInfo, or the bitmap's pixels cannot be accessed, this will return
* NULL.
*/
extern SkImage* SkNewImageFromBitmap(const SkBitmap&, bool canSharePixelRef);
-extern void SkImagePrivDrawPicture(SkCanvas*, SkPicture*,
- SkScalar x, SkScalar y, const SkPaint*);
-
-extern void SkImagePrivDrawPicture(SkCanvas*, SkPicture*,
- const SkRect*, const SkRect&, const SkPaint*);
-
-/**
- * Return an SkImage whose contents are those of the specified picture. Note:
- * The picture itself is unmodified, and may continue to be used for recording
- */
-extern SkImage* SkNewImageFromPicture(const SkPicture*);
-
static inline size_t SkImageMinRowBytes(const SkImageInfo& info) {
return SkAlign4(info.minRowBytes());
}
@@ -52,9 +36,6 @@ static inline size_t SkImageMinRowBytes(const SkImageInfo& info) {
// in which case the surface may need to perform a copy-on-write.
extern SkPixelRef* SkBitmapImageGetPixelRef(SkImage* rasterImage);
-// Given an image created with NewPicture, return its SkPicture.
-extern SkPicture* SkPictureImageGetPicture(SkImage* pictureImage);
-
// Given an image created with NewTexture, return its GrTexture. This
// may be called to see if the surface and the image share the same GrTexture,
// in which case the surface may need to perform a copy-on-write.
diff --git a/chromium/third_party/skia/src/image/SkImage_Base.h b/chromium/third_party/skia/src/image/SkImage_Base.h
index 7bd1f7e6c94..9fdfcd26770 100644
--- a/chromium/third_party/skia/src/image/SkImage_Base.h
+++ b/chromium/third_party/skia/src/image/SkImage_Base.h
@@ -17,6 +17,14 @@ public:
virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) = 0;
virtual void onDrawRectToRect(SkCanvas*, const SkRect* src,
const SkRect& dst, const SkPaint*) = 0;
+
+ // Default impl calls onDraw
+ virtual bool onReadPixels(SkBitmap*, const SkIRect& subset) const;
+
+ virtual const void* onPeekPixels(SkImageInfo*, size_t* /*rowBytes*/) const {
+ return NULL;
+ }
+
virtual GrTexture* onGetTexture() { return NULL; }
// return a read-only copy of the pixels. We promise to not modify them,
diff --git a/chromium/third_party/skia/src/image/SkImage_Codec.cpp b/chromium/third_party/skia/src/image/SkImage_Codec.cpp
index 64f58a6aeff..3d815ce7f43 100644
--- a/chromium/third_party/skia/src/image/SkImage_Codec.cpp
+++ b/chromium/third_party/skia/src/image/SkImage_Codec.cpp
@@ -41,8 +41,7 @@ SkImage_Codec::~SkImage_Codec() {
void SkImage_Codec::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) {
if (!fBitmap.pixelRef()) {
- if (!SkImageDecoder::DecodeMemory(fEncodedData->bytes(), fEncodedData->size(),
- &fBitmap)) {
+ if (!SkImageDecoder::DecodeMemory(fEncodedData->bytes(), fEncodedData->size(), &fBitmap)) {
return;
}
}
@@ -52,8 +51,7 @@ void SkImage_Codec::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPai
void SkImage_Codec::onDrawRectToRect(SkCanvas* canvas, const SkRect* src,
const SkRect& dst, const SkPaint* paint) {
if (!fBitmap.pixelRef()) {
- if (!SkImageDecoder::DecodeMemory(fEncodedData->bytes(), fEncodedData->size(),
- &fBitmap)) {
+ if (!SkImageDecoder::DecodeMemory(fEncodedData->bytes(), fEncodedData->size(), &fBitmap)) {
return;
}
}
@@ -68,8 +66,7 @@ SkImage* SkImage::NewEncodedData(SkData* data) {
}
SkBitmap bitmap;
- if (!SkImageDecoder::DecodeMemory(data->bytes(), data->size(), &bitmap,
- SkBitmap::kNo_Config,
+ if (!SkImageDecoder::DecodeMemory(data->bytes(), data->size(), &bitmap, kUnknown_SkColorType,
SkImageDecoder::kDecodeBounds_Mode)) {
return NULL;
}
diff --git a/chromium/third_party/skia/src/image/SkImage_Gpu.cpp b/chromium/third_party/skia/src/image/SkImage_Gpu.cpp
index ab0a5237fd3..aa08f44260a 100644
--- a/chromium/third_party/skia/src/image/SkImage_Gpu.cpp
+++ b/chromium/third_party/skia/src/image/SkImage_Gpu.cpp
@@ -23,10 +23,7 @@ public:
virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) SK_OVERRIDE;
virtual void onDrawRectToRect(SkCanvas*, const SkRect* src, const SkRect& dst, const SkPaint*) SK_OVERRIDE;
virtual GrTexture* onGetTexture() SK_OVERRIDE;
- virtual bool getROPixels(SkBitmap*) const SK_OVERRIDE {
- // TODO
- return false;
- }
+ virtual bool getROPixels(SkBitmap*) const SK_OVERRIDE;
GrTexture* getTexture() { return fBitmap.getTexture(); }
@@ -61,6 +58,10 @@ GrTexture* SkImage_Gpu::onGetTexture() {
return fBitmap.getTexture();
}
+bool SkImage_Gpu::getROPixels(SkBitmap* dst) const {
+ return fBitmap.copyTo(dst, kN32_SkColorType);
+}
+
///////////////////////////////////////////////////////////////////////////////
SkImage* SkImage::NewTexture(const SkBitmap& bitmap) {
diff --git a/chromium/third_party/skia/src/image/SkImage_Picture.cpp b/chromium/third_party/skia/src/image/SkImage_Picture.cpp
deleted file mode 100644
index 87221de27b5..00000000000
--- a/chromium/third_party/skia/src/image/SkImage_Picture.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkImage_Base.h"
-#include "SkImagePriv.h"
-#include "SkPicture.h"
-
-class SkImage_Picture : public SkImage_Base {
-public:
- SkImage_Picture(SkPicture*);
- virtual ~SkImage_Picture();
-
- virtual void onDraw(SkCanvas*, SkScalar, SkScalar, const SkPaint*) SK_OVERRIDE;
- virtual void onDrawRectToRect(SkCanvas*, const SkRect*, const SkRect&, const SkPaint*) SK_OVERRIDE;
-
- SkPicture* getPicture() { return fPicture; }
-
-private:
- SkPicture* fPicture;
-
- typedef SkImage_Base INHERITED;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-SkImage_Picture::SkImage_Picture(SkPicture* pict) : INHERITED(pict->width(), pict->height()) {
- pict->endRecording();
- pict->ref();
- fPicture = pict;
-}
-
-SkImage_Picture::~SkImage_Picture() {
- fPicture->unref();
-}
-
-void SkImage_Picture::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
- const SkPaint* paint) {
- SkImagePrivDrawPicture(canvas, fPicture, x, y, paint);
-}
-
-void SkImage_Picture::onDrawRectToRect(SkCanvas* canvas, const SkRect* src, const SkRect& dst,
- const SkPaint* paint) {
- SkImagePrivDrawPicture(canvas, fPicture, src, dst, paint);
-}
-
-SkImage* SkNewImageFromPicture(const SkPicture* srcPicture) {
- /**
- * We want to snapshot the playback status of the picture, w/o affecting
- * its ability to continue recording (if needed).
- *
- * Optimally this will shared as much data/buffers as it can with
- * srcPicture, and srcPicture will perform a copy-on-write as needed if it
- * needs to mutate them later on.
- */
- SkAutoTUnref<SkPicture> playback(SkNEW_ARGS(SkPicture, (*srcPicture)));
-
- return SkNEW_ARGS(SkImage_Picture, (playback));
-}
-
-SkPicture* SkPictureImageGetPicture(SkImage* pictureImage) {
- return static_cast<SkImage_Picture*>(pictureImage)->getPicture();
-}
diff --git a/chromium/third_party/skia/src/image/SkImage_Raster.cpp b/chromium/third_party/skia/src/image/SkImage_Raster.cpp
index 807c19e79d4..68fc1b32e6d 100644
--- a/chromium/third_party/skia/src/image/SkImage_Raster.cpp
+++ b/chromium/third_party/skia/src/image/SkImage_Raster.cpp
@@ -10,7 +10,7 @@
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkData.h"
-#include "SkDataPixelRef.h"
+#include "SkMallocPixelRef.h"
class SkImage_Raster : public SkImage_Base {
public:
@@ -31,7 +31,7 @@ public:
return false;
}
- if (SkImageInfoToBitmapConfig(info) == SkBitmap::kNo_Config) {
+ if (kUnknown_SkColorType == info.colorType()) {
return false;
}
@@ -55,6 +55,8 @@ public:
virtual void onDraw(SkCanvas*, SkScalar, SkScalar, const SkPaint*) SK_OVERRIDE;
virtual void onDrawRectToRect(SkCanvas*, const SkRect*, const SkRect&, const SkPaint*) SK_OVERRIDE;
+ virtual bool onReadPixels(SkBitmap*, const SkIRect&) const SK_OVERRIDE;
+ virtual const void* onPeekPixels(SkImageInfo*, size_t* /*rowBytes*/) const SK_OVERRIDE;
virtual bool getROPixels(SkBitmap*) const SK_OVERRIDE;
// exposed for SkSurface_Raster via SkNewImageFromPixelRef
@@ -82,19 +84,29 @@ SkImage* SkImage_Raster::NewEmpty() {
return gEmpty;
}
+static void release_data(void* addr, void* context) {
+ SkData* data = static_cast<SkData*>(context);
+ data->unref();
+}
+
SkImage_Raster::SkImage_Raster(const Info& info, SkData* data, size_t rowBytes)
- : INHERITED(info.fWidth, info.fHeight) {
- fBitmap.setConfig(info, rowBytes);
- fBitmap.setPixelRef(SkNEW_ARGS(SkDataPixelRef, (info, data)))->unref();
+ : INHERITED(info.fWidth, info.fHeight)
+{
+ data->ref();
+ void* addr = const_cast<void*>(data->data());
+ SkColorTable* ctable = NULL;
+
+ fBitmap.installPixels(info, addr, rowBytes, ctable, release_data, data);
fBitmap.setImmutable();
+ fBitmap.lockPixels();
}
SkImage_Raster::SkImage_Raster(const Info& info, SkPixelRef* pr, size_t rowBytes)
-: INHERITED(info.fWidth, info.fHeight) {
- SkBitmap::Config config = SkImageInfoToBitmapConfig(info);
-
- fBitmap.setConfig(config, info.fWidth, info.fHeight, rowBytes, info.fAlphaType);
+ : INHERITED(info.fWidth, info.fHeight)
+{
+ fBitmap.setInfo(info, rowBytes);
fBitmap.setPixelRef(pr);
+ fBitmap.lockPixels();
}
SkImage_Raster::~SkImage_Raster() {}
@@ -103,10 +115,34 @@ void SkImage_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPa
canvas->drawBitmap(fBitmap, x, y, paint);
}
-void SkImage_Raster::onDrawRectToRect(SkCanvas* canvas, const SkRect* src, const SkRect& dst, const SkPaint* paint) {
+void SkImage_Raster::onDrawRectToRect(SkCanvas* canvas, const SkRect* src,
+ const SkRect& dst, const SkPaint* paint) {
canvas->drawBitmapRectToRect(fBitmap, src, dst, paint);
}
+bool SkImage_Raster::onReadPixels(SkBitmap* dst, const SkIRect& subset) const {
+ if (dst->pixelRef()) {
+ return this->INHERITED::onReadPixels(dst, subset);
+ } else {
+ SkBitmap src;
+ if (!fBitmap.extractSubset(&src, subset)) {
+ return false;
+ }
+ return src.copyTo(dst, src.colorType());
+ }
+}
+
+const void* SkImage_Raster::onPeekPixels(SkImageInfo* infoPtr,
+ size_t* rowBytesPtr) const {
+ const SkImageInfo info = fBitmap.info();
+ if ((kUnknown_SkColorType == info.colorType()) || !fBitmap.getPixels()) {
+ return NULL;
+ }
+ *infoPtr = info;
+ *rowBytesPtr = fBitmap.rowBytes();
+ return fBitmap.getPixels();
+}
+
bool SkImage_Raster::getROPixels(SkBitmap* dst) const {
*dst = fBitmap;
return true;
@@ -132,7 +168,7 @@ SkImage* SkImage::NewRasterCopy(const SkImageInfo& info, const void* pixels, siz
}
-SkImage* SkImage::NewRasterData(const SkImageInfo& info, SkData* pixelData, size_t rowBytes) {
+SkImage* SkImage::NewRasterData(const SkImageInfo& info, SkData* data, size_t rowBytes) {
if (!SkImage_Raster::ValidArgs(info, rowBytes)) {
return NULL;
}
@@ -140,17 +176,16 @@ SkImage* SkImage::NewRasterData(const SkImageInfo& info, SkData* pixelData, size
return SkImage_Raster::NewEmpty();
}
// check this after empty-check
- if (NULL == pixelData) {
+ if (NULL == data) {
return NULL;
}
// did they give us enough data?
size_t size = info.fHeight * rowBytes;
- if (pixelData->size() < size) {
+ if (data->size() < size) {
return NULL;
}
- SkAutoDataUnref data(pixelData);
return SkNEW_ARGS(SkImage_Raster, (info, data, rowBytes));
}
diff --git a/chromium/third_party/skia/src/image/SkSurface.cpp b/chromium/third_party/skia/src/image/SkSurface.cpp
index 2dde36b96d9..edc6ef5fa0e 100644
--- a/chromium/third_party/skia/src/image/SkSurface.cpp
+++ b/chromium/third_party/skia/src/image/SkSurface.cpp
@@ -16,6 +16,11 @@ SkSurface_Base::SkSurface_Base(int width, int height) : INHERITED(width, height)
fCachedImage = NULL;
}
+SkSurface_Base::SkSurface_Base(const SkImageInfo& info) : INHERITED(info) {
+ fCachedCanvas = NULL;
+ fCachedImage = NULL;
+}
+
SkSurface_Base::~SkSurface_Base() {
// in case the canvas outsurvives us, we null the callback
if (fCachedCanvas) {
@@ -38,11 +43,7 @@ void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
void SkSurface_Base::aboutToDraw(ContentChangeMode mode) {
this->dirtyGenerationID();
- if (NULL != fCachedCanvas) {
- SkASSERT(fCachedCanvas->getSurfaceBase() == this || \
- NULL == fCachedCanvas->getSurfaceBase());
- fCachedCanvas->setSurfaceBase(NULL);
- }
+ SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
if (NULL != fCachedImage) {
// the surface may need to fork its backend, if its sharing it with
@@ -56,12 +57,13 @@ void SkSurface_Base::aboutToDraw(ContentChangeMode mode) {
// that the next request will get our new contents.
fCachedImage->unref();
fCachedImage = NULL;
+ } else if (kDiscard_ContentChangeMode == mode) {
+ this->onDiscard();
}
}
uint32_t SkSurface_Base::newGenerationID() {
- this->installIntoCanvasForDirtyNotification();
-
+ SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
static int32_t gID;
return sk_atomic_inc(&gID) + 1;
}
@@ -73,8 +75,17 @@ static SkSurface_Base* asSB(SkSurface* surface) {
///////////////////////////////////////////////////////////////////////////////
SkSurface::SkSurface(int width, int height) : fWidth(width), fHeight(height) {
- SkASSERT(width >= 0);
- SkASSERT(height >= 0);
+ SkASSERT(fWidth >= 0);
+ SkASSERT(fHeight >= 0);
+ fGenerationID = 0;
+}
+
+SkSurface::SkSurface(const SkImageInfo& info)
+ : fWidth(info.fWidth)
+ , fHeight(info.fHeight)
+{
+ SkASSERT(fWidth >= 0);
+ SkASSERT(fHeight >= 0);
fGenerationID = 0;
}
@@ -107,3 +118,7 @@ void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y,
const SkPaint* paint) {
return asSB(this)->onDraw(canvas, x, y, paint);
}
+
+const void* SkSurface::peekPixels(SkImageInfo* info, size_t* rowBytes) {
+ return this->getCanvas()->peekPixels(info, rowBytes);
+}
diff --git a/chromium/third_party/skia/src/image/SkSurface_Base.h b/chromium/third_party/skia/src/image/SkSurface_Base.h
index cbae5bc5c4a..2314341f21a 100644
--- a/chromium/third_party/skia/src/image/SkSurface_Base.h
+++ b/chromium/third_party/skia/src/image/SkSurface_Base.h
@@ -14,6 +14,7 @@
class SkSurface_Base : public SkSurface {
public:
SkSurface_Base(int width, int height);
+ explicit SkSurface_Base(const SkImageInfo&);
virtual ~SkSurface_Base();
/**
@@ -46,6 +47,12 @@ public:
virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*);
/**
+ * Called as a performance hint when the Surface is allowed to make it's contents
+ * undefined.
+ */
+ virtual void onDiscard() {}
+
+ /**
* If the surface is about to change, we call this so that our subclass
* can optionally fork their backend (copy-on-write) in case it was
* being shared with the cachedImage.
@@ -66,15 +73,15 @@ private:
friend class SkCanvas;
friend class SkSurface;
- inline void installIntoCanvasForDirtyNotification();
-
typedef SkSurface INHERITED;
};
SkCanvas* SkSurface_Base::getCachedCanvas() {
if (NULL == fCachedCanvas) {
fCachedCanvas = this->onNewCanvas();
- this->installIntoCanvasForDirtyNotification();
+ if (NULL != fCachedCanvas) {
+ fCachedCanvas->setSurfaceBase(this);
+ }
}
return fCachedCanvas;
}
@@ -82,15 +89,9 @@ SkCanvas* SkSurface_Base::getCachedCanvas() {
SkImage* SkSurface_Base::getCachedImage() {
if (NULL == fCachedImage) {
fCachedImage = this->onNewImageSnapshot();
- this->installIntoCanvasForDirtyNotification();
+ SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
}
return fCachedImage;
}
-void SkSurface_Base::installIntoCanvasForDirtyNotification() {
- if (NULL != fCachedCanvas) {
- fCachedCanvas->setSurfaceBase(this);
- }
-}
-
#endif
diff --git a/chromium/third_party/skia/src/image/SkSurface_Gpu.cpp b/chromium/third_party/skia/src/image/SkSurface_Gpu.cpp
index e673cef6703..a34b774397b 100644
--- a/chromium/third_party/skia/src/image/SkSurface_Gpu.cpp
+++ b/chromium/third_party/skia/src/image/SkSurface_Gpu.cpp
@@ -14,8 +14,7 @@ class SkSurface_Gpu : public SkSurface_Base {
public:
SK_DECLARE_INST_COUNT(SkSurface_Gpu)
- SkSurface_Gpu(GrContext*, const SkImageInfo&, int sampleCount);
- SkSurface_Gpu(GrContext*, GrRenderTarget*);
+ SkSurface_Gpu(GrRenderTarget*, bool cached, TextRenderMode trm);
virtual ~SkSurface_Gpu();
virtual SkCanvas* onNewCanvas() SK_OVERRIDE;
@@ -24,6 +23,7 @@ public:
virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y,
const SkPaint*) SK_OVERRIDE;
virtual void onCopyOnWrite(ContentChangeMode) SK_OVERRIDE;
+ virtual void onDiscard() SK_OVERRIDE;
private:
SkGpuDevice* fDevice;
@@ -33,21 +33,12 @@ private:
///////////////////////////////////////////////////////////////////////////////
-SkSurface_Gpu::SkSurface_Gpu(GrContext* ctx, const SkImageInfo& info,
- int sampleCount)
- : INHERITED(info.fWidth, info.fHeight) {
- SkBitmap::Config config = SkImageInfoToBitmapConfig(info);
-
- fDevice = SkNEW_ARGS(SkGpuDevice, (ctx, config, info.fWidth, info.fHeight, sampleCount));
-
- if (!SkAlphaTypeIsOpaque(info.fAlphaType)) {
- fDevice->clear(0x0);
- }
-}
-
-SkSurface_Gpu::SkSurface_Gpu(GrContext* ctx, GrRenderTarget* renderTarget)
+SkSurface_Gpu::SkSurface_Gpu(GrRenderTarget* renderTarget, bool cached, TextRenderMode trm)
: INHERITED(renderTarget->width(), renderTarget->height()) {
- fDevice = SkNEW_ARGS(SkGpuDevice, (ctx, renderTarget));
+ int flags = 0;
+ flags |= cached ? SkGpuDevice::kCached_Flag : 0;
+ flags |= (kDistanceField_TextRenderMode == trm) ? SkGpuDevice::kDFFonts_Flag : 0;
+ fDevice = SkGpuDevice::Create(renderTarget, flags);
if (kRGB_565_GrPixelConfig != renderTarget->config()) {
fDevice->clear(0x0);
@@ -85,44 +76,49 @@ void SkSurface_Gpu::onCopyOnWrite(ContentChangeMode mode) {
// are we sharing our render target with the image?
SkASSERT(NULL != this->getCachedImage());
if (rt->asTexture() == SkTextureImageGetTexture(this->getCachedImage())) {
+ // We call createCompatibleDevice because it uses the texture cache. This isn't
+ // necessarily correct (http://skbug.com/2252), but never using the cache causes
+ // a Chromium regression. (http://crbug.com/344020)
SkGpuDevice* newDevice = static_cast<SkGpuDevice*>(
- fDevice->createCompatibleDevice(fDevice->config(), fDevice->width(),
- fDevice->height(), fDevice->isOpaque()));
+ fDevice->createCompatibleDevice(fDevice->imageInfo()));
SkAutoTUnref<SkGpuDevice> aurd(newDevice);
if (kRetain_ContentChangeMode == mode) {
- fDevice->context()->copyTexture(rt->asTexture(),
- reinterpret_cast<GrRenderTarget*>(newDevice->accessRenderTarget()));
+ fDevice->context()->copyTexture(rt->asTexture(), newDevice->accessRenderTarget());
}
SkASSERT(NULL != this->getCachedCanvas());
SkASSERT(this->getCachedCanvas()->getDevice() == fDevice);
- this->getCachedCanvas()->setDevice(newDevice);
+
+ this->getCachedCanvas()->setRootDevice(newDevice);
SkRefCnt_SafeAssign(fDevice, newDevice);
+ } else if (kDiscard_ContentChangeMode == mode) {
+ this->SkSurface_Gpu::onDiscard();
}
}
+void SkSurface_Gpu::onDiscard() {
+ fDevice->accessRenderTarget()->discard();
+}
+
///////////////////////////////////////////////////////////////////////////////
-SkSurface* SkSurface::NewRenderTargetDirect(GrContext* ctx,
- GrRenderTarget* target) {
- if (NULL == ctx || NULL == target) {
+SkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget* target, TextRenderMode trm) {
+ if (NULL == target) {
return NULL;
}
-
- return SkNEW_ARGS(SkSurface_Gpu, (ctx, target));
+ return SkNEW_ARGS(SkSurface_Gpu, (target, false, trm));
}
-SkSurface* SkSurface::NewRenderTarget(GrContext* ctx, const SkImageInfo& info, int sampleCount) {
+SkSurface* SkSurface::NewRenderTarget(GrContext* ctx, const SkImageInfo& info, int sampleCount,
+ TextRenderMode trm) {
if (NULL == ctx) {
return NULL;
}
- SkBitmap::Config config = SkImageInfoToBitmapConfig(info);
-
GrTextureDesc desc;
desc.fFlags = kRenderTarget_GrTextureFlagBit | kCheckAllocation_GrTextureFlagBit;
- desc.fWidth = info.fWidth;
- desc.fHeight = info.fHeight;
- desc.fConfig = SkBitmapConfig2GrPixelConfig(config);
+ desc.fWidth = info.width();
+ desc.fHeight = info.height();
+ desc.fConfig = SkImageInfo2GrPixelConfig(info);
desc.fSampleCnt = sampleCount;
SkAutoTUnref<GrTexture> tex(ctx->createUncachedTexture(desc, NULL, 0));
@@ -130,5 +126,27 @@ SkSurface* SkSurface::NewRenderTarget(GrContext* ctx, const SkImageInfo& info, i
return NULL;
}
- return SkNEW_ARGS(SkSurface_Gpu, (ctx, tex->asRenderTarget()));
+ return SkNEW_ARGS(SkSurface_Gpu, (tex->asRenderTarget(), false, trm));
+}
+
+SkSurface* SkSurface::NewScratchRenderTarget(GrContext* ctx, const SkImageInfo& info,
+ int sampleCount, TextRenderMode trm) {
+ if (NULL == ctx) {
+ return NULL;
+ }
+
+ GrTextureDesc desc;
+ desc.fFlags = kRenderTarget_GrTextureFlagBit | kCheckAllocation_GrTextureFlagBit;
+ desc.fWidth = info.width();
+ desc.fHeight = info.height();
+ desc.fConfig = SkImageInfo2GrPixelConfig(info);
+ desc.fSampleCnt = sampleCount;
+
+ SkAutoTUnref<GrTexture> tex(ctx->lockAndRefScratchTexture(desc, GrContext::kExact_ScratchTexMatch));
+
+ if (NULL == tex) {
+ return NULL;
+ }
+
+ return SkNEW_ARGS(SkSurface_Gpu, (tex->asRenderTarget(), true, trm));
}
diff --git a/chromium/third_party/skia/src/image/SkSurface_Picture.cpp b/chromium/third_party/skia/src/image/SkSurface_Picture.cpp
deleted file mode 100644
index 8cfe6e87d56..00000000000
--- a/chromium/third_party/skia/src/image/SkSurface_Picture.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkSurface_Base.h"
-#include "SkCanvas.h"
-#include "SkImagePriv.h"
-#include "SkPicture.h"
-
-/**
- * What does it mean to ask for more than one canvas from a picture?
- * How do we return an Image and then "continue" recording?
- */
-class SkSurface_Picture : public SkSurface_Base {
-public:
- SkSurface_Picture(int width, int height);
- virtual ~SkSurface_Picture();
-
- virtual SkCanvas* onNewCanvas() SK_OVERRIDE;
- virtual SkSurface* onNewSurface(const SkImageInfo&) SK_OVERRIDE;
- virtual SkImage* onNewImageSnapshot() SK_OVERRIDE;
- virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y,
- const SkPaint*) SK_OVERRIDE;
- virtual void onCopyOnWrite(ContentChangeMode) SK_OVERRIDE;
-
-private:
- SkPicture* fPicture;
-
- typedef SkSurface_Base INHERITED;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-SkSurface_Picture::SkSurface_Picture(int width, int height) : INHERITED(width, height) {
- fPicture = NULL;
-}
-
-SkSurface_Picture::~SkSurface_Picture() {
- SkSafeUnref(fPicture);
-}
-
-SkCanvas* SkSurface_Picture::onNewCanvas() {
- if (!fPicture) {
- fPicture = SkNEW(SkPicture);
- }
- SkCanvas* canvas = fPicture->beginRecording(this->width(), this->height());
- canvas->ref(); // our caller will call unref()
- return canvas;
-}
-
-SkSurface* SkSurface_Picture::onNewSurface(const SkImageInfo& info) {
- return SkSurface::NewPicture(info.fWidth, info.fHeight);
-}
-
-SkImage* SkSurface_Picture::onNewImageSnapshot() {
- if (fPicture) {
- return SkNewImageFromPicture(fPicture);
- } else {
- SkImageInfo info;
- info.fWidth = info.fHeight = 0;
- info.fColorType = kPMColor_SkColorType;
- info.fAlphaType = kOpaque_SkAlphaType;
- return SkImage::NewRasterCopy(info, NULL, 0);
- }
-}
-
-void SkSurface_Picture::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
- const SkPaint* paint) {
- if (!fPicture) {
- return;
- }
- SkImagePrivDrawPicture(canvas, fPicture, x, y, paint);
-}
-
-void SkSurface_Picture::onCopyOnWrite(ContentChangeMode /*mode*/) {
- // We always spawn a copy of the recording picture when we
- // are asked for a snapshot, so we never need to do anything here.
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-
-SkSurface* SkSurface::NewPicture(int width, int height) {
- if ((width | height) < 0) {
- return NULL;
- }
-
- return SkNEW_ARGS(SkSurface_Picture, (width, height));
-}
diff --git a/chromium/third_party/skia/src/image/SkSurface_Raster.cpp b/chromium/third_party/skia/src/image/SkSurface_Raster.cpp
index 61ade6f46c8..0b6efe19fe6 100644
--- a/chromium/third_party/skia/src/image/SkSurface_Raster.cpp
+++ b/chromium/third_party/skia/src/image/SkSurface_Raster.cpp
@@ -18,7 +18,7 @@ public:
static bool Valid(const SkImageInfo&, size_t rb = kIgnoreRowBytesValue);
SkSurface_Raster(const SkImageInfo&, void*, size_t rb);
- SkSurface_Raster(const SkImageInfo&, SkPixelRef*, size_t rb);
+ SkSurface_Raster(SkPixelRef*);
virtual SkCanvas* onNewCanvas() SK_OVERRIDE;
virtual SkSurface* onNewSurface(const SkImageInfo&) SK_OVERRIDE;
@@ -39,25 +39,21 @@ private:
bool SkSurface_Raster::Valid(const SkImageInfo& info, size_t rowBytes) {
static const size_t kMaxTotalSize = SK_MaxS32;
- SkBitmap::Config config = SkImageInfoToBitmapConfig(info);
-
int shift = 0;
- switch (config) {
- case SkBitmap::kA8_Config:
+ switch (info.fColorType) {
+ case kAlpha_8_SkColorType:
shift = 0;
break;
- case SkBitmap::kRGB_565_Config:
+ case kRGB_565_SkColorType:
shift = 1;
break;
- case SkBitmap::kARGB_8888_Config:
+ case kN32_SkColorType:
shift = 2;
break;
default:
return false;
}
- // TODO: examine colorspace
-
if (kIgnoreRowBytesValue == rowBytes) {
return true;
}
@@ -72,7 +68,7 @@ bool SkSurface_Raster::Valid(const SkImageInfo& info, size_t rowBytes) {
return false;
}
- uint64_t size = (uint64_t)info.fHeight * rowBytes;
+ uint64_t size = sk_64_mul(info.fHeight, rowBytes);
if (size > kMaxTotalSize) {
return false;
}
@@ -81,21 +77,22 @@ bool SkSurface_Raster::Valid(const SkImageInfo& info, size_t rowBytes) {
}
SkSurface_Raster::SkSurface_Raster(const SkImageInfo& info, void* pixels, size_t rb)
- : INHERITED(info.fWidth, info.fHeight) {
- SkBitmap::Config config = SkImageInfoToBitmapConfig(info);
- fBitmap.setConfig(config, info.fWidth, info.fHeight, rb, info.fAlphaType);
- fBitmap.setPixels(pixels);
+ : INHERITED(info)
+{
+ fBitmap.installPixels(info, pixels, rb);
fWeOwnThePixels = false; // We are "Direct"
}
-SkSurface_Raster::SkSurface_Raster(const SkImageInfo& info, SkPixelRef* pr, size_t rb)
- : INHERITED(info.fWidth, info.fHeight) {
- SkBitmap::Config config = SkImageInfoToBitmapConfig(info);
- fBitmap.setConfig(config, info.fWidth, info.fHeight, rb, info.fAlphaType);
+SkSurface_Raster::SkSurface_Raster(SkPixelRef* pr)
+ : INHERITED(pr->info().fWidth, pr->info().fHeight)
+{
+ const SkImageInfo& info = pr->info();
+
+ fBitmap.setInfo(info, info.minRowBytes());
fBitmap.setPixelRef(pr);
fWeOwnThePixels = true;
- if (!SkAlphaTypeIsOpaque(info.fAlphaType)) {
+ if (!info.isOpaque()) {
fBitmap.eraseColor(SK_ColorTRANSPARENT);
}
}
@@ -123,11 +120,11 @@ void SkSurface_Raster::onCopyOnWrite(ContentChangeMode mode) {
if (SkBitmapImageGetPixelRef(this->getCachedImage()) == fBitmap.pixelRef()) {
SkASSERT(fWeOwnThePixels);
if (kDiscard_ContentChangeMode == mode) {
- fBitmap.setPixelRef(NULL, 0);
+ fBitmap.setPixelRef(NULL);
fBitmap.allocPixels();
} else {
SkBitmap prev(fBitmap);
- prev.deepCopyTo(&fBitmap, prev.config());
+ prev.deepCopyTo(&fBitmap);
}
// Now fBitmap is a deep copy of itself (and therefore different from
// what is being used by the image. Next we update the canvas to use
@@ -159,5 +156,5 @@ SkSurface* SkSurface::NewRaster(const SkImageInfo& info) {
if (NULL == pr.get()) {
return NULL;
}
- return SkNEW_ARGS(SkSurface_Raster, (info, pr, info.minRowBytes()));
+ return SkNEW_ARGS(SkSurface_Raster, (pr));
}
diff --git a/chromium/third_party/skia/src/images/SkDecodingImageGenerator.cpp b/chromium/third_party/skia/src/images/SkDecodingImageGenerator.cpp
index a833c636ff9..88cdef9a321 100644
--- a/chromium/third_party/skia/src/images/SkDecodingImageGenerator.cpp
+++ b/chromium/third_party/skia/src/images/SkDecodingImageGenerator.cpp
@@ -5,81 +5,133 @@
* found in the LICENSE file.
*/
-#include "SkDecodingImageGenerator.h"
#include "SkData.h"
+#include "SkDecodingImageGenerator.h"
#include "SkImageDecoder.h"
+#include "SkImageInfo.h"
#include "SkImageGenerator.h"
#include "SkImagePriv.h"
#include "SkStream.h"
-
+#include "SkUtils.h"
namespace {
+bool equal_modulo_alpha(const SkImageInfo& a, const SkImageInfo& b) {
+ return a.width() == b.width() && a.height() == b.height() &&
+ a.colorType() == b.colorType();
+}
+
+class DecodingImageGenerator : public SkImageGenerator {
+public:
+ virtual ~DecodingImageGenerator();
+
+ SkData* fData;
+ SkStreamRewindable* fStream;
+ const SkImageInfo fInfo;
+ const int fSampleSize;
+ const bool fDitherImage;
+
+ DecodingImageGenerator(SkData* data,
+ SkStreamRewindable* stream,
+ const SkImageInfo& info,
+ int sampleSize,
+ bool ditherImage);
+
+protected:
+ virtual SkData* onRefEncodedData() SK_OVERRIDE;
+ virtual bool onGetInfo(SkImageInfo* info) SK_OVERRIDE {
+ *info = fInfo;
+ return true;
+ }
+ virtual bool onGetPixels(const SkImageInfo& info,
+ void* pixels, size_t rowBytes,
+ SkPMColor ctable[], int* ctableCount) SK_OVERRIDE;
+
+private:
+ typedef SkImageGenerator INHERITED;
+};
+
/**
* Special allocator used by getPixels(). Uses preallocated memory
- * provided.
+ * provided if possible, else fall-back on the default allocator
*/
class TargetAllocator : public SkBitmap::Allocator {
public:
- TargetAllocator(void* target, size_t rowBytes, const SkImageInfo& info)
- : fTarget(target)
+ TargetAllocator(const SkImageInfo& info,
+ void* target,
+ size_t rowBytes)
+ : fInfo(info)
+ , fTarget(target)
, fRowBytes(rowBytes)
- , fInfo(info) { }
+ {}
- virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) SK_OVERRIDE {
- if ((SkImageInfoToBitmapConfig(fInfo) != bm->config())
- || (bm->width() != fInfo.fWidth)
- || (bm->height() != fInfo.fHeight)) {
- return false;
+ bool isReady() { return (fTarget != NULL); }
+
+ virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) {
+ if (NULL == fTarget || !equal_modulo_alpha(fInfo, bm->info())) {
+ // Call default allocator.
+ return bm->allocPixels(NULL, ct);
}
- bm->setConfig(bm->config(), bm->width(), bm->height(),
- fRowBytes, bm->alphaType());
- bm->setPixels(fTarget, ct);
+
+ // TODO(halcanary): verify that all callers of this function
+ // will respect new RowBytes. Will be moot once rowbytes belongs
+ // to PixelRef.
+ bm->installPixels(fInfo, fTarget, fRowBytes, ct, NULL, NULL);
+
+ fTarget = NULL; // never alloc same pixels twice!
return true;
}
private:
- void* fTarget;
- size_t fRowBytes;
- SkImageInfo fInfo;
+ const SkImageInfo fInfo;
+ void* fTarget; // Block of memory to be supplied as pixel memory
+ // in allocPixelRef. Must be large enough to hold
+ // a bitmap described by fInfo and fRowBytes
+ const size_t fRowBytes; // rowbytes for the destination bitmap
+
typedef SkBitmap::Allocator INHERITED;
};
-} // namespace
-////////////////////////////////////////////////////////////////////////////////
-SkDecodingImageGenerator::SkDecodingImageGenerator(SkData* data)
- : fData(data)
- , fHasInfo(false)
- , fDoCopyTo(false) {
- SkASSERT(fData != NULL);
- fStream = SkNEW_ARGS(SkMemoryStream, (fData));
- SkASSERT(fStream != NULL);
- SkASSERT(fStream->unique());
- fData->ref();
+// TODO(halcanary): Give this macro a better name and move it into SkTypes.h
+#ifdef SK_DEBUG
+ #define SkCheckResult(expr, value) SkASSERT((value) == (expr))
+#else
+ #define SkCheckResult(expr, value) (void)(expr)
+#endif
+
+#ifdef SK_DEBUG
+inline bool check_alpha(SkAlphaType reported, SkAlphaType actual) {
+ return ((reported == actual)
+ || ((reported == kPremul_SkAlphaType)
+ && (actual == kOpaque_SkAlphaType)));
}
+#endif // SK_DEBUG
+
+////////////////////////////////////////////////////////////////////////////////
-SkDecodingImageGenerator::SkDecodingImageGenerator(SkStreamRewindable* stream)
- : fData(NULL)
+DecodingImageGenerator::DecodingImageGenerator(
+ SkData* data,
+ SkStreamRewindable* stream,
+ const SkImageInfo& info,
+ int sampleSize,
+ bool ditherImage)
+ : fData(data)
, fStream(stream)
- , fHasInfo(false)
- , fDoCopyTo(false) {
- SkASSERT(fStream != NULL);
- SkASSERT(fStream->unique());
+ , fInfo(info)
+ , fSampleSize(sampleSize)
+ , fDitherImage(ditherImage)
+{
+ SkASSERT(stream != NULL);
+ SkSafeRef(fData); // may be NULL.
}
-SkDecodingImageGenerator::~SkDecodingImageGenerator() {
+DecodingImageGenerator::~DecodingImageGenerator() {
SkSafeUnref(fData);
fStream->unref();
}
-// TODO(halcanary): Give this macro a better name and move it into SkTypes.h
-#ifdef SK_DEBUG
- #define SkCheckResult(expr, value) SkASSERT((value) == (expr))
-#else
- #define SkCheckResult(expr, value) (void)(expr)
-#endif
-
-SkData* SkDecodingImageGenerator::refEncodedData() {
+SkData* DecodingImageGenerator::onRefEncodedData() {
// This functionality is used in `gm --serialize`
+ // Does not encode options.
if (fData != NULL) {
return SkSafeRef(fData);
}
@@ -98,111 +150,132 @@ SkData* SkDecodingImageGenerator::refEncodedData() {
return SkSafeRef(fData);
}
-bool SkDecodingImageGenerator::getInfo(SkImageInfo* info) {
- // info can be NULL. If so, will update fInfo, fDoCopyTo, and fHasInfo.
- if (fHasInfo) {
- if (info != NULL) {
- *info = fInfo;
- }
- return true;
+bool DecodingImageGenerator::onGetPixels(const SkImageInfo& info,
+ void* pixels, size_t rowBytes,
+ SkPMColor ctableEntries[], int* ctableCount) {
+ if (fInfo != info) {
+ // The caller has specified a different info. This is an
+ // error for this kind of SkImageGenerator. Use the Options
+ // to change the settings.
+ return false;
}
+
SkAssertResult(fStream->rewind());
SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream));
if (NULL == decoder.get()) {
return false;
}
+ decoder->setDitherImage(fDitherImage);
+ decoder->setSampleSize(fSampleSize);
+ decoder->setRequireUnpremultipliedColors(
+ info.fAlphaType == kUnpremul_SkAlphaType);
+
SkBitmap bitmap;
- if (!decoder->decode(fStream, &bitmap,
- SkImageDecoder::kDecodeBounds_Mode)) {
- return false;
- }
- if (bitmap.config() == SkBitmap::kNo_Config) {
+ TargetAllocator allocator(fInfo, pixels, rowBytes);
+ decoder->setAllocator(&allocator);
+ bool success = decoder->decode(fStream, &bitmap, info.colorType(),
+ SkImageDecoder::kDecodePixels_Mode);
+ decoder->setAllocator(NULL);
+ if (!success) {
return false;
}
- if (!bitmap.asImageInfo(&fInfo)) {
- // We can't use bitmap.config() as is.
- if (!bitmap.canCopyTo(SkBitmap::kARGB_8888_Config)) {
- SkDEBUGFAIL("!bitmap->canCopyTo(SkBitmap::kARGB_8888_Config)");
+ if (allocator.isReady()) { // Did not use pixels!
+ SkBitmap bm;
+ SkASSERT(bitmap.canCopyTo(info.colorType()));
+ bool copySuccess = bitmap.copyTo(&bm, info.colorType(), &allocator);
+ if (!copySuccess || allocator.isReady()) {
+ SkDEBUGFAIL("bitmap.copyTo(requestedConfig) failed.");
+ // Earlier we checked canCopyto(); we expect consistency.
return false;
}
- fDoCopyTo = true;
- fInfo.fWidth = bitmap.width();
- fInfo.fHeight = bitmap.height();
- fInfo.fColorType = kPMColor_SkColorType;
- fInfo.fAlphaType = bitmap.alphaType();
+ SkASSERT(check_alpha(info.alphaType(), bm.alphaType()));
+ } else {
+ SkASSERT(check_alpha(info.alphaType(), bitmap.alphaType()));
}
- if (info != NULL) {
- *info = fInfo;
+
+ if (kIndex_8_SkColorType == info.colorType()) {
+ if (kIndex_8_SkColorType != bitmap.colorType()) {
+ return false; // they asked for Index8, but we didn't receive that from decoder
+ }
+ SkColorTable* ctable = bitmap.getColorTable();
+ if (NULL == ctable) {
+ return false;
+ }
+ const int count = ctable->count();
+ memcpy(ctableEntries, ctable->lockColors(), count * sizeof(SkPMColor));
+ ctable->unlockColors();
+ *ctableCount = count;
}
- fHasInfo = true;
return true;
}
-bool SkDecodingImageGenerator::getPixels(const SkImageInfo& info,
- void* pixels,
- size_t rowBytes) {
- if (NULL == pixels) {
- return false;
- }
- if (!this->getInfo(NULL)) {
- return false;
- }
- if (SkImageInfoToBitmapConfig(info) == SkBitmap::kNo_Config) {
- return false; // Unsupported SkColorType.
- }
- SkAssertResult(fStream->rewind());
- SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream));
+// A contructor-type function that returns NULL on failure. This
+// prevents the returned SkImageGenerator from ever being in a bad
+// state. Called by both Create() functions
+SkImageGenerator* CreateDecodingImageGenerator(
+ SkData* data,
+ SkStreamRewindable* stream,
+ const SkDecodingImageGenerator::Options& opts) {
+ SkASSERT(stream);
+ SkAutoTUnref<SkStreamRewindable> autoStream(stream); // always unref this.
+ SkAssertResult(autoStream->rewind());
+ SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(autoStream));
if (NULL == decoder.get()) {
- return false;
- }
- if (fInfo != info) {
- // The caller has specified a different info. For now, this
- // is an error. In the future, we will check to see if we can
- // convert.
- return false;
- }
- int bpp = SkBitmap::ComputeBytesPerPixel(SkImageInfoToBitmapConfig(info));
- if (static_cast<size_t>(bpp * info.fWidth) > rowBytes) {
- return false;
+ return NULL;
}
SkBitmap bitmap;
- if (!bitmap.setConfig(info, rowBytes)) {
- return false;
+ decoder->setSampleSize(opts.fSampleSize);
+ decoder->setRequireUnpremultipliedColors(opts.fRequireUnpremul);
+ if (!decoder->decode(stream, &bitmap, SkImageDecoder::kDecodeBounds_Mode)) {
+ return NULL;
}
-
- TargetAllocator allocator(pixels, rowBytes, info);
- if (!fDoCopyTo) {
- decoder->setAllocator(&allocator);
+ if (kUnknown_SkColorType == bitmap.colorType()) {
+ return NULL;
}
- bool success = decoder->decode(fStream, &bitmap,
- SkImageDecoder::kDecodePixels_Mode);
- decoder->setAllocator(NULL);
- if (!success) {
- return false;
+
+ SkImageInfo info = bitmap.info();
+
+ if (opts.fUseRequestedColorType && (opts.fRequestedColorType != info.colorType())) {
+ if (!bitmap.canCopyTo(opts.fRequestedColorType)) {
+ SkASSERT(bitmap.colorType() != opts.fRequestedColorType);
+ return NULL; // Can not translate to needed config.
+ }
+ info.fColorType = opts.fRequestedColorType;
}
- if (fDoCopyTo) {
- SkBitmap bm8888;
- bitmap.copyTo(&bm8888, SkBitmap::kARGB_8888_Config, &allocator);
+
+ if (opts.fRequireUnpremul && info.fAlphaType != kOpaque_SkAlphaType) {
+ info.fAlphaType = kUnpremul_SkAlphaType;
}
- return true;
+ return SkNEW_ARGS(DecodingImageGenerator,
+ (data, autoStream.detach(), info,
+ opts.fSampleSize, opts.fDitherImage));
}
-bool SkDecodingImageGenerator::Install(SkData* data, SkBitmap* dst,
- SkDiscardableMemory::Factory* factory) {
+
+} // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+
+SkImageGenerator* SkDecodingImageGenerator::Create(
+ SkData* data,
+ const SkDecodingImageGenerator::Options& opts) {
SkASSERT(data != NULL);
- SkASSERT(dst != NULL);
- SkImageGenerator* gen(SkNEW_ARGS(SkDecodingImageGenerator, (data)));
- return SkInstallDiscardablePixelRef(gen, dst, factory);
+ if (NULL == data) {
+ return NULL;
+ }
+ SkStreamRewindable* stream = SkNEW_ARGS(SkMemoryStream, (data));
+ SkASSERT(stream != NULL);
+ SkASSERT(stream->unique());
+ return CreateDecodingImageGenerator(data, stream, opts);
}
-bool SkDecodingImageGenerator::Install(SkStreamRewindable* stream,
- SkBitmap* dst,
- SkDiscardableMemory::Factory* factory) {
+SkImageGenerator* SkDecodingImageGenerator::Create(
+ SkStreamRewindable* stream,
+ const SkDecodingImageGenerator::Options& opts) {
SkASSERT(stream != NULL);
- SkASSERT(dst != NULL);
+ SkASSERT(stream->unique());
if ((stream == NULL) || !stream->unique()) {
SkSafeUnref(stream);
- return false;
+ return NULL;
}
- SkImageGenerator* gen(SkNEW_ARGS(SkDecodingImageGenerator, (stream)));
- return SkInstallDiscardablePixelRef(gen, dst, factory);
+ return CreateDecodingImageGenerator(NULL, stream, opts);
}
diff --git a/chromium/third_party/skia/src/images/SkDecodingImageGenerator.h b/chromium/third_party/skia/src/images/SkDecodingImageGenerator.h
deleted file mode 100644
index dba234bcf19..00000000000
--- a/chromium/third_party/skia/src/images/SkDecodingImageGenerator.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright 2013 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkDecodingImageGenerator_DEFINED
-#define SkDecodingImageGenerator_DEFINED
-
-#include "SkDiscardableMemory.h"
-#include "SkImageGenerator.h"
-#include "SkImageInfo.h"
-
-class SkBitmap;
-class SkStreamRewindable;
-
-/**
- * Calls into SkImageDecoder::DecodeMemoryToTarget to implement a
- * SkImageGenerator
- */
-class SkDecodingImageGenerator : public SkImageGenerator {
-public:
- /*
- * The constructor will take a reference to the SkData. The
- * destructor will unref() it.
- */
- explicit SkDecodingImageGenerator(SkData* data);
-
- /*
- * The SkData version of this constructor is preferred. If the
- * stream has an underlying SkData (such as a SkMemoryStream)
- * pass that in.
- *
- * This object will unref the stream when done. Since streams
- * have internal state (position), the caller should not pass a
- * shared stream in. Pass either a new duplicated stream in or
- * transfer ownership of the stream. In the latter case, be sure
- * that there are no other consumers of the stream who will
- * modify the stream's position. This constructor asserts
- * stream->unique().
- *
- * For example:
- * SkStreamRewindable* stream;
- * ...
- * SkImageGenerator* gen
- * = SkNEW_ARGS(SkDecodingImageGenerator,
- * (stream->duplicate()));
- * ...
- * SkDELETE(gen);
- */
- explicit SkDecodingImageGenerator(SkStreamRewindable* stream);
-
- virtual ~SkDecodingImageGenerator();
-
- virtual SkData* refEncodedData() SK_OVERRIDE;
-
- virtual bool getInfo(SkImageInfo* info) SK_OVERRIDE;
-
- virtual bool getPixels(const SkImageInfo& info,
- void* pixels,
- size_t rowBytes) SK_OVERRIDE;
-
- /**
- * Install the SkData into the destination bitmap, using a new
- * SkDiscardablePixelRef and a new SkDecodingImageGenerator.
- *
- * @param data Contains the encoded image data that will be used
- * by the SkDecodingImageGenerator. Will be ref()ed.
- *
- * @param destination Upon success, this bitmap will be
- * configured and have a pixelref installed.
- *
- * @param factory If not NULL, this object will be used as a
- * source of discardable memory when decoding. If NULL, then
- * SkDiscardableMemory::Create() will be called.
- *
- * @return true iff successful.
- */
- static bool Install(SkData* data, SkBitmap* destination,
- SkDiscardableMemory::Factory* factory = NULL);
- /**
- * Install the stream into the destination bitmap, using a new
- * SkDiscardablePixelRef and a new SkDecodingImageGenerator.
- *
- * The SkData version of this function is preferred. If the
- * stream has an underlying SkData (such as a SkMemoryStream)
- * pass that in.
- *
- * @param stream The source of encoded data that will be passed
- * to the decoder. The installed SkDecodingImageGenerator will
- * unref the stream when done. If false is returned, this
- * function will perform the unref. Since streams have internal
- * state (position), the caller should not pass a shared stream
- * in. Pass either a new duplicated stream in or transfer
- * ownership of the stream. In the latter case, be sure that
- * there are no other consumers of the stream who will modify the
- * stream's position. This function will fail if
- * (!stream->unique()).
- *
- * @param destination Upon success, this bitmap will be
- * configured and have a pixelref installed.
- *
- * @param factory If not NULL, this object will be used as a
- * source of discardable memory when decoding. If NULL, then
- * SkDiscardableMemory::Create() will be called.
- *
- * @return true iff successful.
- */
- static bool Install(SkStreamRewindable* stream, SkBitmap* destination,
- SkDiscardableMemory::Factory* factory = NULL);
-
-private:
- SkData* fData;
- SkStreamRewindable* fStream;
- SkImageInfo fInfo;
- bool fHasInfo;
- bool fDoCopyTo;
-};
-#endif // SkDecodingImageGenerator_DEFINED
diff --git a/chromium/third_party/skia/src/images/SkForceLinking.cpp b/chromium/third_party/skia/src/images/SkForceLinking.cpp
index e4dc60a4480..2c9a38979ac 100644
--- a/chromium/third_party/skia/src/images/SkForceLinking.cpp
+++ b/chromium/third_party/skia/src/images/SkForceLinking.cpp
@@ -18,6 +18,8 @@ int SkForceLinking(bool doNotPassTrue) {
CreateWEBPImageDecoder();
CreateBMPImageDecoder();
CreateICOImageDecoder();
+ CreatePKMImageDecoder();
+ CreateKTXImageDecoder();
CreateWBMPImageDecoder();
// Only link GIF and PNG on platforms that build them. See images.gyp
#if !defined(SK_BUILD_FOR_MAC) && !defined(SK_BUILD_FOR_WIN) && !defined(SK_BUILD_FOR_NACL) \
diff --git a/chromium/third_party/skia/src/images/SkImageDecoder.cpp b/chromium/third_party/skia/src/images/SkImageDecoder.cpp
index 32cf087ed86..fe61906357d 100644
--- a/chromium/third_party/skia/src/images/SkImageDecoder.cpp
+++ b/chromium/third_party/skia/src/images/SkImageDecoder.cpp
@@ -14,28 +14,18 @@
#include "SkTemplates.h"
#include "SkCanvas.h"
-static SkBitmap::Config gDeviceConfig = SkBitmap::kNo_Config;
-
-SkBitmap::Config SkImageDecoder::GetDeviceConfig()
-{
- return gDeviceConfig;
-}
-
-void SkImageDecoder::SetDeviceConfig(SkBitmap::Config config)
-{
- gDeviceConfig = config;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
SkImageDecoder::SkImageDecoder()
: fPeeker(NULL)
+#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
, fChooser(NULL)
+#endif
, fAllocator(NULL)
, fSampleSize(1)
- , fDefaultPref(SkBitmap::kNo_Config)
+ , fDefaultPref(kUnknown_SkColorType)
, fDitherImage(true)
+#ifdef SK_SUPPORT_LEGACY_BITMAP_CONFIG
, fUsePrefTable(false)
+#endif
, fSkipWritingZeroes(false)
, fPreferQualityOverSpeed(false)
, fRequireUnpremultipliedColors(false) {
@@ -43,7 +33,9 @@ SkImageDecoder::SkImageDecoder()
SkImageDecoder::~SkImageDecoder() {
SkSafeUnref(fPeeker);
+#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
SkSafeUnref(fChooser);
+#endif
SkSafeUnref(fAllocator);
}
@@ -52,14 +44,18 @@ void SkImageDecoder::copyFieldsToOther(SkImageDecoder* other) {
return;
}
other->setPeeker(fPeeker);
+#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
other->setChooser(fChooser);
+#endif
other->setAllocator(fAllocator);
other->setSampleSize(fSampleSize);
+#ifdef SK_SUPPORT_LEGACY_BITMAP_CONFIG
if (fUsePrefTable) {
other->setPrefConfigTable(fPrefTable);
} else {
other->fDefaultPref = fDefaultPref;
}
+#endif
other->setDitherImage(fDitherImage);
other->setSkipWritingZeroes(fSkipWritingZeroes);
other->setPreferQualityOverSpeed(fPreferQualityOverSpeed);
@@ -84,6 +80,10 @@ const char* SkImageDecoder::GetFormatName(Format format) {
return "GIF";
case kICO_Format:
return "ICO";
+ case kPKM_Format:
+ return "PKM";
+ case kKTX_Format:
+ return "KTX";
case kJPEG_Format:
return "JPEG";
case kPNG_Format:
@@ -103,10 +103,12 @@ SkImageDecoder::Peeker* SkImageDecoder::setPeeker(Peeker* peeker) {
return peeker;
}
+#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
SkImageDecoder::Chooser* SkImageDecoder::setChooser(Chooser* chooser) {
SkRefCnt_SafeAssign(fChooser, chooser);
return chooser;
}
+#endif
SkBitmap::Allocator* SkImageDecoder::setAllocator(SkBitmap::Allocator* alloc) {
SkRefCnt_SafeAssign(fAllocator, alloc);
@@ -120,17 +122,20 @@ void SkImageDecoder::setSampleSize(int size) {
fSampleSize = size;
}
-bool SkImageDecoder::chooseFromOneChoice(SkBitmap::Config config, int width,
- int height) const {
+#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
+// TODO: change Chooser virtual to take colorType, so we can stop calling SkColorTypeToBitmapConfig
+//
+bool SkImageDecoder::chooseFromOneChoice(SkColorType colorType, int width, int height) const {
Chooser* chooser = fChooser;
-
+
if (NULL == chooser) { // no chooser, we just say YES to decoding :)
return true;
}
chooser->begin(1);
- chooser->inspect(0, config, width, height);
+ chooser->inspect(0, SkColorTypeToBitmapConfig(colorType), width, height);
return chooser->choose() == 0;
}
+#endif
bool SkImageDecoder::allocPixelRef(SkBitmap* bitmap,
SkColorTable* ctable) const {
@@ -139,16 +144,22 @@ bool SkImageDecoder::allocPixelRef(SkBitmap* bitmap,
///////////////////////////////////////////////////////////////////////////////
+#ifdef SK_SUPPORT_LEGACY_BITMAP_CONFIG
void SkImageDecoder::setPrefConfigTable(const PrefConfigTable& prefTable) {
fUsePrefTable = true;
fPrefTable = prefTable;
}
+#endif
-SkBitmap::Config SkImageDecoder::getPrefConfig(SrcDepth srcDepth,
- bool srcHasAlpha) const {
- SkBitmap::Config config = SkBitmap::kNo_Config;
+// TODO: use colortype in fPrefTable, fDefaultPref so we can stop using SkBitmapConfigToColorType()
+//
+SkColorType SkImageDecoder::getPrefColorType(SrcDepth srcDepth, bool srcHasAlpha) const {
+ SkColorType ct = fDefaultPref;
+#ifdef SK_SUPPORT_LEGACY_BITMAP_CONFIG
if (fUsePrefTable) {
+ // Until we kill or change the PrefTable, we have to go into Config land for a moment.
+ SkBitmap::Config config = SkBitmap::kNo_Config;
switch (srcDepth) {
case kIndex_SrcDepth:
config = srcHasAlpha ? fPrefTable.fPrefFor_8Index_YesAlpha_src
@@ -162,21 +173,17 @@ SkBitmap::Config SkImageDecoder::getPrefConfig(SrcDepth srcDepth,
: fPrefTable.fPrefFor_8bpc_NoAlpha_src;
break;
}
- } else {
- config = fDefaultPref;
- }
-
- if (SkBitmap::kNo_Config == config) {
- config = SkImageDecoder::GetDeviceConfig();
+ // now return to SkColorType land
+ ct = SkBitmapConfigToColorType(config);
}
- return config;
+#endif
+ return ct;
}
-bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm,
- SkBitmap::Config pref, Mode mode) {
+bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm, SkColorType pref, Mode mode) {
// we reset this to false before calling onDecode
fShouldCancelDecode = false;
- // assign this, for use by getPrefConfig(), in case fUsePrefTable is false
+ // assign this, for use by getPrefColorType(), in case fUsePrefTable is false
fDefaultPref = pref;
// pass a temporary bitmap, so that if we return false, we are assured of
@@ -189,18 +196,16 @@ bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm,
return true;
}
-bool SkImageDecoder::decodeSubset(SkBitmap* bm, const SkIRect& rect,
- SkBitmap::Config pref) {
+bool SkImageDecoder::decodeSubset(SkBitmap* bm, const SkIRect& rect, SkColorType pref) {
// we reset this to false before calling onDecodeSubset
fShouldCancelDecode = false;
- // assign this, for use by getPrefConfig(), in case fUsePrefTable is false
+ // assign this, for use by getPrefColorType(), in case fUsePrefTable is false
fDefaultPref = pref;
return this->onDecodeSubset(bm, rect);
}
-bool SkImageDecoder::buildTileIndex(SkStreamRewindable* stream,
- int *width, int *height) {
+bool SkImageDecoder::buildTileIndex(SkStreamRewindable* stream, int *width, int *height) {
// we reset this to false before calling onBuildTileIndex
fShouldCancelDecode = false;
@@ -212,7 +217,7 @@ bool SkImageDecoder::cropBitmap(SkBitmap *dst, SkBitmap *src, int sampleSize,
int srcX, int srcY) {
int w = width / sampleSize;
int h = height / sampleSize;
- if (src->config() == SkBitmap::kIndex8_Config) {
+ if (src->colorType() == kIndex_8_SkColorType) {
// kIndex8 does not allow drawing via an SkCanvas, as is done below.
// Instead, use extractSubset. Note that this shares the SkPixelRef and
// SkColorTable.
@@ -228,7 +233,7 @@ bool SkImageDecoder::cropBitmap(SkBitmap *dst, SkBitmap *src, int sampleSize,
}
// if the destination has no pixels then we must allocate them.
if (dst->isNull()) {
- dst->setConfig(src->config(), w, h, 0, src->alphaType());
+ dst->setInfo(src->info().makeWH(w, h));
if (!this->allocPixelRef(dst, NULL)) {
SkDEBUGF(("failed to allocate pixels needed to crop the bitmap"));
@@ -256,8 +261,8 @@ bool SkImageDecoder::cropBitmap(SkBitmap *dst, SkBitmap *src, int sampleSize,
///////////////////////////////////////////////////////////////////////////////
-bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm,
- SkBitmap::Config pref, Mode mode, Format* format) {
+bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm, SkColorType pref, Mode mode,
+ Format* format) {
SkASSERT(file);
SkASSERT(bm);
@@ -271,8 +276,8 @@ bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm,
return false;
}
-bool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm,
- SkBitmap::Config pref, Mode mode, Format* format) {
+bool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm, SkColorType pref,
+ Mode mode, Format* format) {
if (0 == size) {
return false;
}
@@ -282,9 +287,8 @@ bool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm,
return SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format);
}
-bool SkImageDecoder::DecodeStream(SkStreamRewindable* stream, SkBitmap* bm,
- SkBitmap::Config pref, Mode mode,
- Format* format) {
+bool SkImageDecoder::DecodeStream(SkStreamRewindable* stream, SkBitmap* bm, SkColorType pref,
+ Mode mode, Format* format) {
SkASSERT(stream);
SkASSERT(bm);
diff --git a/chromium/third_party/skia/src/images/SkImageDecoder_ktx.cpp b/chromium/third_party/skia/src/images/SkImageDecoder_ktx.cpp
new file mode 100644
index 00000000000..effc1edcc11
--- /dev/null
+++ b/chromium/third_party/skia/src/images/SkImageDecoder_ktx.cpp
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkColorPriv.h"
+#include "SkImageDecoder.h"
+#include "SkPixelRef.h"
+#include "SkScaledBitmapSampler.h"
+#include "SkStream.h"
+#include "SkStreamHelpers.h"
+#include "SkTypes.h"
+
+#include "ktx.h"
+#include "etc1.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+// KTX Image decoder
+// ---
+// KTX is a general texture data storage file format ratified by the Khronos Group. As an
+// overview, a KTX file contains all of the appropriate values needed to fully specify a
+// texture in an OpenGL application, including the use of compressed data.
+//
+// This decoder is meant to be used with an SkDiscardablePixelRef so that GPU backends
+// can sniff the data before creating a texture. If they encounter a compressed format
+// that they understand, they can then upload the data directly to the GPU. Otherwise,
+// they will decode the data into a format that Skia supports.
+
+class SkKTXImageDecoder : public SkImageDecoder {
+public:
+ SkKTXImageDecoder() { }
+
+ virtual Format getFormat() const SK_OVERRIDE {
+ return kKTX_Format;
+ }
+
+protected:
+ virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE;
+
+private:
+ typedef SkImageDecoder INHERITED;
+};
+
+bool SkKTXImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
+ // TODO: Implement SkStream::copyToData() that's cheap for memory and file streams
+ SkAutoDataUnref data(CopyStreamToData(stream));
+ if (NULL == data) {
+ return false;
+ }
+
+ SkKTXFile ktxFile(data);
+ if (!ktxFile.valid()) {
+ return false;
+ }
+
+ const unsigned short width = ktxFile.width();
+ const unsigned short height = ktxFile.height();
+
+#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
+ // should we allow the Chooser (if present) to pick a config for us???
+ if (!this->chooseFromOneChoice(kN32_SkColorType, width, height)) {
+ return false;
+ }
+#endif
+
+ // Set a flag if our source is premultiplied alpha
+ const SkString premulKey("KTXPremultipliedAlpha");
+ const bool bSrcIsPremul = ktxFile.getValueForKey(premulKey) == SkString("True");
+
+ // Setup the sampler...
+ SkScaledBitmapSampler sampler(width, height, this->getSampleSize());
+
+ // Determine the alpha of the bitmap...
+ SkAlphaType alphaType = kOpaque_SkAlphaType;
+ if (ktxFile.isRGBA8()) {
+ if (this->getRequireUnpremultipliedColors()) {
+ alphaType = kUnpremul_SkAlphaType;
+ // If the client wants unpremul colors and we only have
+ // premul, then we cannot honor their wish.
+ if (bSrcIsPremul) {
+ return false;
+ }
+ } else {
+ alphaType = kPremul_SkAlphaType;
+ }
+ }
+
+ // Set the config...
+ bm->setInfo(SkImageInfo::MakeN32(sampler.scaledWidth(), sampler.scaledHeight(), alphaType));
+ if (SkImageDecoder::kDecodeBounds_Mode == mode) {
+ return true;
+ }
+
+ // If we've made it this far, then we know how to grok the data.
+ if (!this->allocPixelRef(bm, NULL)) {
+ return false;
+ }
+
+ // Lock the pixels, since we're about to write to them...
+ SkAutoLockPixels alp(*bm);
+
+ if (ktxFile.isETC1()) {
+ if (!sampler.begin(bm, SkScaledBitmapSampler::kRGB, *this)) {
+ return false;
+ }
+
+ // ETC1 Data is encoded as RGB pixels, so we should extract it as such
+ int nPixels = width * height;
+ SkAutoMalloc outRGBData(nPixels * 3);
+ etc1_byte *outRGBDataPtr = reinterpret_cast<etc1_byte *>(outRGBData.get());
+
+ // Decode ETC1
+ const etc1_byte *buf = reinterpret_cast<const etc1_byte *>(ktxFile.pixelData());
+ if (etc1_decode_image(buf, outRGBDataPtr, width, height, 3, width*3)) {
+ return false;
+ }
+
+ // Set each of the pixels...
+ const int srcRowBytes = width * 3;
+ const int dstHeight = sampler.scaledHeight();
+ const uint8_t *srcRow = reinterpret_cast<uint8_t *>(outRGBDataPtr);
+ srcRow += sampler.srcY0() * srcRowBytes;
+ for (int y = 0; y < dstHeight; ++y) {
+ sampler.next(srcRow);
+ srcRow += sampler.srcDY() * srcRowBytes;
+ }
+
+ return true;
+
+ } else if (ktxFile.isRGB8()) {
+
+ // Uncompressed RGB data (without alpha)
+ if (!sampler.begin(bm, SkScaledBitmapSampler::kRGB, *this)) {
+ return false;
+ }
+
+ // Just need to read RGB pixels
+ const int srcRowBytes = width * 3;
+ const int dstHeight = sampler.scaledHeight();
+ const uint8_t *srcRow = reinterpret_cast<const uint8_t *>(ktxFile.pixelData());
+ srcRow += sampler.srcY0() * srcRowBytes;
+ for (int y = 0; y < dstHeight; ++y) {
+ sampler.next(srcRow);
+ srcRow += sampler.srcDY() * srcRowBytes;
+ }
+
+ return true;
+
+ } else if (ktxFile.isRGBA8()) {
+
+ // Uncompressed RGBA data
+
+ // If we know that the image contains premultiplied alpha, then
+ // we need to turn off the premultiplier
+ SkScaledBitmapSampler::Options opts (*this);
+ if (bSrcIsPremul) {
+ SkASSERT(bm->alphaType() == kPremul_SkAlphaType);
+ SkASSERT(!this->getRequireUnpremultipliedColors());
+
+ opts.fPremultiplyAlpha = false;
+ }
+
+ if (!sampler.begin(bm, SkScaledBitmapSampler::kRGBA, opts)) {
+ return false;
+ }
+
+ // Just need to read RGBA pixels
+ const int srcRowBytes = width * 4;
+ const int dstHeight = sampler.scaledHeight();
+ const uint8_t *srcRow = reinterpret_cast<const uint8_t *>(ktxFile.pixelData());
+ srcRow += sampler.srcY0() * srcRowBytes;
+ for (int y = 0; y < dstHeight; ++y) {
+ sampler.next(srcRow);
+ srcRow += sampler.srcDY() * srcRowBytes;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+// KTX Image Encoder
+//
+// This encoder takes a best guess at how to encode the bitmap passed to it. If
+// there is an installed discardable pixel ref with existing PKM data, then we
+// will repurpose the existing ETC1 data into a KTX file. If the data contains
+// KTX data, then we simply return a copy of the same data. For all other files,
+// the underlying KTX library tries to do its best to encode the appropriate
+// data specified by the bitmap based on the config. (i.e. kAlpha8_Config will
+// be represented as a full resolution 8-bit image dump with the appropriate
+// OpenGL defines in the header).
+
+class SkKTXImageEncoder : public SkImageEncoder {
+protected:
+ virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) SK_OVERRIDE;
+
+private:
+ virtual bool encodePKM(SkWStream* stream, const SkData *data);
+ typedef SkImageEncoder INHERITED;
+};
+
+bool SkKTXImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bitmap, int) {
+ SkAutoDataUnref data(bitmap.pixelRef()->refEncodedData());
+
+ // Is this even encoded data?
+ if (NULL != data) {
+ const uint8_t *bytes = data->bytes();
+ if (etc1_pkm_is_valid(bytes)) {
+ return this->encodePKM(stream, data);
+ }
+
+ // Is it a KTX file??
+ if (SkKTXFile::is_ktx(bytes)) {
+ return stream->write(bytes, data->size());
+ }
+
+ // If it's neither a KTX nor a PKM, then we need to
+ // get at the actual pixels, so fall through and decompress...
+ }
+
+ return SkKTXFile::WriteBitmapToKTX(stream, bitmap);
+}
+
+bool SkKTXImageEncoder::encodePKM(SkWStream* stream, const SkData *data) {
+ const uint8_t* bytes = data->bytes();
+ SkASSERT(etc1_pkm_is_valid(bytes));
+
+ etc1_uint32 width = etc1_pkm_get_width(bytes);
+ etc1_uint32 height = etc1_pkm_get_height(bytes);
+
+ // ETC1 Data is stored as compressed 4x4 pixel blocks, so we must make sure
+ // that our dimensions are valid.
+ if (width == 0 || (width & 3) != 0 || height == 0 || (height & 3) != 0) {
+ return false;
+ }
+
+ // Advance pointer to etc1 data.
+ bytes += ETC_PKM_HEADER_SIZE;
+
+ return SkKTXFile::WriteETC1ToKTX(stream, bytes, width, height);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+DEFINE_DECODER_CREATOR(KTXImageDecoder);
+DEFINE_ENCODER_CREATOR(KTXImageEncoder);
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static SkImageDecoder* sk_libktx_dfactory(SkStreamRewindable* stream) {
+ if (SkKTXFile::is_ktx(stream)) {
+ return SkNEW(SkKTXImageDecoder);
+ }
+ return NULL;
+}
+
+static SkImageDecoder::Format get_format_ktx(SkStreamRewindable* stream) {
+ if (SkKTXFile::is_ktx(stream)) {
+ return SkImageDecoder::kKTX_Format;
+ }
+ return SkImageDecoder::kUnknown_Format;
+}
+
+SkImageEncoder* sk_libktx_efactory(SkImageEncoder::Type t) {
+ return (SkImageEncoder::kKTX_Type == t) ? SkNEW(SkKTXImageEncoder) : NULL;
+}
+
+static SkImageDecoder_DecodeReg gReg(sk_libktx_dfactory);
+static SkImageDecoder_FormatReg gFormatReg(get_format_ktx);
+static SkImageEncoder_EncodeReg gEReg(sk_libktx_efactory);
diff --git a/chromium/third_party/skia/src/images/SkImageDecoder_libbmp.cpp b/chromium/third_party/skia/src/images/SkImageDecoder_libbmp.cpp
index 34a88ac6b00..f9dd2472a0b 100644
--- a/chromium/third_party/skia/src/images/SkImageDecoder_libbmp.cpp
+++ b/chromium/third_party/skia/src/images/SkImageDecoder_libbmp.cpp
@@ -123,18 +123,17 @@ bool SkBMPImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
int width = callback.width();
int height = callback.height();
- SkBitmap::Config config = this->getPrefConfig(k32Bit_SrcDepth, false);
+ SkColorType colorType = this->getPrefColorType(k32Bit_SrcDepth, false);
// only accept prefConfig if it makes sense for us
- if (SkBitmap::kARGB_4444_Config != config &&
- SkBitmap::kRGB_565_Config != config) {
- config = SkBitmap::kARGB_8888_Config;
+ if (kARGB_4444_SkColorType != colorType && kRGB_565_SkColorType != colorType) {
+ colorType = kN32_SkColorType;
}
SkScaledBitmapSampler sampler(width, height, getSampleSize());
- bm->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight(), 0,
- kOpaque_SkAlphaType);
+ bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(),
+ colorType, kOpaque_SkAlphaType));
if (justBounds) {
return true;
diff --git a/chromium/third_party/skia/src/images/SkImageDecoder_libgif.cpp b/chromium/third_party/skia/src/images/SkImageDecoder_libgif.cpp
index f484441c8c3..0c8461f893e 100644
--- a/chromium/third_party/skia/src/images/SkImageDecoder_libgif.cpp
+++ b/chromium/third_party/skia/src/images/SkImageDecoder_libgif.cpp
@@ -185,6 +185,49 @@ static bool skip_src_rows(GifFileType* gif, uint8_t* dst, int width, int rowsToS
return true;
}
+/**
+ * GIFs with fewer then 256 color entries will sometimes index out of
+ * bounds of the color table (this is malformed, but libgif does not
+ * check sicne it is rare). This function checks for this error and
+ * fixes it. This makes the output image consistantly deterministic.
+ */
+static void sanitize_indexed_bitmap(SkBitmap* bm) {
+ if ((kIndex_8_SkColorType == bm->colorType()) && !(bm->empty())) {
+ SkAutoLockPixels alp(*bm);
+ if (NULL != bm->getPixels()) {
+ SkColorTable* ct = bm->getColorTable(); // Index8 must have it.
+ SkASSERT(ct != NULL);
+ uint32_t count = ct->count();
+ SkASSERT(count > 0);
+ SkASSERT(count <= 0x100);
+ if (count != 0x100) { // Full colortables can't go wrong.
+ // Count is a power of 2; asserted elsewhere.
+ uint8_t byteMask = (~(count - 1));
+ bool warning = false;
+ uint8_t* addr = static_cast<uint8_t*>(bm->getPixels());
+ int height = bm->height();
+ int width = bm->width();
+ size_t rowBytes = bm->rowBytes();
+ while (--height >= 0) {
+ uint8_t* ptr = addr;
+ int x = width;
+ while (--x >= 0) {
+ if (0 != ((*ptr) & byteMask)) {
+ warning = true;
+ *ptr = 0;
+ }
+ ++ptr;
+ }
+ addr += rowBytes;
+ }
+ if (warning) {
+ gif_warning(*bm, "Index out of bounds.");
+ }
+ }
+ }
+ }
+}
+
bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, Mode mode) {
#if GIFLIB_MAJOR < 5
GifFileType* gif = DGifOpen(sk_stream, DecodeCallBackProc);
@@ -266,15 +309,17 @@ bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, Mode mode) {
imageTop = 0;
}
+#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
// FIXME: We could give the caller a choice of images or configs.
- if (!this->chooseFromOneChoice(SkBitmap::kIndex8_Config, width, height)) {
+ if (!this->chooseFromOneChoice(kIndex_8_SkColorType, width, height)) {
return error_return(*bm, "chooseFromOneChoice");
}
+#endif
SkScaledBitmapSampler sampler(width, height, this->getSampleSize());
- bm->setConfig(SkBitmap::kIndex8_Config, sampler.scaledWidth(),
- sampler.scaledHeight());
+ bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(),
+ kIndex_8_SkColorType, kPremul_SkAlphaType));
if (SkImageDecoder::kDecodeBounds_Mode == mode) {
return true;
@@ -289,6 +334,7 @@ bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, Mode mode) {
const ColorMapObject* cmap = find_colormap(gif);
SkAlphaType alphaType = kOpaque_SkAlphaType;
if (cmap != NULL) {
+ SkASSERT(cmap->ColorCount == (1 << (cmap->BitsPerPixel)));
colorCount = cmap->ColorCount;
if (colorCount > 256) {
colorCount = 256; // our kIndex8 can't support more
@@ -410,6 +456,7 @@ bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, Mode mode) {
SkASSERT(read <= innerHeight);
skip_src_rows(gif, scanline, innerWidth, innerHeight - read);
}
+ sanitize_indexed_bitmap(bm);
return true;
} break;
@@ -454,6 +501,7 @@ bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, Mode mode) {
}
} while (recType != TERMINATE_RECORD_TYPE);
+ sanitize_indexed_bitmap(bm);
return true;
}
diff --git a/chromium/third_party/skia/src/images/SkImageDecoder_libico.cpp b/chromium/third_party/skia/src/images/SkImageDecoder_libico.cpp
index 2b65a36c76f..e6ae16f0bd4 100644
--- a/chromium/third_party/skia/src/images/SkImageDecoder_libico.cpp
+++ b/chromium/third_party/skia/src/images/SkImageDecoder_libico.cpp
@@ -94,6 +94,7 @@ bool SkICOImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode)
if (length < (size_t)(6 + count*16))
return false;
+#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
int choice;
Chooser* chooser = this->getChooser();
//FIXME:if no chooser, consider providing the largest color image
@@ -138,6 +139,9 @@ bool SkICOImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode)
//you never know what the chooser is going to supply
if (choice >= count || choice < 0)
return false;
+#else
+ const int choice = 0; // TODO: fold this value into the expressions below
+#endif
//skip ahead to the correct header
//commented out lines are not used, but if i switch to other read method, need to know how many to skip
@@ -246,7 +250,7 @@ bool SkICOImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode)
//if the andbitmap (mask) is all zeroes, then we can easily do an index bitmap
//however, with small images with large colortables, maybe it's better to still do argb_8888
- bm->setConfig(SkBitmap::kARGB_8888_Config, w, h, calculateRowBytesFor8888(w, bitCount));
+ bm->setInfo(SkImageInfo::MakeN32Premul(w, h), calculateRowBytesFor8888(w, bitCount));
if (SkImageDecoder::kDecodeBounds_Mode == mode) {
delete[] colors;
diff --git a/chromium/third_party/skia/src/images/SkImageDecoder_libjpeg.cpp b/chromium/third_party/skia/src/images/SkImageDecoder_libjpeg.cpp
index b08835b5423..9b937162b3e 100644
--- a/chromium/third_party/skia/src/images/SkImageDecoder_libjpeg.cpp
+++ b/chromium/third_party/skia/src/images/SkImageDecoder_libjpeg.cpp
@@ -248,12 +248,12 @@ private:
#endif
/**
- * Determine the appropriate bitmap config and out_color_space based on
+ * Determine the appropriate bitmap colortype and out_color_space based on
* both the preference of the caller and the jpeg_color_space on the
* jpeg_decompress_struct passed in.
* Must be called after jpeg_read_header.
*/
- SkBitmap::Config getBitmapConfig(jpeg_decompress_struct*);
+ SkColorType getBitmapColorType(jpeg_decompress_struct*);
typedef SkImageDecoder INHERITED;
};
@@ -400,7 +400,7 @@ static void set_dct_method(const SkImageDecoder& decoder, jpeg_decompress_struct
#endif
}
-SkBitmap::Config SkJPEGImageDecoder::getBitmapConfig(jpeg_decompress_struct* cinfo) {
+SkColorType SkJPEGImageDecoder::getBitmapColorType(jpeg_decompress_struct* cinfo) {
SkASSERT(cinfo != NULL);
SrcDepth srcDepth = k32Bit_SrcDepth;
@@ -408,26 +408,26 @@ SkBitmap::Config SkJPEGImageDecoder::getBitmapConfig(jpeg_decompress_struct* cin
srcDepth = k8BitGray_SrcDepth;
}
- SkBitmap::Config config = this->getPrefConfig(srcDepth, /*hasAlpha*/ false);
- switch (config) {
- case SkBitmap::kA8_Config:
- // Only respect A8 config if the original is grayscale,
+ SkColorType colorType = this->getPrefColorType(srcDepth, /*hasAlpha*/ false);
+ switch (colorType) {
+ case kAlpha_8_SkColorType:
+ // Only respect A8 colortype if the original is grayscale,
// in which case we will treat the grayscale as alpha
// values.
if (cinfo->jpeg_color_space != JCS_GRAYSCALE) {
- config = SkBitmap::kARGB_8888_Config;
+ colorType = kN32_SkColorType;
}
break;
- case SkBitmap::kARGB_8888_Config:
+ case kN32_SkColorType:
// Fall through.
- case SkBitmap::kARGB_4444_Config:
+ case kARGB_4444_SkColorType:
// Fall through.
- case SkBitmap::kRGB_565_Config:
- // These are acceptable destination configs.
+ case kRGB_565_SkColorType:
+ // These are acceptable destination colortypes.
break;
default:
- // Force all other configs to 8888.
- config = SkBitmap::kARGB_8888_Config;
+ // Force all other colortypes to 8888.
+ colorType = kN32_SkColorType;
break;
}
@@ -441,37 +441,37 @@ SkBitmap::Config SkJPEGImageDecoder::getBitmapConfig(jpeg_decompress_struct* cin
cinfo->out_color_space = JCS_CMYK;
break;
case JCS_GRAYSCALE:
- if (SkBitmap::kA8_Config == config) {
+ if (kAlpha_8_SkColorType == colorType) {
cinfo->out_color_space = JCS_GRAYSCALE;
break;
}
// The data is JCS_GRAYSCALE, but the caller wants some sort of RGB
- // config. Fall through to set to the default.
+ // colortype. Fall through to set to the default.
default:
cinfo->out_color_space = JCS_RGB;
break;
}
- return config;
+ return colorType;
}
-#ifdef ANDROID_RGB
/**
- * Based on the config and dither mode, adjust out_color_space and
- * dither_mode of cinfo.
+ * Based on the colortype and dither mode, adjust out_color_space and
+ * dither_mode of cinfo. Only does work in ANDROID_RGB
*/
static void adjust_out_color_space_and_dither(jpeg_decompress_struct* cinfo,
- SkBitmap::Config config,
+ SkColorType colorType,
const SkImageDecoder& decoder) {
SkASSERT(cinfo != NULL);
+#ifdef ANDROID_RGB
cinfo->dither_mode = JDITHER_NONE;
if (JCS_CMYK == cinfo->out_color_space) {
return;
}
- switch(config) {
- case SkBitmap::kARGB_8888_Config:
+ switch (colorType) {
+ case kN32_SkColorType:
cinfo->out_color_space = JCS_RGBA_8888;
break;
- case SkBitmap::kRGB_565_Config:
+ case kRGB_565_SkColorType:
cinfo->out_color_space = JCS_RGB_565;
if (decoder.getDitherImage()) {
cinfo->dither_mode = JDITHER_ORDERED;
@@ -480,8 +480,8 @@ static void adjust_out_color_space_and_dither(jpeg_decompress_struct* cinfo,
default:
break;
}
-}
#endif
+}
/**
@@ -569,20 +569,19 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
turn_off_visual_optimizations(&cinfo);
- const SkBitmap::Config config = this->getBitmapConfig(&cinfo);
+ const SkColorType colorType = this->getBitmapColorType(&cinfo);
+ const SkAlphaType alphaType = kAlpha_8_SkColorType == colorType ?
+ kPremul_SkAlphaType : kOpaque_SkAlphaType;
-#ifdef ANDROID_RGB
- adjust_out_color_space_and_dither(&cinfo, config, *this);
-#endif
+ adjust_out_color_space_and_dither(&cinfo, colorType, *this);
if (1 == sampleSize && SkImageDecoder::kDecodeBounds_Mode == mode) {
// Assume an A8 bitmap is not opaque to avoid the check of each
// individual pixel. It is very unlikely to be opaque, since
// an opaque A8 bitmap would not be very interesting.
// Otherwise, a jpeg image is opaque.
- return bm->setConfig(config, cinfo.image_width, cinfo.image_height, 0,
- SkBitmap::kA8_Config == config ?
- kPremul_SkAlphaType : kOpaque_SkAlphaType);
+ return bm->setInfo(SkImageInfo::Make(cinfo.image_width, cinfo.image_height,
+ colorType, alphaType));
}
/* image_width and image_height are the original dimensions, available
@@ -606,27 +605,28 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
// individual pixel. It is very unlikely to be opaque, since
// an opaque A8 bitmap would not be very interesting.
// Otherwise, a jpeg image is opaque.
- return bm->setConfig(config, smpl.scaledWidth(), smpl.scaledHeight(),
- 0, SkBitmap::kA8_Config == config ?
- kPremul_SkAlphaType : kOpaque_SkAlphaType);
+ return bm->setInfo(SkImageInfo::Make(smpl.scaledWidth(), smpl.scaledHeight(),
+ colorType, alphaType));
} else {
return return_false(cinfo, *bm, "start_decompress");
}
}
sampleSize = recompute_sampleSize(sampleSize, cinfo);
- // should we allow the Chooser (if present) to pick a config for us???
- if (!this->chooseFromOneChoice(config, cinfo.output_width, cinfo.output_height)) {
+#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
+ // should we allow the Chooser (if present) to pick a colortype for us???
+ if (!this->chooseFromOneChoice(colorType, cinfo.output_width, cinfo.output_height)) {
return return_false(cinfo, *bm, "chooseFromOneChoice");
}
+#endif
SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampleSize);
// Assume an A8 bitmap is not opaque to avoid the check of each
// individual pixel. It is very unlikely to be opaque, since
// an opaque A8 bitmap would not be very interesting.
// Otherwise, a jpeg image is opaque.
- bm->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight(), 0,
- SkBitmap::kA8_Config != config ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
+ bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(),
+ colorType, alphaType));
if (SkImageDecoder::kDecodeBounds_Mode == mode) {
return true;
}
@@ -641,10 +641,8 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
a significant performance boost.
*/
if (sampleSize == 1 &&
- ((config == SkBitmap::kARGB_8888_Config &&
- cinfo.out_color_space == JCS_RGBA_8888) ||
- (config == SkBitmap::kRGB_565_Config &&
- cinfo.out_color_space == JCS_RGB_565)))
+ ((kN32_SkColorType == colorType && cinfo.out_color_space == JCS_RGBA_8888) ||
+ (kRGB_565_SkColorType == colorType && cinfo.out_color_space == JCS_RGB_565)))
{
JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels();
INT32 const bpr = bm->rowBytes();
@@ -764,7 +762,7 @@ bool SkJPEGImageDecoder::onBuildTileIndex(SkStreamRewindable* stream, int *width
// based on the config in onDecodeSubset. This should be fine, since
// jpeg_init_read_tile_scanline will check out_color_space again after
// that change (when it calls jinit_color_deconverter).
- (void) this->getBitmapConfig(cinfo);
+ (void) this->getBitmapColorType(cinfo);
turn_off_visual_optimizations(cinfo);
@@ -815,10 +813,8 @@ bool SkJPEGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) {
set_dct_method(*this, cinfo);
- const SkBitmap::Config config = this->getBitmapConfig(cinfo);
-#ifdef ANDROID_RGB
- adjust_out_color_space_and_dither(cinfo, config, *this);
-#endif
+ const SkColorType colorType = this->getBitmapColorType(cinfo);
+ adjust_out_color_space_and_dither(cinfo, colorType, *this);
int startX = rect.fLeft;
int startY = rect.fTop;
@@ -833,14 +829,13 @@ bool SkJPEGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) {
SkScaledBitmapSampler sampler(width, height, skiaSampleSize);
SkBitmap bitmap;
- bitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight());
// Assume an A8 bitmap is not opaque to avoid the check of each
// individual pixel. It is very unlikely to be opaque, since
// an opaque A8 bitmap would not be very interesting.
// Otherwise, a jpeg image is opaque.
- bitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight(), 0,
- config == SkBitmap::kA8_Config ? kPremul_SkAlphaType :
- kOpaque_SkAlphaType);
+ bitmap.setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(), colorType,
+ kAlpha_8_SkColorType == colorType ?
+ kPremul_SkAlphaType : kOpaque_SkAlphaType));
// Check ahead of time if the swap(dest, src) is possible or not.
// If yes, then we will stick to AllocPixelRef since it's cheaper with the
@@ -869,10 +864,8 @@ bool SkJPEGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) {
a significant performance boost.
*/
if (skiaSampleSize == 1 &&
- ((config == SkBitmap::kARGB_8888_Config &&
- cinfo->out_color_space == JCS_RGBA_8888) ||
- (config == SkBitmap::kRGB_565_Config &&
- cinfo->out_color_space == JCS_RGB_565)))
+ ((kN32_SkColorType == colorType && cinfo->out_color_space == JCS_RGBA_8888) ||
+ (kRGB_565_SkColorType == colorType && cinfo->out_color_space == JCS_RGB_565)))
{
JSAMPLE* rowptr = (JSAMPLE*)bitmap.getPixels();
INT32 const bpr = bitmap.rowBytes();
@@ -1116,14 +1109,14 @@ static void Write_Index_YUV(uint8_t* SK_RESTRICT dst,
}
static WriteScanline ChooseWriter(const SkBitmap& bm) {
- switch (bm.config()) {
- case SkBitmap::kARGB_8888_Config:
+ switch (bm.colorType()) {
+ case kN32_SkColorType:
return Write_32_YUV;
- case SkBitmap::kRGB_565_Config:
+ case kRGB_565_SkColorType:
return Write_16_YUV;
- case SkBitmap::kARGB_4444_Config:
+ case kARGB_4444_SkColorType:
return Write_4444_YUV;
- case SkBitmap::kIndex8_Config:
+ case kIndex_8_SkColorType:
return Write_Index_YUV;
default:
return NULL;
diff --git a/chromium/third_party/skia/src/images/SkImageDecoder_libpng.cpp b/chromium/third_party/skia/src/images/SkImageDecoder_libpng.cpp
index 02ba6af90a3..7ff15584c4f 100644
--- a/chromium/third_party/skia/src/images/SkImageDecoder_libpng.cpp
+++ b/chromium/third_party/skia/src/images/SkImageDecoder_libpng.cpp
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -6,7 +5,6 @@
* found in the LICENSE file.
*/
-
#include "SkImageDecoder.h"
#include "SkImageEncoder.h"
#include "SkColor.h"
@@ -59,7 +57,7 @@ public:
: fStream(stream)
, fPng_ptr(png_ptr)
, fInfo_ptr(info_ptr)
- , fConfig(SkBitmap::kNo_Config) {
+ , fColorType(kUnknown_SkColorType) {
SkASSERT(stream != NULL);
stream->ref();
}
@@ -72,7 +70,7 @@ public:
SkAutoTUnref<SkStreamRewindable> fStream;
png_structp fPng_ptr;
png_infop fInfo_ptr;
- SkBitmap::Config fConfig;
+ SkColorType fColorType;
};
class SkPNGImageDecoder : public SkImageDecoder {
@@ -102,9 +100,8 @@ private:
bool decodePalette(png_structp png_ptr, png_infop info_ptr,
bool * SK_RESTRICT hasAlphap, bool *reallyHasAlphap,
SkColorTable **colorTablep);
- bool getBitmapConfig(png_structp png_ptr, png_infop info_ptr,
- SkBitmap::Config *config, bool *hasAlpha,
- SkPMColor *theTranspColor);
+ bool getBitmapColorType(png_structp, png_infop, SkColorType*, bool* hasAlpha,
+ SkPMColor* theTranspColor);
typedef SkImageDecoder INHERITED;
};
@@ -169,7 +166,7 @@ static bool pos_le(int value, int max) {
}
static bool substituteTranspColor(SkBitmap* bm, SkPMColor match) {
- SkASSERT(bm->config() == SkBitmap::kARGB_8888_Config);
+ SkASSERT(bm->colorType() == kN32_SkColorType);
bool reallyHasAlpha = false;
@@ -186,13 +183,12 @@ static bool substituteTranspColor(SkBitmap* bm, SkPMColor match) {
return reallyHasAlpha;
}
-static bool canUpscalePaletteToConfig(SkBitmap::Config dstConfig,
- bool srcHasAlpha) {
- switch (dstConfig) {
- case SkBitmap::kARGB_8888_Config:
- case SkBitmap::kARGB_4444_Config:
+static bool canUpscalePaletteToConfig(SkColorType dstColorType, bool srcHasAlpha) {
+ switch (dstColorType) {
+ case kN32_SkColorType:
+ case kARGB_4444_SkColorType:
return true;
- case SkBitmap::kRGB_565_Config:
+ case kRGB_565_SkColorType:
// only return true if the src is opaque (since 565 is opaque)
return !srcHasAlpha;
default:
@@ -317,21 +313,24 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap,
}
png_uint_32 origWidth, origHeight;
- int bitDepth, colorType, interlaceType;
+ int bitDepth, pngColorType, interlaceType;
png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth,
- &colorType, &interlaceType, int_p_NULL, int_p_NULL);
+ &pngColorType, &interlaceType, int_p_NULL, int_p_NULL);
- SkBitmap::Config config;
+ SkColorType colorType;
bool hasAlpha = false;
SkPMColor theTranspColor = 0; // 0 tells us not to try to match
- if (!this->getBitmapConfig(png_ptr, info_ptr, &config, &hasAlpha, &theTranspColor)) {
+ if (!this->getBitmapColorType(png_ptr, info_ptr, &colorType, &hasAlpha, &theTranspColor)) {
return false;
}
+ SkAlphaType alphaType = this->getRequireUnpremultipliedColors() ?
+ kUnpremul_SkAlphaType : kPremul_SkAlphaType;
const int sampleSize = this->getSampleSize();
SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize);
- decodedBitmap->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight());
+ decodedBitmap->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(),
+ colorType, alphaType));
if (SkImageDecoder::kDecodeBounds_Mode == mode) {
return true;
@@ -345,14 +344,14 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap,
bool reallyHasAlpha = false;
SkColorTable* colorTable = NULL;
- if (colorType == PNG_COLOR_TYPE_PALETTE) {
+ if (pngColorType == PNG_COLOR_TYPE_PALETTE) {
decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable);
}
SkAutoUnref aur(colorTable);
if (!this->allocPixelRef(decodedBitmap,
- SkBitmap::kIndex8_Config == config ? colorTable : NULL)) {
+ kIndex_8_SkColorType == colorType ? colorTable : NULL)) {
return false;
}
@@ -371,15 +370,15 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap,
*/
png_read_update_info(png_ptr, info_ptr);
- if ((SkBitmap::kA8_Config == config || SkBitmap::kIndex8_Config == config)
- && 1 == sampleSize) {
- if (SkBitmap::kA8_Config == config) {
+ if ((kAlpha_8_SkColorType == colorType || kIndex_8_SkColorType == colorType) &&
+ 1 == sampleSize) {
+ if (kAlpha_8_SkColorType == colorType) {
// For an A8 bitmap, we assume there is an alpha for speed. It is
// possible the bitmap is opaque, but that is an unlikely use case
// since it would not be very interesting.
reallyHasAlpha = true;
// A8 is only allowed if the original was GRAY.
- SkASSERT(PNG_COLOR_TYPE_GRAY == colorType);
+ SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType);
}
for (int i = 0; i < number_passes; i++) {
for (png_uint_32 y = 0; y < origHeight; y++) {
@@ -394,9 +393,9 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap,
if (colorTable != NULL) {
sc = SkScaledBitmapSampler::kIndex;
srcBytesPerPixel = 1;
- } else if (SkBitmap::kA8_Config == config) {
+ } else if (kAlpha_8_SkColorType == colorType) {
// A8 is only allowed if the original was GRAY.
- SkASSERT(PNG_COLOR_TYPE_GRAY == colorType);
+ SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType);
sc = SkScaledBitmapSampler::kGray;
srcBytesPerPixel = 1;
} else if (hasAlpha) {
@@ -463,14 +462,14 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap,
reallyHasAlpha |= substituteTranspColor(decodedBitmap, theTranspColor);
}
if (reallyHasAlpha && this->getRequireUnpremultipliedColors()) {
- switch (decodedBitmap->config()) {
- case SkBitmap::kIndex8_Config:
+ switch (decodedBitmap->colorType()) {
+ case kIndex_8_SkColorType:
// Fall through.
- case SkBitmap::kARGB_4444_Config:
- // We have chosen not to support unpremul for these configs.
+ case kARGB_4444_SkColorType:
+ // We have chosen not to support unpremul for these colortypes.
return false;
default: {
- // Fall through to finish the decode. This config either
+ // Fall through to finish the decode. This colortype either
// supports unpremul or it is irrelevant because it has no
// alpha (or only alpha).
// These brackets prevent a warning.
@@ -478,24 +477,18 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap,
}
}
- SkAlphaType alphaType = kOpaque_SkAlphaType;
- if (reallyHasAlpha) {
- if (this->getRequireUnpremultipliedColors()) {
- alphaType = kUnpremul_SkAlphaType;
- } else {
- alphaType = kPremul_SkAlphaType;
- }
+ if (!reallyHasAlpha) {
+ decodedBitmap->setAlphaType(kOpaque_SkAlphaType);
}
- decodedBitmap->setAlphaType(alphaType);
return true;
}
-bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr,
- SkBitmap::Config* SK_RESTRICT configp,
- bool* SK_RESTRICT hasAlphap,
- SkPMColor* SK_RESTRICT theTranspColorp) {
+bool SkPNGImageDecoder::getBitmapColorType(png_structp png_ptr, png_infop info_ptr,
+ SkColorType* colorTypep,
+ bool* hasAlphap,
+ SkPMColor* SK_RESTRICT theTranspColorp) {
png_uint_32 origWidth, origHeight;
int bitDepth, colorType;
png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth,
@@ -519,10 +512,10 @@ bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr,
if (colorType == PNG_COLOR_TYPE_PALETTE) {
bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr);
- *configp = this->getPrefConfig(kIndex_SrcDepth, paletteHasAlpha);
- // now see if we can upscale to their requested config
- if (!canUpscalePaletteToConfig(*configp, paletteHasAlpha)) {
- *configp = SkBitmap::kIndex8_Config;
+ *colorTypep = this->getPrefColorType(kIndex_SrcDepth, paletteHasAlpha);
+ // now see if we can upscale to their requested colortype
+ if (!canUpscalePaletteToConfig(*colorTypep, paletteHasAlpha)) {
+ *colorTypep = kIndex_8_SkColorType;
}
} else {
png_color_16p transpColor = NULL;
@@ -586,62 +579,59 @@ bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr,
//SkASSERT(!*hasAlphap);
}
- *configp = this->getPrefConfig(srcDepth, *hasAlphap);
+ *colorTypep = this->getPrefColorType(srcDepth, *hasAlphap);
// now match the request against our capabilities
if (*hasAlphap) {
- if (*configp != SkBitmap::kARGB_4444_Config) {
- *configp = SkBitmap::kARGB_8888_Config;
+ if (*colorTypep != kARGB_4444_SkColorType) {
+ *colorTypep = kN32_SkColorType;
}
} else {
- if (SkBitmap::kA8_Config == *configp) {
+ if (kAlpha_8_SkColorType == *colorTypep) {
if (k8BitGray_SrcDepth != srcDepth) {
// Converting a non grayscale image to A8 is not currently supported.
- *configp = SkBitmap::kARGB_8888_Config;
+ *colorTypep = kN32_SkColorType;
}
- } else if (*configp != SkBitmap::kRGB_565_Config &&
- *configp != SkBitmap::kARGB_4444_Config) {
- *configp = SkBitmap::kARGB_8888_Config;
+ } else if (*colorTypep != kRGB_565_SkColorType &&
+ *colorTypep != kARGB_4444_SkColorType) {
+ *colorTypep = kN32_SkColorType;
}
}
}
// sanity check for size
{
- Sk64 size;
- size.setMul(origWidth, origHeight);
- if (size.isNeg() || !size.is32()) {
- return false;
- }
+ int64_t size = sk_64_mul(origWidth, origHeight);
// now check that if we are 4-bytes per pixel, we also don't overflow
- if (size.get32() > (0x7FFFFFFF >> 2)) {
+ if (size < 0 || size > (0x7FFFFFFF >> 2)) {
return false;
}
}
- if (!this->chooseFromOneChoice(*configp, origWidth, origHeight)) {
+#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
+ if (!this->chooseFromOneChoice(*colorTypep, origWidth, origHeight)) {
return false;
}
+#endif
// If the image has alpha and the decoder wants unpremultiplied
- // colors, the only supported config is 8888.
+ // colors, the only supported colortype is 8888.
if (this->getRequireUnpremultipliedColors() && *hasAlphap) {
- *configp = SkBitmap::kARGB_8888_Config;
+ *colorTypep = kN32_SkColorType;
}
if (fImageIndex != NULL) {
- if (SkBitmap::kNo_Config == fImageIndex->fConfig) {
+ if (kUnknown_SkColorType == fImageIndex->fColorType) {
// This is the first time for this subset decode. From now on,
- // all decodes must be in the same config.
- fImageIndex->fConfig = *configp;
- } else if (fImageIndex->fConfig != *configp) {
- // Requesting a different config for a subsequent decode is not
+ // all decodes must be in the same colortype.
+ fImageIndex->fColorType = *colorTypep;
+ } else if (fImageIndex->fColorType != *colorTypep) {
+ // Requesting a different colortype for a subsequent decode is not
// supported. Report failure before we make changes to png_ptr.
return false;
}
}
- bool convertGrayToRGB = PNG_COLOR_TYPE_GRAY == colorType
- && *configp != SkBitmap::kA8_Config;
+ bool convertGrayToRGB = PNG_COLOR_TYPE_GRAY == colorType && *colorTypep != kAlpha_8_SkColorType;
// Unless the user is requesting A8, convert a grayscale image into RGB.
// GRAY_ALPHA will always be converted to RGB
@@ -695,7 +685,7 @@ bool SkPNGImageDecoder::decodePalette(png_structp png_ptr, png_infop info_ptr,
int transLessThanFF = 0;
// Choose which function to use to create the color table. If the final destination's
- // config is unpremultiplied, the color table will store unpremultiplied colors.
+ // colortype is unpremultiplied, the color table will store unpremultiplied colors.
PackColorProc proc;
if (this->getRequireUnpremultipliedColors()) {
proc = &SkPackARGB32NoCheck;
@@ -779,9 +769,9 @@ bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) {
}
png_uint_32 origWidth, origHeight;
- int bitDepth, colorType, interlaceType;
+ int bitDepth, pngColorType, interlaceType;
png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth,
- &colorType, &interlaceType, int_p_NULL, int_p_NULL);
+ &pngColorType, &interlaceType, int_p_NULL, int_p_NULL);
SkIRect rect = SkIRect::MakeWH(origWidth, origHeight);
@@ -791,11 +781,11 @@ bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) {
return false;
}
- SkBitmap::Config config;
+ SkColorType colorType;
bool hasAlpha = false;
SkPMColor theTranspColor = 0; // 0 tells us not to try to match
- if (!this->getBitmapConfig(png_ptr, info_ptr, &config, &hasAlpha, &theTranspColor)) {
+ if (!this->getBitmapColorType(png_ptr, info_ptr, &colorType, &hasAlpha, &theTranspColor)) {
return false;
}
@@ -803,7 +793,8 @@ bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) {
SkScaledBitmapSampler sampler(origWidth, rect.height(), sampleSize);
SkBitmap decodedBitmap;
- decodedBitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight());
+ decodedBitmap.setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(),
+ colorType, kPremul_SkAlphaType));
// from here down we are concerned with colortables and pixels
@@ -813,7 +804,7 @@ bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) {
bool reallyHasAlpha = false;
SkColorTable* colorTable = NULL;
- if (colorType == PNG_COLOR_TYPE_PALETTE) {
+ if (pngColorType == PNG_COLOR_TYPE_PALETTE) {
decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable);
}
@@ -826,7 +817,7 @@ bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) {
int h = rect.height() / sampleSize;
const bool swapOnly = (rect == region) && (w == decodedBitmap.width()) &&
(h == decodedBitmap.height()) && bm->isNull();
- const bool needColorTable = SkBitmap::kIndex8_Config == config;
+ const bool needColorTable = kIndex_8_SkColorType == colorType;
if (swapOnly) {
if (!this->allocPixelRef(&decodedBitmap, needColorTable ? colorTable : NULL)) {
return false;
@@ -861,15 +852,15 @@ bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) {
int actualTop = rect.fTop;
- if ((SkBitmap::kA8_Config == config || SkBitmap::kIndex8_Config == config)
+ if ((kAlpha_8_SkColorType == colorType || kIndex_8_SkColorType == colorType)
&& 1 == sampleSize) {
- if (SkBitmap::kA8_Config == config) {
+ if (kAlpha_8_SkColorType == colorType) {
// For an A8 bitmap, we assume there is an alpha for speed. It is
// possible the bitmap is opaque, but that is an unlikely use case
// since it would not be very interesting.
reallyHasAlpha = true;
// A8 is only allowed if the original was GRAY.
- SkASSERT(PNG_COLOR_TYPE_GRAY == colorType);
+ SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType);
}
for (int i = 0; i < number_passes; i++) {
@@ -891,9 +882,9 @@ bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) {
if (colorTable != NULL) {
sc = SkScaledBitmapSampler::kIndex;
srcBytesPerPixel = 1;
- } else if (SkBitmap::kA8_Config == config) {
+ } else if (kAlpha_8_SkColorType == colorType) {
// A8 is only allowed if the original was GRAY.
- SkASSERT(PNG_COLOR_TYPE_GRAY == colorType);
+ SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType);
sc = SkScaledBitmapSampler::kGray;
srcBytesPerPixel = 1;
} else if (hasAlpha) {
@@ -962,11 +953,11 @@ bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) {
reallyHasAlpha |= substituteTranspColor(&decodedBitmap, theTranspColor);
}
if (reallyHasAlpha && this->getRequireUnpremultipliedColors()) {
- switch (decodedBitmap.config()) {
- case SkBitmap::kIndex8_Config:
+ switch (decodedBitmap.colorType()) {
+ case kIndex_8_SkColorType:
// Fall through.
- case SkBitmap::kARGB_4444_Config:
- // We have chosen not to support unpremul for these configs.
+ case kARGB_4444_SkColorType:
+ // We have chosen not to support unpremul for these colortypess.
return false;
default: {
// Fall through to finish the decode. This config either
@@ -1007,29 +998,28 @@ static void sk_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) {
}
}
-static transform_scanline_proc choose_proc(SkBitmap::Config config,
- bool hasAlpha) {
+static transform_scanline_proc choose_proc(SkColorType ct, bool hasAlpha) {
// we don't care about search on alpha if we're kIndex8, since only the
// colortable packing cares about that distinction, not the pixels
- if (SkBitmap::kIndex8_Config == config) {
+ if (kIndex_8_SkColorType == ct) {
hasAlpha = false; // we store false in the table entries for kIndex8
}
static const struct {
- SkBitmap::Config fConfig;
+ SkColorType fColorType;
bool fHasAlpha;
transform_scanline_proc fProc;
} gMap[] = {
- { SkBitmap::kRGB_565_Config, false, transform_scanline_565 },
- { SkBitmap::kARGB_8888_Config, false, transform_scanline_888 },
- { SkBitmap::kARGB_8888_Config, true, transform_scanline_8888 },
- { SkBitmap::kARGB_4444_Config, false, transform_scanline_444 },
- { SkBitmap::kARGB_4444_Config, true, transform_scanline_4444 },
- { SkBitmap::kIndex8_Config, false, transform_scanline_memcpy },
+ { kRGB_565_SkColorType, false, transform_scanline_565 },
+ { kN32_SkColorType, false, transform_scanline_888 },
+ { kN32_SkColorType, true, transform_scanline_8888 },
+ { kARGB_4444_SkColorType, false, transform_scanline_444 },
+ { kARGB_4444_SkColorType, true, transform_scanline_4444 },
+ { kIndex_8_SkColorType, false, transform_scanline_memcpy },
};
for (int i = SK_ARRAY_COUNT(gMap) - 1; i >= 0; --i) {
- if (gMap[i].fConfig == config && gMap[i].fHasAlpha == hasAlpha) {
+ if (gMap[i].fColorType == ct && gMap[i].fHasAlpha == hasAlpha) {
return gMap[i].fProc;
}
}
@@ -1116,38 +1106,37 @@ protected:
private:
bool doEncode(SkWStream* stream, const SkBitmap& bm,
const bool& hasAlpha, int colorType,
- int bitDepth, SkBitmap::Config config,
+ int bitDepth, SkColorType ct,
png_color_8& sig_bit);
typedef SkImageEncoder INHERITED;
};
-bool SkPNGImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bitmap,
- int /*quality*/) {
- SkBitmap::Config config = bitmap.config();
+bool SkPNGImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bitmap, int /*quality*/) {
+ SkColorType ct = bitmap.colorType();
const bool hasAlpha = !bitmap.isOpaque();
int colorType = PNG_COLOR_MASK_COLOR;
int bitDepth = 8; // default for color
png_color_8 sig_bit;
- switch (config) {
- case SkBitmap::kIndex8_Config:
+ switch (ct) {
+ case kIndex_8_SkColorType:
colorType |= PNG_COLOR_MASK_PALETTE;
// fall through to the ARGB_8888 case
- case SkBitmap::kARGB_8888_Config:
+ case kN32_SkColorType:
sig_bit.red = 8;
sig_bit.green = 8;
sig_bit.blue = 8;
sig_bit.alpha = 8;
break;
- case SkBitmap::kARGB_4444_Config:
+ case kARGB_4444_SkColorType:
sig_bit.red = 4;
sig_bit.green = 4;
sig_bit.blue = 4;
sig_bit.alpha = 4;
break;
- case SkBitmap::kRGB_565_Config:
+ case kRGB_565_SkColorType:
sig_bit.red = 5;
sig_bit.green = 6;
sig_bit.blue = 5;
@@ -1182,13 +1171,12 @@ bool SkPNGImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bitmap,
bitDepth = computeBitDepth(ctable->count());
}
- return doEncode(stream, bitmap, hasAlpha, colorType,
- bitDepth, config, sig_bit);
+ return doEncode(stream, bitmap, hasAlpha, colorType, bitDepth, ct, sig_bit);
}
bool SkPNGImageEncoder::doEncode(SkWStream* stream, const SkBitmap& bitmap,
const bool& hasAlpha, int colorType,
- int bitDepth, SkBitmap::Config config,
+ int bitDepth, SkColorType ct,
png_color_8& sig_bit) {
png_structp png_ptr;
@@ -1233,7 +1221,7 @@ bool SkPNGImageEncoder::doEncode(SkWStream* stream, const SkBitmap& bitmap,
// set our colortable/trans arrays if needed
png_color paletteColors[256];
png_byte trans[256];
- if (SkBitmap::kIndex8_Config == config) {
+ if (kIndex_8_SkColorType == ct) {
SkColorTable* ct = bitmap.getColorTable();
int numTrans = pack_palette(ct, paletteColors, trans, hasAlpha);
png_set_PLTE(png_ptr, info_ptr, paletteColors, ct->count());
@@ -1248,7 +1236,7 @@ bool SkPNGImageEncoder::doEncode(SkWStream* stream, const SkBitmap& bitmap,
const char* srcImage = (const char*)bitmap.getPixels();
SkAutoSMalloc<1024> rowStorage(bitmap.width() << 2);
char* storage = (char*)rowStorage.get();
- transform_scanline_proc proc = choose_proc(config, hasAlpha);
+ transform_scanline_proc proc = choose_proc(ct, hasAlpha);
for (int y = 0; y < bitmap.height(); y++) {
png_bytep row_ptr = (png_bytep)storage;
diff --git a/chromium/third_party/skia/src/images/SkImageDecoder_libwebp.cpp b/chromium/third_party/skia/src/images/SkImageDecoder_libwebp.cpp
index ab58aef135b..f7cfa8b4cca 100644
--- a/chromium/third_party/skia/src/images/SkImageDecoder_libwebp.cpp
+++ b/chromium/third_party/skia/src/images/SkImageDecoder_libwebp.cpp
@@ -80,13 +80,12 @@ static bool webp_parse_header(SkStream* stream, int* width, int* height, int* al
// sanity check for image size that's about to be decoded.
{
- Sk64 size;
- size.setMul(*width, *height);
- if (size.isNeg() || !size.is32()) {
+ int64_t size = sk_64_mul(*width, *height);
+ if (!sk_64_isS32(size)) {
return false;
}
// now check that if we are 4-bytes per pixel, we also don't overflow
- if (size.get32() > (0x7FFFFFFF >> 2)) {
+ if (sk_64_asS32(size) > (0x7FFFFFFF >> 2)) {
return false;
}
}
@@ -170,13 +169,19 @@ static bool return_false(const SkBitmap& bm, const char msg[]) {
static WEBP_CSP_MODE webp_decode_mode(const SkBitmap* decodedBitmap, bool premultiply) {
WEBP_CSP_MODE mode = MODE_LAST;
- SkBitmap::Config config = decodedBitmap->config();
-
- if (config == SkBitmap::kARGB_8888_Config) {
- mode = premultiply ? MODE_rgbA : MODE_RGBA;
- } else if (config == SkBitmap::kARGB_4444_Config) {
+ const SkColorType ct = decodedBitmap->colorType();
+
+ if (ct == kN32_SkColorType) {
+ #if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
+ mode = premultiply ? MODE_bgrA : MODE_BGRA;
+ #elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
+ mode = premultiply ? MODE_rgbA : MODE_RGBA;
+ #else
+ #error "Skia uses BGRA or RGBA byte order"
+ #endif
+ } else if (ct == kARGB_4444_SkColorType) {
mode = premultiply ? MODE_rgbA_4444 : MODE_RGBA_4444;
- } else if (config == SkBitmap::kRGB_565_Config) {
+ } else if (ct == kRGB_565_SkColorType) {
mode = MODE_RGB_565;
}
SkASSERT(MODE_LAST != mode);
@@ -273,28 +278,35 @@ static bool webp_get_config_resize_crop(WebPDecoderConfig* config,
return true;
}
-bool SkWEBPImageDecoder::setDecodeConfig(SkBitmap* decodedBitmap,
- int width, int height) {
- SkBitmap::Config config = this->getPrefConfig(k32Bit_SrcDepth, SkToBool(fHasAlpha));
+bool SkWEBPImageDecoder::setDecodeConfig(SkBitmap* decodedBitmap, int width, int height) {
+ SkColorType colorType = this->getPrefColorType(k32Bit_SrcDepth, SkToBool(fHasAlpha));
// YUV converter supports output in RGB565, RGBA4444 and RGBA8888 formats.
if (fHasAlpha) {
- if (config != SkBitmap::kARGB_4444_Config) {
- config = SkBitmap::kARGB_8888_Config;
+ if (colorType != kARGB_4444_SkColorType) {
+ colorType = kN32_SkColorType;
}
} else {
- if (config != SkBitmap::kRGB_565_Config &&
- config != SkBitmap::kARGB_4444_Config) {
- config = SkBitmap::kARGB_8888_Config;
+ if (colorType != kRGB_565_SkColorType && colorType != kARGB_4444_SkColorType) {
+ colorType = kN32_SkColorType;
}
}
- if (!this->chooseFromOneChoice(config, width, height)) {
+#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
+ if (!this->chooseFromOneChoice(colorType, width, height)) {
return false;
}
+#endif
- return decodedBitmap->setConfig(config, width, height, 0,
- fHasAlpha ? kPremul_SkAlphaType : kOpaque_SkAlphaType);
+ SkAlphaType alphaType = kOpaque_SkAlphaType;
+ if (SkToBool(fHasAlpha)) {
+ if (this->getRequireUnpremultipliedColors()) {
+ alphaType = kUnpremul_SkAlphaType;
+ } else {
+ alphaType = kPremul_SkAlphaType;
+ }
+ }
+ return decodedBitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType));
}
bool SkWEBPImageDecoder::onBuildTileIndex(SkStreamRewindable* stream,
@@ -321,10 +333,8 @@ bool SkWEBPImageDecoder::onBuildTileIndex(SkStreamRewindable* stream,
}
static bool is_config_compatible(const SkBitmap& bitmap) {
- SkBitmap::Config config = bitmap.config();
- return config == SkBitmap::kARGB_4444_Config ||
- config == SkBitmap::kRGB_565_Config ||
- config == SkBitmap::kARGB_8888_Config;
+ const SkColorType ct = bitmap.colorType();
+ return ct == kARGB_4444_SkColorType || ct == kRGB_565_SkColorType || ct == kN32_SkColorType;
}
bool SkWEBPImageDecoder::onDecodeSubset(SkBitmap* decodedBitmap,
@@ -369,12 +379,14 @@ bool SkWEBPImageDecoder::onDecodeSubset(SkBitmap* decodedBitmap,
if (!allocResult) {
return return_false(*decodedBitmap, "allocPixelRef");
}
+#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
} else {
// This is also called in setDecodeConfig in above block.
// i.e., when bitmap->isNull() is true.
- if (!chooseFromOneChoice(bitmap->config(), width, height)) {
+ if (!chooseFromOneChoice(bitmap->colorType(), width, height)) {
return false;
}
+#endif
}
SkAutoLockPixels alp(*bitmap);
@@ -439,6 +451,8 @@ bool SkWEBPImageDecoder::onDecode(SkStream* stream, SkBitmap* decodedBitmap,
///////////////////////////////////////////////////////////////////////////////
+#include "SkUnPreMultiply.h"
+
typedef void (*ScanlineImporter)(const uint8_t* in, uint8_t* out, int width,
const SkPMColor* SK_RESTRICT ctable);
@@ -454,6 +468,31 @@ static void ARGB_8888_To_RGB(const uint8_t* in, uint8_t* rgb, int width,
}
}
+static void ARGB_8888_To_RGBA(const uint8_t* in, uint8_t* rgb, int width,
+ const SkPMColor*) {
+ const uint32_t* SK_RESTRICT src = (const uint32_t*)in;
+ const SkUnPreMultiply::Scale* SK_RESTRICT table =
+ SkUnPreMultiply::GetScaleTable();
+ for (int i = 0; i < width; ++i) {
+ const uint32_t c = *src++;
+ uint8_t a = SkGetPackedA32(c);
+ uint8_t r = SkGetPackedR32(c);
+ uint8_t g = SkGetPackedG32(c);
+ uint8_t b = SkGetPackedB32(c);
+ if (0 != a && 255 != a) {
+ SkUnPreMultiply::Scale scale = table[a];
+ r = SkUnPreMultiply::ApplyScale(scale, r);
+ g = SkUnPreMultiply::ApplyScale(scale, g);
+ b = SkUnPreMultiply::ApplyScale(scale, b);
+ }
+ rgb[0] = r;
+ rgb[1] = g;
+ rgb[2] = b;
+ rgb[3] = a;
+ rgb += 4;
+ }
+}
+
static void RGB_565_To_RGB(const uint8_t* in, uint8_t* rgb, int width,
const SkPMColor*) {
const uint16_t* SK_RESTRICT src = (const uint16_t*)in;
@@ -478,6 +517,31 @@ static void ARGB_4444_To_RGB(const uint8_t* in, uint8_t* rgb, int width,
}
}
+static void ARGB_4444_To_RGBA(const uint8_t* in, uint8_t* rgb, int width,
+ const SkPMColor*) {
+ const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)in;
+ const SkUnPreMultiply::Scale* SK_RESTRICT table =
+ SkUnPreMultiply::GetScaleTable();
+ for (int i = 0; i < width; ++i) {
+ const SkPMColor16 c = *src++;
+ uint8_t a = SkPacked4444ToA32(c);
+ uint8_t r = SkPacked4444ToR32(c);
+ uint8_t g = SkPacked4444ToG32(c);
+ uint8_t b = SkPacked4444ToB32(c);
+ if (0 != a && 255 != a) {
+ SkUnPreMultiply::Scale scale = table[a];
+ r = SkUnPreMultiply::ApplyScale(scale, r);
+ g = SkUnPreMultiply::ApplyScale(scale, g);
+ b = SkUnPreMultiply::ApplyScale(scale, b);
+ }
+ rgb[0] = r;
+ rgb[1] = g;
+ rgb[2] = b;
+ rgb[3] = a;
+ rgb += 4;
+ }
+}
+
static void Index8_To_RGB(const uint8_t* in, uint8_t* rgb, int width,
const SkPMColor* SK_RESTRICT ctable) {
const uint8_t* SK_RESTRICT src = (const uint8_t*)in;
@@ -490,15 +554,29 @@ static void Index8_To_RGB(const uint8_t* in, uint8_t* rgb, int width,
}
}
-static ScanlineImporter ChooseImporter(const SkBitmap::Config& config) {
- switch (config) {
- case SkBitmap::kARGB_8888_Config:
- return ARGB_8888_To_RGB;
- case SkBitmap::kRGB_565_Config:
+static ScanlineImporter ChooseImporter(SkColorType ct, bool hasAlpha, int* bpp) {
+ switch (ct) {
+ case kN32_SkColorType:
+ if (hasAlpha) {
+ *bpp = 4;
+ return ARGB_8888_To_RGBA;
+ } else {
+ *bpp = 3;
+ return ARGB_8888_To_RGB;
+ }
+ case kARGB_4444_SkColorType:
+ if (hasAlpha) {
+ *bpp = 4;
+ return ARGB_4444_To_RGBA;
+ } else {
+ *bpp = 3;
+ return ARGB_4444_To_RGB;
+ }
+ case kRGB_565_SkColorType:
+ *bpp = 3;
return RGB_565_To_RGB;
- case SkBitmap::kARGB_4444_Config:
- return ARGB_4444_To_RGB;
- case SkBitmap::kIndex8_Config:
+ case kIndex_8_SkColorType:
+ *bpp = 3;
return Index8_To_RGB;
default:
return NULL;
@@ -521,11 +599,15 @@ private:
bool SkWEBPImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bm,
int quality) {
- const SkBitmap::Config config = bm.config();
- const ScanlineImporter scanline_import = ChooseImporter(config);
+ const bool hasAlpha = !bm.isOpaque();
+ int bpp = -1;
+ const ScanlineImporter scanline_import = ChooseImporter(bm.colorType(), hasAlpha, &bpp);
if (NULL == scanline_import) {
return false;
}
+ if (-1 == bpp) {
+ return false;
+ }
SkAutoLockPixels alp(bm);
SkAutoLockColors ctLocker;
@@ -547,7 +629,7 @@ bool SkWEBPImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bm,
const SkPMColor* colors = ctLocker.lockColors(bm);
const uint8_t* src = (uint8_t*)bm.getPixels();
- const int rgbStride = pic.width * 3;
+ const int rgbStride = pic.width * bpp;
// Import (for each scanline) the bit-map image (in appropriate color-space)
// to RGB color space.
@@ -557,7 +639,12 @@ bool SkWEBPImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bm,
pic.width, colors);
}
- bool ok = SkToBool(WebPPictureImportRGB(&pic, rgb, rgbStride));
+ bool ok;
+ if (bpp == 3) {
+ ok = SkToBool(WebPPictureImportRGB(&pic, rgb, rgbStride));
+ } else {
+ ok = SkToBool(WebPPictureImportRGBA(&pic, rgb, rgbStride));
+ }
delete[] rgb;
ok = ok && WebPEncode(&webp_config, &pic);
diff --git a/chromium/third_party/skia/src/images/SkImageDecoder_pkm.cpp b/chromium/third_party/skia/src/images/SkImageDecoder_pkm.cpp
new file mode 100644
index 00000000000..d555c6afccc
--- /dev/null
+++ b/chromium/third_party/skia/src/images/SkImageDecoder_pkm.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkColorPriv.h"
+#include "SkImageDecoder.h"
+#include "SkScaledBitmapSampler.h"
+#include "SkStream.h"
+#include "SkStreamHelpers.h"
+#include "SkTypes.h"
+
+#include "etc1.h"
+
+class SkPKMImageDecoder : public SkImageDecoder {
+public:
+ SkPKMImageDecoder() { }
+
+ virtual Format getFormat() const SK_OVERRIDE {
+ return kPKM_Format;
+ }
+
+protected:
+ virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE;
+
+private:
+ typedef SkImageDecoder INHERITED;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+bool SkPKMImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
+ SkAutoMalloc autoMal;
+ const size_t length = CopyStreamToStorage(&autoMal, stream);
+ if (0 == length) {
+ return false;
+ }
+
+ unsigned char* buf = (unsigned char*)autoMal.get();
+
+ // Make sure original PKM header is there...
+ SkASSERT(etc1_pkm_is_valid(buf));
+
+ const unsigned short width = etc1_pkm_get_width(buf);
+ const unsigned short height = etc1_pkm_get_height(buf);
+
+#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
+ // should we allow the Chooser (if present) to pick a config for us???
+ if (!this->chooseFromOneChoice(kN32_SkColorType, width, height)) {
+ return false;
+ }
+#endif
+
+ // Setup the sampler...
+ SkScaledBitmapSampler sampler(width, height, this->getSampleSize());
+
+ // Set the config...
+ bm->setInfo(SkImageInfo::MakeN32(sampler.scaledWidth(), sampler.scaledHeight(),
+ kOpaque_SkAlphaType));
+ if (SkImageDecoder::kDecodeBounds_Mode == mode) {
+ return true;
+ }
+
+ if (!this->allocPixelRef(bm, NULL)) {
+ return false;
+ }
+
+ // Lock the pixels, since we're about to write to them...
+ SkAutoLockPixels alp(*bm);
+
+ if (!sampler.begin(bm, SkScaledBitmapSampler::kRGB, *this)) {
+ return false;
+ }
+
+ // Advance buffer past the header
+ buf += ETC_PKM_HEADER_SIZE;
+
+ // ETC1 Data is encoded as RGB pixels, so we should extract it as such
+ int nPixels = width * height;
+ SkAutoMalloc outRGBData(nPixels * 3);
+ etc1_byte *outRGBDataPtr = reinterpret_cast<etc1_byte *>(outRGBData.get());
+
+ // Decode ETC1
+ if (etc1_decode_image(buf, outRGBDataPtr, width, height, 3, width*3)) {
+ return false;
+ }
+
+ // Set each of the pixels...
+ const int srcRowBytes = width * 3;
+ const int dstHeight = sampler.scaledHeight();
+ const uint8_t *srcRow = reinterpret_cast<uint8_t *>(outRGBDataPtr);
+ srcRow += sampler.srcY0() * srcRowBytes;
+ for (int y = 0; y < dstHeight; ++y) {
+ sampler.next(srcRow);
+ srcRow += sampler.srcDY() * srcRowBytes;
+ }
+
+ return true;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+DEFINE_DECODER_CREATOR(PKMImageDecoder);
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static bool is_pkm(SkStreamRewindable* stream) {
+ // Read the PKM header and make sure it's valid.
+ unsigned char buf[ETC_PKM_HEADER_SIZE];
+ if (stream->read((void*)buf, ETC_PKM_HEADER_SIZE) != ETC_PKM_HEADER_SIZE) {
+ return false;
+ }
+
+ return SkToBool(etc1_pkm_is_valid(buf));
+}
+
+static SkImageDecoder* sk_libpkm_dfactory(SkStreamRewindable* stream) {
+ if (is_pkm(stream)) {
+ return SkNEW(SkPKMImageDecoder);
+ }
+ return NULL;
+}
+
+static SkImageDecoder_DecodeReg gReg(sk_libpkm_dfactory);
+
+static SkImageDecoder::Format get_format_pkm(SkStreamRewindable* stream) {
+ if (is_pkm(stream)) {
+ return SkImageDecoder::kPKM_Format;
+ }
+ return SkImageDecoder::kUnknown_Format;
+}
+
+static SkImageDecoder_FormatReg gFormatReg(get_format_pkm);
diff --git a/chromium/third_party/skia/src/images/SkImageDecoder_wbmp.cpp b/chromium/third_party/skia/src/images/SkImageDecoder_wbmp.cpp
index 8dce62cdf00..0bf138940da 100644
--- a/chromium/third_party/skia/src/images/SkImageDecoder_wbmp.cpp
+++ b/chromium/third_party/skia/src/images/SkImageDecoder_wbmp.cpp
@@ -111,8 +111,8 @@ bool SkWBMPImageDecoder::onDecode(SkStream* stream, SkBitmap* decodedBitmap,
int width = head.fWidth;
int height = head.fHeight;
- decodedBitmap->setConfig(SkBitmap::kIndex8_Config, width, height, 0,
- kOpaque_SkAlphaType);
+ decodedBitmap->setInfo(SkImageInfo::Make(width, height,
+ kIndex_8_SkColorType, kOpaque_SkAlphaType));
if (SkImageDecoder::kDecodeBounds_Mode == mode) {
return true;
diff --git a/chromium/third_party/skia/src/images/SkImageEncoder_argb.cpp b/chromium/third_party/skia/src/images/SkImageEncoder_argb.cpp
index 97b741b8bf1..296491eef81 100644
--- a/chromium/third_party/skia/src/images/SkImageEncoder_argb.cpp
+++ b/chromium/third_party/skia/src/images/SkImageEncoder_argb.cpp
@@ -71,15 +71,15 @@ static void Index8_To_ARGB(const uint8_t* in, uint8_t* argb, int width,
}
}
-static ScanlineImporter ChooseImporter(const SkBitmap::Config& config) {
- switch (config) {
- case SkBitmap::kARGB_8888_Config:
+static ScanlineImporter ChooseImporter(SkColorType ct) {
+ switch (ct) {
+ case kN32_SkColorType:
return ARGB_8888_To_ARGB;
- case SkBitmap::kRGB_565_Config:
+ case kRGB_565_SkColorType:
return RGB_565_To_ARGB;
- case SkBitmap::kARGB_4444_Config:
+ case kARGB_4444_SkColorType:
return ARGB_4444_To_ARGB;
- case SkBitmap::kIndex8_Config:
+ case kIndex_8_SkColorType:
return Index8_To_ARGB;
default:
return NULL;
@@ -87,8 +87,7 @@ static ScanlineImporter ChooseImporter(const SkBitmap::Config& config) {
}
bool SkARGBImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bitmap, int) {
- const SkBitmap::Config config = bitmap.config();
- const ScanlineImporter scanline_import = ChooseImporter(config);
+ const ScanlineImporter scanline_import = ChooseImporter(bitmap.colorType());
if (NULL == scanline_import) {
return false;
}
diff --git a/chromium/third_party/skia/src/images/SkImageRef.cpp b/chromium/third_party/skia/src/images/SkImageRef.cpp
deleted file mode 100644
index 716519f080d..00000000000
--- a/chromium/third_party/skia/src/images/SkImageRef.cpp
+++ /dev/null
@@ -1,191 +0,0 @@
-
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "SkImageRef.h"
-#include "SkBitmap.h"
-#include "SkFlattenableBuffers.h"
-#include "SkImageDecoder.h"
-#include "SkStream.h"
-#include "SkTemplates.h"
-#include "SkThread.h"
-
-//#define DUMP_IMAGEREF_LIFECYCLE
-
-
-///////////////////////////////////////////////////////////////////////////////
-
-SkImageRef::SkImageRef(const SkImageInfo& info, SkStreamRewindable* stream,
- int sampleSize, SkBaseMutex* mutex)
- : SkPixelRef(info, mutex), fErrorInDecoding(false) {
- SkASSERT(stream);
- stream->ref();
- fStream = stream;
- fSampleSize = sampleSize;
- fDoDither = true;
- fPrev = fNext = NULL;
- fFactory = NULL;
-
-#ifdef DUMP_IMAGEREF_LIFECYCLE
- SkDebugf("add ImageRef %p [%d] data=%d\n",
- this, this->info().fColorType, (int)stream->getLength());
-#endif
-}
-
-SkImageRef::~SkImageRef() {
-
-#ifdef DUMP_IMAGEREF_LIFECYCLE
- SkDebugf("delete ImageRef %p [%d] data=%d\n",
- this, fConfig, (int)fStream->getLength());
-#endif
-
- fStream->unref();
- SkSafeUnref(fFactory);
-}
-
-bool SkImageRef::getInfo(SkBitmap* bitmap) {
- SkAutoMutexAcquire ac(this->mutex());
-
- if (!this->prepareBitmap(SkImageDecoder::kDecodeBounds_Mode)) {
- return false;
- }
-
- SkASSERT(SkBitmap::kNo_Config != fBitmap.config());
- if (bitmap) {
- bitmap->setConfig(fBitmap.config(), fBitmap.width(), fBitmap.height());
- }
- return true;
-}
-
-bool SkImageRef::isOpaque(SkBitmap* bitmap) {
- if (bitmap && bitmap->pixelRef() == this) {
- bitmap->lockPixels();
- // what about colortables??????
- bitmap->setAlphaType(fBitmap.alphaType());
- bitmap->unlockPixels();
- return true;
- }
- return false;
-}
-
-SkImageDecoderFactory* SkImageRef::setDecoderFactory(
- SkImageDecoderFactory* fact) {
- SkRefCnt_SafeAssign(fFactory, fact);
- return fact;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-bool SkImageRef::onDecode(SkImageDecoder* codec, SkStreamRewindable* stream,
- SkBitmap* bitmap, SkBitmap::Config config,
- SkImageDecoder::Mode mode) {
- return codec->decode(stream, bitmap, config, mode);
-}
-
-bool SkImageRef::prepareBitmap(SkImageDecoder::Mode mode) {
-
- if (fErrorInDecoding) {
- return false;
- }
-
- if (NULL != fBitmap.getPixels() ||
- (SkBitmap::kNo_Config != fBitmap.config() &&
- SkImageDecoder::kDecodeBounds_Mode == mode)) {
- return true;
- }
-
- SkASSERT(fBitmap.getPixels() == NULL);
-
- if (!fStream->rewind()) {
- SkDEBUGF(("Failed to rewind SkImageRef stream!"));
- return false;
- }
-
- SkImageDecoder* codec;
- if (fFactory) {
- codec = fFactory->newDecoder(fStream);
- } else {
- codec = SkImageDecoder::Factory(fStream);
- }
-
- if (codec) {
- SkAutoTDelete<SkImageDecoder> ad(codec);
-
- codec->setSampleSize(fSampleSize);
- codec->setDitherImage(fDoDither);
- if (this->onDecode(codec, fStream, &fBitmap, fBitmap.config(), mode)) {
- return true;
- }
- }
-
-#ifdef DUMP_IMAGEREF_LIFECYCLE
- if (NULL == codec) {
- SkDebugf("--- ImageRef: <%s> failed to find codec\n", this->getURI());
- } else {
- SkDebugf("--- ImageRef: <%s> failed in codec for %d mode\n",
- this->getURI(), mode);
- }
-#endif
- fErrorInDecoding = true;
- fBitmap.reset();
- return false;
-}
-
-void* SkImageRef::onLockPixels(SkColorTable** ct) {
- if (NULL == fBitmap.getPixels()) {
- (void)this->prepareBitmap(SkImageDecoder::kDecodePixels_Mode);
- }
-
- if (ct) {
- *ct = fBitmap.getColorTable();
- }
- return fBitmap.getPixels();
-}
-
-size_t SkImageRef::ramUsed() const {
- size_t size = 0;
-
- if (fBitmap.getPixels()) {
- size = fBitmap.getSize();
- if (fBitmap.getColorTable()) {
- size += fBitmap.getColorTable()->count() * sizeof(SkPMColor);
- }
- }
- return size;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-SkImageRef::SkImageRef(SkFlattenableReadBuffer& buffer, SkBaseMutex* mutex)
- : INHERITED(buffer, mutex), fErrorInDecoding(false) {
- fSampleSize = buffer.readInt();
- fDoDither = buffer.readBool();
-
- size_t length = buffer.getArrayCount();
- fStream = SkNEW_ARGS(SkMemoryStream, (length));
- buffer.readByteArray((void*)fStream->getMemoryBase(), length);
-
- fPrev = fNext = NULL;
- fFactory = NULL;
-}
-
-void SkImageRef::flatten(SkFlattenableWriteBuffer& buffer) const {
- this->INHERITED::flatten(buffer);
-
- buffer.writeInt(fSampleSize);
- buffer.writeBool(fDoDither);
- // FIXME: Consider moving this logic should go into writeStream itself.
- // writeStream currently has no other callers, so this may be fine for
- // now.
- if (!fStream->rewind()) {
- SkDEBUGF(("Failed to rewind SkImageRef stream!"));
- buffer.write32(0);
- } else {
- // FIXME: Handle getLength properly here. Perhaps this class should
- // take an SkStreamAsset.
- buffer.writeStream(fStream, fStream->getLength());
- }
-}
diff --git a/chromium/third_party/skia/src/images/SkImageRefPool.cpp b/chromium/third_party/skia/src/images/SkImageRefPool.cpp
deleted file mode 100644
index 0a3d7bf8cc4..00000000000
--- a/chromium/third_party/skia/src/images/SkImageRefPool.cpp
+++ /dev/null
@@ -1,192 +0,0 @@
-
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "SkImageRefPool.h"
-#include "SkImageRef.h"
-#include "SkThread.h"
-
-SkImageRefPool::SkImageRefPool() {
- fRAMBudget = 0; // means no explicit limit
- fRAMUsed = 0;
- fCount = 0;
- fHead = fTail = NULL;
-}
-
-SkImageRefPool::~SkImageRefPool() {
- // SkASSERT(NULL == fHead);
-}
-
-void SkImageRefPool::setRAMBudget(size_t size) {
- if (fRAMBudget != size) {
- fRAMBudget = size;
- this->purgeIfNeeded();
- }
-}
-
-void SkImageRefPool::justAddedPixels(SkImageRef* ref) {
-#ifdef DUMP_IMAGEREF_LIFECYCLE
- SkDebugf("=== ImagePool: add pixels %s [%d %d %d] bytes=%d heap=%d\n",
- ref->getURI(),
- ref->fBitmap.width(), ref->fBitmap.height(),
- ref->fBitmap.bytesPerPixel(),
- ref->fBitmap.getSize(), (int)fRAMUsed);
-#endif
- fRAMUsed += ref->ramUsed();
- this->purgeIfNeeded();
-}
-
-void SkImageRefPool::canLosePixels(SkImageRef* ref) {
- // the refs near fHead have recently been released (used)
- // if we purge, we purge from the tail
- this->detach(ref);
- this->addToHead(ref);
- this->purgeIfNeeded();
-}
-
-void SkImageRefPool::purgeIfNeeded() {
- // do nothing if we have a zero-budget (i.e. unlimited)
- if (fRAMBudget != 0) {
- this->setRAMUsed(fRAMBudget);
- }
-}
-
-void SkImageRefPool::setRAMUsed(size_t limit) {
- SkImageRef* ref = fTail;
-
- while (NULL != ref && fRAMUsed > limit) {
- // only purge it if its pixels are unlocked
- if (!ref->isLocked() && ref->fBitmap.getPixels()) {
- size_t size = ref->ramUsed();
- SkASSERT(size <= fRAMUsed);
- fRAMUsed -= size;
-
-#ifdef DUMP_IMAGEREF_LIFECYCLE
- SkDebugf("=== ImagePool: purge %s [%d %d %d] bytes=%d heap=%d\n",
- ref->getURI(),
- ref->fBitmap.width(), ref->fBitmap.height(),
- ref->fBitmap.bytesPerPixel(),
- (int)size, (int)fRAMUsed);
-#endif
-
- // remember the bitmap config (don't call reset),
- // just clear the pixel memory
- ref->fBitmap.setPixels(NULL);
- SkASSERT(NULL == ref->fBitmap.getPixels());
- }
- ref = ref->fPrev;
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-void SkImageRefPool::addToHead(SkImageRef* ref) {
- ref->fNext = fHead;
- ref->fPrev = NULL;
-
- if (fHead) {
- SkASSERT(NULL == fHead->fPrev);
- fHead->fPrev = ref;
- }
- fHead = ref;
-
- if (NULL == fTail) {
- fTail = ref;
- }
- fCount += 1;
- SkASSERT(computeCount() == fCount);
-
- fRAMUsed += ref->ramUsed();
-}
-
-void SkImageRefPool::addToTail(SkImageRef* ref) {
- ref->fNext = NULL;
- ref->fPrev = fTail;
-
- if (fTail) {
- SkASSERT(NULL == fTail->fNext);
- fTail->fNext = ref;
- }
- fTail = ref;
-
- if (NULL == fHead) {
- fHead = ref;
- }
- fCount += 1;
- SkASSERT(computeCount() == fCount);
-
- fRAMUsed += ref->ramUsed();
-}
-
-void SkImageRefPool::detach(SkImageRef* ref) {
- SkASSERT(fCount > 0);
-
- if (fHead == ref) {
- fHead = ref->fNext;
- }
- if (fTail == ref) {
- fTail = ref->fPrev;
- }
- if (ref->fPrev) {
- ref->fPrev->fNext = ref->fNext;
- }
- if (ref->fNext) {
- ref->fNext->fPrev = ref->fPrev;
- }
-
- ref->fNext = ref->fPrev = NULL;
-
- fCount -= 1;
- SkASSERT(computeCount() == fCount);
-
- SkASSERT(fRAMUsed >= ref->ramUsed());
- fRAMUsed -= ref->ramUsed();
-}
-
-int SkImageRefPool::computeCount() const {
- SkImageRef* ref = fHead;
- int count = 0;
-
- while (ref != NULL) {
- count += 1;
- ref = ref->fNext;
- }
-
-#ifdef SK_DEBUG
- ref = fTail;
- int count2 = 0;
-
- while (ref != NULL) {
- count2 += 1;
- ref = ref->fPrev;
- }
- SkASSERT(count2 == count);
-#endif
-
- return count;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-#include "SkStream.h"
-
-void SkImageRefPool::dump() const {
-#if defined(SK_DEBUG) || defined(DUMP_IMAGEREF_LIFECYCLE)
- SkDebugf("ImagePool dump: bugdet: %d used: %d count: %d\n",
- (int)fRAMBudget, (int)fRAMUsed, fCount);
-
- SkImageRef* ref = fHead;
-
- while (ref != NULL) {
- SkDebugf(" [%3d %3d %d] ram=%d data=%d locked=%d %s\n", ref->fBitmap.width(),
- ref->fBitmap.height(), ref->fBitmap.config(),
- ref->ramUsed(), (int)ref->fStream->getLength(),
- ref->isLocked(), ref->getURI());
-
- ref = ref->fNext;
- }
-#endif
-}
diff --git a/chromium/third_party/skia/src/images/SkImageRefPool.h b/chromium/third_party/skia/src/images/SkImageRefPool.h
deleted file mode 100644
index 1e74a6d077c..00000000000
--- a/chromium/third_party/skia/src/images/SkImageRefPool.h
+++ /dev/null
@@ -1,49 +0,0 @@
-
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#ifndef SkImageRefPool_DEFINED
-#define SkImageRefPool_DEFINED
-
-#include "SkTypes.h"
-
-class SkImageRef;
-class SkImageRef_GlobalPool;
-
-class SkImageRefPool {
-public:
- SkImageRefPool();
- ~SkImageRefPool();
-
- size_t getRAMBudget() const { return fRAMBudget; }
- void setRAMBudget(size_t);
-
- size_t getRAMUsed() const { return fRAMUsed; }
- void setRAMUsed(size_t limit);
-
- void addToHead(SkImageRef*);
- void addToTail(SkImageRef*);
- void detach(SkImageRef*);
-
- void dump() const;
-
-private:
- size_t fRAMBudget;
- size_t fRAMUsed;
-
- int fCount;
- SkImageRef* fHead, *fTail;
-
- int computeCount() const;
-
- friend class SkImageRef_GlobalPool;
-
- void justAddedPixels(SkImageRef*);
- void canLosePixels(SkImageRef*);
- void purgeIfNeeded();
-};
-
-#endif
diff --git a/chromium/third_party/skia/src/images/SkImageRef_GlobalPool.cpp b/chromium/third_party/skia/src/images/SkImageRef_GlobalPool.cpp
deleted file mode 100644
index f91cebabbf8..00000000000
--- a/chromium/third_party/skia/src/images/SkImageRef_GlobalPool.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "SkImageRef_GlobalPool.h"
-#include "SkImageRefPool.h"
-#include "SkThread.h"
-
-SK_DECLARE_STATIC_MUTEX(gGlobalPoolMutex);
-
-/*
- * This returns the lazily-allocated global pool. It must be called
- * from inside the guard mutex, so we safely only ever allocate 1.
- */
-static SkImageRefPool* GetGlobalPool() {
- static SkImageRefPool* gPool;
- if (NULL == gPool) {
- gPool = SkNEW(SkImageRefPool);
- // call sk_atexit(...) when we have that, to free the global pool
- }
- return gPool;
-}
-
-SkImageRef_GlobalPool::SkImageRef_GlobalPool(const SkImageInfo& info,
- SkStreamRewindable* stream,
- int sampleSize)
- : SkImageRef(info, stream, sampleSize, &gGlobalPoolMutex) {
- SkASSERT(&gGlobalPoolMutex == this->mutex());
- SkAutoMutexAcquire ac(gGlobalPoolMutex);
- GetGlobalPool()->addToHead(this);
-}
-
-SkImageRef_GlobalPool::~SkImageRef_GlobalPool() {
- SkASSERT(&gGlobalPoolMutex == this->mutex());
- SkAutoMutexAcquire ac(gGlobalPoolMutex);
- GetGlobalPool()->detach(this);
-}
-
-/* By design, onUnlockPixels() already is inside the mutex-lock,
- * and it is the (indirect) caller of onDecode(), therefore we can assume
- * that we also are already inside the mutex. Hence, we can reference
- * the global-pool directly.
- */
-bool SkImageRef_GlobalPool::onDecode(SkImageDecoder* codec, SkStreamRewindable* stream,
- SkBitmap* bitmap, SkBitmap::Config config,
- SkImageDecoder::Mode mode) {
- if (!this->INHERITED::onDecode(codec, stream, bitmap, config, mode)) {
- return false;
- }
- if (mode == SkImageDecoder::kDecodePixels_Mode) {
- // no need to grab the mutex here, it has already been acquired.
- GetGlobalPool()->justAddedPixels(this);
- }
- return true;
-}
-
-void SkImageRef_GlobalPool::onUnlockPixels() {
- this->INHERITED::onUnlockPixels();
-
- // by design, onUnlockPixels() already is inside the mutex-lock
- GetGlobalPool()->canLosePixels(this);
-}
-
-SkImageRef_GlobalPool::SkImageRef_GlobalPool(SkFlattenableReadBuffer& buffer)
- : INHERITED(buffer, &gGlobalPoolMutex) {
- SkASSERT(&gGlobalPoolMutex == this->mutex());
- SkAutoMutexAcquire ac(gGlobalPoolMutex);
- GetGlobalPool()->addToHead(this);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// global imagerefpool wrappers
-
-size_t SkImageRef_GlobalPool::GetRAMBudget() {
- SkAutoMutexAcquire ac(gGlobalPoolMutex);
- return GetGlobalPool()->getRAMBudget();
-}
-
-void SkImageRef_GlobalPool::SetRAMBudget(size_t size) {
- SkAutoMutexAcquire ac(gGlobalPoolMutex);
- GetGlobalPool()->setRAMBudget(size);
-}
-
-size_t SkImageRef_GlobalPool::GetRAMUsed() {
- SkAutoMutexAcquire ac(gGlobalPoolMutex);
- return GetGlobalPool()->getRAMUsed();
-}
-
-void SkImageRef_GlobalPool::SetRAMUsed(size_t usage) {
- SkAutoMutexAcquire ac(gGlobalPoolMutex);
- GetGlobalPool()->setRAMUsed(usage);
-}
-
-void SkImageRef_GlobalPool::DumpPool() {
- SkAutoMutexAcquire ac(gGlobalPoolMutex);
- GetGlobalPool()->dump();
-}
diff --git a/chromium/third_party/skia/src/images/SkImageRef_ashmem.cpp b/chromium/third_party/skia/src/images/SkImageRef_ashmem.cpp
deleted file mode 100644
index 269199faf84..00000000000
--- a/chromium/third_party/skia/src/images/SkImageRef_ashmem.cpp
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkImageRef_ashmem.h"
-#include "SkImageDecoder.h"
-#include "SkFlattenableBuffers.h"
-#include "SkThread.h"
-
-#include "android/ashmem.h"
-
-#include <sys/mman.h>
-#include <unistd.h>
-
-//#define TRACE_ASH_PURGE // just trace purges
-
-#ifdef DUMP_IMAGEREF_LIFECYCLE
- #define DUMP_ASHMEM_LIFECYCLE
-#else
-// #define DUMP_ASHMEM_LIFECYCLE
-#endif
-
-// ashmem likes lengths on page boundaries
-static size_t roundToPageSize(size_t size) {
- const size_t mask = getpagesize() - 1;
- size_t newsize = (size + mask) & ~mask;
-// SkDebugf("---- oldsize %d newsize %d\n", size, newsize);
- return newsize;
-}
-
-SkImageRef_ashmem::SkImageRef_ashmem(const SkImageInfo& info,
- SkStreamRewindable* stream,
- int sampleSize)
- : SkImageRef(info, stream, sampleSize)
-{
- fRec.fFD = -1;
- fRec.fAddr = NULL;
- fRec.fSize = 0;
- fRec.fPinned = false;
-
- fCT = NULL;
-}
-
-SkImageRef_ashmem::~SkImageRef_ashmem() {
- SkSafeUnref(fCT);
- this->closeFD();
-}
-
-void SkImageRef_ashmem::closeFD() {
- if (-1 != fRec.fFD) {
-#ifdef DUMP_ASHMEM_LIFECYCLE
- SkDebugf("=== ashmem close %d\n", fRec.fFD);
-#endif
- SkASSERT(fRec.fAddr);
- SkASSERT(fRec.fSize);
- munmap(fRec.fAddr, fRec.fSize);
- close(fRec.fFD);
- fRec.fFD = -1;
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-class AshmemAllocator : public SkBitmap::Allocator {
-public:
- AshmemAllocator(SkAshmemRec* rec, const char name[])
- : fRec(rec), fName(name) {}
-
- virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) {
- const size_t size = roundToPageSize(bm->getSize());
- int fd = fRec->fFD;
- void* addr = fRec->fAddr;
-
- SkASSERT(!fRec->fPinned);
-
- if (-1 == fd) {
- SkASSERT(NULL == addr);
- SkASSERT(0 == fRec->fSize);
-
- fd = ashmem_create_region(fName, size);
-#ifdef DUMP_ASHMEM_LIFECYCLE
- SkDebugf("=== ashmem_create_region %s size=%d fd=%d\n", fName, size, fd);
-#endif
- if (-1 == fd) {
- SkDebugf("------- imageref_ashmem create failed <%s> %d\n",
- fName, size);
- return false;
- }
-
- int err = ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE);
- if (err) {
- SkDebugf("------ ashmem_set_prot_region(%d) failed %d\n",
- fd, err);
- close(fd);
- return false;
- }
-
- addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
- if (-1 == (long)addr) {
- SkDebugf("---------- mmap failed for imageref_ashmem size=%d\n",
- size);
- close(fd);
- return false;
- }
-
- fRec->fFD = fd;
- fRec->fAddr = addr;
- fRec->fSize = size;
- } else {
- SkASSERT(addr);
- SkASSERT(size == fRec->fSize);
- (void)ashmem_pin_region(fd, 0, 0);
- }
-
- bm->setPixels(addr, ct);
- fRec->fPinned = true;
- return true;
- }
-
-private:
- // we just point to our caller's memory, these are not copies
- SkAshmemRec* fRec;
- const char* fName;
-};
-
-bool SkImageRef_ashmem::onDecode(SkImageDecoder* codec, SkStreamRewindable* stream,
- SkBitmap* bitmap, SkBitmap::Config config,
- SkImageDecoder::Mode mode) {
-
- if (SkImageDecoder::kDecodeBounds_Mode == mode) {
- return this->INHERITED::onDecode(codec, stream, bitmap, config, mode);
- }
-
- // Ashmem memory is guaranteed to be initialized to 0.
- codec->setSkipWritingZeroes(true);
-
- AshmemAllocator alloc(&fRec, this->getURI());
-
- codec->setAllocator(&alloc);
- bool success = this->INHERITED::onDecode(codec, stream, bitmap, config,
- mode);
- // remove the allocator, since its on the stack
- codec->setAllocator(NULL);
-
- if (success) {
- // remember the colortable (if any)
- SkRefCnt_SafeAssign(fCT, bitmap->getColorTable());
- return true;
- } else {
- if (fRec.fPinned) {
- ashmem_unpin_region(fRec.fFD, 0, 0);
- fRec.fPinned = false;
- }
- this->closeFD();
- return false;
- }
-}
-
-void* SkImageRef_ashmem::onLockPixels(SkColorTable** ct) {
- SkASSERT(fBitmap.getPixels() == NULL);
- SkASSERT(fBitmap.getColorTable() == NULL);
-
- // fast case: check if we can just pin and get the cached data
- if (-1 != fRec.fFD) {
- SkASSERT(fRec.fAddr);
- SkASSERT(!fRec.fPinned);
- int pin = ashmem_pin_region(fRec.fFD, 0, 0);
-
- if (ASHMEM_NOT_PURGED == pin) { // yea, fast case!
- fBitmap.setPixels(fRec.fAddr, fCT);
- fRec.fPinned = true;
- } else if (ASHMEM_WAS_PURGED == pin) {
- ashmem_unpin_region(fRec.fFD, 0, 0);
- // let go of our colortable if we lost the pixels. Well get it back
- // again when we re-decode
- if (fCT) {
- fCT->unref();
- fCT = NULL;
- }
-#if defined(DUMP_ASHMEM_LIFECYCLE) || defined(TRACE_ASH_PURGE)
- SkDebugf("===== ashmem purged %d\n", fBitmap.getSize());
-#endif
- } else {
- SkDebugf("===== ashmem pin_region(%d) returned %d\n", fRec.fFD, pin);
- // return null result for failure
- if (ct) {
- *ct = NULL;
- }
- return NULL;
- }
- } else {
- // no FD, will create an ashmem region in allocator
- }
-
- return this->INHERITED::onLockPixels(ct);
-}
-
-void SkImageRef_ashmem::onUnlockPixels() {
- this->INHERITED::onUnlockPixels();
-
- if (-1 != fRec.fFD) {
- SkASSERT(fRec.fAddr);
- SkASSERT(fRec.fPinned);
-
- ashmem_unpin_region(fRec.fFD, 0, 0);
- fRec.fPinned = false;
- }
-
- // we clear this with or without an error, since we've either closed or
- // unpinned the region
- fBitmap.setPixels(NULL, NULL);
-}
-
-void SkImageRef_ashmem::flatten(SkFlattenableWriteBuffer& buffer) const {
- this->INHERITED::flatten(buffer);
- buffer.writeString(getURI());
-}
-
-SkImageRef_ashmem::SkImageRef_ashmem(SkFlattenableReadBuffer& buffer)
- : INHERITED(buffer) {
- fRec.fFD = -1;
- fRec.fAddr = NULL;
- fRec.fSize = 0;
- fRec.fPinned = false;
- fCT = NULL;
-
- SkString uri;
- buffer.readString(&uri);
- this->setURI(uri);
-}
diff --git a/chromium/third_party/skia/src/images/SkImageRef_ashmem.h b/chromium/third_party/skia/src/images/SkImageRef_ashmem.h
deleted file mode 100644
index a2652fbc300..00000000000
--- a/chromium/third_party/skia/src/images/SkImageRef_ashmem.h
+++ /dev/null
@@ -1,47 +0,0 @@
-
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#ifndef SkImageRef_ashmem_DEFINED
-#define SkImageRef_ashmem_DEFINED
-
-#include "SkImageRef.h"
-
-struct SkAshmemRec {
- int fFD;
- void* fAddr;
- size_t fSize;
- bool fPinned;
-};
-
-class SkImageRef_ashmem : public SkImageRef {
-public:
- SkImageRef_ashmem(const SkImageInfo&, SkStreamRewindable*, int sampleSize = 1);
- virtual ~SkImageRef_ashmem();
-
- SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkImageRef_ashmem)
-
-protected:
- SkImageRef_ashmem(SkFlattenableReadBuffer&);
- virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
-
- virtual bool onDecode(SkImageDecoder* codec, SkStreamRewindable* stream,
- SkBitmap* bitmap, SkBitmap::Config config,
- SkImageDecoder::Mode mode);
-
- virtual void* onLockPixels(SkColorTable**);
- virtual void onUnlockPixels();
-
-private:
- void closeFD();
-
- SkColorTable* fCT;
- SkAshmemRec fRec;
-
- typedef SkImageRef INHERITED;
-};
-
-#endif
diff --git a/chromium/third_party/skia/src/images/SkImages.cpp b/chromium/third_party/skia/src/images/SkImages.cpp
deleted file mode 100644
index 5b6bf6b7ce9..00000000000
--- a/chromium/third_party/skia/src/images/SkImages.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkFlattenable.h"
-#include "SkImageRef_GlobalPool.h"
-#include "SkImages.h"
-
-#ifdef SK_BUILD_FOR_ANDROID
-#include "SkImageRef_ashmem.h"
-#endif
-
-void SkImages::InitializeFlattenables() {
- SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkImageRef_GlobalPool)
-#ifdef SK_BUILD_FOR_ANDROID
- SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkImageRef_ashmem)
-#endif
-}
diff --git a/chromium/third_party/skia/src/images/SkMovie_gif.cpp b/chromium/third_party/skia/src/images/SkMovie_gif.cpp
index b6d068a391c..decefd5acc5 100644
--- a/chromium/third_party/skia/src/images/SkMovie_gif.cpp
+++ b/chromium/third_party/skia/src/images/SkMovie_gif.cpp
@@ -364,13 +364,11 @@ bool SkGIFMovie::onGetBitmap(SkBitmap* bm)
startIndex = 0;
// create bitmap
- bm->setConfig(SkBitmap::kARGB_8888_Config, width, height, 0);
- if (!bm->allocPixels(NULL)) {
+ if (!bm->allocPixels(SkImageInfo::MakeN32Premul(width, height))) {
return false;
}
// create bitmap for backup
- fBackup.setConfig(SkBitmap::kARGB_8888_Config, width, height, 0);
- if (!fBackup.allocPixels(NULL)) {
+ if (!fBackup.allocPixels(SkImageInfo::MakeN32Premul(width, height))) {
return false;
}
} else if (startIndex > fCurrIndex) {
diff --git a/chromium/third_party/skia/src/images/SkScaledBitmapSampler.cpp b/chromium/third_party/skia/src/images/SkScaledBitmapSampler.cpp
index 03ee2eed62b..d78502d2bbd 100644
--- a/chromium/third_party/skia/src/images/SkScaledBitmapSampler.cpp
+++ b/chromium/third_party/skia/src/images/SkScaledBitmapSampler.cpp
@@ -25,7 +25,8 @@ static bool Sample_Gray_D8888(void* SK_RESTRICT dstRow,
return false;
}
-static SkScaledBitmapSampler::RowProc get_gray_to_8888_proc(const SkImageDecoder& decoder) {
+static SkScaledBitmapSampler::RowProc
+get_gray_to_8888_proc(const SkScaledBitmapSampler::Options& opts) {
// Dither, unpremul, and skipZeroes have no effect
return Sample_Gray_D8888;
}
@@ -41,7 +42,8 @@ static bool Sample_RGBx_D8888(void* SK_RESTRICT dstRow,
return false;
}
-static SkScaledBitmapSampler::RowProc get_RGBx_to_8888_proc(const SkImageDecoder& decoder) {
+static SkScaledBitmapSampler::RowProc
+get_RGBx_to_8888_proc(const SkScaledBitmapSampler::Options& opts) {
// Dither, unpremul, and skipZeroes have no effect
return Sample_RGBx_D8888;
}
@@ -92,15 +94,16 @@ static bool Sample_RGBA_D8888_SkipZ(void* SK_RESTRICT dstRow,
return alphaMask != 0xFF;
}
-static SkScaledBitmapSampler::RowProc get_RGBA_to_8888_proc(const SkImageDecoder& decoder) {
+static SkScaledBitmapSampler::RowProc
+get_RGBA_to_8888_proc(const SkScaledBitmapSampler::Options& opts) {
// Dither has no effect.
- if (decoder.getRequireUnpremultipliedColors()) {
+ if (!opts.fPremultiplyAlpha) {
// We could check each component for a zero, at the expense of extra checks.
// For now, just return unpremul.
return Sample_RGBA_D8888_Unpremul;
}
// Supply the versions that premultiply the colors
- if (decoder.getSkipWritingZeroes()) {
+ if (opts.fSkipZeros) {
return Sample_RGBA_D8888_SkipZ;
}
return Sample_RGBA_D8888;
@@ -131,9 +134,10 @@ static bool Sample_Gray_D565_D(void* SK_RESTRICT dstRow,
return false;
}
-static SkScaledBitmapSampler::RowProc get_gray_to_565_proc(const SkImageDecoder& decoder) {
+static SkScaledBitmapSampler::RowProc
+get_gray_to_565_proc(const SkScaledBitmapSampler::Options& opts) {
// Unpremul and skip zeroes make no difference
- if (decoder.getDitherImage()) {
+ if (opts.fDither) {
return Sample_Gray_D565_D;
}
return Sample_Gray_D565;
@@ -163,9 +167,10 @@ static bool Sample_RGBx_D565_D(void* SK_RESTRICT dstRow,
return false;
}
-static SkScaledBitmapSampler::RowProc get_RGBx_to_565_proc(const SkImageDecoder& decoder) {
+static SkScaledBitmapSampler::RowProc
+get_RGBx_to_565_proc(const SkScaledBitmapSampler::Options& opts) {
// Unpremul and skip zeroes make no difference
- if (decoder.getDitherImage()) {
+ if (opts.fDither) {
return Sample_RGBx_D565_D;
}
return Sample_RGBx_D565;
@@ -184,7 +189,8 @@ static bool Sample_D565_D565(void* SK_RESTRICT dstRow,
return false;
}
-static SkScaledBitmapSampler::RowProc get_565_to_565_proc(const SkImageDecoder& decoder) {
+static SkScaledBitmapSampler::RowProc
+get_565_to_565_proc(const SkScaledBitmapSampler::Options& opts) {
// Unpremul, dither, and skip zeroes have no effect
return Sample_D565_D565;
}
@@ -216,9 +222,10 @@ static bool Sample_Gray_D4444_D(void* SK_RESTRICT dstRow,
return false;
}
-static SkScaledBitmapSampler::RowProc get_gray_to_4444_proc(const SkImageDecoder& decoder) {
+static SkScaledBitmapSampler::RowProc
+get_gray_to_4444_proc(const SkScaledBitmapSampler::Options& opts) {
// Skip zeroes and unpremul make no difference
- if (decoder.getDitherImage()) {
+ if (opts.fDither) {
return Sample_Gray_D4444_D;
}
return Sample_Gray_D4444;
@@ -249,9 +256,10 @@ static bool Sample_RGBx_D4444_D(void* SK_RESTRICT dstRow,
return false;
}
-static SkScaledBitmapSampler::RowProc get_RGBx_to_4444_proc(const SkImageDecoder& decoder) {
+static SkScaledBitmapSampler::RowProc
+get_RGBx_to_4444_proc(const SkScaledBitmapSampler::Options& opts) {
// Skip zeroes and unpremul make no difference
- if (decoder.getDitherImage()) {
+ if (opts.fDither) {
return Sample_RGBx_D4444_D;
}
return Sample_RGBx_D4444;
@@ -331,19 +339,19 @@ static bool Sample_RGBA_D4444_D_SkipZ(void* SK_RESTRICT dstRow,
return alphaMask != 0xFF;
}
-static SkScaledBitmapSampler::RowProc get_RGBA_to_4444_proc(const SkImageDecoder& decoder) {
- if (decoder.getRequireUnpremultipliedColors()) {
+static SkScaledBitmapSampler::RowProc
+get_RGBA_to_4444_proc(const SkScaledBitmapSampler::Options& opts) {
+ if (!opts.fPremultiplyAlpha) {
// Unpremultiplied is not supported for 4444
return NULL;
}
- const bool dither = decoder.getDitherImage();
- if (decoder.getSkipWritingZeroes()) {
- if (dither) {
+ if (opts.fSkipZeros) {
+ if (opts.fDither) {
return Sample_RGBA_D4444_D_SkipZ;
}
return Sample_RGBA_D4444_SkipZ;
}
- if (dither) {
+ if (opts.fDither) {
return Sample_RGBA_D4444_D;
}
return Sample_RGBA_D4444;
@@ -386,13 +394,14 @@ static bool Sample_Index_D8888_SkipZ(void* SK_RESTRICT dstRow,
return cc != A32_MASK_IN_PLACE;
}
-static SkScaledBitmapSampler::RowProc get_index_to_8888_proc(const SkImageDecoder& decoder) {
- if (decoder.getRequireUnpremultipliedColors()) {
+static SkScaledBitmapSampler::RowProc
+get_index_to_8888_proc(const SkScaledBitmapSampler::Options& opts) {
+ if (!opts.fPremultiplyAlpha) {
// Unpremultiplied is not supported for an index source.
return NULL;
}
// Dither makes no difference
- if (decoder.getSkipWritingZeroes()) {
+ if (opts.fSkipZeros) {
return Sample_Index_D8888_SkipZ;
}
return Sample_Index_D8888;
@@ -426,9 +435,10 @@ static bool Sample_Index_D565_D(void* SK_RESTRICT dstRow,
return false;
}
-static SkScaledBitmapSampler::RowProc get_index_to_565_proc(const SkImageDecoder& decoder) {
+static SkScaledBitmapSampler::RowProc
+get_index_to_565_proc(const SkScaledBitmapSampler::Options& opts) {
// Unpremultiplied and skip zeroes make no difference
- if (decoder.getDitherImage()) {
+ if (opts.fDither) {
return Sample_Index_D565_D;
}
return Sample_Index_D565;
@@ -502,19 +512,19 @@ static bool Sample_Index_D4444_D_SkipZ(void* SK_RESTRICT dstRow,
return cc != A32_MASK_IN_PLACE;
}
-static SkScaledBitmapSampler::RowProc get_index_to_4444_proc(const SkImageDecoder& decoder) {
+static SkScaledBitmapSampler::RowProc
+get_index_to_4444_proc(const SkScaledBitmapSampler::Options& opts) {
// Unpremul not allowed
- if (decoder.getRequireUnpremultipliedColors()) {
+ if (!opts.fPremultiplyAlpha) {
return NULL;
}
- const bool dither = decoder.getDitherImage();
- if (decoder.getSkipWritingZeroes()) {
- if (dither) {
+ if (opts.fSkipZeros) {
+ if (opts.fDither) {
return Sample_Index_D4444_D_SkipZ;
}
return Sample_Index_D4444_SkipZ;
}
- if (dither) {
+ if (opts.fDither) {
return Sample_Index_D4444_D;
}
return Sample_Index_D4444;
@@ -535,9 +545,10 @@ static bool Sample_Index_DI(void* SK_RESTRICT dstRow,
return false;
}
-static SkScaledBitmapSampler::RowProc get_index_to_index_proc(const SkImageDecoder& decoder) {
+static SkScaledBitmapSampler::RowProc
+get_index_to_index_proc(const SkScaledBitmapSampler::Options& opts) {
// Unpremul not allowed
- if (decoder.getRequireUnpremultipliedColors()) {
+ if (!opts.fPremultiplyAlpha) {
return NULL;
}
// Ignore dither and skip zeroes
@@ -557,15 +568,16 @@ static bool Sample_Gray_DA8(void* SK_RESTRICT dstRow,
return true;
}
-static SkScaledBitmapSampler::RowProc get_gray_to_A8_proc(const SkImageDecoder& decoder) {
- if (decoder.getRequireUnpremultipliedColors()) {
+static SkScaledBitmapSampler::RowProc
+get_gray_to_A8_proc(const SkScaledBitmapSampler::Options& opts) {
+ if (!opts.fPremultiplyAlpha) {
return NULL;
}
// Ignore skip and dither.
return Sample_Gray_DA8;
}
-typedef SkScaledBitmapSampler::RowProc (*RowProcChooser)(const SkImageDecoder& decoder);
+typedef SkScaledBitmapSampler::RowProc (*RowProcChooser)(const SkScaledBitmapSampler::Options&);
///////////////////////////////////////////////////////////////////////////////
#include "SkScaledBitmapSampler.h"
@@ -613,7 +625,7 @@ SkScaledBitmapSampler::SkScaledBitmapSampler(int width, int height,
}
bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc,
- const SkImageDecoder& decoder,
+ const Options& opts,
const SkPMColor ctable[]) {
static const RowProcChooser gProcChoosers[] = {
get_gray_to_8888_proc,
@@ -684,20 +696,20 @@ bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc,
return false;
}
- switch (dst->config()) {
- case SkBitmap::kARGB_8888_Config:
+ switch (dst->colorType()) {
+ case kN32_SkColorType:
index += 0 * gProcDstConfigSpan;
break;
- case SkBitmap::kRGB_565_Config:
+ case kRGB_565_SkColorType:
index += 1 * gProcDstConfigSpan;
break;
- case SkBitmap::kARGB_4444_Config:
+ case kARGB_4444_SkColorType:
index += 2 * gProcDstConfigSpan;
break;
- case SkBitmap::kIndex8_Config:
+ case kIndex_8_SkColorType:
index += 3 * gProcDstConfigSpan;
break;
- case SkBitmap::kA8_Config:
+ case kAlpha_8_SkColorType:
index += 4 * gProcDstConfigSpan;
break;
default:
@@ -708,7 +720,7 @@ bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc,
if (NULL == chooser) {
fRowProc = NULL;
} else {
- fRowProc = chooser(decoder);
+ fRowProc = chooser(opts);
}
fDstRow = (char*)dst->getPixels();
fDstRowBytes = dst->rowBytes();
@@ -716,6 +728,12 @@ bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc,
return fRowProc != NULL;
}
+bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc,
+ const SkImageDecoder& decoder,
+ const SkPMColor ctable[]) {
+ return this->begin(dst, sc, Options(decoder), ctable);
+}
+
bool SkScaledBitmapSampler::next(const uint8_t* SK_RESTRICT src) {
SkASSERT(kInterlaced_SampleMode != fSampleMode);
SkDEBUGCODE(fSampleMode = kConsecutive_SampleMode);
@@ -824,17 +842,23 @@ protected:
void test_row_proc_choice();
void test_row_proc_choice() {
+ const SkColorType colorTypes[] = {
+ kAlpha_8_SkColorType, kIndex_8_SkColorType, kRGB_565_SkColorType, kARGB_4444_SkColorType,
+ kN32_SkColorType
+ };
+
SkBitmap dummyBitmap;
DummyDecoder dummyDecoder;
size_t procCounter = 0;
for (int sc = SkScaledBitmapSampler::kGray; sc <= SkScaledBitmapSampler::kRGB_565; ++sc) {
- for (int c = SkBitmap::kA8_Config; c <= SkBitmap::kARGB_8888_Config; ++c) {
+ for (size_t c = 0; c < SK_ARRAY_COUNT(colorTypes); ++c) {
for (int unpremul = 0; unpremul <= 1; ++unpremul) {
for (int dither = 0; dither <= 1; ++dither) {
// Arbitrary width/height/sampleSize to allow SkScaledBitmapSampler to
// be considered valid.
SkScaledBitmapSampler sampler(10, 10, 1);
- dummyBitmap.setConfig((SkBitmap::Config) c, 10, 10);
+ dummyBitmap.setInfo(SkImageInfo::Make(10, 10,
+ colorTypes[c], kPremul_SkAlphaType));
dummyDecoder.setDitherImage(SkToBool(dither));
dummyDecoder.setRequireUnpremultipliedColors(SkToBool(unpremul));
sampler.begin(&dummyBitmap, (SkScaledBitmapSampler::SrcConfig) sc,
diff --git a/chromium/third_party/skia/src/images/SkScaledBitmapSampler.h b/chromium/third_party/skia/src/images/SkScaledBitmapSampler.h
index e6c4577174c..90c4142bdfb 100644
--- a/chromium/third_party/skia/src/images/SkScaledBitmapSampler.h
+++ b/chromium/third_party/skia/src/images/SkScaledBitmapSampler.h
@@ -34,11 +34,24 @@ public:
kRGB_565 // 2 bytes per pixel
};
+ struct Options {
+ bool fDither;
+ bool fPremultiplyAlpha;
+ bool fSkipZeros;
+ explicit Options(const SkImageDecoder &dec)
+ : fDither(dec.getDitherImage())
+ , fPremultiplyAlpha(!dec.getRequireUnpremultipliedColors())
+ , fSkipZeros(dec.getSkipWritingZeroes())
+ { }
+ };
+
// Given a dst bitmap (with pixels already allocated) and a src-config,
// prepares iterator to process the src colors and write them into dst.
// Returns false if the request cannot be fulfulled.
bool begin(SkBitmap* dst, SrcConfig sc, const SkImageDecoder& decoder,
const SkPMColor* = NULL);
+ bool begin(SkBitmap* dst, SrcConfig sc, const Options& opts,
+ const SkPMColor* = NULL);
// call with row of src pixels, for y = 0...scaledHeight-1.
// returns true if the row had non-opaque alpha in it
bool next(const uint8_t* SK_RESTRICT src);
diff --git a/chromium/third_party/skia/src/images/SkStreamHelpers.cpp b/chromium/third_party/skia/src/images/SkStreamHelpers.cpp
index 3e9ee45345b..c7c66b4b0fa 100644
--- a/chromium/third_party/skia/src/images/SkStreamHelpers.cpp
+++ b/chromium/third_party/skia/src/images/SkStreamHelpers.cpp
@@ -5,6 +5,7 @@
* found in the LICENSE file.
*/
+#include "SkData.h"
#include "SkStream.h"
#include "SkStreamHelpers.h"
#include "SkTypes.h"
@@ -38,3 +39,29 @@ size_t CopyStreamToStorage(SkAutoMalloc* storage, SkStream* stream) {
tempStream.copyTo(dst);
return length;
}
+
+SkData *CopyStreamToData(SkStream* stream) {
+ SkASSERT(stream != NULL);
+
+ if (stream->hasLength()) {
+ const size_t length = stream->getLength();
+ void* dst = sk_malloc_throw(length);
+ if (stream->read(dst, length) != length) {
+ return 0;
+ }
+ return SkData::NewFromMalloc(dst, length);
+ }
+
+ SkDynamicMemoryWStream tempStream;
+ // Arbitrary buffer size.
+ const size_t bufferSize = 256 * 1024; // 256KB
+ char buffer[bufferSize];
+ SkDEBUGCODE(size_t debugLength = 0;)
+ do {
+ size_t bytesRead = stream->read(buffer, bufferSize);
+ tempStream.write(buffer, bytesRead);
+ SkDEBUGCODE(debugLength += bytesRead);
+ SkASSERT(tempStream.bytesWritten() == debugLength);
+ } while (!stream->isAtEnd());
+ return tempStream.copyToData();
+}
diff --git a/chromium/third_party/skia/src/images/SkStreamHelpers.h b/chromium/third_party/skia/src/images/SkStreamHelpers.h
index 7e766b7eccc..008dd8e17a0 100644
--- a/chromium/third_party/skia/src/images/SkStreamHelpers.h
+++ b/chromium/third_party/skia/src/images/SkStreamHelpers.h
@@ -10,6 +10,7 @@
class SkAutoMalloc;
class SkStream;
+class SkData;
/**
* Copy the provided stream to memory allocated by storage.
@@ -24,4 +25,12 @@ class SkStream;
*/
size_t CopyStreamToStorage(SkAutoMalloc* storage, SkStream* stream);
+/**
+ * Copy the provided stream to an SkData variable. Used by SkImageDecoder_libktx.
+ * @param stream SkStream to be copied into data.
+ * @return SkData* The resulting SkData after the copy. This data will have a
+ * ref count of one upon return and belongs to the caller. Returns NULL on failure.
+ */
+SkData *CopyStreamToData(SkStream* stream);
+
#endif // SkStreamHelpers_DEFINED
diff --git a/chromium/third_party/skia/src/lazy/SkCachingPixelRef.cpp b/chromium/third_party/skia/src/lazy/SkCachingPixelRef.cpp
index 668f57ef302..76510f63cd5 100644
--- a/chromium/third_party/skia/src/lazy/SkCachingPixelRef.cpp
+++ b/chromium/third_party/skia/src/lazy/SkCachingPixelRef.cpp
@@ -8,15 +8,13 @@
#include "SkCachingPixelRef.h"
#include "SkScaledImageCache.h"
-
bool SkCachingPixelRef::Install(SkImageGenerator* generator,
SkBitmap* dst) {
SkImageInfo info;
- SkASSERT(generator != NULL);
SkASSERT(dst != NULL);
if ((NULL == generator)
|| !(generator->getInfo(&info))
- || !dst->setConfig(info, 0)) {
+ || !dst->setInfo(info)) {
SkDELETE(generator);
return false;
}
@@ -42,12 +40,12 @@ SkCachingPixelRef::~SkCachingPixelRef() {
// Assert always unlock before unref.
}
-void* SkCachingPixelRef::onLockPixels(SkColorTable**) {
- const SkImageInfo& info = this->info();
-
+bool SkCachingPixelRef::onNewLockPixels(LockRec* rec) {
if (fErrorInDecoding) {
- return NULL; // don't try again.
+ return false; // don't try again.
}
+
+ const SkImageInfo& info = this->info();
SkBitmap bitmap;
SkASSERT(NULL == fScaledCacheId);
fScaledCacheId = SkScaledImageCache::FindAndLock(this->getGenerationID(),
@@ -56,14 +54,14 @@ void* SkCachingPixelRef::onLockPixels(SkColorTable**) {
&bitmap);
if (NULL == fScaledCacheId) {
// Cache has been purged, must re-decode.
- if ((!bitmap.setConfig(info, fRowBytes)) || !bitmap.allocPixels()) {
+ if ((!bitmap.setInfo(info, fRowBytes)) || !bitmap.allocPixels()) {
fErrorInDecoding = true;
- return NULL;
+ return false;
}
SkAutoLockPixels autoLockPixels(bitmap);
if (!fImageGenerator->getPixels(info, bitmap.getPixels(), fRowBytes)) {
fErrorInDecoding = true;
- return NULL;
+ return false;
}
fScaledCacheId = SkScaledImageCache::AddAndLock(this->getGenerationID(),
info.fWidth,
@@ -77,6 +75,7 @@ void* SkCachingPixelRef::onLockPixels(SkColorTable**) {
SkAutoLockPixels autoLockPixels(bitmap);
void* pixels = bitmap.getPixels();
SkASSERT(pixels != NULL);
+
// At this point, the autoLockPixels will unlockPixels()
// to remove bitmap's lock on the pixels. We will then
// destroy bitmap. The *only* guarantee that this pointer
@@ -85,7 +84,10 @@ void* SkCachingPixelRef::onLockPixels(SkColorTable**) {
// bitmap (SkScaledImageCache::Rec.fBitmap) that holds a
// reference to the concrete PixelRef while this record is
// locked.
- return pixels;
+ rec->fPixels = pixels;
+ rec->fColorTable = NULL;
+ rec->fRowBytes = bitmap.rowBytes();
+ return true;
}
void SkCachingPixelRef::onUnlockPixels() {
diff --git a/chromium/third_party/skia/src/lazy/SkCachingPixelRef.h b/chromium/third_party/skia/src/lazy/SkCachingPixelRef.h
index b1f2fcd6692..9fc71c3616e 100644
--- a/chromium/third_party/skia/src/lazy/SkCachingPixelRef.h
+++ b/chromium/third_party/skia/src/lazy/SkCachingPixelRef.h
@@ -25,6 +25,7 @@ class SkColorTable;
*/
class SkCachingPixelRef : public SkPixelRef {
public:
+ SK_DECLARE_INST_COUNT(SkCachingPixelRef)
/**
* Takes ownership of SkImageGenerator. If this method fails for
* whatever reason, it will return false and immediatetely delete
@@ -40,7 +41,7 @@ public:
protected:
virtual ~SkCachingPixelRef();
- virtual void* onLockPixels(SkColorTable** colorTable) SK_OVERRIDE;
+ virtual bool onNewLockPixels(LockRec*) SK_OVERRIDE;
virtual void onUnlockPixels() SK_OVERRIDE;
virtual bool onLockPixelsAreWritable() const SK_OVERRIDE { return false; }
@@ -48,9 +49,9 @@ protected:
return fImageGenerator->refEncodedData();
}
// No need to flatten this object. When flattening an SkBitmap,
- // SkOrderedWriteBuffer will check the encoded data and write that
+ // SkWriteBuffer will check the encoded data and write that
// instead.
- // Future implementations of SkFlattenableWriteBuffer will need to
+ // Future implementations of SkWriteBuffer will need to
// special case for onRefEncodedData as well.
SK_DECLARE_UNFLATTENABLE_OBJECT()
diff --git a/chromium/third_party/skia/src/lazy/SkDiscardableMemoryPool.cpp b/chromium/third_party/skia/src/lazy/SkDiscardableMemoryPool.cpp
index 4709709861f..db2754e473a 100644
--- a/chromium/third_party/skia/src/lazy/SkDiscardableMemoryPool.cpp
+++ b/chromium/third_party/skia/src/lazy/SkDiscardableMemoryPool.cpp
@@ -5,37 +5,95 @@
* found in the LICENSE file.
*/
+#include "SkDiscardableMemory.h"
#include "SkDiscardableMemoryPool.h"
-#include "SkOnce.h"
+#include "SkLazyPtr.h"
+#include "SkTInternalLList.h"
+#include "SkThread.h"
// Note:
// A PoolDiscardableMemory is memory that is counted in a pool.
// A DiscardableMemoryPool is a pool of PoolDiscardableMemorys.
+namespace {
+
+class PoolDiscardableMemory;
+
/**
- * A SkPoolDiscardableMemory is a SkDiscardableMemory that relies on
- * a SkDiscardableMemoryPool object to manage the memory.
+ * This non-global pool can be used for unit tests to verify that the
+ * pool works.
*/
-class SkPoolDiscardableMemory : public SkDiscardableMemory {
+class DiscardableMemoryPool : public SkDiscardableMemoryPool {
public:
- SkPoolDiscardableMemory(SkDiscardableMemoryPool* pool,
+ /**
+ * Without mutex, will be not be thread safe.
+ */
+ DiscardableMemoryPool(size_t budget, SkBaseMutex* mutex = NULL);
+ virtual ~DiscardableMemoryPool();
+
+ virtual SkDiscardableMemory* create(size_t bytes) SK_OVERRIDE;
+
+ virtual size_t getRAMUsed() SK_OVERRIDE;
+ virtual void setRAMBudget(size_t budget) SK_OVERRIDE;
+ virtual size_t getRAMBudget() SK_OVERRIDE { return fBudget; }
+
+ /** purges all unlocked DMs */
+ virtual void dumpPool() SK_OVERRIDE;
+
+ #if SK_LAZY_CACHE_STATS // Defined in SkDiscardableMemoryPool.h
+ virtual int getCacheHits() SK_OVERRIDE { return fCacheHits; }
+ virtual int getCacheMisses() SK_OVERRIDE { return fCacheMisses; }
+ virtual void resetCacheHitsAndMisses() SK_OVERRIDE {
+ fCacheHits = fCacheMisses = 0;
+ }
+ int fCacheHits;
+ int fCacheMisses;
+ #endif // SK_LAZY_CACHE_STATS
+
+private:
+ SkBaseMutex* fMutex;
+ size_t fBudget;
+ size_t fUsed;
+ SkTInternalLList<PoolDiscardableMemory> fList;
+
+ /** Function called to free memory if needed */
+ void dumpDownTo(size_t budget);
+ /** called by DiscardableMemoryPool upon destruction */
+ void free(PoolDiscardableMemory* dm);
+ /** called by DiscardableMemoryPool::lock() */
+ bool lock(PoolDiscardableMemory* dm);
+ /** called by DiscardableMemoryPool::unlock() */
+ void unlock(PoolDiscardableMemory* dm);
+
+ friend class PoolDiscardableMemory;
+
+ typedef SkDiscardableMemory::Factory INHERITED;
+};
+
+/**
+ * A PoolDiscardableMemory is a SkDiscardableMemory that relies on
+ * a DiscardableMemoryPool object to manage the memory.
+ */
+class PoolDiscardableMemory : public SkDiscardableMemory {
+public:
+ PoolDiscardableMemory(DiscardableMemoryPool* pool,
void* pointer, size_t bytes);
- virtual ~SkPoolDiscardableMemory();
+ virtual ~PoolDiscardableMemory();
virtual bool lock() SK_OVERRIDE;
virtual void* data() SK_OVERRIDE;
virtual void unlock() SK_OVERRIDE;
- friend class SkDiscardableMemoryPool;
+ friend class DiscardableMemoryPool;
private:
- SK_DECLARE_INTERNAL_LLIST_INTERFACE(SkPoolDiscardableMemory);
- SkDiscardableMemoryPool* const fPool;
- bool fLocked;
- void* fPointer;
- const size_t fBytes;
+ SK_DECLARE_INTERNAL_LLIST_INTERFACE(PoolDiscardableMemory);
+ DiscardableMemoryPool* const fPool;
+ bool fLocked;
+ void* fPointer;
+ const size_t fBytes;
};
-SkPoolDiscardableMemory::SkPoolDiscardableMemory(SkDiscardableMemoryPool* pool,
- void* pointer,
- size_t bytes)
+PoolDiscardableMemory::PoolDiscardableMemory(DiscardableMemoryPool* pool,
+ void* pointer,
+ size_t bytes)
: fPool(pool)
, fLocked(true)
, fPointer(pointer)
@@ -46,59 +104,59 @@ SkPoolDiscardableMemory::SkPoolDiscardableMemory(SkDiscardableMemoryPool* pool,
fPool->ref();
}
-SkPoolDiscardableMemory::~SkPoolDiscardableMemory() {
+PoolDiscardableMemory::~PoolDiscardableMemory() {
SkASSERT(!fLocked); // contract for SkDiscardableMemory
fPool->free(this);
fPool->unref();
}
-bool SkPoolDiscardableMemory::lock() {
+bool PoolDiscardableMemory::lock() {
SkASSERT(!fLocked); // contract for SkDiscardableMemory
return fPool->lock(this);
}
-void* SkPoolDiscardableMemory::data() {
+void* PoolDiscardableMemory::data() {
SkASSERT(fLocked); // contract for SkDiscardableMemory
return fPointer;
}
-void SkPoolDiscardableMemory::unlock() {
+void PoolDiscardableMemory::unlock() {
SkASSERT(fLocked); // contract for SkDiscardableMemory
fPool->unlock(this);
}
////////////////////////////////////////////////////////////////////////////////
-SkDiscardableMemoryPool::SkDiscardableMemoryPool(size_t budget,
- SkBaseMutex* mutex)
+DiscardableMemoryPool::DiscardableMemoryPool(size_t budget,
+ SkBaseMutex* mutex)
: fMutex(mutex)
, fBudget(budget)
, fUsed(0) {
- #if LAZY_CACHE_STATS
+ #if SK_LAZY_CACHE_STATS
fCacheHits = 0;
fCacheMisses = 0;
- #endif // LAZY_CACHE_STATS
+ #endif // SK_LAZY_CACHE_STATS
}
-SkDiscardableMemoryPool::~SkDiscardableMemoryPool() {
- // SkPoolDiscardableMemory objects that belong to this pool are
+DiscardableMemoryPool::~DiscardableMemoryPool() {
+ // PoolDiscardableMemory objects that belong to this pool are
// always deleted before deleting this pool since each one has a
// ref to the pool.
SkASSERT(fList.isEmpty());
}
-void SkDiscardableMemoryPool::dumpDownTo(size_t budget) {
- // assert((NULL = fMutex) || fMutex->isLocked());
- // TODO(halcanary) implement bool fMutex::isLocked().
- // WARNING: only call this function after aquiring lock.
+void DiscardableMemoryPool::dumpDownTo(size_t budget) {
+ if (fMutex != NULL) {
+ fMutex->assertHeld();
+ }
if (fUsed <= budget) {
return;
}
- typedef SkTInternalLList<SkPoolDiscardableMemory>::Iter Iter;
+ typedef SkTInternalLList<PoolDiscardableMemory>::Iter Iter;
Iter iter;
- SkPoolDiscardableMemory* cur = iter.init(fList, Iter::kTail_IterStart);
+ PoolDiscardableMemory* cur = iter.init(fList, Iter::kTail_IterStart);
while ((fUsed > budget) && (NULL != cur)) {
if (!cur->fLocked) {
- SkPoolDiscardableMemory* dm = cur;
+ PoolDiscardableMemory* dm = cur;
SkASSERT(dm->fPointer != NULL);
sk_free(dm->fPointer);
dm->fPointer = NULL;
@@ -114,12 +172,12 @@ void SkDiscardableMemoryPool::dumpDownTo(size_t budget) {
}
}
-SkDiscardableMemory* SkDiscardableMemoryPool::create(size_t bytes) {
+SkDiscardableMemory* DiscardableMemoryPool::create(size_t bytes) {
void* addr = sk_malloc_flags(bytes, 0);
if (NULL == addr) {
return NULL;
}
- SkPoolDiscardableMemory* dm = SkNEW_ARGS(SkPoolDiscardableMemory,
+ PoolDiscardableMemory* dm = SkNEW_ARGS(PoolDiscardableMemory,
(this, addr, bytes));
SkAutoMutexAcquire autoMutexAcquire(fMutex);
fList.addToHead(dm);
@@ -128,7 +186,7 @@ SkDiscardableMemory* SkDiscardableMemoryPool::create(size_t bytes) {
return dm;
}
-void SkDiscardableMemoryPool::free(SkPoolDiscardableMemory* dm) {
+void DiscardableMemoryPool::free(PoolDiscardableMemory* dm) {
// This is called by dm's destructor.
if (dm->fPointer != NULL) {
SkAutoMutexAcquire autoMutexAcquire(fMutex);
@@ -142,66 +200,72 @@ void SkDiscardableMemoryPool::free(SkPoolDiscardableMemory* dm) {
}
}
-bool SkDiscardableMemoryPool::lock(SkPoolDiscardableMemory* dm) {
+bool DiscardableMemoryPool::lock(PoolDiscardableMemory* dm) {
SkASSERT(dm != NULL);
if (NULL == dm->fPointer) {
- #if LAZY_CACHE_STATS
+ #if SK_LAZY_CACHE_STATS
SkAutoMutexAcquire autoMutexAcquire(fMutex);
++fCacheMisses;
- #endif // LAZY_CACHE_STATS
+ #endif // SK_LAZY_CACHE_STATS
return false;
}
SkAutoMutexAcquire autoMutexAcquire(fMutex);
if (NULL == dm->fPointer) {
// May have been purged while waiting for lock.
- #if LAZY_CACHE_STATS
+ #if SK_LAZY_CACHE_STATS
++fCacheMisses;
- #endif // LAZY_CACHE_STATS
+ #endif // SK_LAZY_CACHE_STATS
return false;
}
dm->fLocked = true;
fList.remove(dm);
fList.addToHead(dm);
- #if LAZY_CACHE_STATS
+ #if SK_LAZY_CACHE_STATS
++fCacheHits;
- #endif // LAZY_CACHE_STATS
+ #endif // SK_LAZY_CACHE_STATS
return true;
}
-void SkDiscardableMemoryPool::unlock(SkPoolDiscardableMemory* dm) {
+void DiscardableMemoryPool::unlock(PoolDiscardableMemory* dm) {
SkASSERT(dm != NULL);
SkAutoMutexAcquire autoMutexAcquire(fMutex);
dm->fLocked = false;
this->dumpDownTo(fBudget);
}
-size_t SkDiscardableMemoryPool::getRAMUsed() {
+size_t DiscardableMemoryPool::getRAMUsed() {
return fUsed;
}
-void SkDiscardableMemoryPool::setRAMBudget(size_t budget) {
+void DiscardableMemoryPool::setRAMBudget(size_t budget) {
SkAutoMutexAcquire autoMutexAcquire(fMutex);
fBudget = budget;
this->dumpDownTo(fBudget);
}
-void SkDiscardableMemoryPool::dumpPool() {
+void DiscardableMemoryPool::dumpPool() {
SkAutoMutexAcquire autoMutexAcquire(fMutex);
this->dumpDownTo(0);
}
////////////////////////////////////////////////////////////////////////////////
SK_DECLARE_STATIC_MUTEX(gMutex);
-static void create_pool(SkDiscardableMemoryPool** pool) {
- SkASSERT(NULL == *pool);
- *pool = SkNEW_ARGS(SkDiscardableMemoryPool,
- (SK_DEFAULT_GLOBAL_DISCARDABLE_MEMORY_POOL_SIZE,
- &gMutex));
+SkDiscardableMemoryPool* create_global_pool() {
+ return SkDiscardableMemoryPool::Create(SK_DEFAULT_GLOBAL_DISCARDABLE_MEMORY_POOL_SIZE,
+ &gMutex);
}
+
+} // namespace
+
+SkDiscardableMemoryPool* SkDiscardableMemoryPool::Create(size_t size, SkBaseMutex* mutex) {
+ return SkNEW_ARGS(DiscardableMemoryPool, (size, mutex));
+}
+
SkDiscardableMemoryPool* SkGetGlobalDiscardableMemoryPool() {
- static SkDiscardableMemoryPool* gPool(NULL);
- SK_DECLARE_STATIC_ONCE(create_pool_once);
- SkOnce(&create_pool_once, create_pool, &gPool);
- SkASSERT(NULL != gPool);
- return gPool;
+ SK_DECLARE_STATIC_LAZY_PTR(SkDiscardableMemoryPool, global, create_global_pool);
+ return global.get();
}
+// defined in SkImageGenerator.h
+void SkPurgeGlobalDiscardableMemoryPool() {
+ SkGetGlobalDiscardableMemoryPool()->dumpPool();
+}
////////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/third_party/skia/src/lazy/SkDiscardableMemoryPool.h b/chromium/third_party/skia/src/lazy/SkDiscardableMemoryPool.h
index 61bad701825..d1415070041 100644
--- a/chromium/third_party/skia/src/lazy/SkDiscardableMemoryPool.h
+++ b/chromium/third_party/skia/src/lazy/SkDiscardableMemoryPool.h
@@ -9,60 +9,50 @@
#define SkDiscardableMemoryPool_DEFINED
#include "SkDiscardableMemory.h"
-#include "SkTInternalLList.h"
-#include "SkThread.h"
-class SkPoolDiscardableMemory;
-
-#ifdef SK_DEBUG
- #define LAZY_CACHE_STATS 1
-#elif !defined(LAZY_CACHE_STATS)
- #define LAZY_CACHE_STATS 0
+#ifndef SK_LAZY_CACHE_STATS
+ #ifdef SK_DEBUG
+ #define SK_LAZY_CACHE_STATS 1
+ #else
+ #define SK_LAZY_CACHE_STATS 0
+ #endif
#endif
/**
- * This non-global pool can be used for unit tests to verify that the
- * pool works.
+ * An implementation of Discardable Memory that manages a fixed-size
+ * budget of memory. When the allocated memory exceeds this size,
+ * unlocked blocks of memory are purged. If all memory is locked, it
+ * can exceed the memory-use budget.
*/
class SkDiscardableMemoryPool : public SkDiscardableMemory::Factory {
public:
- /**
- * Without mutex, will be not be thread safe.
- */
- SkDiscardableMemoryPool(size_t budget, SkBaseMutex* mutex = NULL);
- virtual ~SkDiscardableMemoryPool();
+ virtual ~SkDiscardableMemoryPool() { }
- virtual SkDiscardableMemory* create(size_t bytes) SK_OVERRIDE;
-
- size_t getRAMUsed();
- void setRAMBudget(size_t budget);
+ virtual size_t getRAMUsed() = 0;
+ virtual void setRAMBudget(size_t budget) = 0;
+ virtual size_t getRAMBudget() = 0;
/** purges all unlocked DMs */
- void dumpPool();
-
- #if LAZY_CACHE_STATS
- int fCacheHits;
- int fCacheMisses;
- #endif // LAZY_CACHE_STATS
-
-private:
- SkBaseMutex* fMutex;
- size_t fBudget;
- size_t fUsed;
- SkTInternalLList<SkPoolDiscardableMemory> fList;
+ virtual void dumpPool() = 0;
- /** Function called to free memory if needed */
- void dumpDownTo(size_t budget);
- /** called by SkDiscardableMemoryPool upon destruction */
- void free(SkPoolDiscardableMemory* dm);
- /** called by SkDiscardableMemoryPool::lock() */
- bool lock(SkPoolDiscardableMemory* dm);
- /** called by SkDiscardableMemoryPool::unlock() */
- void unlock(SkPoolDiscardableMemory* dm);
-
- friend class SkPoolDiscardableMemory;
+ #if SK_LAZY_CACHE_STATS
+ /**
+ * These two values are a count of the number of successful and
+ * failed calls to SkDiscardableMemory::lock() for all DMs managed
+ * by this pool.
+ */
+ virtual int getCacheHits() = 0;
+ virtual int getCacheMisses() = 0;
+ virtual void resetCacheHitsAndMisses() = 0;
+ #endif
- typedef SkDiscardableMemory::Factory INHERITED;
+ /**
+ * This non-global pool can be used for unit tests to verify that
+ * the pool works.
+ * Without mutex, will be not be thread safe.
+ */
+ static SkDiscardableMemoryPool* Create(
+ size_t size, SkBaseMutex* mutex = NULL);
};
/**
diff --git a/chromium/third_party/skia/src/lazy/SkDiscardablePixelRef.cpp b/chromium/third_party/skia/src/lazy/SkDiscardablePixelRef.cpp
index 160ca5b4fba..f0d7affdc8f 100644
--- a/chromium/third_party/skia/src/lazy/SkDiscardablePixelRef.cpp
+++ b/chromium/third_party/skia/src/lazy/SkDiscardablePixelRef.cpp
@@ -36,10 +36,13 @@ SkDiscardablePixelRef::~SkDiscardablePixelRef() {
SkDELETE(fGenerator);
}
-void* SkDiscardablePixelRef::onLockPixels(SkColorTable**) {
+bool SkDiscardablePixelRef::onNewLockPixels(LockRec* rec) {
if (fDiscardableMemory != NULL) {
if (fDiscardableMemory->lock()) {
- return fDiscardableMemory->data();
+ rec->fPixels = fDiscardableMemory->data();
+ rec->fColorTable = NULL;
+ rec->fRowBytes = fRowBytes;
+ return true;
}
SkDELETE(fDiscardableMemory);
fDiscardableMemory = NULL;
@@ -53,39 +56,67 @@ void* SkDiscardablePixelRef::onLockPixels(SkColorTable**) {
fDiscardableMemory = SkDiscardableMemory::Create(size);
}
if (NULL == fDiscardableMemory) {
- return NULL; // Memory allocation failed.
+ return false; // Memory allocation failed.
}
+
void* pixels = fDiscardableMemory->data();
- if (!fGenerator->getPixels(this->info(), pixels, fRowBytes)) {
+ const SkImageInfo& info = this->info();
+ SkPMColor colors[256];
+ int colorCount = 0;
+
+#ifdef SK_SUPPORT_LEGACY_IMAGEGENERATORAPI
+ if (!fGenerator->getPixels(info, pixels, fRowBytes)) {
+#else
+ if (!fGenerator->getPixels(info, pixels, fRowBytes, colors, &colorCount)) {
+#endif
fDiscardableMemory->unlock();
SkDELETE(fDiscardableMemory);
fDiscardableMemory = NULL;
- return NULL;
+ return false;
+ }
+
+ // Note: our ctable is not purgable, as it is not stored in the discardablememory block.
+ // This is because SkColorTable is refcntable, and therefore our caller could hold onto it
+ // beyond the scope of a lock/unlock. If we change the API/lifecycle for SkColorTable, we
+ // could move it into the block, but then again perhaps it is small enough that this doesn't
+ // really matter.
+ if (colorCount > 0) {
+ fCTable.reset(SkNEW_ARGS(SkColorTable, (colors, colorCount)));
+ } else {
+ fCTable.reset(NULL);
}
- return pixels;
+
+ rec->fPixels = pixels;
+ rec->fColorTable = fCTable.get();
+ rec->fRowBytes = fRowBytes;
+ return true;
}
+
void SkDiscardablePixelRef::onUnlockPixels() {
fDiscardableMemory->unlock();
}
-bool SkInstallDiscardablePixelRef(SkImageGenerator* generator,
- SkBitmap* dst,
+bool SkInstallDiscardablePixelRef(SkImageGenerator* generator, SkBitmap* dst,
SkDiscardableMemory::Factory* factory) {
SkImageInfo info;
- SkASSERT(generator != NULL);
- if ((NULL == generator)
- || (!generator->getInfo(&info))
- || (!dst->setConfig(info, 0))) {
- SkDELETE(generator);
+ SkAutoTDelete<SkImageGenerator> autoGenerator(generator);
+ if ((NULL == autoGenerator.get())
+ || (!autoGenerator->getInfo(&info))
+ || (!dst->setInfo(info))) {
return false;
}
- SkASSERT(dst->config() != SkBitmap::kNo_Config);
- if (dst->empty()) { // Use a normal pixelref.
- SkDELETE(generator); // Do not need this anymore.
- return dst->allocPixels(NULL, NULL);
+ SkASSERT(dst->colorType() != kUnknown_SkColorType);
+ if (dst->empty()) { // Use a normal pixelref.
+ return dst->allocPixels();
}
- SkAutoTUnref<SkDiscardablePixelRef> ref(SkNEW_ARGS(SkDiscardablePixelRef,
- (info, generator, dst->rowBytes(), factory)));
+ SkAutoTUnref<SkDiscardablePixelRef> ref(
+ SkNEW_ARGS(SkDiscardablePixelRef,
+ (info, autoGenerator.detach(), dst->rowBytes(), factory)));
dst->setPixelRef(ref);
return true;
}
+
+// This is the public API
+bool SkInstallDiscardablePixelRef(SkImageGenerator* generator, SkBitmap* dst) {
+ return SkInstallDiscardablePixelRef(generator, dst, NULL);
+}
diff --git a/chromium/third_party/skia/src/lazy/SkDiscardablePixelRef.h b/chromium/third_party/skia/src/lazy/SkDiscardablePixelRef.h
index 4b6693837d5..52a1d6ce370 100644
--- a/chromium/third_party/skia/src/lazy/SkDiscardablePixelRef.h
+++ b/chromium/third_party/skia/src/lazy/SkDiscardablePixelRef.h
@@ -13,13 +13,20 @@
#include "SkImageInfo.h"
#include "SkPixelRef.h"
+/**
+ * A PixelRef backed by SkDiscardableMemory, with the ability to
+ * re-generate the pixels (via a SkImageGenerator) if the DM is
+ * purged.
+ */
class SkDiscardablePixelRef : public SkPixelRef {
public:
+ SK_DECLARE_INST_COUNT(SkDiscardablePixelRef)
SK_DECLARE_UNFLATTENABLE_OBJECT()
protected:
~SkDiscardablePixelRef();
- virtual void* onLockPixels(SkColorTable**) SK_OVERRIDE;
+
+ virtual bool onNewLockPixels(LockRec*) SK_OVERRIDE;
virtual void onUnlockPixels() SK_OVERRIDE;
virtual bool onLockPixelsAreWritable() const SK_OVERRIDE { return false; }
@@ -35,14 +42,17 @@ private:
// PixelRef, since the SkBitmap doesn't expect them to change.
SkDiscardableMemory* fDiscardableMemory;
+ SkAutoTUnref<SkColorTable> fCTable;
/* Takes ownership of SkImageGenerator. */
SkDiscardablePixelRef(const SkImageInfo&, SkImageGenerator*,
size_t rowBytes,
SkDiscardableMemory::Factory* factory);
- friend bool SkInstallDiscardablePixelRef(SkImageGenerator*,
- SkBitmap*,
+
+ friend bool SkInstallDiscardablePixelRef(SkImageGenerator*, SkBitmap*,
SkDiscardableMemory::Factory*);
+
typedef SkPixelRef INHERITED;
};
+
#endif // SkDiscardablePixelRef_DEFINED
diff --git a/chromium/third_party/skia/src/lazy/SkPurgeableMemoryBlock.h b/chromium/third_party/skia/src/lazy/SkPurgeableMemoryBlock.h
deleted file mode 100644
index 1750ad9d6cd..00000000000
--- a/chromium/third_party/skia/src/lazy/SkPurgeableMemoryBlock.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2013 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkPurgeableMemoryBlock_DEFINED
-#define SkPurgeableMemoryBlock_DEFINED
-
-#include "SkTypes.h"
-
-class SkPurgeableMemoryBlock : public SkNoncopyable {
-
-public:
- /**
- * Whether or not this platform has an implementation for purgeable memory.
- */
- static bool IsSupported();
-
- /**
- * Create a new purgeable memory block of 'size' bytes. Returns NULL if not supported on this
- * platform or on failure.
- * @param size Number of bytes requested.
- * @return A new block, or NULL on failure.
- */
- static SkPurgeableMemoryBlock* Create(size_t size);
-
-#ifdef SK_DEBUG
- /**
- * Whether the platform supports one shot purge of all unpinned blocks. If so,
- * PurgeAllUnpinnedBlocks will be used to test a purge. Otherwise, purge will be called on
- * individual blocks.
- */
- static bool PlatformSupportsPurgingAllUnpinnedBlocks();
-
- /**
- * Purge all unpinned blocks at once, if the platform supports it.
- */
- static bool PurgeAllUnpinnedBlocks();
-
- // If PlatformSupportsPurgingAllUnpinnedBlocks returns true, this will not be called, so it can
- // simply return false.
- bool purge();
-
- bool isPinned() const { return fPinned; }
-#endif
-
- ~SkPurgeableMemoryBlock();
-
- /**
- * Output parameter for pin(), stating whether the data has been retained.
- */
- enum PinResult {
- /**
- * The data has been purged, or this is the first call to pin.
- */
- kUninitialized_PinResult,
-
- /**
- * The data has been retained. The memory contains the same data it held when unpin() was
- * called.
- */
- kRetained_PinResult,
- };
-
- /**
- * Pin the memory for use. Must not be called while already pinned.
- * @param PinResult Whether the data was retained. Ignored on failure.
- * @return Pointer to the pinned data on success. NULL on failure.
- */
- void* pin(PinResult*);
-
- /**
- * Unpin the data so it can be purged if necessary.
- */
- void unpin();
-
-private:
- void* fAddr;
- size_t fSize;
- bool fPinned;
-#ifdef SK_BUILD_FOR_ANDROID
- int fFD;
-#endif
-
- // Unimplemented default constructor is private, to prevent manual creation.
- SkPurgeableMemoryBlock();
-
- // The correct way to create a new one is from the static Create.
- SkPurgeableMemoryBlock(size_t);
-};
-
-#endif // SkPurgeableMemoryBlock_DEFINED
diff --git a/chromium/third_party/skia/src/lazy/SkPurgeableMemoryBlock_common.cpp b/chromium/third_party/skia/src/lazy/SkPurgeableMemoryBlock_common.cpp
deleted file mode 100644
index a549c46e264..00000000000
--- a/chromium/third_party/skia/src/lazy/SkPurgeableMemoryBlock_common.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright 2013 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkPurgeableMemoryBlock.h"
-
-SkPurgeableMemoryBlock* SkPurgeableMemoryBlock::Create(size_t size) {
- SkASSERT(IsSupported());
- if (!IsSupported()) {
- return NULL;
- }
- return SkNEW_ARGS(SkPurgeableMemoryBlock, (size));
-}
diff --git a/chromium/third_party/skia/src/opts/SkBitmapFilter_opts_SSE2.cpp b/chromium/third_party/skia/src/opts/SkBitmapFilter_opts_SSE2.cpp
index 259e2efc0ec..b0405669218 100644
--- a/chromium/third_party/skia/src/opts/SkBitmapFilter_opts_SSE2.cpp
+++ b/chromium/third_party/skia/src/opts/SkBitmapFilter_opts_SSE2.cpp
@@ -5,17 +5,15 @@
* found in the LICENSE file.
*/
-#include "SkBitmapProcState.h"
+#include <emmintrin.h>
#include "SkBitmap.h"
+#include "SkBitmapFilter_opts_SSE2.h"
+#include "SkBitmapProcState.h"
#include "SkColor.h"
#include "SkColorPriv.h"
-#include "SkUnPreMultiply.h"
-#include "SkShader.h"
#include "SkConvolver.h"
-
-#include "SkBitmapFilter_opts_SSE2.h"
-
-#include <emmintrin.h>
+#include "SkShader.h"
+#include "SkUnPreMultiply.h"
#if 0
static inline void print128i(__m128i value) {
@@ -175,7 +173,6 @@ void highQualityFilter_ScaleOnly_SSE2(const SkBitmapProcState &s, int x, int y,
s.fInvProc(s.fInvMatrix, SkIntToScalar(x),
SkIntToScalar(y), &srcPt);
-
}
}
@@ -185,126 +182,126 @@ void convolveHorizontally_SSE2(const unsigned char* src_data,
const SkConvolutionFilter1D& filter,
unsigned char* out_row,
bool /*has_alpha*/) {
- int num_values = filter.numValues();
-
- int filter_offset, filter_length;
- __m128i zero = _mm_setzero_si128();
- __m128i mask[4];
- // |mask| will be used to decimate all extra filter coefficients that are
- // loaded by SIMD when |filter_length| is not divisible by 4.
- // mask[0] is not used in following algorithm.
- mask[1] = _mm_set_epi16(0, 0, 0, 0, 0, 0, 0, -1);
- mask[2] = _mm_set_epi16(0, 0, 0, 0, 0, 0, -1, -1);
- mask[3] = _mm_set_epi16(0, 0, 0, 0, 0, -1, -1, -1);
-
- // Output one pixel each iteration, calculating all channels (RGBA) together.
- for (int out_x = 0; out_x < num_values; out_x++) {
- const SkConvolutionFilter1D::ConvolutionFixed* filter_values =
- filter.FilterForValue(out_x, &filter_offset, &filter_length);
-
- __m128i accum = _mm_setzero_si128();
-
- // Compute the first pixel in this row that the filter affects. It will
- // touch |filter_length| pixels (4 bytes each) after this.
- const __m128i* row_to_filter =
- reinterpret_cast<const __m128i*>(&src_data[filter_offset << 2]);
-
- // We will load and accumulate with four coefficients per iteration.
- for (int filter_x = 0; filter_x < filter_length >> 2; filter_x++) {
-
- // Load 4 coefficients => duplicate 1st and 2nd of them for all channels.
- __m128i coeff, coeff16;
- // [16] xx xx xx xx c3 c2 c1 c0
- coeff = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(filter_values));
- // [16] xx xx xx xx c1 c1 c0 c0
- coeff16 = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(1, 1, 0, 0));
- // [16] c1 c1 c1 c1 c0 c0 c0 c0
- coeff16 = _mm_unpacklo_epi16(coeff16, coeff16);
-
- // Load four pixels => unpack the first two pixels to 16 bits =>
- // multiply with coefficients => accumulate the convolution result.
- // [8] a3 b3 g3 r3 a2 b2 g2 r2 a1 b1 g1 r1 a0 b0 g0 r0
- __m128i src8 = _mm_loadu_si128(row_to_filter);
- // [16] a1 b1 g1 r1 a0 b0 g0 r0
- __m128i src16 = _mm_unpacklo_epi8(src8, zero);
- __m128i mul_hi = _mm_mulhi_epi16(src16, coeff16);
- __m128i mul_lo = _mm_mullo_epi16(src16, coeff16);
- // [32] a0*c0 b0*c0 g0*c0 r0*c0
- __m128i t = _mm_unpacklo_epi16(mul_lo, mul_hi);
- accum = _mm_add_epi32(accum, t);
- // [32] a1*c1 b1*c1 g1*c1 r1*c1
- t = _mm_unpackhi_epi16(mul_lo, mul_hi);
- accum = _mm_add_epi32(accum, t);
-
- // Duplicate 3rd and 4th coefficients for all channels =>
- // unpack the 3rd and 4th pixels to 16 bits => multiply with coefficients
- // => accumulate the convolution results.
- // [16] xx xx xx xx c3 c3 c2 c2
- coeff16 = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(3, 3, 2, 2));
- // [16] c3 c3 c3 c3 c2 c2 c2 c2
- coeff16 = _mm_unpacklo_epi16(coeff16, coeff16);
- // [16] a3 g3 b3 r3 a2 g2 b2 r2
- src16 = _mm_unpackhi_epi8(src8, zero);
- mul_hi = _mm_mulhi_epi16(src16, coeff16);
- mul_lo = _mm_mullo_epi16(src16, coeff16);
- // [32] a2*c2 b2*c2 g2*c2 r2*c2
- t = _mm_unpacklo_epi16(mul_lo, mul_hi);
- accum = _mm_add_epi32(accum, t);
- // [32] a3*c3 b3*c3 g3*c3 r3*c3
- t = _mm_unpackhi_epi16(mul_lo, mul_hi);
- accum = _mm_add_epi32(accum, t);
-
- // Advance the pixel and coefficients pointers.
- row_to_filter += 1;
- filter_values += 4;
- }
+ int num_values = filter.numValues();
+
+ int filter_offset, filter_length;
+ __m128i zero = _mm_setzero_si128();
+ __m128i mask[4];
+ // |mask| will be used to decimate all extra filter coefficients that are
+ // loaded by SIMD when |filter_length| is not divisible by 4.
+ // mask[0] is not used in following algorithm.
+ mask[1] = _mm_set_epi16(0, 0, 0, 0, 0, 0, 0, -1);
+ mask[2] = _mm_set_epi16(0, 0, 0, 0, 0, 0, -1, -1);
+ mask[3] = _mm_set_epi16(0, 0, 0, 0, 0, -1, -1, -1);
+
+ // Output one pixel each iteration, calculating all channels (RGBA) together.
+ for (int out_x = 0; out_x < num_values; out_x++) {
+ const SkConvolutionFilter1D::ConvolutionFixed* filter_values =
+ filter.FilterForValue(out_x, &filter_offset, &filter_length);
+
+ __m128i accum = _mm_setzero_si128();
+
+ // Compute the first pixel in this row that the filter affects. It will
+ // touch |filter_length| pixels (4 bytes each) after this.
+ const __m128i* row_to_filter =
+ reinterpret_cast<const __m128i*>(&src_data[filter_offset << 2]);
+
+ // We will load and accumulate with four coefficients per iteration.
+ for (int filter_x = 0; filter_x < filter_length >> 2; filter_x++) {
+
+ // Load 4 coefficients => duplicate 1st and 2nd of them for all channels.
+ __m128i coeff, coeff16;
+ // [16] xx xx xx xx c3 c2 c1 c0
+ coeff = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(filter_values));
+ // [16] xx xx xx xx c1 c1 c0 c0
+ coeff16 = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(1, 1, 0, 0));
+ // [16] c1 c1 c1 c1 c0 c0 c0 c0
+ coeff16 = _mm_unpacklo_epi16(coeff16, coeff16);
+
+ // Load four pixels => unpack the first two pixels to 16 bits =>
+ // multiply with coefficients => accumulate the convolution result.
+ // [8] a3 b3 g3 r3 a2 b2 g2 r2 a1 b1 g1 r1 a0 b0 g0 r0
+ __m128i src8 = _mm_loadu_si128(row_to_filter);
+ // [16] a1 b1 g1 r1 a0 b0 g0 r0
+ __m128i src16 = _mm_unpacklo_epi8(src8, zero);
+ __m128i mul_hi = _mm_mulhi_epi16(src16, coeff16);
+ __m128i mul_lo = _mm_mullo_epi16(src16, coeff16);
+ // [32] a0*c0 b0*c0 g0*c0 r0*c0
+ __m128i t = _mm_unpacklo_epi16(mul_lo, mul_hi);
+ accum = _mm_add_epi32(accum, t);
+ // [32] a1*c1 b1*c1 g1*c1 r1*c1
+ t = _mm_unpackhi_epi16(mul_lo, mul_hi);
+ accum = _mm_add_epi32(accum, t);
+
+ // Duplicate 3rd and 4th coefficients for all channels =>
+ // unpack the 3rd and 4th pixels to 16 bits => multiply with coefficients
+ // => accumulate the convolution results.
+ // [16] xx xx xx xx c3 c3 c2 c2
+ coeff16 = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(3, 3, 2, 2));
+ // [16] c3 c3 c3 c3 c2 c2 c2 c2
+ coeff16 = _mm_unpacklo_epi16(coeff16, coeff16);
+ // [16] a3 g3 b3 r3 a2 g2 b2 r2
+ src16 = _mm_unpackhi_epi8(src8, zero);
+ mul_hi = _mm_mulhi_epi16(src16, coeff16);
+ mul_lo = _mm_mullo_epi16(src16, coeff16);
+ // [32] a2*c2 b2*c2 g2*c2 r2*c2
+ t = _mm_unpacklo_epi16(mul_lo, mul_hi);
+ accum = _mm_add_epi32(accum, t);
+ // [32] a3*c3 b3*c3 g3*c3 r3*c3
+ t = _mm_unpackhi_epi16(mul_lo, mul_hi);
+ accum = _mm_add_epi32(accum, t);
+
+ // Advance the pixel and coefficients pointers.
+ row_to_filter += 1;
+ filter_values += 4;
+ }
- // When |filter_length| is not divisible by 4, we need to decimate some of
- // the filter coefficient that was loaded incorrectly to zero; Other than
- // that the algorithm is same with above, exceot that the 4th pixel will be
- // always absent.
- int r = filter_length&3;
- if (r) {
- // Note: filter_values must be padded to align_up(filter_offset, 8).
- __m128i coeff, coeff16;
- coeff = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(filter_values));
- // Mask out extra filter taps.
- coeff = _mm_and_si128(coeff, mask[r]);
- coeff16 = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(1, 1, 0, 0));
- coeff16 = _mm_unpacklo_epi16(coeff16, coeff16);
-
- // Note: line buffer must be padded to align_up(filter_offset, 16).
- // We resolve this by use C-version for the last horizontal line.
- __m128i src8 = _mm_loadu_si128(row_to_filter);
- __m128i src16 = _mm_unpacklo_epi8(src8, zero);
- __m128i mul_hi = _mm_mulhi_epi16(src16, coeff16);
- __m128i mul_lo = _mm_mullo_epi16(src16, coeff16);
- __m128i t = _mm_unpacklo_epi16(mul_lo, mul_hi);
- accum = _mm_add_epi32(accum, t);
- t = _mm_unpackhi_epi16(mul_lo, mul_hi);
- accum = _mm_add_epi32(accum, t);
-
- src16 = _mm_unpackhi_epi8(src8, zero);
- coeff16 = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(3, 3, 2, 2));
- coeff16 = _mm_unpacklo_epi16(coeff16, coeff16);
- mul_hi = _mm_mulhi_epi16(src16, coeff16);
- mul_lo = _mm_mullo_epi16(src16, coeff16);
- t = _mm_unpacklo_epi16(mul_lo, mul_hi);
- accum = _mm_add_epi32(accum, t);
- }
+ // When |filter_length| is not divisible by 4, we need to decimate some of
+ // the filter coefficient that was loaded incorrectly to zero; Other than
+ // that the algorithm is same with above, exceot that the 4th pixel will be
+ // always absent.
+ int r = filter_length&3;
+ if (r) {
+ // Note: filter_values must be padded to align_up(filter_offset, 8).
+ __m128i coeff, coeff16;
+ coeff = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(filter_values));
+ // Mask out extra filter taps.
+ coeff = _mm_and_si128(coeff, mask[r]);
+ coeff16 = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(1, 1, 0, 0));
+ coeff16 = _mm_unpacklo_epi16(coeff16, coeff16);
+
+ // Note: line buffer must be padded to align_up(filter_offset, 16).
+ // We resolve this by use C-version for the last horizontal line.
+ __m128i src8 = _mm_loadu_si128(row_to_filter);
+ __m128i src16 = _mm_unpacklo_epi8(src8, zero);
+ __m128i mul_hi = _mm_mulhi_epi16(src16, coeff16);
+ __m128i mul_lo = _mm_mullo_epi16(src16, coeff16);
+ __m128i t = _mm_unpacklo_epi16(mul_lo, mul_hi);
+ accum = _mm_add_epi32(accum, t);
+ t = _mm_unpackhi_epi16(mul_lo, mul_hi);
+ accum = _mm_add_epi32(accum, t);
+
+ src16 = _mm_unpackhi_epi8(src8, zero);
+ coeff16 = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(3, 3, 2, 2));
+ coeff16 = _mm_unpacklo_epi16(coeff16, coeff16);
+ mul_hi = _mm_mulhi_epi16(src16, coeff16);
+ mul_lo = _mm_mullo_epi16(src16, coeff16);
+ t = _mm_unpacklo_epi16(mul_lo, mul_hi);
+ accum = _mm_add_epi32(accum, t);
+ }
- // Shift right for fixed point implementation.
- accum = _mm_srai_epi32(accum, SkConvolutionFilter1D::kShiftBits);
+ // Shift right for fixed point implementation.
+ accum = _mm_srai_epi32(accum, SkConvolutionFilter1D::kShiftBits);
- // Packing 32 bits |accum| to 16 bits per channel (signed saturation).
- accum = _mm_packs_epi32(accum, zero);
- // Packing 16 bits |accum| to 8 bits per channel (unsigned saturation).
- accum = _mm_packus_epi16(accum, zero);
+ // Packing 32 bits |accum| to 16 bits per channel (signed saturation).
+ accum = _mm_packs_epi32(accum, zero);
+ // Packing 16 bits |accum| to 8 bits per channel (unsigned saturation).
+ accum = _mm_packus_epi16(accum, zero);
- // Store the pixel value of 32 bits.
- *(reinterpret_cast<int*>(out_row)) = _mm_cvtsi128_si32(accum);
- out_row += 4;
- }
+ // Store the pixel value of 32 bits.
+ *(reinterpret_cast<int*>(out_row)) = _mm_cvtsi128_si32(accum);
+ out_row += 4;
+ }
}
// Convolves horizontally along four rows. The row data is given in
@@ -314,116 +311,116 @@ void convolveHorizontally_SSE2(const unsigned char* src_data,
void convolve4RowsHorizontally_SSE2(const unsigned char* src_data[4],
const SkConvolutionFilter1D& filter,
unsigned char* out_row[4]) {
- int num_values = filter.numValues();
-
- int filter_offset, filter_length;
- __m128i zero = _mm_setzero_si128();
- __m128i mask[4];
- // |mask| will be used to decimate all extra filter coefficients that are
- // loaded by SIMD when |filter_length| is not divisible by 4.
- // mask[0] is not used in following algorithm.
- mask[1] = _mm_set_epi16(0, 0, 0, 0, 0, 0, 0, -1);
- mask[2] = _mm_set_epi16(0, 0, 0, 0, 0, 0, -1, -1);
- mask[3] = _mm_set_epi16(0, 0, 0, 0, 0, -1, -1, -1);
-
- // Output one pixel each iteration, calculating all channels (RGBA) together.
- for (int out_x = 0; out_x < num_values; out_x++) {
- const SkConvolutionFilter1D::ConvolutionFixed* filter_values =
- filter.FilterForValue(out_x, &filter_offset, &filter_length);
-
- // four pixels in a column per iteration.
- __m128i accum0 = _mm_setzero_si128();
- __m128i accum1 = _mm_setzero_si128();
- __m128i accum2 = _mm_setzero_si128();
- __m128i accum3 = _mm_setzero_si128();
- int start = (filter_offset<<2);
- // We will load and accumulate with four coefficients per iteration.
- for (int filter_x = 0; filter_x < (filter_length >> 2); filter_x++) {
- __m128i coeff, coeff16lo, coeff16hi;
- // [16] xx xx xx xx c3 c2 c1 c0
- coeff = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(filter_values));
- // [16] xx xx xx xx c1 c1 c0 c0
- coeff16lo = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(1, 1, 0, 0));
- // [16] c1 c1 c1 c1 c0 c0 c0 c0
- coeff16lo = _mm_unpacklo_epi16(coeff16lo, coeff16lo);
- // [16] xx xx xx xx c3 c3 c2 c2
- coeff16hi = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(3, 3, 2, 2));
- // [16] c3 c3 c3 c3 c2 c2 c2 c2
- coeff16hi = _mm_unpacklo_epi16(coeff16hi, coeff16hi);
-
- __m128i src8, src16, mul_hi, mul_lo, t;
-
-#define ITERATION(src, accum) \
- src8 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(src)); \
- src16 = _mm_unpacklo_epi8(src8, zero); \
- mul_hi = _mm_mulhi_epi16(src16, coeff16lo); \
- mul_lo = _mm_mullo_epi16(src16, coeff16lo); \
- t = _mm_unpacklo_epi16(mul_lo, mul_hi); \
- accum = _mm_add_epi32(accum, t); \
- t = _mm_unpackhi_epi16(mul_lo, mul_hi); \
- accum = _mm_add_epi32(accum, t); \
- src16 = _mm_unpackhi_epi8(src8, zero); \
- mul_hi = _mm_mulhi_epi16(src16, coeff16hi); \
- mul_lo = _mm_mullo_epi16(src16, coeff16hi); \
- t = _mm_unpacklo_epi16(mul_lo, mul_hi); \
- accum = _mm_add_epi32(accum, t); \
- t = _mm_unpackhi_epi16(mul_lo, mul_hi); \
- accum = _mm_add_epi32(accum, t)
-
- ITERATION(src_data[0] + start, accum0);
- ITERATION(src_data[1] + start, accum1);
- ITERATION(src_data[2] + start, accum2);
- ITERATION(src_data[3] + start, accum3);
-
- start += 16;
- filter_values += 4;
- }
+ int num_values = filter.numValues();
+
+ int filter_offset, filter_length;
+ __m128i zero = _mm_setzero_si128();
+ __m128i mask[4];
+ // |mask| will be used to decimate all extra filter coefficients that are
+ // loaded by SIMD when |filter_length| is not divisible by 4.
+ // mask[0] is not used in following algorithm.
+ mask[1] = _mm_set_epi16(0, 0, 0, 0, 0, 0, 0, -1);
+ mask[2] = _mm_set_epi16(0, 0, 0, 0, 0, 0, -1, -1);
+ mask[3] = _mm_set_epi16(0, 0, 0, 0, 0, -1, -1, -1);
+
+ // Output one pixel each iteration, calculating all channels (RGBA) together.
+ for (int out_x = 0; out_x < num_values; out_x++) {
+ const SkConvolutionFilter1D::ConvolutionFixed* filter_values =
+ filter.FilterForValue(out_x, &filter_offset, &filter_length);
+
+ // four pixels in a column per iteration.
+ __m128i accum0 = _mm_setzero_si128();
+ __m128i accum1 = _mm_setzero_si128();
+ __m128i accum2 = _mm_setzero_si128();
+ __m128i accum3 = _mm_setzero_si128();
+ int start = (filter_offset<<2);
+ // We will load and accumulate with four coefficients per iteration.
+ for (int filter_x = 0; filter_x < (filter_length >> 2); filter_x++) {
+ __m128i coeff, coeff16lo, coeff16hi;
+ // [16] xx xx xx xx c3 c2 c1 c0
+ coeff = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(filter_values));
+ // [16] xx xx xx xx c1 c1 c0 c0
+ coeff16lo = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(1, 1, 0, 0));
+ // [16] c1 c1 c1 c1 c0 c0 c0 c0
+ coeff16lo = _mm_unpacklo_epi16(coeff16lo, coeff16lo);
+ // [16] xx xx xx xx c3 c3 c2 c2
+ coeff16hi = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(3, 3, 2, 2));
+ // [16] c3 c3 c3 c3 c2 c2 c2 c2
+ coeff16hi = _mm_unpacklo_epi16(coeff16hi, coeff16hi);
+
+ __m128i src8, src16, mul_hi, mul_lo, t;
+
+#define ITERATION(src, accum) \
+ src8 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(src)); \
+ src16 = _mm_unpacklo_epi8(src8, zero); \
+ mul_hi = _mm_mulhi_epi16(src16, coeff16lo); \
+ mul_lo = _mm_mullo_epi16(src16, coeff16lo); \
+ t = _mm_unpacklo_epi16(mul_lo, mul_hi); \
+ accum = _mm_add_epi32(accum, t); \
+ t = _mm_unpackhi_epi16(mul_lo, mul_hi); \
+ accum = _mm_add_epi32(accum, t); \
+ src16 = _mm_unpackhi_epi8(src8, zero); \
+ mul_hi = _mm_mulhi_epi16(src16, coeff16hi); \
+ mul_lo = _mm_mullo_epi16(src16, coeff16hi); \
+ t = _mm_unpacklo_epi16(mul_lo, mul_hi); \
+ accum = _mm_add_epi32(accum, t); \
+ t = _mm_unpackhi_epi16(mul_lo, mul_hi); \
+ accum = _mm_add_epi32(accum, t)
+
+ ITERATION(src_data[0] + start, accum0);
+ ITERATION(src_data[1] + start, accum1);
+ ITERATION(src_data[2] + start, accum2);
+ ITERATION(src_data[3] + start, accum3);
+
+ start += 16;
+ filter_values += 4;
+ }
- int r = filter_length & 3;
- if (r) {
- // Note: filter_values must be padded to align_up(filter_offset, 8);
- __m128i coeff;
- coeff = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(filter_values));
- // Mask out extra filter taps.
- coeff = _mm_and_si128(coeff, mask[r]);
-
- __m128i coeff16lo = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(1, 1, 0, 0));
- /* c1 c1 c1 c1 c0 c0 c0 c0 */
- coeff16lo = _mm_unpacklo_epi16(coeff16lo, coeff16lo);
- __m128i coeff16hi = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(3, 3, 2, 2));
- coeff16hi = _mm_unpacklo_epi16(coeff16hi, coeff16hi);
-
- __m128i src8, src16, mul_hi, mul_lo, t;
-
- ITERATION(src_data[0] + start, accum0);
- ITERATION(src_data[1] + start, accum1);
- ITERATION(src_data[2] + start, accum2);
- ITERATION(src_data[3] + start, accum3);
- }
+ int r = filter_length & 3;
+ if (r) {
+ // Note: filter_values must be padded to align_up(filter_offset, 8);
+ __m128i coeff;
+ coeff = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(filter_values));
+ // Mask out extra filter taps.
+ coeff = _mm_and_si128(coeff, mask[r]);
+
+ __m128i coeff16lo = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(1, 1, 0, 0));
+ /* c1 c1 c1 c1 c0 c0 c0 c0 */
+ coeff16lo = _mm_unpacklo_epi16(coeff16lo, coeff16lo);
+ __m128i coeff16hi = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(3, 3, 2, 2));
+ coeff16hi = _mm_unpacklo_epi16(coeff16hi, coeff16hi);
+
+ __m128i src8, src16, mul_hi, mul_lo, t;
+
+ ITERATION(src_data[0] + start, accum0);
+ ITERATION(src_data[1] + start, accum1);
+ ITERATION(src_data[2] + start, accum2);
+ ITERATION(src_data[3] + start, accum3);
+ }
- accum0 = _mm_srai_epi32(accum0, SkConvolutionFilter1D::kShiftBits);
- accum0 = _mm_packs_epi32(accum0, zero);
- accum0 = _mm_packus_epi16(accum0, zero);
- accum1 = _mm_srai_epi32(accum1, SkConvolutionFilter1D::kShiftBits);
- accum1 = _mm_packs_epi32(accum1, zero);
- accum1 = _mm_packus_epi16(accum1, zero);
- accum2 = _mm_srai_epi32(accum2, SkConvolutionFilter1D::kShiftBits);
- accum2 = _mm_packs_epi32(accum2, zero);
- accum2 = _mm_packus_epi16(accum2, zero);
- accum3 = _mm_srai_epi32(accum3, SkConvolutionFilter1D::kShiftBits);
- accum3 = _mm_packs_epi32(accum3, zero);
- accum3 = _mm_packus_epi16(accum3, zero);
-
- *(reinterpret_cast<int*>(out_row[0])) = _mm_cvtsi128_si32(accum0);
- *(reinterpret_cast<int*>(out_row[1])) = _mm_cvtsi128_si32(accum1);
- *(reinterpret_cast<int*>(out_row[2])) = _mm_cvtsi128_si32(accum2);
- *(reinterpret_cast<int*>(out_row[3])) = _mm_cvtsi128_si32(accum3);
-
- out_row[0] += 4;
- out_row[1] += 4;
- out_row[2] += 4;
- out_row[3] += 4;
- }
+ accum0 = _mm_srai_epi32(accum0, SkConvolutionFilter1D::kShiftBits);
+ accum0 = _mm_packs_epi32(accum0, zero);
+ accum0 = _mm_packus_epi16(accum0, zero);
+ accum1 = _mm_srai_epi32(accum1, SkConvolutionFilter1D::kShiftBits);
+ accum1 = _mm_packs_epi32(accum1, zero);
+ accum1 = _mm_packus_epi16(accum1, zero);
+ accum2 = _mm_srai_epi32(accum2, SkConvolutionFilter1D::kShiftBits);
+ accum2 = _mm_packs_epi32(accum2, zero);
+ accum2 = _mm_packus_epi16(accum2, zero);
+ accum3 = _mm_srai_epi32(accum3, SkConvolutionFilter1D::kShiftBits);
+ accum3 = _mm_packs_epi32(accum3, zero);
+ accum3 = _mm_packus_epi16(accum3, zero);
+
+ *(reinterpret_cast<int*>(out_row[0])) = _mm_cvtsi128_si32(accum0);
+ *(reinterpret_cast<int*>(out_row[1])) = _mm_cvtsi128_si32(accum1);
+ *(reinterpret_cast<int*>(out_row[2])) = _mm_cvtsi128_si32(accum2);
+ *(reinterpret_cast<int*>(out_row[3])) = _mm_cvtsi128_si32(accum3);
+
+ out_row[0] += 4;
+ out_row[1] += 4;
+ out_row[2] += 4;
+ out_row[3] += 4;
+ }
}
// Does vertical convolution to produce one output row. The filter values and
@@ -438,166 +435,166 @@ void convolveVertically_SSE2(const SkConvolutionFilter1D::ConvolutionFixed* filt
unsigned char* const* source_data_rows,
int pixel_width,
unsigned char* out_row) {
- int width = pixel_width & ~3;
-
- __m128i zero = _mm_setzero_si128();
- __m128i accum0, accum1, accum2, accum3, coeff16;
- const __m128i* src;
- // Output four pixels per iteration (16 bytes).
- for (int out_x = 0; out_x < width; out_x += 4) {
-
- // Accumulated result for each pixel. 32 bits per RGBA channel.
- accum0 = _mm_setzero_si128();
- accum1 = _mm_setzero_si128();
- accum2 = _mm_setzero_si128();
- accum3 = _mm_setzero_si128();
-
- // Convolve with one filter coefficient per iteration.
- for (int filter_y = 0; filter_y < filter_length; filter_y++) {
-
- // Duplicate the filter coefficient 8 times.
- // [16] cj cj cj cj cj cj cj cj
- coeff16 = _mm_set1_epi16(filter_values[filter_y]);
-
- // Load four pixels (16 bytes) together.
- // [8] a3 b3 g3 r3 a2 b2 g2 r2 a1 b1 g1 r1 a0 b0 g0 r0
- src = reinterpret_cast<const __m128i*>(
- &source_data_rows[filter_y][out_x << 2]);
- __m128i src8 = _mm_loadu_si128(src);
-
- // Unpack 1st and 2nd pixels from 8 bits to 16 bits for each channels =>
- // multiply with current coefficient => accumulate the result.
- // [16] a1 b1 g1 r1 a0 b0 g0 r0
- __m128i src16 = _mm_unpacklo_epi8(src8, zero);
- __m128i mul_hi = _mm_mulhi_epi16(src16, coeff16);
- __m128i mul_lo = _mm_mullo_epi16(src16, coeff16);
- // [32] a0 b0 g0 r0
- __m128i t = _mm_unpacklo_epi16(mul_lo, mul_hi);
- accum0 = _mm_add_epi32(accum0, t);
- // [32] a1 b1 g1 r1
- t = _mm_unpackhi_epi16(mul_lo, mul_hi);
- accum1 = _mm_add_epi32(accum1, t);
-
- // Unpack 3rd and 4th pixels from 8 bits to 16 bits for each channels =>
- // multiply with current coefficient => accumulate the result.
- // [16] a3 b3 g3 r3 a2 b2 g2 r2
- src16 = _mm_unpackhi_epi8(src8, zero);
- mul_hi = _mm_mulhi_epi16(src16, coeff16);
- mul_lo = _mm_mullo_epi16(src16, coeff16);
- // [32] a2 b2 g2 r2
- t = _mm_unpacklo_epi16(mul_lo, mul_hi);
- accum2 = _mm_add_epi32(accum2, t);
- // [32] a3 b3 g3 r3
- t = _mm_unpackhi_epi16(mul_lo, mul_hi);
- accum3 = _mm_add_epi32(accum3, t);
- }
-
- // Shift right for fixed point implementation.
- accum0 = _mm_srai_epi32(accum0, SkConvolutionFilter1D::kShiftBits);
- accum1 = _mm_srai_epi32(accum1, SkConvolutionFilter1D::kShiftBits);
- accum2 = _mm_srai_epi32(accum2, SkConvolutionFilter1D::kShiftBits);
- accum3 = _mm_srai_epi32(accum3, SkConvolutionFilter1D::kShiftBits);
-
- // Packing 32 bits |accum| to 16 bits per channel (signed saturation).
- // [16] a1 b1 g1 r1 a0 b0 g0 r0
- accum0 = _mm_packs_epi32(accum0, accum1);
- // [16] a3 b3 g3 r3 a2 b2 g2 r2
- accum2 = _mm_packs_epi32(accum2, accum3);
+ int width = pixel_width & ~3;
+
+ __m128i zero = _mm_setzero_si128();
+ __m128i accum0, accum1, accum2, accum3, coeff16;
+ const __m128i* src;
+ // Output four pixels per iteration (16 bytes).
+ for (int out_x = 0; out_x < width; out_x += 4) {
+
+ // Accumulated result for each pixel. 32 bits per RGBA channel.
+ accum0 = _mm_setzero_si128();
+ accum1 = _mm_setzero_si128();
+ accum2 = _mm_setzero_si128();
+ accum3 = _mm_setzero_si128();
+
+ // Convolve with one filter coefficient per iteration.
+ for (int filter_y = 0; filter_y < filter_length; filter_y++) {
+
+ // Duplicate the filter coefficient 8 times.
+ // [16] cj cj cj cj cj cj cj cj
+ coeff16 = _mm_set1_epi16(filter_values[filter_y]);
+
+ // Load four pixels (16 bytes) together.
+ // [8] a3 b3 g3 r3 a2 b2 g2 r2 a1 b1 g1 r1 a0 b0 g0 r0
+ src = reinterpret_cast<const __m128i*>(
+ &source_data_rows[filter_y][out_x << 2]);
+ __m128i src8 = _mm_loadu_si128(src);
+
+ // Unpack 1st and 2nd pixels from 8 bits to 16 bits for each channels =>
+ // multiply with current coefficient => accumulate the result.
+ // [16] a1 b1 g1 r1 a0 b0 g0 r0
+ __m128i src16 = _mm_unpacklo_epi8(src8, zero);
+ __m128i mul_hi = _mm_mulhi_epi16(src16, coeff16);
+ __m128i mul_lo = _mm_mullo_epi16(src16, coeff16);
+ // [32] a0 b0 g0 r0
+ __m128i t = _mm_unpacklo_epi16(mul_lo, mul_hi);
+ accum0 = _mm_add_epi32(accum0, t);
+ // [32] a1 b1 g1 r1
+ t = _mm_unpackhi_epi16(mul_lo, mul_hi);
+ accum1 = _mm_add_epi32(accum1, t);
+
+ // Unpack 3rd and 4th pixels from 8 bits to 16 bits for each channels =>
+ // multiply with current coefficient => accumulate the result.
+ // [16] a3 b3 g3 r3 a2 b2 g2 r2
+ src16 = _mm_unpackhi_epi8(src8, zero);
+ mul_hi = _mm_mulhi_epi16(src16, coeff16);
+ mul_lo = _mm_mullo_epi16(src16, coeff16);
+ // [32] a2 b2 g2 r2
+ t = _mm_unpacklo_epi16(mul_lo, mul_hi);
+ accum2 = _mm_add_epi32(accum2, t);
+ // [32] a3 b3 g3 r3
+ t = _mm_unpackhi_epi16(mul_lo, mul_hi);
+ accum3 = _mm_add_epi32(accum3, t);
+ }
- // Packing 16 bits |accum| to 8 bits per channel (unsigned saturation).
- // [8] a3 b3 g3 r3 a2 b2 g2 r2 a1 b1 g1 r1 a0 b0 g0 r0
- accum0 = _mm_packus_epi16(accum0, accum2);
+ // Shift right for fixed point implementation.
+ accum0 = _mm_srai_epi32(accum0, SkConvolutionFilter1D::kShiftBits);
+ accum1 = _mm_srai_epi32(accum1, SkConvolutionFilter1D::kShiftBits);
+ accum2 = _mm_srai_epi32(accum2, SkConvolutionFilter1D::kShiftBits);
+ accum3 = _mm_srai_epi32(accum3, SkConvolutionFilter1D::kShiftBits);
+
+ // Packing 32 bits |accum| to 16 bits per channel (signed saturation).
+ // [16] a1 b1 g1 r1 a0 b0 g0 r0
+ accum0 = _mm_packs_epi32(accum0, accum1);
+ // [16] a3 b3 g3 r3 a2 b2 g2 r2
+ accum2 = _mm_packs_epi32(accum2, accum3);
+
+ // Packing 16 bits |accum| to 8 bits per channel (unsigned saturation).
+ // [8] a3 b3 g3 r3 a2 b2 g2 r2 a1 b1 g1 r1 a0 b0 g0 r0
+ accum0 = _mm_packus_epi16(accum0, accum2);
+
+ if (has_alpha) {
+ // Compute the max(ri, gi, bi) for each pixel.
+ // [8] xx a3 b3 g3 xx a2 b2 g2 xx a1 b1 g1 xx a0 b0 g0
+ __m128i a = _mm_srli_epi32(accum0, 8);
+ // [8] xx xx xx max3 xx xx xx max2 xx xx xx max1 xx xx xx max0
+ __m128i b = _mm_max_epu8(a, accum0); // Max of r and g.
+ // [8] xx xx a3 b3 xx xx a2 b2 xx xx a1 b1 xx xx a0 b0
+ a = _mm_srli_epi32(accum0, 16);
+ // [8] xx xx xx max3 xx xx xx max2 xx xx xx max1 xx xx xx max0
+ b = _mm_max_epu8(a, b); // Max of r and g and b.
+ // [8] max3 00 00 00 max2 00 00 00 max1 00 00 00 max0 00 00 00
+ b = _mm_slli_epi32(b, 24);
+
+ // Make sure the value of alpha channel is always larger than maximum
+ // value of color channels.
+ accum0 = _mm_max_epu8(b, accum0);
+ } else {
+ // Set value of alpha channels to 0xFF.
+ __m128i mask = _mm_set1_epi32(0xff000000);
+ accum0 = _mm_or_si128(accum0, mask);
+ }
- if (has_alpha) {
- // Compute the max(ri, gi, bi) for each pixel.
- // [8] xx a3 b3 g3 xx a2 b2 g2 xx a1 b1 g1 xx a0 b0 g0
- __m128i a = _mm_srli_epi32(accum0, 8);
- // [8] xx xx xx max3 xx xx xx max2 xx xx xx max1 xx xx xx max0
- __m128i b = _mm_max_epu8(a, accum0); // Max of r and g.
- // [8] xx xx a3 b3 xx xx a2 b2 xx xx a1 b1 xx xx a0 b0
- a = _mm_srli_epi32(accum0, 16);
- // [8] xx xx xx max3 xx xx xx max2 xx xx xx max1 xx xx xx max0
- b = _mm_max_epu8(a, b); // Max of r and g and b.
- // [8] max3 00 00 00 max2 00 00 00 max1 00 00 00 max0 00 00 00
- b = _mm_slli_epi32(b, 24);
-
- // Make sure the value of alpha channel is always larger than maximum
- // value of color channels.
- accum0 = _mm_max_epu8(b, accum0);
- } else {
- // Set value of alpha channels to 0xFF.
- __m128i mask = _mm_set1_epi32(0xff000000);
- accum0 = _mm_or_si128(accum0, mask);
+ // Store the convolution result (16 bytes) and advance the pixel pointers.
+ _mm_storeu_si128(reinterpret_cast<__m128i*>(out_row), accum0);
+ out_row += 16;
}
- // Store the convolution result (16 bytes) and advance the pixel pointers.
- _mm_storeu_si128(reinterpret_cast<__m128i*>(out_row), accum0);
- out_row += 16;
- }
-
- // When the width of the output is not divisible by 4, We need to save one
- // pixel (4 bytes) each time. And also the fourth pixel is always absent.
- if (pixel_width & 3) {
- accum0 = _mm_setzero_si128();
- accum1 = _mm_setzero_si128();
- accum2 = _mm_setzero_si128();
- for (int filter_y = 0; filter_y < filter_length; ++filter_y) {
- coeff16 = _mm_set1_epi16(filter_values[filter_y]);
- // [8] a3 b3 g3 r3 a2 b2 g2 r2 a1 b1 g1 r1 a0 b0 g0 r0
- src = reinterpret_cast<const __m128i*>(
- &source_data_rows[filter_y][width<<2]);
- __m128i src8 = _mm_loadu_si128(src);
- // [16] a1 b1 g1 r1 a0 b0 g0 r0
- __m128i src16 = _mm_unpacklo_epi8(src8, zero);
- __m128i mul_hi = _mm_mulhi_epi16(src16, coeff16);
- __m128i mul_lo = _mm_mullo_epi16(src16, coeff16);
- // [32] a0 b0 g0 r0
- __m128i t = _mm_unpacklo_epi16(mul_lo, mul_hi);
- accum0 = _mm_add_epi32(accum0, t);
- // [32] a1 b1 g1 r1
- t = _mm_unpackhi_epi16(mul_lo, mul_hi);
- accum1 = _mm_add_epi32(accum1, t);
- // [16] a3 b3 g3 r3 a2 b2 g2 r2
- src16 = _mm_unpackhi_epi8(src8, zero);
- mul_hi = _mm_mulhi_epi16(src16, coeff16);
- mul_lo = _mm_mullo_epi16(src16, coeff16);
- // [32] a2 b2 g2 r2
- t = _mm_unpacklo_epi16(mul_lo, mul_hi);
- accum2 = _mm_add_epi32(accum2, t);
- }
+ // When the width of the output is not divisible by 4, We need to save one
+ // pixel (4 bytes) each time. And also the fourth pixel is always absent.
+ if (pixel_width & 3) {
+ accum0 = _mm_setzero_si128();
+ accum1 = _mm_setzero_si128();
+ accum2 = _mm_setzero_si128();
+ for (int filter_y = 0; filter_y < filter_length; ++filter_y) {
+ coeff16 = _mm_set1_epi16(filter_values[filter_y]);
+ // [8] a3 b3 g3 r3 a2 b2 g2 r2 a1 b1 g1 r1 a0 b0 g0 r0
+ src = reinterpret_cast<const __m128i*>(
+ &source_data_rows[filter_y][width<<2]);
+ __m128i src8 = _mm_loadu_si128(src);
+ // [16] a1 b1 g1 r1 a0 b0 g0 r0
+ __m128i src16 = _mm_unpacklo_epi8(src8, zero);
+ __m128i mul_hi = _mm_mulhi_epi16(src16, coeff16);
+ __m128i mul_lo = _mm_mullo_epi16(src16, coeff16);
+ // [32] a0 b0 g0 r0
+ __m128i t = _mm_unpacklo_epi16(mul_lo, mul_hi);
+ accum0 = _mm_add_epi32(accum0, t);
+ // [32] a1 b1 g1 r1
+ t = _mm_unpackhi_epi16(mul_lo, mul_hi);
+ accum1 = _mm_add_epi32(accum1, t);
+ // [16] a3 b3 g3 r3 a2 b2 g2 r2
+ src16 = _mm_unpackhi_epi8(src8, zero);
+ mul_hi = _mm_mulhi_epi16(src16, coeff16);
+ mul_lo = _mm_mullo_epi16(src16, coeff16);
+ // [32] a2 b2 g2 r2
+ t = _mm_unpacklo_epi16(mul_lo, mul_hi);
+ accum2 = _mm_add_epi32(accum2, t);
+ }
- accum0 = _mm_srai_epi32(accum0, SkConvolutionFilter1D::kShiftBits);
- accum1 = _mm_srai_epi32(accum1, SkConvolutionFilter1D::kShiftBits);
- accum2 = _mm_srai_epi32(accum2, SkConvolutionFilter1D::kShiftBits);
- // [16] a1 b1 g1 r1 a0 b0 g0 r0
- accum0 = _mm_packs_epi32(accum0, accum1);
- // [16] a3 b3 g3 r3 a2 b2 g2 r2
- accum2 = _mm_packs_epi32(accum2, zero);
- // [8] a3 b3 g3 r3 a2 b2 g2 r2 a1 b1 g1 r1 a0 b0 g0 r0
- accum0 = _mm_packus_epi16(accum0, accum2);
- if (has_alpha) {
- // [8] xx a3 b3 g3 xx a2 b2 g2 xx a1 b1 g1 xx a0 b0 g0
- __m128i a = _mm_srli_epi32(accum0, 8);
- // [8] xx xx xx max3 xx xx xx max2 xx xx xx max1 xx xx xx max0
- __m128i b = _mm_max_epu8(a, accum0); // Max of r and g.
- // [8] xx xx a3 b3 xx xx a2 b2 xx xx a1 b1 xx xx a0 b0
- a = _mm_srli_epi32(accum0, 16);
- // [8] xx xx xx max3 xx xx xx max2 xx xx xx max1 xx xx xx max0
- b = _mm_max_epu8(a, b); // Max of r and g and b.
- // [8] max3 00 00 00 max2 00 00 00 max1 00 00 00 max0 00 00 00
- b = _mm_slli_epi32(b, 24);
- accum0 = _mm_max_epu8(b, accum0);
- } else {
- __m128i mask = _mm_set1_epi32(0xff000000);
- accum0 = _mm_or_si128(accum0, mask);
- }
+ accum0 = _mm_srai_epi32(accum0, SkConvolutionFilter1D::kShiftBits);
+ accum1 = _mm_srai_epi32(accum1, SkConvolutionFilter1D::kShiftBits);
+ accum2 = _mm_srai_epi32(accum2, SkConvolutionFilter1D::kShiftBits);
+ // [16] a1 b1 g1 r1 a0 b0 g0 r0
+ accum0 = _mm_packs_epi32(accum0, accum1);
+ // [16] a3 b3 g3 r3 a2 b2 g2 r2
+ accum2 = _mm_packs_epi32(accum2, zero);
+ // [8] a3 b3 g3 r3 a2 b2 g2 r2 a1 b1 g1 r1 a0 b0 g0 r0
+ accum0 = _mm_packus_epi16(accum0, accum2);
+ if (has_alpha) {
+ // [8] xx a3 b3 g3 xx a2 b2 g2 xx a1 b1 g1 xx a0 b0 g0
+ __m128i a = _mm_srli_epi32(accum0, 8);
+ // [8] xx xx xx max3 xx xx xx max2 xx xx xx max1 xx xx xx max0
+ __m128i b = _mm_max_epu8(a, accum0); // Max of r and g.
+ // [8] xx xx a3 b3 xx xx a2 b2 xx xx a1 b1 xx xx a0 b0
+ a = _mm_srli_epi32(accum0, 16);
+ // [8] xx xx xx max3 xx xx xx max2 xx xx xx max1 xx xx xx max0
+ b = _mm_max_epu8(a, b); // Max of r and g and b.
+ // [8] max3 00 00 00 max2 00 00 00 max1 00 00 00 max0 00 00 00
+ b = _mm_slli_epi32(b, 24);
+ accum0 = _mm_max_epu8(b, accum0);
+ } else {
+ __m128i mask = _mm_set1_epi32(0xff000000);
+ accum0 = _mm_or_si128(accum0, mask);
+ }
- for (int out_x = width; out_x < pixel_width; out_x++) {
- *(reinterpret_cast<int*>(out_row)) = _mm_cvtsi128_si32(accum0);
- accum0 = _mm_srli_si128(accum0, 4);
- out_row += 4;
+ for (int out_x = width; out_x < pixel_width; out_x++) {
+ *(reinterpret_cast<int*>(out_row)) = _mm_cvtsi128_si32(accum0);
+ accum0 = _mm_srli_si128(accum0, 4);
+ out_row += 4;
+ }
}
- }
}
void convolveVertically_SSE2(const SkConvolutionFilter1D::ConvolutionFixed* filter_values,
@@ -606,19 +603,19 @@ void convolveVertically_SSE2(const SkConvolutionFilter1D::ConvolutionFixed* filt
int pixel_width,
unsigned char* out_row,
bool has_alpha) {
- if (has_alpha) {
- convolveVertically_SSE2<true>(filter_values,
- filter_length,
- source_data_rows,
- pixel_width,
- out_row);
- } else {
- convolveVertically_SSE2<false>(filter_values,
- filter_length,
- source_data_rows,
- pixel_width,
- out_row);
- }
+ if (has_alpha) {
+ convolveVertically_SSE2<true>(filter_values,
+ filter_length,
+ source_data_rows,
+ pixel_width,
+ out_row);
+ } else {
+ convolveVertically_SSE2<false>(filter_values,
+ filter_length,
+ source_data_rows,
+ pixel_width,
+ out_row);
+ }
}
void applySIMDPadding_SSE2(SkConvolutionFilter1D *filter) {
diff --git a/chromium/third_party/skia/src/opts/SkBitmapFilter_opts_SSE2.h b/chromium/third_party/skia/src/opts/SkBitmapFilter_opts_SSE2.h
index 588f4ef18bb..661a824e227 100644
--- a/chromium/third_party/skia/src/opts/SkBitmapFilter_opts_SSE2.h
+++ b/chromium/third_party/skia/src/opts/SkBitmapFilter_opts_SSE2.h
@@ -1,4 +1,3 @@
-
/*
* Copyright 2013 Google Inc.
*
@@ -6,7 +5,6 @@
* found in the LICENSE file.
*/
-
#ifndef SkBitmapFilter_opts_sse2_DEFINED
#define SkBitmapFilter_opts_sse2_DEFINED
@@ -14,9 +12,9 @@
#include "SkConvolver.h"
void highQualityFilter_ScaleOnly_SSE2(const SkBitmapProcState &s, int x, int y,
- SkPMColor *SK_RESTRICT colors, int count);
+ SkPMColor *SK_RESTRICT colors, int count);
void highQualityFilter_SSE2(const SkBitmapProcState &s, int x, int y,
- SkPMColor *SK_RESTRICT colors, int count);
+ SkPMColor *SK_RESTRICT colors, int count);
void convolveVertically_SSE2(const SkConvolutionFilter1D::ConvolutionFixed* filter_values,
diff --git a/chromium/third_party/skia/src/opts/SkBitmapProcState_filter_neon.h b/chromium/third_party/skia/src/opts/SkBitmapProcState_filter_neon.h
index e56b683b874..0887145c3d0 100644
--- a/chromium/third_party/skia/src/opts/SkBitmapProcState_filter_neon.h
+++ b/chromium/third_party/skia/src/opts/SkBitmapProcState_filter_neon.h
@@ -17,12 +17,15 @@
* exact results for the color components, but if the 4 incoming colors are
* all opaque, then the output color must also be opaque. Subsequent parts of
* the drawing pipeline may rely on this (e.g. which blitrow proc to use).
+ *
*/
-
-static inline void Filter_32_opaque_neon(unsigned x, unsigned y,
- SkPMColor a00, SkPMColor a01,
- SkPMColor a10, SkPMColor a11,
- SkPMColor *dst) {
+// Chrome on Android uses -Os so we need to force these inline. Otherwise
+// calling the function in the inner loops will cause significant overhead on
+// some platforms.
+static SK_ALWAYS_INLINE void Filter_32_opaque_neon(unsigned x, unsigned y,
+ SkPMColor a00, SkPMColor a01,
+ SkPMColor a10, SkPMColor a11,
+ SkPMColor *dst) {
uint8x8_t vy, vconst16_8, v16_y, vres;
uint16x4_t vx, vconst16_16, v16_x, tmp;
uint32x2_t va0, va1;
@@ -53,10 +56,11 @@ static inline void Filter_32_opaque_neon(unsigned x, unsigned y,
vst1_lane_u32(dst, vreinterpret_u32_u8(vres), 0); // store result
}
-static inline void Filter_32_alpha_neon(unsigned x, unsigned y,
- SkPMColor a00, SkPMColor a01,
- SkPMColor a10, SkPMColor a11,
- SkPMColor *dst, uint16_t scale) {
+static SK_ALWAYS_INLINE void Filter_32_alpha_neon(unsigned x, unsigned y,
+ SkPMColor a00, SkPMColor a01,
+ SkPMColor a10, SkPMColor a11,
+ SkPMColor *dst,
+ uint16_t scale) {
uint8x8_t vy, vconst16_8, v16_y, vres;
uint16x4_t vx, vconst16_16, v16_x, tmp, vscale;
uint32x2_t va0, va1;
diff --git a/chromium/third_party/skia/src/opts/SkBitmapProcState_matrixProcs_neon.cpp b/chromium/third_party/skia/src/opts/SkBitmapProcState_matrixProcs_neon.cpp
index e81da670526..7789031c028 100644
--- a/chromium/third_party/skia/src/opts/SkBitmapProcState_matrixProcs_neon.cpp
+++ b/chromium/third_party/skia/src/opts/SkBitmapProcState_matrixProcs_neon.cpp
@@ -10,26 +10,140 @@
#include "SkUtilsArm.h"
#include "SkBitmapProcState_utils.h"
+#include <arm_neon.h>
+
extern const SkBitmapProcState::MatrixProc ClampX_ClampY_Procs_neon[];
extern const SkBitmapProcState::MatrixProc RepeatX_RepeatY_Procs_neon[];
static void decal_nofilter_scale_neon(uint32_t dst[], SkFixed fx, SkFixed dx, int count);
static void decal_filter_scale_neon(uint32_t dst[], SkFixed fx, SkFixed dx, int count);
-#define MAKENAME(suffix) ClampX_ClampY ## suffix ## _neon
-#define TILEX_PROCF(fx, max) SkClampMax((fx) >> 16, max)
-#define TILEY_PROCF(fy, max) SkClampMax((fy) >> 16, max)
-#define TILEX_LOW_BITS(fx, max) (((fx) >> 12) & 0xF)
-#define TILEY_LOW_BITS(fy, max) (((fy) >> 12) & 0xF)
+// TILEX_PROCF(fx, max) SkClampMax((fx) >> 16, max)
+static inline int16x8_t sbpsm_clamp_tile8(int32x4_t low, int32x4_t high, unsigned max) {
+ int16x8_t res;
+
+ // get the hi 16s of all those 32s
+ res = vuzpq_s16(vreinterpretq_s16_s32(low), vreinterpretq_s16_s32(high)).val[1];
+
+ // clamp
+ res = vmaxq_s16(res, vdupq_n_s16(0));
+ res = vminq_s16(res, vdupq_n_s16(max));
+
+ return res;
+}
+
+// TILEX_PROCF(fx, max) SkClampMax((fx) >> 16, max)
+static inline int32x4_t sbpsm_clamp_tile4(int32x4_t f, unsigned max) {
+ int32x4_t res;
+
+ // get the hi 16s of all those 32s
+ res = vshrq_n_s32(f, 16);
+
+ // clamp
+ res = vmaxq_s32(res, vdupq_n_s32(0));
+ res = vminq_s32(res, vdupq_n_s32(max));
+
+ return res;
+}
+
+// TILEY_LOW_BITS(fy, max) (((fy) >> 12) & 0xF)
+static inline int32x4_t sbpsm_clamp_tile4_low_bits(int32x4_t fx) {
+ int32x4_t ret;
+
+ ret = vshrq_n_s32(fx, 12);
+
+ /* We don't need the mask below because the caller will
+ * overwrite the non-masked bits
+ */
+ //ret = vandq_s32(ret, vdupq_n_s32(0xF));
+
+ return ret;
+}
+
+// TILEX_PROCF(fx, max) (((fx)&0xFFFF)*((max)+1)>> 16)
+static inline int16x8_t sbpsm_repeat_tile8(int32x4_t low, int32x4_t high, unsigned max) {
+ uint16x8_t res;
+ uint32x4_t tmpl, tmph;
+
+ // get the lower 16 bits
+ res = vuzpq_u16(vreinterpretq_u16_s32(low), vreinterpretq_u16_s32(high)).val[0];
+
+ // bare multiplication, not SkFixedMul
+ tmpl = vmull_u16(vget_low_u16(res), vdup_n_u16(max+1));
+ tmph = vmull_u16(vget_high_u16(res), vdup_n_u16(max+1));
+
+ // extraction of the 16 upper bits
+ res = vuzpq_u16(vreinterpretq_u16_u32(tmpl), vreinterpretq_u16_u32(tmph)).val[1];
+
+ return vreinterpretq_s16_u16(res);
+}
+
+// TILEX_PROCF(fx, max) (((fx)&0xFFFF)*((max)+1)>> 16)
+static inline int32x4_t sbpsm_repeat_tile4(int32x4_t f, unsigned max) {
+ uint16x4_t res;
+ uint32x4_t tmp;
+
+ // get the lower 16 bits
+ res = vmovn_u32(vreinterpretq_u32_s32(f));
+
+ // bare multiplication, not SkFixedMul
+ tmp = vmull_u16(res, vdup_n_u16(max+1));
+
+ // extraction of the 16 upper bits
+ tmp = vshrq_n_u32(tmp, 16);
+
+ return vreinterpretq_s32_u32(tmp);
+}
+
+// TILEX_LOW_BITS(fx, max) ((((fx) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
+static inline int32x4_t sbpsm_repeat_tile4_low_bits(int32x4_t fx, unsigned max) {
+ uint16x4_t res;
+ uint32x4_t tmp;
+ int32x4_t ret;
+
+ // get the lower 16 bits
+ res = vmovn_u32(vreinterpretq_u32_s32(fx));
+
+ // bare multiplication, not SkFixedMul
+ tmp = vmull_u16(res, vdup_n_u16(max + 1));
+
+ // shift and mask
+ ret = vshrq_n_s32(vreinterpretq_s32_u32(tmp), 12);
+
+ /* We don't need the mask below because the caller will
+ * overwrite the non-masked bits
+ */
+ //ret = vandq_s32(ret, vdupq_n_s32(0xF));
+
+ return ret;
+}
+
+#define MAKENAME(suffix) ClampX_ClampY ## suffix ## _neon
+#define TILEX_PROCF(fx, max) SkClampMax((fx) >> 16, max)
+#define TILEY_PROCF(fy, max) SkClampMax((fy) >> 16, max)
+#define TILEX_PROCF_NEON8(l, h, max) sbpsm_clamp_tile8(l, h, max)
+#define TILEY_PROCF_NEON8(l, h, max) sbpsm_clamp_tile8(l, h, max)
+#define TILEX_PROCF_NEON4(fx, max) sbpsm_clamp_tile4(fx, max)
+#define TILEY_PROCF_NEON4(fy, max) sbpsm_clamp_tile4(fy, max)
+#define TILEX_LOW_BITS(fx, max) (((fx) >> 12) & 0xF)
+#define TILEY_LOW_BITS(fy, max) (((fy) >> 12) & 0xF)
+#define TILEX_LOW_BITS_NEON4(fx, max) sbpsm_clamp_tile4_low_bits(fx)
+#define TILEY_LOW_BITS_NEON4(fy, max) sbpsm_clamp_tile4_low_bits(fy)
#define CHECK_FOR_DECAL
-#include "SkBitmapProcState_matrix_clamp_neon.h"
-
-#define MAKENAME(suffix) RepeatX_RepeatY ## suffix ## _neon
-#define TILEX_PROCF(fx, max) SK_USHIFT16(((fx) & 0xFFFF) * ((max) + 1))
-#define TILEY_PROCF(fy, max) SK_USHIFT16(((fy) & 0xFFFF) * ((max) + 1))
-#define TILEX_LOW_BITS(fx, max) ((((fx) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
-#define TILEY_LOW_BITS(fy, max) ((((fy) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
-#include "SkBitmapProcState_matrix_repeat_neon.h"
+#include "SkBitmapProcState_matrix_neon.h"
+
+#define MAKENAME(suffix) RepeatX_RepeatY ## suffix ## _neon
+#define TILEX_PROCF(fx, max) SK_USHIFT16(((fx) & 0xFFFF) * ((max) + 1))
+#define TILEY_PROCF(fy, max) SK_USHIFT16(((fy) & 0xFFFF) * ((max) + 1))
+#define TILEX_PROCF_NEON8(l, h, max) sbpsm_repeat_tile8(l, h, max)
+#define TILEY_PROCF_NEON8(l, h, max) sbpsm_repeat_tile8(l, h, max)
+#define TILEX_PROCF_NEON4(fx, max) sbpsm_repeat_tile4(fx, max)
+#define TILEY_PROCF_NEON4(fy, max) sbpsm_repeat_tile4(fy, max)
+#define TILEX_LOW_BITS(fx, max) ((((fx) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
+#define TILEY_LOW_BITS(fy, max) ((((fy) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
+#define TILEX_LOW_BITS_NEON4(fx, max) sbpsm_repeat_tile4_low_bits(fx, max)
+#define TILEY_LOW_BITS_NEON4(fy, max) sbpsm_repeat_tile4_low_bits(fy, max)
+#include "SkBitmapProcState_matrix_neon.h"
diff --git a/chromium/third_party/skia/src/opts/SkBitmapProcState_matrix_clamp_neon.h b/chromium/third_party/skia/src/opts/SkBitmapProcState_matrix_clamp_neon.h
deleted file mode 100644
index a615e26b240..00000000000
--- a/chromium/third_party/skia/src/opts/SkBitmapProcState_matrix_clamp_neon.h
+++ /dev/null
@@ -1,911 +0,0 @@
-/* NEON optimized code (C) COPYRIGHT 2009 Motorola
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/*
- * Modifications done in-house at Motorola
- *
- * this is a clone of SkBitmapProcState_matrix.h
- * and has been tuned to work with the NEON unit.
- *
- * Still going back and forth between whether this approach
- * (clone the entire SkBitmapProcState_matrix.h file or
- * if I should put just the modified routines in here and
- * then use a construct like #define DONT_DO_THIS_FUNCTION or
- * something like that...
- *
- * This is for the ClampX_ClampY instance
- *
- */
-
-
-#include <arm_neon.h>
-
-/*
- * This has been modified on the knowledge that (at the time)
- * we had the following macro definitions in the parent file
- *
- * #define MAKENAME(suffix) ClampX_ClampY ## suffix
- * #define TILEX_PROCF(fx, max) SkClampMax((fx) >> 16, max)
- * #define TILEY_PROCF(fy, max) SkClampMax((fy) >> 16, max)
- * #define TILEX_LOW_BITS(fx, max) (((fx) >> 12) & 0xF)
- * #define TILEY_LOW_BITS(fy, max) (((fy) >> 12) & 0xF)
- * #define CHECK_FOR_DECAL
- */
-
-/* SkClampMax(val,max) -- bound to 0..max */
-
-#define SCALE_NOFILTER_NAME MAKENAME(_nofilter_scale)
-#define SCALE_FILTER_NAME MAKENAME(_filter_scale)
-#define AFFINE_NOFILTER_NAME MAKENAME(_nofilter_affine)
-#define AFFINE_FILTER_NAME MAKENAME(_filter_affine)
-#define PERSP_NOFILTER_NAME MAKENAME(_nofilter_persp)
-#define PERSP_FILTER_NAME MAKENAME(_filter_persp)
-
-#define PACK_FILTER_X_NAME MAKENAME(_pack_filter_x)
-#define PACK_FILTER_Y_NAME MAKENAME(_pack_filter_y)
-
-#ifndef PREAMBLE
- #define PREAMBLE(state)
- #define PREAMBLE_PARAM_X
- #define PREAMBLE_PARAM_Y
- #define PREAMBLE_ARG_X
- #define PREAMBLE_ARG_Y
-#endif
-
-static void SCALE_NOFILTER_NAME(const SkBitmapProcState& s,
- uint32_t xy[], int count, int x, int y) {
- SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
- SkMatrix::kScale_Mask)) == 0);
-
- PREAMBLE(s);
- // we store y, x, x, x, x, x
-
- const unsigned maxX = s.fBitmap->width() - 1;
- SkFixed fx;
- {
- SkPoint pt;
- s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, &pt);
- fx = SkScalarToFixed(pt.fY);
- const unsigned maxY = s.fBitmap->height() - 1;
- *xy++ = TILEY_PROCF(fx, maxY);
- fx = SkScalarToFixed(pt.fX);
- }
-
- if (0 == maxX) {
- // all of the following X values must be 0
- memset(xy, 0, count * sizeof(uint16_t));
- return;
- }
-
- const SkFixed dx = s.fInvSx;
-
-#ifdef CHECK_FOR_DECAL
- // test if we don't need to apply the tile proc
- if ((unsigned)(fx >> 16) <= maxX &&
- (unsigned)((fx + dx * (count - 1)) >> 16) <= maxX) {
- decal_nofilter_scale_neon(xy, fx, dx, count);
- return;
- }
-#endif
-
- int i;
-
- /* very much like done in decal_nofilter, but with
- * an extra clamping function applied.
- * TILEX_PROCF(fx,max) SkClampMax((fx)>>16, max)
- */
- if (count >= 8) {
- /* SkFixed is 16.16 fixed point */
- SkFixed dx2 = dx+dx;
- SkFixed dx4 = dx2+dx2;
- SkFixed dx8 = dx4+dx4;
-
- /* now build fx/fx+dx/fx+2dx/fx+3dx */
- SkFixed fx1, fx2, fx3;
- int32x4_t lbase, hbase;
- int16_t *dst16 = (int16_t *)xy;
-
- fx1 = fx+dx;
- fx2 = fx1+dx;
- fx3 = fx2+dx;
-
- /* build my template(s) */
- /* avoid the 'lbase unitialized' warning */
- lbase = vdupq_n_s32(fx);
- lbase = vsetq_lane_s32(fx1, lbase, 1);
- lbase = vsetq_lane_s32(fx2, lbase, 2);
- lbase = vsetq_lane_s32(fx3, lbase, 3);
-
- hbase = vaddq_s32(lbase, vdupq_n_s32(dx4));
-
- /* store & bump */
- do {
- int32x4_t lout;
- int32x4_t hout;
- int16x8_t hi16;
-
- /* get the hi 16s of all those 32s */
- lout = lbase;
- hout = hbase;
- /* this sets up all lout's then all hout's in hout */
- asm ("vuzpq.16 %q0, %q1" : "+w" (lout), "+w" (hout));
- hi16 = vreinterpretq_s16_s32(hout);
-
- /* clamp & output */
- hi16 = vmaxq_s16(hi16, vdupq_n_s16(0));
- hi16 = vminq_s16(hi16, vdupq_n_s16(maxX));
- vst1q_s16(dst16, hi16);
-
- /* but preserving base & on to the next */
- lbase = vaddq_s32 (lbase, vdupq_n_s32(dx8));
- hbase = vaddq_s32 (hbase, vdupq_n_s32(dx8));
- dst16 += 8;
- count -= 8;
- fx += dx8;
- } while (count >= 8);
- xy = (uint32_t *) dst16;
- }
-
- uint16_t* xx = (uint16_t*)xy;
- for (i = count; i > 0; --i) {
- *xx++ = TILEX_PROCF(fx, maxX); fx += dx;
- }
-}
-
-// note: we could special-case on a matrix which is skewed in X but not Y.
-// this would require a more general setup thatn SCALE does, but could use
-// SCALE's inner loop that only looks at dx
-
-static void AFFINE_NOFILTER_NAME(const SkBitmapProcState& s,
- uint32_t xy[], int count, int x, int y) {
- SkASSERT(s.fInvType & SkMatrix::kAffine_Mask);
- SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
- SkMatrix::kScale_Mask |
- SkMatrix::kAffine_Mask)) == 0);
-
- PREAMBLE(s);
- SkPoint srcPt;
- s.fInvProc(s.fInvMatrix,
- SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
-
- SkFixed fx = SkScalarToFixed(srcPt.fX);
- SkFixed fy = SkScalarToFixed(srcPt.fY);
- SkFixed dx = s.fInvSx;
- SkFixed dy = s.fInvKy;
- int maxX = s.fBitmap->width() - 1;
- int maxY = s.fBitmap->height() - 1;
-
- /* NEON lets us do an 8x unrolling */
- if (count >= 8) {
- /* SkFixed is 16.16 fixed point */
- SkFixed dx4 = dx * 4;
- SkFixed dy4 = dy * 4;
- SkFixed dx8 = dx * 8;
- SkFixed dy8 = dy * 8;
-
- int32x4_t xbase, ybase;
- int32x4_t x2base, y2base;
- int16_t *dst16 = (int16_t *) xy;
-
- /* my sets of maxx/maxy for clamping */
- int32_t maxpair = (maxX&0xffff) | ((maxY&0xffff)<<16);
- int16x8_t maxXY = vreinterpretq_s16_s32(vdupq_n_s32(maxpair));
-
- /* now build fx/fx+dx/fx+2dx/fx+3dx */
- /* avoid the 'xbase unitialized' warning...*/
- xbase = vdupq_n_s32(fx);
- xbase = vsetq_lane_s32(fx+dx, xbase, 1);
- xbase = vsetq_lane_s32(fx+dx+dx, xbase, 2);
- xbase = vsetq_lane_s32(fx+dx+dx+dx, xbase, 3);
-
- /* same for fy */
- /* avoid the 'ybase unitialized' warning...*/
- ybase = vdupq_n_s32(fy);
- ybase = vsetq_lane_s32(fy+dy, ybase, 1);
- ybase = vsetq_lane_s32(fy+dy+dy, ybase, 2);
- ybase = vsetq_lane_s32(fy+dy+dy+dy, ybase, 3);
-
- x2base = vaddq_s32(xbase, vdupq_n_s32(dx4));
- y2base = vaddq_s32(ybase, vdupq_n_s32(dy4));
-
- /* store & bump */
- do {
- int32x4_t xout, yout;
- int32x4_t x2out, y2out;
- int16x8_t hi16, hi16_2;
-
- xout = xbase;
- yout = ybase;
-
- /* overlay y's low16 with hi16 from x */
- /* so we properly shifted xyxyxyxy */
- yout = vsriq_n_s32(yout, xout, 16);
- hi16 = vreinterpretq_s16_s32 (yout);
-
- /* do the clamping; both guys get 0's */
- hi16 = vmaxq_s16 (hi16, vdupq_n_s16(0));
- hi16 = vminq_s16 (hi16, maxXY);
-
- vst1q_s16 (dst16, hi16);
-
- /* and for the other 4 pieces of this iteration */
- x2out = x2base;
- y2out = y2base;
-
- /* overlay y's low16 with hi16 from x */
- /* so we properly shifted xyxyxyxy */
- y2out = vsriq_n_s32(y2out, x2out, 16);
- hi16_2 = vreinterpretq_s16_s32 (y2out);
-
- /* do the clamping; both guys get 0's */
- hi16_2 = vmaxq_s16 (hi16_2, vdupq_n_s16(0));
- hi16_2 = vminq_s16 (hi16_2, maxXY);
-
- /* RBE: gcc regenerates dst16+8 all the time instead
- * of folding it into an addressing mode. *sigh* */
- vst1q_s16 (dst16+8, hi16_2);
-
- /* moving base and on to the next */
- xbase = vaddq_s32 (xbase, vdupq_n_s32 (dx8));
- ybase = vaddq_s32 (ybase, vdupq_n_s32 (dy8));
- x2base = vaddq_s32 (x2base, vdupq_n_s32 (dx8));
- y2base = vaddq_s32 (y2base, vdupq_n_s32 (dy8));
-
- dst16 += 16; /* 8x32 aka 16x16 */
- count -= 8;
- fx += dx8;
- fy += dy8;
- } while (count >= 8);
- xy = (uint32_t *) dst16;
- }
-
- for (int i = count; i > 0; --i) {
- *xy++ = (TILEY_PROCF(fy, maxY) << 16) | TILEX_PROCF(fx, maxX);
- fx += dx; fy += dy;
- }
-}
-
-#undef DEBUG_PERSP_NOFILTER
-
-static void PERSP_NOFILTER_NAME(const SkBitmapProcState& s,
- uint32_t* SK_RESTRICT xy,
- int count, int x, int y) {
- SkASSERT(s.fInvType & SkMatrix::kPerspective_Mask);
-
- PREAMBLE(s);
- /* max{X,Y} are int here, but later shown/assumed to fit in 16 bits */
- int maxX = s.fBitmap->width() - 1;
- int maxY = s.fBitmap->height() - 1;
-
- SkPerspIter iter(s.fInvMatrix,
- SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, count);
-
- while ((count = iter.next()) != 0) {
- const SkFixed* SK_RESTRICT srcXY = iter.getXY();
-
-#if defined(DEBUG_PERSP_NOFILTER)
- /* debugging stuff */
- const SkFixed *end_srcXY = srcXY + (count*2);
- uint32_t *end_xy = xy + (count);
- const SkFixed *base_srcXY = srcXY;
- uint32_t *base_xy = xy;
- int base_count = count;
-#endif
-
-#if 1
- // 2009/9/30: crashes in ApiDemos - Views - Animation - 3D Transition
- // 2009/10/9: reworked to avoid illegal (but allowed by gas) insn
-
- /* srcXY is a batch of 32 bit numbers X0,Y0,X1,Y1...
- * but we immediately discard the low 16 bits...
- * so what we're going to do is vld4, which will give us
- * xlo,xhi,ylo,yhi distribution and we can ignore the 'lo'
- * parts....
- */
- if (count >= 8) {
- int16_t *mysrc = (int16_t *) srcXY;
- int16_t *mydst = (int16_t *) xy;
- int16x4_t maxX4 = vdup_n_s16((int16_t)maxX);
- int16x4_t maxY4 = vdup_n_s16((int16_t)maxY);
- int16x4_t zero4 = vdup_n_s16(0);
-
- /* The constructs with local blocks for register assignments
- * and asm() instructions is to make keep any hard register
- * assignments to as small a scope as possible. and to avoid
- * burning call-preserved hard registers on the vld/vst
- * instructions.
- */
-
- do {
- int16x4_t xhi, yhi;
- int16x4_t x2hi, y2hi;
-
- /* vld4 does the de-interleaving for us */
- {
- register int16x4_t t_xlo asm("d0");
- register int16x4_t t_xhi asm("d1");
- register int16x4_t t_ylo asm("d2");
- register int16x4_t t_yhi asm("d3");
-
- asm ("vld4.16 {d0-d3},[%4] /* xlo=%P0 xhi=%P1 ylo=%P2 yhi=%P3 */"
- : "=w" (t_xlo), "=w" (t_xhi), "=w" (t_ylo), "=w" (t_yhi)
- : "r" (mysrc)
- );
- xhi = t_xhi;
- yhi = t_yhi;
- }
-
- /* clamp X>>16 (aka xhi) to 0..maxX */
- xhi = vmax_s16(xhi, zero4); /* now 0.. */
- xhi = vmin_s16(xhi, maxX4); /* now 0..maxX */
-
- /* clamp Y>>16 (aka yhi) to 0..maxY */
- yhi = vmax_s16(yhi, zero4); /* now 0.. */
- yhi = vmin_s16(yhi, maxY4); /* now 0..maxY */
-
- /* deal with the second set of numbers */
- {
- register int16x4_t t_xlo asm("d4");
- register int16x4_t t_xhi asm("d5");
- register int16x4_t t_ylo asm("d6");
- register int16x4_t t_yhi asm("d7");
-
- /* offset == 256 bits == 32 bytes == 8 longs == 16 shorts */
- asm ("vld4.16 {d4-d7},[%4] /* xlo=%P0 xhi=%P1 ylo=%P2 yhi=%P3 */"
- : "=w" (t_xlo), "=w" (t_xhi), "=w" (t_ylo), "=w" (t_yhi)
- : "r" (mysrc+16)
- );
- x2hi = t_xhi;
- y2hi = t_yhi;
- }
-
- /* clamp the second 4 here */
-
- if (0) { extern void rbe(void); rbe(); }
-
- /* clamp X>>16 (aka xhi) to 0..maxX */
- x2hi = vmax_s16(x2hi, zero4); /* now 0.. */
- x2hi = vmin_s16(x2hi, maxX4); /* now 0..maxX */
-
- /* clamp Y>>16 (aka yhi) to 0..maxY */
- y2hi = vmax_s16(y2hi, zero4); /* now 0.. */
- y2hi = vmin_s16(y2hi, maxY4); /* now 0..maxY */
-
- /* we're storing as {x,y}s: x is [0], y is [1] */
- /* we'll use vst2 to make this happen */
-
- {
- register int16x4_t out_x asm("d16") = xhi;
- register int16x4_t out_y asm("d17") = yhi;
-
- asm ("vst2.16 {d16-d17},[%2] /* xlo=%P0 xhi=%P1 */"
- :
- : "w" (out_x), "w" (out_y), "r" (mydst)
- );
- }
- {
- register int16x4_t out_x asm("d18") = x2hi;
- register int16x4_t out_y asm("d19") = y2hi;
-
- asm ("vst2.16 {d18-d19},[%2] /* xlo=%P0 xhi=%P1 */"
- :
- : "w" (out_x), "w" (out_y), "r" (mydst+8)
- );
- }
-
- /* XXX: gcc isn't interleaving these with the NEON ops
- * but i think that all the scoreboarding works out */
- count -= 8; /* 8 iterations */
- mysrc += 32; /* 16 longs, aka 32 shorts */
- mydst += 16; /* 16 shorts, aka 8 longs */
- } while (count >= 8);
- /* get xy and srcXY fixed up */
- srcXY = (const SkFixed *) mysrc;
- xy = (uint32_t *) mydst;
- }
-#endif
-
- while (--count >= 0) {
- *xy++ = (TILEY_PROCF(srcXY[1], maxY) << 16) |
- TILEX_PROCF(srcXY[0], maxX);
- srcXY += 2;
- }
-
-#if defined(DEBUG_PERSP_NOFILTER)
- /* for checking our NEON-produced results against vanilla code */
- {
- int bad = (-1);
- for (int i = 0; i < base_count; i++) {
- uint32_t val;
- val = (TILEY_PROCF (base_srcXY[i * 2 + 1], maxY) << 16) |
- TILEX_PROCF (base_srcXY[i * 2 + 0], maxX);
-
- if (val != base_xy[i]) {
- bad = i;
- break;
- }
- }
- if (bad >= 0) {
- SkDebugf("clamp-nofilter-persp failed piece %d\n", bad);
- SkDebugf(" maxX %08x maxY %08x\n", maxX, maxY);
- bad -= (bad & 0x7); /* align */
- for (int i = bad; i < bad + 8; i++) {
- uint32_t val;
- val = (TILEY_PROCF (base_srcXY[i * 2 + 1], maxY) << 16) |
- TILEX_PROCF (base_srcXY[i * 2 + 0], maxX);
-
- SkDebugf("%d: got %08x want %08x srcXY[0] %08x srcXY[1] %08x\n",
- i, base_xy[i], val, base_srcXY[i * 2 + 0],
- base_srcXY[i * 2 + 1]);
- }
- SkDebugf ("---\n");
- }
-
- if (end_xy != xy) {
- SkDebugf("xy ended at %08x, should be %08x\n", xy, end_xy);
- }
- if (end_srcXY != srcXY) {
- SkDebugf("srcXY ended at %08x, should be %08x\n", srcXY,
- end_srcXY);
- }
- }
-#endif
- }
-}
-
-#undef DEBUG_PERSP_NOFILTER
-
-//////////////////////////////////////////////////////////////////////////////
-
-static inline uint32_t PACK_FILTER_Y_NAME(SkFixed f, unsigned max,
- SkFixed one PREAMBLE_PARAM_Y) {
- unsigned i = TILEY_PROCF(f, max);
- i = (i << 4) | TILEY_LOW_BITS(f, max);
- return (i << 14) | (TILEY_PROCF((f + one), max));
-}
-
-static inline uint32_t PACK_FILTER_X_NAME(SkFixed f, unsigned max,
- SkFixed one PREAMBLE_PARAM_X) {
- unsigned i = TILEX_PROCF(f, max);
- i = (i << 4) | TILEX_LOW_BITS(f, max);
- return (i << 14) | (TILEX_PROCF((f + one), max));
-}
-
-static void SCALE_FILTER_NAME(const SkBitmapProcState& s,
- uint32_t xy[], int count, int x, int y) {
- SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
- SkMatrix::kScale_Mask)) == 0);
- SkASSERT(s.fInvKy == 0);
-
- PREAMBLE(s);
-
- const unsigned maxX = s.fBitmap->width() - 1;
- const SkFixed one = s.fFilterOneX;
- const SkFixed dx = s.fInvSx;
- SkFixed fx;
-
- {
- SkPoint pt;
- s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, &pt);
- const SkFixed fy = SkScalarToFixed(pt.fY) - (s.fFilterOneY >> 1);
- const unsigned maxY = s.fBitmap->height() - 1;
- // compute our two Y values up front
- *xy++ = PACK_FILTER_Y_NAME(fy, maxY, s.fFilterOneY PREAMBLE_ARG_Y);
- // now initialize fx
- fx = SkScalarToFixed(pt.fX) - (one >> 1);
- }
-
-#ifdef CHECK_FOR_DECAL
- // test if we don't need to apply the tile proc
- if (dx > 0 &&
- (unsigned)(fx >> 16) <= maxX &&
- (unsigned)((fx + dx * (count - 1)) >> 16) < maxX) {
- decal_filter_scale_neon(xy, fx, dx, count);
- } else
-#endif
-
- if (count >= 4) {
- int32x4_t wide_one, wide_fx, wide_fx1, wide_i, wide_lo;
- #if 0
- /* verification hooks -- see below */
- SkFixed debug_fx = fx;
- int count_done = 0;
- #endif
-
- wide_fx = vdupq_n_s32(fx);
- wide_fx = vsetq_lane_s32(fx+dx, wide_fx, 1);
- wide_fx = vsetq_lane_s32(fx+dx+dx, wide_fx, 2);
- wide_fx = vsetq_lane_s32(fx+dx+dx+dx, wide_fx, 3);
-
- wide_one = vdupq_n_s32(one);
-
- while (count >= 4) {
- /* original expands to:
- * unsigned i = SkClampMax((f) >> 16, max);
- * i = (i << 4) | (((f) >> 12) & 0xF);
- * return (i << 14) | (SkClampMax(((f + one)) >> 16, max));
- */
-
- /* i = SkClampMax(f>>16, maxX) */
- wide_i = vmaxq_s32(vshrq_n_s32(wide_fx,16), vdupq_n_s32(0));
- wide_i = vminq_s32(wide_i, vdupq_n_s32(maxX));
-
- /* i<<4 | TILEX_LOW_BITS(fx) */
- wide_lo = vshrq_n_s32(wide_fx, 12);
- wide_i = vsliq_n_s32(wide_lo, wide_i, 4);
-
- /* i<<14 */
- wide_i = vshlq_n_s32(wide_i, 14);
-
- /* SkClampMax(((f + one)) >> 16, max) */
- wide_fx1 = vaddq_s32(wide_fx, wide_one);
- wide_fx1 = vmaxq_s32(vshrq_n_s32(wide_fx1,16), vdupq_n_s32(0));
- wide_fx1 = vminq_s32(wide_fx1, vdupq_n_s32(maxX));
-
- /* final combination */
- wide_i = vorrq_s32(wide_i, wide_fx1);
-
- vst1q_u32(xy, vreinterpretq_u32_s32(wide_i));
-
- #if 0
- /* having a verification hook is a good idea */
- /* use debug_fx, debug_fx+dx, etc. */
-
- for (int i=0;i<4;i++) {
- uint32_t want = PACK_FILTER_X_NAME(debug_fx, maxX, one PREAMBLE_ARG_X);
- if (xy[i] != want)
- {
- /* print a nastygram */
- SkDebugf("clamp-filter-scale fails\n");
- SkDebugf("got %08x want %08x\n", xy[i], want);
- SkDebugf("fx %08x debug_fx %08x dx %08x done %d\n",
- fx, debug_fx, dx, count_done);
- SkDebugf(" maxX %08x one %08x\n", maxX, one);
-
- }
- debug_fx += dx;
- count_done++;
- }
- #endif
- wide_fx += vdupq_n_s32(dx+dx+dx+dx);
- fx += dx+dx+dx+dx;
- xy += 4;
- count -= 4;
- }
- }
-
- while (--count >= 0) {
- *xy++ = PACK_FILTER_X_NAME(fx, maxX, one PREAMBLE_ARG_X);
- fx += dx;
- }
-}
-
-static void AFFINE_FILTER_NAME(const SkBitmapProcState& s,
- uint32_t xy[], int count, int x, int y) {
- SkASSERT(s.fInvType & SkMatrix::kAffine_Mask);
- SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
- SkMatrix::kScale_Mask |
- SkMatrix::kAffine_Mask)) == 0);
-
- PREAMBLE(s);
- SkPoint srcPt;
- s.fInvProc(s.fInvMatrix,
- SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
-
- SkFixed oneX = s.fFilterOneX;
- SkFixed oneY = s.fFilterOneY;
- SkFixed fx = SkScalarToFixed(srcPt.fX) - (oneX >> 1);
- SkFixed fy = SkScalarToFixed(srcPt.fY) - (oneY >> 1);
- SkFixed dx = s.fInvSx;
- SkFixed dy = s.fInvKy;
- unsigned maxX = s.fBitmap->width() - 1;
- unsigned maxY = s.fBitmap->height() - 1;
-
- if (count >= 4) {
- int32x4_t wide_i, wide_lo;
- int32x4_t wide_fx, wide_onex, wide_fx1;
- int32x4_t wide_fy, wide_oney, wide_fy1;
-
- #undef AFFINE_DEBUG
- #if defined(AFFINE_DEBUG)
- SkFixed fyp = fy;
- SkFixed fxp = fx;
- uint32_t *xyp = xy;
- int count_done = 0;
- #endif
-
- wide_fx = vdupq_n_s32(fx);
- wide_fx = vsetq_lane_s32(fx+dx, wide_fx, 1);
- wide_fx = vsetq_lane_s32(fx+dx+dx, wide_fx, 2);
- wide_fx = vsetq_lane_s32(fx+dx+dx+dx, wide_fx, 3);
-
- wide_fy = vdupq_n_s32(fy);
- wide_fy = vsetq_lane_s32(fy+dy, wide_fy, 1);
- wide_fy = vsetq_lane_s32(fy+dy+dy, wide_fy, 2);
- wide_fy = vsetq_lane_s32(fy+dy+dy+dy, wide_fy, 3);
-
- wide_onex = vdupq_n_s32(oneX);
- wide_oney = vdupq_n_s32(oneY);
-
- while (count >= 4) {
- int32x4_t wide_x;
- int32x4_t wide_y;
-
- /* do the X side, then the Y side, then interleave them */
-
- /* original expands to:
- * unsigned i = SkClampMax((f) >> 16, max);
- * i = (i << 4) | (((f) >> 12) & 0xF);
- * return (i << 14) | (SkClampMax(((f + one)) >> 16, max));
- */
-
- /* i = SkClampMax(f>>16, maxX) */
- wide_i = vmaxq_s32(vshrq_n_s32(wide_fx,16), vdupq_n_s32(0));
- wide_i = vminq_s32(wide_i, vdupq_n_s32(maxX));
-
- /* i<<4 | TILEX_LOW_BITS(fx) */
- wide_lo = vshrq_n_s32(wide_fx, 12);
- wide_i = vsliq_n_s32(wide_lo, wide_i, 4);
-
- /* i<<14 */
- wide_i = vshlq_n_s32(wide_i, 14);
-
- /* SkClampMax(((f + one)) >> 16, max) */
- wide_fx1 = vaddq_s32(wide_fx, wide_onex);
- wide_fx1 = vmaxq_s32(vshrq_n_s32(wide_fx1,16), vdupq_n_s32(0));
- wide_fx1 = vminq_s32(wide_fx1, vdupq_n_s32(maxX));
-
- /* final combination */
- wide_x = vorrq_s32(wide_i, wide_fx1);
-
- /* And now the Y side */
-
- /* i = SkClampMax(f>>16, maxX) */
- wide_i = vmaxq_s32(vshrq_n_s32(wide_fy,16), vdupq_n_s32(0));
- wide_i = vminq_s32(wide_i, vdupq_n_s32(maxY));
-
- /* i<<4 | TILEX_LOW_BITS(fx) */
- wide_lo = vshrq_n_s32(wide_fy, 12);
- wide_i = vsliq_n_s32(wide_lo, wide_i, 4);
-
- /* i<<14 */
- wide_i = vshlq_n_s32(wide_i, 14);
-
- /* SkClampMax(((f + one)) >> 16, max) */
- wide_fy1 = vaddq_s32(wide_fy, wide_oney);
- wide_fy1 = vmaxq_s32(vshrq_n_s32(wide_fy1,16), vdupq_n_s32(0));
- wide_fy1 = vminq_s32(wide_fy1, vdupq_n_s32(maxY));
-
- /* final combination */
- wide_y = vorrq_s32(wide_i, wide_fy1);
-
- /* interleave as YXYXYXYX as part of the storing */
- {
- /* vst2.32 needs side-by-side registers */
- register int32x4_t t_x asm("q1");
- register int32x4_t t_y asm("q0");
-
- t_x = wide_x; t_y = wide_y;
- asm ("vst2.32 {q0-q1},[%2] /* y=%q0 x=%q1 */"
- :
- : "w" (t_y), "w" (t_x), "r" (xy)
- );
- }
-
- #if defined(AFFINE_DEBUG)
- /* make sure we're good here -- check the 4 we just output */
- for (int i = 0; i<4;i++) {
- uint32_t val;
- val = PACK_FILTER_Y_NAME(fyp, maxY, oneY PREAMBLE_ARG_Y);
- if (val != xy[i*2+0]) {
- /* print a nastygram */
- SkDebugf("clamp-filter-affine fails\n");
- SkDebugf("[bad-y] got %08x want %08x\n", xy[i*2+0], val);
- SkDebugf("fy %08x fxp %08x fyp %08x dx %08x dy %08x done %d\n",
- fy, fxp, fyp, dx, dy, count_done);
- SkDebugf(" maxY %08x oneY %08x\n", maxY, oneY);
- }
- val = PACK_FILTER_X_NAME(fxp, maxX, oneX PREAMBLE_ARG_X);
- if (val != xy[i*2+1]) {
- /* print a nastygram */
- SkDebugf("clamp-filter-affine fails\n");
- SkDebugf("[bad-x] got %08x want %08x\n", xy[i*2+1], val);
- SkDebugf("fx %08x fxp %08x fyp %08x dx %08x dy %08x done %d\n",
- fx, fxp, fyp, dx, dy, count_done);
- SkDebugf(" maxX %08x one %08x\n", maxX, oneX);
- }
- fyp += dy;
- fxp += dx;
- count_done++;
- }
- #endif
-
- wide_fx += vdupq_n_s32(dx+dx+dx+dx);
- fx += dx+dx+dx+dx;
- wide_fy += vdupq_n_s32(dy+dy+dy+dy);
- fy += dy+dy+dy+dy;
- xy += 8; /* 4 x's, 4 y's */
- count -= 4;
- }
- }
-
- while (--count >= 0) {
- /* NB: writing Y/X */
- *xy++ = PACK_FILTER_Y_NAME(fy, maxY, oneY PREAMBLE_ARG_Y);
- fy += dy;
- *xy++ = PACK_FILTER_X_NAME(fx, maxX, oneX PREAMBLE_ARG_X);
- fx += dx;
- }
-}
-
-static void PERSP_FILTER_NAME(const SkBitmapProcState& s,
- uint32_t* SK_RESTRICT xy, int count,
- int x, int y) {
- SkASSERT(s.fInvType & SkMatrix::kPerspective_Mask);
-
- PREAMBLE(s);
- unsigned maxX = s.fBitmap->width() - 1;
- unsigned maxY = s.fBitmap->height() - 1;
- SkFixed oneX = s.fFilterOneX;
- SkFixed oneY = s.fFilterOneY;
-
- SkPerspIter iter(s.fInvMatrix,
- SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, count);
-
- while ((count = iter.next()) != 0) {
- const SkFixed* SK_RESTRICT srcXY = iter.getXY();
-
- if (count >= 4) {
- int32x4_t wide_i, wide_lo;
- int32x4_t wide_fx1;
- int32x4_t wide_fy1;
- int32x4_t wide_x, wide_y;
-
- while (count >= 4) {
- /* RBE: it's good, but:
- * -- we spill a constant that could be easily regnerated
- * [perhaps tweak gcc's NEON constant costs?]
- */
-
- /* load src: x-y-x-y-x-y-x-y */
- {
- register int32x4_t q0 asm ("q0");
- register int32x4_t q1 asm ("q1");
- asm ("vld2.32 {q0-q1},[%2] /* x=%q0 y=%q1 */"
- : "=w" (q0), "=w" (q1)
- : "r" (srcXY));
- wide_x = q0; wide_y = q1;
- }
-
- /* do the X side, then the Y side, then interleave them */
-
- wide_x = vsubq_s32(wide_x, vdupq_n_s32 (oneX>>1));
-
- /* original expands to:
- * unsigned i = SkClampMax((f) >> 16, max);
- * i = (i << 4) | (((f) >> 12) & 0xF);
- * return (i << 14) | (SkClampMax(((f + one)) >> 16, max));
- */
-
- /* i = SkClampMax(f>>16, maxX) */
- wide_i = vmaxq_s32 (vshrq_n_s32 (wide_x, 16), vdupq_n_s32 (0));
- wide_i = vminq_s32 (wide_i, vdupq_n_s32 (maxX));
-
- /* i<<4 | TILEX_LOW_BITS(fx) */
- wide_lo = vshrq_n_s32 (wide_x, 12);
- wide_i = vsliq_n_s32 (wide_lo, wide_i, 4);
-
- /* i<<14 */
- wide_i = vshlq_n_s32 (wide_i, 14);
-
- /* SkClampMax(((f + one)) >> 16, max) */
- wide_fx1 = vaddq_s32 (wide_x, vdupq_n_s32(oneX));
- wide_fx1 = vmaxq_s32 (vshrq_n_s32 (wide_fx1, 16), vdupq_n_s32 (0));
- wide_fx1 = vminq_s32 (wide_fx1, vdupq_n_s32 (maxX));
-
- /* final combination */
- wide_x = vorrq_s32 (wide_i, wide_fx1);
-
-
- /* And now the Y side */
-
- wide_y = vsubq_s32(wide_y, vdupq_n_s32 (oneY>>1));
-
- /* i = SkClampMax(f>>16, maxX) */
- wide_i = vmaxq_s32 (vshrq_n_s32 (wide_y, 16), vdupq_n_s32 (0));
- wide_i = vminq_s32 (wide_i, vdupq_n_s32 (maxY));
-
- /* i<<4 | TILEX_LOW_BITS(fx) */
- wide_lo = vshrq_n_s32 (wide_y, 12);
- wide_i = vsliq_n_s32 (wide_lo, wide_i, 4);
-
- /* i<<14 */
- wide_i = vshlq_n_s32 (wide_i, 14);
-
- /* SkClampMax(((f + one)) >> 16, max) */
-
- /* wide_fy1_1 and wide_fy1_2 are just temporary variables to
- * work-around an ICE in debug */
- int32x4_t wide_fy1_1 = vaddq_s32 (wide_y, vdupq_n_s32(oneY));
- int32x4_t wide_fy1_2 = vmaxq_s32 (vshrq_n_s32 (wide_fy1_1, 16),
- vdupq_n_s32 (0));
- wide_fy1 = vminq_s32 (wide_fy1_2, vdupq_n_s32 (maxY));
-
- /* final combination */
- wide_y = vorrq_s32 (wide_i, wide_fy1);
-
- /* switch them around; have to do it this way to get them
- * in the proper registers to match our instruction */
-
- /* iteration bookkeeping, ahead of the asm() for scheduling */
- srcXY += 2*4;
- count -= 4;
-
- /* store interleaved as y-x-y-x-y-x-y-x (NB != read order) */
- {
- register int32x4_t q0 asm ("q0") = wide_y;
- register int32x4_t q1 asm ("q1") = wide_x;
-
- asm ("vst2.32 {q0-q1},[%2] /* y=%q0 x=%q1 */"
- :
- : "w" (q0), "w" (q1), "r" (xy));
- }
-
- /* on to the next iteration */
- /* count, srcXY are handled above */
- xy += 2*4;
- }
- }
-
- /* was do-while; NEON code invalidates original count>0 assumption */
- while (--count >= 0) {
- /* NB: we read x/y, we write y/x */
- *xy++ = PACK_FILTER_Y_NAME(srcXY[1] - (oneY >> 1), maxY,
- oneY PREAMBLE_ARG_Y);
- *xy++ = PACK_FILTER_X_NAME(srcXY[0] - (oneX >> 1), maxX,
- oneX PREAMBLE_ARG_X);
- srcXY += 2;
- }
- }
-}
-
-const SkBitmapProcState::MatrixProc MAKENAME(_Procs)[] = {
- SCALE_NOFILTER_NAME,
- SCALE_FILTER_NAME,
- AFFINE_NOFILTER_NAME,
- AFFINE_FILTER_NAME,
- PERSP_NOFILTER_NAME,
- PERSP_FILTER_NAME
-};
-
-#undef MAKENAME
-#undef TILEX_PROCF
-#undef TILEY_PROCF
-#ifdef CHECK_FOR_DECAL
- #undef CHECK_FOR_DECAL
-#endif
-
-#undef SCALE_NOFILTER_NAME
-#undef SCALE_FILTER_NAME
-#undef AFFINE_NOFILTER_NAME
-#undef AFFINE_FILTER_NAME
-#undef PERSP_NOFILTER_NAME
-#undef PERSP_FILTER_NAME
-
-#undef PREAMBLE
-#undef PREAMBLE_PARAM_X
-#undef PREAMBLE_PARAM_Y
-#undef PREAMBLE_ARG_X
-#undef PREAMBLE_ARG_Y
-
-#undef TILEX_LOW_BITS
-#undef TILEY_LOW_BITS
diff --git a/chromium/third_party/skia/src/opts/SkBitmapProcState_matrix_neon.h b/chromium/third_party/skia/src/opts/SkBitmapProcState_matrix_neon.h
new file mode 100644
index 00000000000..72bf1bce336
--- /dev/null
+++ b/chromium/third_party/skia/src/opts/SkBitmapProcState_matrix_neon.h
@@ -0,0 +1,506 @@
+
+#include <arm_neon.h>
+
+
+#define SCALE_NOFILTER_NAME MAKENAME(_nofilter_scale)
+#define SCALE_FILTER_NAME MAKENAME(_filter_scale)
+#define AFFINE_NOFILTER_NAME MAKENAME(_nofilter_affine)
+#define AFFINE_FILTER_NAME MAKENAME(_filter_affine)
+#define PERSP_NOFILTER_NAME MAKENAME(_nofilter_persp)
+#define PERSP_FILTER_NAME MAKENAME(_filter_persp)
+
+#define PACK_FILTER_X_NAME MAKENAME(_pack_filter_x)
+#define PACK_FILTER_Y_NAME MAKENAME(_pack_filter_y)
+#define PACK_FILTER_X4_NAME MAKENAME(_pack_filter_x4)
+#define PACK_FILTER_Y4_NAME MAKENAME(_pack_filter_y4)
+
+#ifndef PREAMBLE
+ #define PREAMBLE(state)
+ #define PREAMBLE_PARAM_X
+ #define PREAMBLE_PARAM_Y
+ #define PREAMBLE_ARG_X
+ #define PREAMBLE_ARG_Y
+#endif
+
+static void SCALE_NOFILTER_NAME(const SkBitmapProcState& s,
+ uint32_t xy[], int count, int x, int y) {
+ SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
+ SkMatrix::kScale_Mask)) == 0);
+
+ PREAMBLE(s);
+
+ // we store y, x, x, x, x, x
+ const unsigned maxX = s.fBitmap->width() - 1;
+ SkFractionalInt fx;
+ {
+ SkPoint pt;
+ s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
+ SkIntToScalar(y) + SK_ScalarHalf, &pt);
+ fx = SkScalarToFractionalInt(pt.fY);
+ const unsigned maxY = s.fBitmap->height() - 1;
+ *xy++ = TILEY_PROCF(SkFractionalIntToFixed(fx), maxY);
+ fx = SkScalarToFractionalInt(pt.fX);
+ }
+
+ if (0 == maxX) {
+ // all of the following X values must be 0
+ memset(xy, 0, count * sizeof(uint16_t));
+ return;
+ }
+
+ const SkFractionalInt dx = s.fInvSxFractionalInt;
+
+#ifdef CHECK_FOR_DECAL
+ // test if we don't need to apply the tile proc
+ if (can_truncate_to_fixed_for_decal(fx, dx, count, maxX)) {
+ decal_nofilter_scale_neon(xy, SkFractionalIntToFixed(fx),
+ SkFractionalIntToFixed(dx), count);
+ return;
+ }
+#endif
+
+ if (count >= 8) {
+ SkFractionalInt dx2 = dx+dx;
+ SkFractionalInt dx4 = dx2+dx2;
+ SkFractionalInt dx8 = dx4+dx4;
+
+ // now build fx/fx+dx/fx+2dx/fx+3dx
+ SkFractionalInt fx1, fx2, fx3;
+ int32x4_t lbase, hbase;
+ int16_t *dst16 = (int16_t *)xy;
+
+ fx1 = fx+dx;
+ fx2 = fx1+dx;
+ fx3 = fx2+dx;
+
+ lbase = vdupq_n_s32(SkFractionalIntToFixed(fx));
+ lbase = vsetq_lane_s32(SkFractionalIntToFixed(fx1), lbase, 1);
+ lbase = vsetq_lane_s32(SkFractionalIntToFixed(fx2), lbase, 2);
+ lbase = vsetq_lane_s32(SkFractionalIntToFixed(fx3), lbase, 3);
+ hbase = vaddq_s32(lbase, vdupq_n_s32(SkFractionalIntToFixed(dx4)));
+
+ // store & bump
+ while (count >= 8) {
+
+ int16x8_t fx8;
+
+ fx8 = TILEX_PROCF_NEON8(lbase, hbase, maxX);
+
+ vst1q_s16(dst16, fx8);
+
+ // but preserving base & on to the next
+ lbase = vaddq_s32 (lbase, vdupq_n_s32(SkFractionalIntToFixed(dx8)));
+ hbase = vaddq_s32 (hbase, vdupq_n_s32(SkFractionalIntToFixed(dx8)));
+ dst16 += 8;
+ count -= 8;
+ fx += dx8;
+ };
+ xy = (uint32_t *) dst16;
+ }
+
+ uint16_t* xx = (uint16_t*)xy;
+ for (int i = count; i > 0; --i) {
+ *xx++ = TILEX_PROCF(SkFractionalIntToFixed(fx), maxX);
+ fx += dx;
+ }
+}
+
+static void AFFINE_NOFILTER_NAME(const SkBitmapProcState& s,
+ uint32_t xy[], int count, int x, int y) {
+ SkASSERT(s.fInvType & SkMatrix::kAffine_Mask);
+ SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
+ SkMatrix::kScale_Mask |
+ SkMatrix::kAffine_Mask)) == 0);
+
+ PREAMBLE(s);
+ SkPoint srcPt;
+ s.fInvProc(s.fInvMatrix,
+ SkIntToScalar(x) + SK_ScalarHalf,
+ SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
+
+ SkFractionalInt fx = SkScalarToFractionalInt(srcPt.fX);
+ SkFractionalInt fy = SkScalarToFractionalInt(srcPt.fY);
+ SkFractionalInt dx = s.fInvSxFractionalInt;
+ SkFractionalInt dy = s.fInvKyFractionalInt;
+ int maxX = s.fBitmap->width() - 1;
+ int maxY = s.fBitmap->height() - 1;
+
+ if (count >= 8) {
+ SkFractionalInt dx4 = dx * 4;
+ SkFractionalInt dy4 = dy * 4;
+ SkFractionalInt dx8 = dx * 8;
+ SkFractionalInt dy8 = dy * 8;
+
+ int32x4_t xbase, ybase;
+ int32x4_t x2base, y2base;
+ int16_t *dst16 = (int16_t *) xy;
+
+ // now build fx, fx+dx, fx+2dx, fx+3dx
+ xbase = vdupq_n_s32(SkFractionalIntToFixed(fx));
+ xbase = vsetq_lane_s32(SkFractionalIntToFixed(fx+dx), xbase, 1);
+ xbase = vsetq_lane_s32(SkFractionalIntToFixed(fx+dx+dx), xbase, 2);
+ xbase = vsetq_lane_s32(SkFractionalIntToFixed(fx+dx+dx+dx), xbase, 3);
+
+ // same for fy
+ ybase = vdupq_n_s32(SkFractionalIntToFixed(fy));
+ ybase = vsetq_lane_s32(SkFractionalIntToFixed(fy+dy), ybase, 1);
+ ybase = vsetq_lane_s32(SkFractionalIntToFixed(fy+dy+dy), ybase, 2);
+ ybase = vsetq_lane_s32(SkFractionalIntToFixed(fy+dy+dy+dy), ybase, 3);
+
+ x2base = vaddq_s32(xbase, vdupq_n_s32(SkFractionalIntToFixed(dx4)));
+ y2base = vaddq_s32(ybase, vdupq_n_s32(SkFractionalIntToFixed(dy4)));
+
+ // store & bump
+ do {
+ int16x8x2_t hi16;
+
+ hi16.val[0] = TILEX_PROCF_NEON8(xbase, x2base, maxX);
+ hi16.val[1] = TILEY_PROCF_NEON8(ybase, y2base, maxY);
+
+ vst2q_s16(dst16, hi16);
+
+ // moving base and on to the next
+ xbase = vaddq_s32(xbase, vdupq_n_s32(SkFractionalIntToFixed(dx8)));
+ ybase = vaddq_s32(ybase, vdupq_n_s32(SkFractionalIntToFixed(dy8)));
+ x2base = vaddq_s32(x2base, vdupq_n_s32(SkFractionalIntToFixed(dx8)));
+ y2base = vaddq_s32(y2base, vdupq_n_s32(SkFractionalIntToFixed(dy8)));
+
+ dst16 += 16; // 8x32 aka 16x16
+ count -= 8;
+ fx += dx8;
+ fy += dy8;
+ } while (count >= 8);
+ xy = (uint32_t *) dst16;
+ }
+
+ for (int i = count; i > 0; --i) {
+ *xy++ = (TILEY_PROCF(SkFractionalIntToFixed(fy), maxY) << 16) |
+ TILEX_PROCF(SkFractionalIntToFixed(fx), maxX);
+ fx += dx; fy += dy;
+ }
+}
+
+static void PERSP_NOFILTER_NAME(const SkBitmapProcState& s,
+ uint32_t* SK_RESTRICT xy,
+ int count, int x, int y) {
+ SkASSERT(s.fInvType & SkMatrix::kPerspective_Mask);
+
+ PREAMBLE(s);
+ // max{X,Y} are int here, but later shown/assumed to fit in 16 bits
+ int maxX = s.fBitmap->width() - 1;
+ int maxY = s.fBitmap->height() - 1;
+
+ SkPerspIter iter(s.fInvMatrix,
+ SkIntToScalar(x) + SK_ScalarHalf,
+ SkIntToScalar(y) + SK_ScalarHalf, count);
+
+ while ((count = iter.next()) != 0) {
+ const SkFixed* SK_RESTRICT srcXY = iter.getXY();
+
+ if (count >= 8) {
+ int32_t *mysrc = (int32_t *) srcXY;
+ int16_t *mydst = (int16_t *) xy;
+ do {
+ int16x8x2_t hi16;
+ int32x4x2_t xy1, xy2;
+
+ xy1 = vld2q_s32(mysrc);
+ xy2 = vld2q_s32(mysrc+8);
+
+ hi16.val[0] = TILEX_PROCF_NEON8(xy1.val[0], xy2.val[0], maxX);
+ hi16.val[1] = TILEY_PROCF_NEON8(xy1.val[1], xy2.val[1], maxY);
+
+ vst2q_s16(mydst, hi16);
+
+ count -= 8; // 8 iterations
+ mysrc += 16; // 16 longs
+ mydst += 16; // 16 shorts, aka 8 longs
+ } while (count >= 8);
+ // get xy and srcXY fixed up
+ srcXY = (const SkFixed *) mysrc;
+ xy = (uint32_t *) mydst;
+ }
+
+ while (--count >= 0) {
+ *xy++ = (TILEY_PROCF(srcXY[1], maxY) << 16) |
+ TILEX_PROCF(srcXY[0], maxX);
+ srcXY += 2;
+ }
+ }
+}
+
+static inline uint32_t PACK_FILTER_Y_NAME(SkFixed f, unsigned max,
+ SkFixed one PREAMBLE_PARAM_Y) {
+ unsigned i = TILEY_PROCF(f, max);
+ i = (i << 4) | TILEY_LOW_BITS(f, max);
+ return (i << 14) | (TILEY_PROCF((f + one), max));
+}
+
+static inline uint32_t PACK_FILTER_X_NAME(SkFixed f, unsigned max,
+ SkFixed one PREAMBLE_PARAM_X) {
+ unsigned i = TILEX_PROCF(f, max);
+ i = (i << 4) | TILEX_LOW_BITS(f, max);
+ return (i << 14) | (TILEX_PROCF((f + one), max));
+}
+
+static inline int32x4_t PACK_FILTER_X4_NAME(int32x4_t f, unsigned max,
+ SkFixed one PREAMBLE_PARAM_X) {
+ int32x4_t ret, res, wide_one;
+
+ // Prepare constants
+ wide_one = vdupq_n_s32(one);
+
+ // Step 1
+ res = TILEX_PROCF_NEON4(f, max);
+
+ // Step 2
+ ret = TILEX_LOW_BITS_NEON4(f, max);
+ ret = vsliq_n_s32(ret, res, 4);
+
+ // Step 3
+ res = TILEX_PROCF_NEON4(f + wide_one, max);
+ ret = vorrq_s32(vshlq_n_s32(ret, 14), res);
+
+ return ret;
+}
+
+static inline int32x4_t PACK_FILTER_Y4_NAME(int32x4_t f, unsigned max,
+ SkFixed one PREAMBLE_PARAM_X) {
+ int32x4_t ret, res, wide_one;
+
+ // Prepare constants
+ wide_one = vdupq_n_s32(one);
+
+ // Step 1
+ res = TILEY_PROCF_NEON4(f, max);
+
+ // Step 2
+ ret = TILEY_LOW_BITS_NEON4(f, max);
+ ret = vsliq_n_s32(ret, res, 4);
+
+ // Step 3
+ res = TILEY_PROCF_NEON4(f + wide_one, max);
+ ret = vorrq_s32(vshlq_n_s32(ret, 14), res);
+
+ return ret;
+}
+
+static void SCALE_FILTER_NAME(const SkBitmapProcState& s,
+ uint32_t xy[], int count, int x, int y) {
+ SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
+ SkMatrix::kScale_Mask)) == 0);
+ SkASSERT(s.fInvKy == 0);
+
+ PREAMBLE(s);
+
+ const unsigned maxX = s.fBitmap->width() - 1;
+ const SkFixed one = s.fFilterOneX;
+ const SkFractionalInt dx = s.fInvSxFractionalInt;
+ SkFractionalInt fx;
+
+ {
+ SkPoint pt;
+ s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
+ SkIntToScalar(y) + SK_ScalarHalf, &pt);
+ const SkFixed fy = SkScalarToFixed(pt.fY) - (s.fFilterOneY >> 1);
+ const unsigned maxY = s.fBitmap->height() - 1;
+ // compute our two Y values up front
+ *xy++ = PACK_FILTER_Y_NAME(fy, maxY, s.fFilterOneY PREAMBLE_ARG_Y);
+ // now initialize fx
+ fx = SkScalarToFractionalInt(pt.fX) - (SkFixedToFractionalInt(one) >> 1);
+ }
+
+#ifdef CHECK_FOR_DECAL
+ // test if we don't need to apply the tile proc
+ if (can_truncate_to_fixed_for_decal(fx, dx, count, maxX)) {
+ decal_filter_scale_neon(xy, SkFractionalIntToFixed(fx),
+ SkFractionalIntToFixed(dx), count);
+ return;
+ }
+#endif
+ {
+
+ if (count >= 4) {
+ int32x4_t wide_fx;
+
+ wide_fx = vdupq_n_s32(SkFractionalIntToFixed(fx));
+ wide_fx = vsetq_lane_s32(SkFractionalIntToFixed(fx+dx), wide_fx, 1);
+ wide_fx = vsetq_lane_s32(SkFractionalIntToFixed(fx+dx+dx), wide_fx, 2);
+ wide_fx = vsetq_lane_s32(SkFractionalIntToFixed(fx+dx+dx+dx), wide_fx, 3);
+
+ while (count >= 4) {
+ int32x4_t res;
+
+ res = PACK_FILTER_X4_NAME(wide_fx, maxX, one PREAMBLE_ARG_X);
+
+ vst1q_u32(xy, vreinterpretq_u32_s32(res));
+
+ wide_fx += vdupq_n_s32(SkFractionalIntToFixed(dx+dx+dx+dx));
+ fx += dx+dx+dx+dx;
+ xy += 4;
+ count -= 4;
+ }
+ }
+
+ while (--count >= 0) {
+ *xy++ = PACK_FILTER_X_NAME(SkFractionalIntToFixed(fx), maxX, one PREAMBLE_ARG_X);
+ fx += dx;
+ }
+
+ }
+}
+
+static void AFFINE_FILTER_NAME(const SkBitmapProcState& s,
+ uint32_t xy[], int count, int x, int y) {
+ SkASSERT(s.fInvType & SkMatrix::kAffine_Mask);
+ SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
+ SkMatrix::kScale_Mask |
+ SkMatrix::kAffine_Mask)) == 0);
+
+ PREAMBLE(s);
+ SkPoint srcPt;
+ s.fInvProc(s.fInvMatrix,
+ SkIntToScalar(x) + SK_ScalarHalf,
+ SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
+
+ SkFixed oneX = s.fFilterOneX;
+ SkFixed oneY = s.fFilterOneY;
+ SkFixed fx = SkScalarToFixed(srcPt.fX) - (oneX >> 1);
+ SkFixed fy = SkScalarToFixed(srcPt.fY) - (oneY >> 1);
+ SkFixed dx = s.fInvSx;
+ SkFixed dy = s.fInvKy;
+ unsigned maxX = s.fBitmap->width() - 1;
+ unsigned maxY = s.fBitmap->height() - 1;
+
+ if (count >= 4) {
+ int32x4_t wide_fy, wide_fx;
+
+ wide_fx = vdupq_n_s32(fx);
+ wide_fx = vsetq_lane_s32(fx+dx, wide_fx, 1);
+ wide_fx = vsetq_lane_s32(fx+dx+dx, wide_fx, 2);
+ wide_fx = vsetq_lane_s32(fx+dx+dx+dx, wide_fx, 3);
+
+ wide_fy = vdupq_n_s32(fy);
+ wide_fy = vsetq_lane_s32(fy+dy, wide_fy, 1);
+ wide_fy = vsetq_lane_s32(fy+dy+dy, wide_fy, 2);
+ wide_fy = vsetq_lane_s32(fy+dy+dy+dy, wide_fy, 3);
+
+ while (count >= 4) {
+ int32x4x2_t vxy;
+
+ // do the X side, then the Y side, then interleave them
+ vxy.val[0] = PACK_FILTER_Y4_NAME(wide_fy, maxY, oneY PREAMBLE_ARG_Y);
+ vxy.val[1] = PACK_FILTER_X4_NAME(wide_fx, maxX, oneX PREAMBLE_ARG_X);
+
+ // interleave as YXYXYXYX as part of the storing
+ vst2q_s32((int32_t*)xy, vxy);
+
+ // prepare next iteration
+ wide_fx += vdupq_n_s32(dx+dx+dx+dx);
+ fx += dx + dx + dx + dx;
+ wide_fy += vdupq_n_s32(dy+dy+dy+dy);
+ fy += dy+dy+dy+dy;
+ xy += 8; // 4 x's, 4 y's
+ count -= 4;
+ }
+ }
+
+ while (--count >= 0) {
+ // NB: writing Y/X
+ *xy++ = PACK_FILTER_Y_NAME(fy, maxY, oneY PREAMBLE_ARG_Y);
+ fy += dy;
+ *xy++ = PACK_FILTER_X_NAME(fx, maxX, oneX PREAMBLE_ARG_X);
+ fx += dx;
+ }
+}
+
+static void PERSP_FILTER_NAME(const SkBitmapProcState& s,
+ uint32_t* SK_RESTRICT xy, int count,
+ int x, int y) {
+ SkASSERT(s.fInvType & SkMatrix::kPerspective_Mask);
+
+ PREAMBLE(s);
+ unsigned maxX = s.fBitmap->width() - 1;
+ unsigned maxY = s.fBitmap->height() - 1;
+ SkFixed oneX = s.fFilterOneX;
+ SkFixed oneY = s.fFilterOneY;
+
+ SkPerspIter iter(s.fInvMatrix,
+ SkIntToScalar(x) + SK_ScalarHalf,
+ SkIntToScalar(y) + SK_ScalarHalf, count);
+
+ while ((count = iter.next()) != 0) {
+ const SkFixed* SK_RESTRICT srcXY = iter.getXY();
+
+ while (count >= 4) {
+ int32x4_t wide_x, wide_y;
+ int32x4x2_t vxy, vresyx;
+
+ // load src: x-y-x-y-x-y-x-y
+ vxy = vld2q_s32(srcXY);
+
+ // do the X side, then the Y side, then interleave them
+ wide_x = vsubq_s32(vxy.val[0], vdupq_n_s32(oneX>>1));
+ wide_y = vsubq_s32(vxy.val[1], vdupq_n_s32(oneY>>1));
+
+ vresyx.val[0] = PACK_FILTER_Y4_NAME(wide_y, maxY, oneY PREAMBLE_ARG_Y);
+ vresyx.val[1] = PACK_FILTER_X4_NAME(wide_x, maxX, oneX PREAMBLE_ARG_X);
+
+ // store interleaved as y-x-y-x-y-x-y-x (NB != read order)
+ vst2q_s32((int32_t*)xy, vresyx);
+
+ // on to the next iteration
+ srcXY += 2*4;
+ count -= 4;
+ xy += 2*4;
+ }
+
+ while (--count >= 0) {
+ // NB: we read x/y, we write y/x
+ *xy++ = PACK_FILTER_Y_NAME(srcXY[1] - (oneY >> 1), maxY,
+ oneY PREAMBLE_ARG_Y);
+ *xy++ = PACK_FILTER_X_NAME(srcXY[0] - (oneX >> 1), maxX,
+ oneX PREAMBLE_ARG_X);
+ srcXY += 2;
+ }
+ }
+}
+
+const SkBitmapProcState::MatrixProc MAKENAME(_Procs)[] = {
+ SCALE_NOFILTER_NAME,
+ SCALE_FILTER_NAME,
+ AFFINE_NOFILTER_NAME,
+ AFFINE_FILTER_NAME,
+ PERSP_NOFILTER_NAME,
+ PERSP_FILTER_NAME
+};
+
+#undef TILEX_PROCF_NEON8
+#undef TILEY_PROCF_NEON8
+#undef TILEX_PROCF_NEON4
+#undef TILEY_PROCF_NEON4
+#undef TILEX_LOW_BITS_NEON4
+#undef TILEY_LOW_BITS_NEON4
+
+#undef MAKENAME
+#undef TILEX_PROCF
+#undef TILEY_PROCF
+#ifdef CHECK_FOR_DECAL
+ #undef CHECK_FOR_DECAL
+#endif
+
+#undef SCALE_NOFILTER_NAME
+#undef SCALE_FILTER_NAME
+#undef AFFINE_NOFILTER_NAME
+#undef AFFINE_FILTER_NAME
+#undef PERSP_NOFILTER_NAME
+#undef PERSP_FILTER_NAME
+
+#undef PREAMBLE
+#undef PREAMBLE_PARAM_X
+#undef PREAMBLE_PARAM_Y
+#undef PREAMBLE_ARG_X
+#undef PREAMBLE_ARG_Y
+
+#undef TILEX_LOW_BITS
+#undef TILEY_LOW_BITS
diff --git a/chromium/third_party/skia/src/opts/SkBitmapProcState_matrix_repeat_neon.h b/chromium/third_party/skia/src/opts/SkBitmapProcState_matrix_repeat_neon.h
deleted file mode 100644
index 55e2997a5ef..00000000000
--- a/chromium/third_party/skia/src/opts/SkBitmapProcState_matrix_repeat_neon.h
+++ /dev/null
@@ -1,542 +0,0 @@
-/* NEON optimized code (C) COPYRIGHT 2009 Motorola
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/*
- * Modifications done in-house at Motorola
- *
- * this is a clone of SkBitmapProcState_matrix.h
- * and has been tuned to work with the NEON unit.
- *
- * Still going back and forth between whether this approach
- * (clone the entire SkBitmapProcState_matrix.h file or
- * if I should put just the modified routines in here and
- * then use a construct like #define DONT_DO_THIS_FUNCTION or
- * something like that...
- *
- * This is for the RepeatX_RepeatY part of the world
- */
-
-
-#include <arm_neon.h>
-
-/*
- * This has been modified on the knowledge that (at the time)
- * we had the following macro definitions in the parent file
- *
- * #define MAKENAME(suffix) RepeatX_RepeatY ## suffix
- * #define TILEX_PROCF(fx, max) (((fx) & 0xFFFF) * ((max) + 1) >> 16)
- * #define TILEY_PROCF(fy, max) (((fy) & 0xFFFF) * ((max) + 1) >> 16)
- * #define TILEX_LOW_BITS(fx, max) ((((fx) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
- * #define TILEY_LOW_BITS(fy, max) ((((fy) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
- */
-
-/* SkClampMax(val,max) -- bound to 0..max */
-
-#define SCALE_NOFILTER_NAME MAKENAME(_nofilter_scale)
-#define SCALE_FILTER_NAME MAKENAME(_filter_scale)
-#define AFFINE_NOFILTER_NAME MAKENAME(_nofilter_affine)
-#define AFFINE_FILTER_NAME MAKENAME(_filter_affine)
-#define PERSP_NOFILTER_NAME MAKENAME(_nofilter_persp)
-#define PERSP_FILTER_NAME MAKENAME(_filter_persp)
-
-#define PACK_FILTER_X_NAME MAKENAME(_pack_filter_x)
-#define PACK_FILTER_Y_NAME MAKENAME(_pack_filter_y)
-
-#ifndef PREAMBLE
- #define PREAMBLE(state)
- #define PREAMBLE_PARAM_X
- #define PREAMBLE_PARAM_Y
- #define PREAMBLE_ARG_X
- #define PREAMBLE_ARG_Y
-#endif
-
-static void SCALE_NOFILTER_NAME(const SkBitmapProcState& s,
- uint32_t xy[], int count, int x, int y) {
- SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
- SkMatrix::kScale_Mask)) == 0);
-
- PREAMBLE(s);
- // we store y, x, x, x, x, x
-
- const unsigned maxX = s.fBitmap->width() - 1;
- SkFixed fx;
- {
- SkPoint pt;
- s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, &pt);
- fx = SkScalarToFixed(pt.fY);
- const unsigned maxY = s.fBitmap->height() - 1;
- *xy++ = TILEY_PROCF(fx, maxY);
- fx = SkScalarToFixed(pt.fX);
- }
-
- if (0 == maxX) {
- // all of the following X values must be 0
- memset(xy, 0, count * sizeof(uint16_t));
- return;
- }
-
- const SkFixed dx = s.fInvSx;
-
-#ifdef CHECK_FOR_DECAL
- // test if we don't need to apply the tile proc
- if ((unsigned)(fx >> 16) <= maxX &&
- (unsigned)((fx + dx * (count - 1)) >> 16) <= maxX) {
- decal_nofilter_scale_neon(xy, fx, dx, count);
- } else
-#endif
- {
- int i;
-
- /* RBE: very much like done in decal_nofilter ,
- * but some processing of the 'fx' information
- * TILEX_PROCF(fx, max) (((fx) & 0xFFFF) * ((max) + 1) >> 16)
- */
- if (count >= 8) {
- /* SkFixed is 16.16 fixed point */
- SkFixed dx2 = dx+dx;
- SkFixed dx4 = dx2+dx2;
- SkFixed dx8 = dx4+dx4;
-
- /* now build fx/fx+dx/fx+2dx/fx+3dx */
- SkFixed fx1, fx2, fx3;
- int32x4_t lbase, hbase;
- int16_t *dst16 = (int16_t *)xy;
-
- fx1 = fx+dx;
- fx2 = fx1+dx;
- fx3 = fx2+dx;
-
- lbase = vdupq_n_s32(fx);
- lbase = vsetq_lane_s32(fx1, lbase, 1);
- lbase = vsetq_lane_s32(fx2, lbase, 2);
- lbase = vsetq_lane_s32(fx3, lbase, 3);
- hbase = vaddq_s32(lbase, vdupq_n_s32(dx4));
-
- /* store & bump */
- do
- {
- int32x4_t lout;
- int32x4_t hout;
- int16x8_t hi16;
-
- /* TILEX_PROCF(fx, max) (((fx)&0xFFFF)*((max)+1)>> 16) */
- /* mask to low 16 [would like to use uzp tricks) */
- lout = vandq_s32(lbase, vdupq_n_s32(0xffff));
- hout = vandq_s32(hbase, vdupq_n_s32(0xffff));
- /* bare multiplication, not SkFixedMul */
- lout = vmulq_s32(lout, vdupq_n_s32(maxX+1));
- hout = vmulq_s32(hout, vdupq_n_s32(maxX+1));
-
- /* extraction, using uzp */
- /* this is ok -- we want all hi(lout)s then all hi(hout)s */
- asm ("vuzpq.16 %q0, %q1" : "+w" (lout), "+w" (hout));
- hi16 = vreinterpretq_s16_s32(hout);
- vst1q_s16(dst16, hi16);
-
- /* bump our base on to the next */
- lbase = vaddq_s32 (lbase, vdupq_n_s32(dx8));
- hbase = vaddq_s32 (hbase, vdupq_n_s32(dx8));
- dst16 += 8;
- count -= 8;
- fx += dx8;
- } while (count >= 8);
- xy = (uint32_t *) dst16;
- }
- uint16_t* xx = (uint16_t*)xy;
- for (i = count; i > 0; --i) {
- *xx++ = TILEX_PROCF(fx, maxX); fx += dx;
- }
- }
-}
-
-// note: we could special-case on a matrix which is skewed in X but not Y.
-// this would require a more general setup thatn SCALE does, but could use
-// SCALE's inner loop that only looks at dx
-
-
-static void AFFINE_NOFILTER_NAME(const SkBitmapProcState& s,
- uint32_t xy[], int count, int x, int y) {
- SkASSERT(s.fInvType & SkMatrix::kAffine_Mask);
- SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
- SkMatrix::kScale_Mask |
- SkMatrix::kAffine_Mask)) == 0);
-
- PREAMBLE(s);
- SkPoint srcPt;
- s.fInvProc(s.fInvMatrix,
- SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
-
- SkFixed fx = SkScalarToFixed(srcPt.fX);
- SkFixed fy = SkScalarToFixed(srcPt.fY);
- SkFixed dx = s.fInvSx;
- SkFixed dy = s.fInvKy;
- int maxX = s.fBitmap->width() - 1;
- int maxY = s.fBitmap->height() - 1;
-
-#if 0
- int ocount = count;
- uint32_t *oxy = xy;
- SkFixed bfx = fx, bfy=fy, bdx=dx, bdy=dy;
-#endif
-
-
- if (0) { extern void rbe(void); rbe(); }
-
- /* RBE: benchmarks show this eats up time; can we neonize it? */
- /* RBE: very much like done in decal_nofilter ,
- * but some processing of the 'fx' information
- * TILEX_PROCF(fx, max) (((fx) & 0xFFFF) * ((max) + 1) >> 16)
- */
- if (count >= 4) {
- /* SkFixed is 16.16 fixed point */
- SkFixed dx4 = dx*4;
- SkFixed dy4 = dy*4;
-
- /* now build fx/fx+dx/fx+2dx/fx+3dx */
- int32x4_t xbase, ybase;
- int16_t *dst16 = (int16_t *)xy;
-
- /* synthesize 4x for both X and Y */
- xbase = vdupq_n_s32(fx);
- xbase = vsetq_lane_s32(fx+dx, xbase, 1);
- xbase = vsetq_lane_s32(fx+dx+dx, xbase, 2);
- xbase = vsetq_lane_s32(fx+dx+dx+dx, xbase, 3);
-
- ybase = vdupq_n_s32(fy);
- ybase = vsetq_lane_s32(fy+dy, ybase, 1);
- ybase = vsetq_lane_s32(fy+dy+dy, ybase, 2);
- ybase = vsetq_lane_s32(fy+dy+dy+dy, ybase, 3);
-
- /* store & bump */
- do {
- int32x4_t xout;
- int32x4_t yout;
- int16x8_t hi16;
-
- /* TILEX_PROCF(fx, max) (((fx)&0xFFFF)*((max)+1)>> 16) */
- /* mask to low 16 [would like to use uzp tricks) */
- xout = vandq_s32(xbase, vdupq_n_s32(0xffff));
- yout = vandq_s32(ybase, vdupq_n_s32(0xffff));
- /* bare multiplication, not SkFixedMul */
- xout = vmulq_s32(xout, vdupq_n_s32(maxX+1));
- yout = vmulq_s32(yout, vdupq_n_s32(maxY+1));
-
- /* put hi16 from xout over low16 from yout */
- yout = vsriq_n_s32(yout, xout, 16);
-
- /* and then yout has the interleaved upper 16's */
- hi16 = vreinterpretq_s16_s32(yout);
- vst1q_s16(dst16, hi16);
-
- /* bump preserved base & on to the next */
- xbase = vaddq_s32 (xbase, vdupq_n_s32(dx4));
- ybase = vaddq_s32 (ybase, vdupq_n_s32(dy4));
- dst16 += 8; /* 8 x16 aka 4x32 */
- count -= 4;
- fx += dx4;
- fy += dy4;
- } while (count >= 4);
- xy = (uint32_t *) dst16;
- }
-
-#if 0
- /* diagnostics... see whether we agree with the NEON code */
- int bad = 0;
- uint32_t *myxy = oxy;
- int myi = (-1);
- SkFixed ofx = bfx, ofy= bfy, odx= bdx, ody= bdy;
- for (myi = ocount; myi > 0; --myi) {
- uint32_t val = (TILEY_PROCF(ofy, maxY) << 16) | TILEX_PROCF(ofx, maxX);
- if (val != *myxy++) {
- bad++;
- break;
- }
- ofx += odx; ofy += ody;
- }
- if (bad) {
- SkDebugf("repeat-nofilter-affine fails\n");
- SkDebugf("count %d myi %d\n", ocount, myi);
- SkDebugf(" bfx %08x, bdx %08x, bfy %08x bdy %08x\n",
- bfx, bdx, bfy, bdy);
- SkDebugf("maxX %08x maxY %08x\n", maxX, maxY);
- }
-#endif
-
- for (int i = count; i > 0; --i) {
- /* fx, fy, dx, dy are all 32 bit 16.16 fixed point */
- /* (((fx) & 0xFFFF) * ((max) + 1) >> 16) */
- *xy++ = (TILEY_PROCF(fy, maxY) << 16) | TILEX_PROCF(fx, maxX);
- fx += dx; fy += dy;
- }
-}
-
-static void PERSP_NOFILTER_NAME(const SkBitmapProcState& s,
- uint32_t* SK_RESTRICT xy,
- int count, int x, int y) {
- SkASSERT(s.fInvType & SkMatrix::kPerspective_Mask);
-
- PREAMBLE(s);
- int maxX = s.fBitmap->width() - 1;
- int maxY = s.fBitmap->height() - 1;
-
- SkPerspIter iter(s.fInvMatrix,
- SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, count);
-
- while ((count = iter.next()) != 0) {
- const SkFixed* SK_RESTRICT srcXY = iter.getXY();
-
- /* RBE: */
- /* TILEX_PROCF(fx, max) (((fx) & 0xFFFF) * ((max) + 1) >> 16) */
- /* it's a little more complicated than what I did for the
- * clamp case -- where I could immediately snip to the top
- * 16 bits and do my min/max games there.
- * ... might only be able to get 4x unrolling here
- */
-
- /* vld2 to get a set of 32x4's ... */
- /* do the tile[xy]_procf operations */
- /* which includes doing vuzp to get hi16's */
- /* store it */
- /* -- inner loop (other than vld2) can be had from above */
-
- /* srcXY is a batch of 32 bit numbers X0,Y0,X1,Y1...
- * but we immediately discard the low 16 bits...
- * so what we're going to do is vld4, which will give us
- * xlo,xhi,ylo,yhi distribution and we can ignore the 'lo'
- * parts....
- */
- if (0) { extern void rbe(void); rbe(); }
- if (count >= 8) {
- int32_t *mysrc = (int32_t *) srcXY;
- int16_t *mydst = (int16_t *) xy;
- do {
- int32x4_t x, y, x2, y2;
- int16x8_t hi, hi2;
-
- /* read array of x,y,x,y,x,y */
- /* vld2 does the de-interleaving for us */
- /* isolate reg-bound scopes; gcc will minimize register
- * motion if possible; this ensures that we don't lose
- * a register across a debugging call because it happens
- * to be bound into a call-clobbered register
- */
- {
- register int32x4_t q0 asm("q0");
- register int32x4_t q1 asm("q1");
- asm ("vld2.32 {q0-q1},[%2] /* x=%q0 y=%q1 */"
- : "=w" (q0), "=w" (q1)
- : "r" (mysrc)
- );
- x = q0; y = q1;
- }
-
- /* offset == 256 bits == 32 bytes == 8 longs */
- {
- register int32x4_t q2 asm("q2");
- register int32x4_t q3 asm("q3");
- asm ("vld2.32 {q2-q3},[%2] /* x=%q0 y=%q1 */"
- : "=w" (q2), "=w" (q3)
- : "r" (mysrc+8)
- );
- x2 = q2; y2 = q3;
- }
-
- /* TILEX_PROCF(fx, max) (((fx)&0xFFFF)*((max)+1)>> 16) */
- /* mask to low 16 [would like to use uzp tricks) */
- /* bare multiplication, not SkFixedMul */
- x = vandq_s32(x, vdupq_n_s32(0xffff));
- x = vmulq_s32(x, vdupq_n_s32(maxX+1));
- y = vandq_s32(y, vdupq_n_s32(0xffff));
- y = vmulq_s32(y, vdupq_n_s32(maxY+1));
-
- x2 = vandq_s32(x2, vdupq_n_s32(0xffff));
- x2 = vmulq_s32(x2, vdupq_n_s32(maxX+1));
- y2 = vandq_s32(y2, vdupq_n_s32(0xffff));
- y2 = vmulq_s32(y2, vdupq_n_s32(maxY+1));
-
- /* now collect interleaved high 16's */
- /* (hi-x, hi-y)4 (hi-x2; hi-y2)4 */
-
- /* extraction, using uzp, leaves hi16's in y */
- y = vsriq_n_s32(y, x, 16);
- hi = vreinterpretq_s16_s32(y);
- vst1q_s16(mydst, hi);
-
- /* and likewise for the second 8 entries */
- y2 = vsriq_n_s32(y2, x2, 16);
- hi2 = vreinterpretq_s16_s32(y2);
- vst1q_s16(mydst+8, hi2);
-
- /* XXX: gcc isn't interleaving these with the NEON ops
- * but i think that all the scoreboarding works out */
- count -= 8; /* 8 iterations */
- mysrc += 16; /* 16 longs */
- mydst += 16; /* 16 shorts, aka 8 longs */
- } while (count >= 8);
- /* get xy and srcXY fixed up */
- srcXY = (const SkFixed *) mysrc;
- xy = (uint32_t *) mydst;
- }
- while (--count >= 0) {
- *xy++ = (TILEY_PROCF(srcXY[1], maxY) << 16) |
- TILEX_PROCF(srcXY[0], maxX);
- srcXY += 2;
- }
- }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-static inline uint32_t PACK_FILTER_Y_NAME(SkFixed f, unsigned max,
- SkFixed one PREAMBLE_PARAM_Y) {
- unsigned i = TILEY_PROCF(f, max);
- i = (i << 4) | TILEY_LOW_BITS(f, max);
- return (i << 14) | (TILEY_PROCF((f + one), max));
-}
-
-static inline uint32_t PACK_FILTER_X_NAME(SkFixed f, unsigned max,
- SkFixed one PREAMBLE_PARAM_X) {
- unsigned i = TILEX_PROCF(f, max);
- i = (i << 4) | TILEX_LOW_BITS(f, max);
- return (i << 14) | (TILEX_PROCF((f + one), max));
-}
-
-static void SCALE_FILTER_NAME(const SkBitmapProcState& s,
- uint32_t xy[], int count, int x, int y) {
- SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
- SkMatrix::kScale_Mask)) == 0);
- SkASSERT(s.fInvKy == 0);
-
- PREAMBLE(s);
-
- const unsigned maxX = s.fBitmap->width() - 1;
- const SkFixed one = s.fFilterOneX;
- const SkFractionalInt dx = s.fInvSxFractionalInt;
- SkFractionalInt fx;
-
- {
- SkPoint pt;
- s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, &pt);
- const SkFixed fy = SkScalarToFixed(pt.fY) - (s.fFilterOneY >> 1);
- const unsigned maxY = s.fBitmap->height() - 1;
- // compute our two Y values up front
- *xy++ = PACK_FILTER_Y_NAME(fy, maxY, s.fFilterOneY PREAMBLE_ARG_Y);
- // now initialize fx
- fx = SkScalarToFractionalInt(pt.fX) - (SkFixedToFractionalInt(one) >> 1);
- }
-
-#ifdef CHECK_FOR_DECAL
- // test if we don't need to apply the tile proc
- if (can_truncate_to_fixed_for_decal(fx, dx, count, maxX)) {
- decal_filter_scale_neon(xy, SkFractionalIntToFixed(fx),
- SkFractionalIntToFixed(dx), count);
- } else
-#endif
- {
- do {
- SkFixed fixedFx = SkFractionalIntToFixed(fx);
- *xy++ = PACK_FILTER_X_NAME(fixedFx, maxX, one PREAMBLE_ARG_X);
- fx += dx;
- } while (--count != 0);
- }
-}
-
-static void AFFINE_FILTER_NAME(const SkBitmapProcState& s,
- uint32_t xy[], int count, int x, int y) {
- SkASSERT(s.fInvType & SkMatrix::kAffine_Mask);
- SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
- SkMatrix::kScale_Mask |
- SkMatrix::kAffine_Mask)) == 0);
-
- PREAMBLE(s);
- SkPoint srcPt;
- s.fInvProc(s.fInvMatrix,
- SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
-
- SkFixed oneX = s.fFilterOneX;
- SkFixed oneY = s.fFilterOneY;
- SkFixed fx = SkScalarToFixed(srcPt.fX) - (oneX >> 1);
- SkFixed fy = SkScalarToFixed(srcPt.fY) - (oneY >> 1);
- SkFixed dx = s.fInvSx;
- SkFixed dy = s.fInvKy;
- unsigned maxX = s.fBitmap->width() - 1;
- unsigned maxY = s.fBitmap->height() - 1;
-
- do {
- *xy++ = PACK_FILTER_Y_NAME(fy, maxY, oneY PREAMBLE_ARG_Y);
- fy += dy;
- *xy++ = PACK_FILTER_X_NAME(fx, maxX, oneX PREAMBLE_ARG_X);
- fx += dx;
- } while (--count != 0);
-}
-
-static void PERSP_FILTER_NAME(const SkBitmapProcState& s,
- uint32_t* SK_RESTRICT xy, int count,
- int x, int y) {
- SkASSERT(s.fInvType & SkMatrix::kPerspective_Mask);
-
- extern void rbe(void);
-
- PREAMBLE(s);
- unsigned maxX = s.fBitmap->width() - 1;
- unsigned maxY = s.fBitmap->height() - 1;
- SkFixed oneX = s.fFilterOneX;
- SkFixed oneY = s.fFilterOneY;
-
-
-
- SkPerspIter iter(s.fInvMatrix,
- SkIntToScalar(x) + SK_ScalarHalf,
- SkIntToScalar(y) + SK_ScalarHalf, count);
-
- while ((count = iter.next()) != 0) {
- const SkFixed* SK_RESTRICT srcXY = iter.getXY();
- do {
- *xy++ = PACK_FILTER_Y_NAME(srcXY[1] - (oneY >> 1), maxY,
- oneY PREAMBLE_ARG_Y);
- *xy++ = PACK_FILTER_X_NAME(srcXY[0] - (oneX >> 1), maxX,
- oneX PREAMBLE_ARG_X);
- srcXY += 2;
- } while (--count != 0);
- }
-}
-
-const SkBitmapProcState::MatrixProc MAKENAME(_Procs)[] = {
- SCALE_NOFILTER_NAME,
- SCALE_FILTER_NAME,
- AFFINE_NOFILTER_NAME,
- AFFINE_FILTER_NAME,
- PERSP_NOFILTER_NAME,
- PERSP_FILTER_NAME
-};
-
-#undef MAKENAME
-#undef TILEX_PROCF
-#undef TILEY_PROCF
-#ifdef CHECK_FOR_DECAL
- #undef CHECK_FOR_DECAL
-#endif
-
-#undef SCALE_NOFILTER_NAME
-#undef SCALE_FILTER_NAME
-#undef AFFINE_NOFILTER_NAME
-#undef AFFINE_FILTER_NAME
-#undef PERSP_NOFILTER_NAME
-#undef PERSP_FILTER_NAME
-
-#undef PREAMBLE
-#undef PREAMBLE_PARAM_X
-#undef PREAMBLE_PARAM_Y
-#undef PREAMBLE_ARG_X
-#undef PREAMBLE_ARG_Y
-
-#undef TILEX_LOW_BITS
-#undef TILEY_LOW_BITS
diff --git a/chromium/third_party/skia/src/opts/SkBitmapProcState_opts_SSE2.cpp b/chromium/third_party/skia/src/opts/SkBitmapProcState_opts_SSE2.cpp
index 0b079977eb8..1f3bbc1f8f7 100644
--- a/chromium/third_party/skia/src/opts/SkBitmapProcState_opts_SSE2.cpp
+++ b/chromium/third_party/skia/src/opts/SkBitmapProcState_opts_SSE2.cpp
@@ -1,4 +1,3 @@
-
/*
* Copyright 2009 The Android Open Source Project
*
@@ -6,9 +5,9 @@
* found in the LICENSE file.
*/
-
#include <emmintrin.h>
#include "SkBitmapProcState_opts_SSE2.h"
+#include "SkColorPriv.h"
#include "SkPaint.h"
#include "SkUtils.h"
@@ -17,7 +16,7 @@ void S32_opaque_D32_filter_DX_SSE2(const SkBitmapProcState& s,
int count, uint32_t* colors) {
SkASSERT(count > 0 && colors != NULL);
SkASSERT(s.fFilterLevel != SkPaint::kNone_FilterLevel);
- SkASSERT(s.fBitmap->config() == SkBitmap::kARGB_8888_Config);
+ SkASSERT(kN32_SkColorType == s.fBitmap->colorType());
SkASSERT(s.fAlphaScale == 256);
const char* srcAddr = static_cast<const char*>(s.fBitmap->getPixels());
@@ -123,7 +122,7 @@ void S32_alpha_D32_filter_DX_SSE2(const SkBitmapProcState& s,
int count, uint32_t* colors) {
SkASSERT(count > 0 && colors != NULL);
SkASSERT(s.fFilterLevel != SkPaint::kNone_FilterLevel);
- SkASSERT(s.fBitmap->config() == SkBitmap::kARGB_8888_Config);
+ SkASSERT(kN32_SkColorType == s.fBitmap->colorType());
SkASSERT(s.fAlphaScale < 256);
const char* srcAddr = static_cast<const char*>(s.fBitmap->getPixels());
@@ -639,11 +638,11 @@ void ClampX_ClampY_nofilter_affine_SSE2(const SkBitmapProcState& s,
* It combines S32_opaque_D32_filter_DX_SSE2 and SkPixel32ToPixel16
*/
void S32_D16_filter_DX_SSE2(const SkBitmapProcState& s,
- const uint32_t* xy,
- int count, uint16_t* colors) {
+ const uint32_t* xy,
+ int count, uint16_t* colors) {
SkASSERT(count > 0 && colors != NULL);
SkASSERT(s.fFilterLevel != SkPaint::kNone_FilterLevel);
- SkASSERT(s.fBitmap->config() == SkBitmap::kARGB_8888_Config);
+ SkASSERT(kN32_SkColorType == s.fBitmap->colorType());
SkASSERT(s.fBitmap->isOpaque());
SkPMColor dstColor;
@@ -744,23 +743,6 @@ void S32_D16_filter_DX_SSE2(const SkBitmapProcState& s,
// Extract low int and store.
dstColor = _mm_cvtsi128_si32(sum);
- //*colors++ = SkPixel32ToPixel16(dstColor);
- // below is much faster than the above. It's tested for Android benchmark--Softweg
- __m128i _m_temp1 = _mm_set1_epi32(dstColor);
- __m128i _m_temp2 = _mm_srli_epi32(_m_temp1, 3);
-
- unsigned int r32 = _mm_cvtsi128_si32(_m_temp2);
- unsigned r = (r32 & ((1<<5) -1)) << 11;
-
- _m_temp2 = _mm_srli_epi32(_m_temp2, 7);
- unsigned int g32 = _mm_cvtsi128_si32(_m_temp2);
- unsigned g = (g32 & ((1<<6) -1)) << 5;
-
- _m_temp2 = _mm_srli_epi32(_m_temp2, 9);
- unsigned int b32 = _mm_cvtsi128_si32(_m_temp2);
- unsigned b = (b32 & ((1<<5) -1));
-
- *colors++ = r | g | b;
-
+ *colors++ = SkPixel32ToPixel16(dstColor);
} while (--count > 0);
}
diff --git a/chromium/third_party/skia/src/opts/SkBitmapProcState_opts_SSE2.h b/chromium/third_party/skia/src/opts/SkBitmapProcState_opts_SSE2.h
index 46e35a0f96f..82c5cc8d6e1 100644
--- a/chromium/third_party/skia/src/opts/SkBitmapProcState_opts_SSE2.h
+++ b/chromium/third_party/skia/src/opts/SkBitmapProcState_opts_SSE2.h
@@ -1,4 +1,3 @@
-
/*
* Copyright 2009 The Android Open Source Project
*
@@ -6,6 +5,8 @@
* found in the LICENSE file.
*/
+#ifndef SkBitmapProcState_opts_SSE2_DEFINED
+#define SkBitmapProcState_opts_SSE2_DEFINED
#include "SkBitmapProcState.h"
@@ -24,7 +25,9 @@ void ClampX_ClampY_nofilter_scale_SSE2(const SkBitmapProcState& s,
void ClampX_ClampY_filter_affine_SSE2(const SkBitmapProcState& s,
uint32_t xy[], int count, int x, int y);
void ClampX_ClampY_nofilter_affine_SSE2(const SkBitmapProcState& s,
- uint32_t xy[], int count, int x, int y);
+ uint32_t xy[], int count, int x, int y);
void S32_D16_filter_DX_SSE2(const SkBitmapProcState& s,
- const uint32_t* xy,
- int count, uint16_t* colors);
+ const uint32_t* xy,
+ int count, uint16_t* colors);
+
+#endif
diff --git a/chromium/third_party/skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp b/chromium/third_party/skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp
index f8342ecaad5..5b97215cc01 100644
--- a/chromium/third_party/skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp
+++ b/chromium/third_party/skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp
@@ -5,11 +5,19 @@
* found in the LICENSE file.
*/
-#include <tmmintrin.h> // SSSE3
#include "SkBitmapProcState_opts_SSSE3.h"
#include "SkPaint.h"
#include "SkUtils.h"
+/* With the exception of the Android framework we always build the SSSE3 functions
+ * and enable the caller to determine SSSE3 support. However for the Android framework
+ * if the device does not support SSSE3 then the compiler will not supply the required
+ * -mssse3 option needed to build this file, so instead we provide a stub implementation.
+ */
+#if !defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) || SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSSE3
+
+#include <tmmintrin.h> // SSSE3
+
// adding anonymous namespace seemed to force gcc to inline directly the
// instantiation, instead of creating the functions
// S32_generic_D32_filter_DX_SSSE3<true> and
@@ -387,7 +395,7 @@ void S32_generic_D32_filter_DX_SSSE3(const SkBitmapProcState& s,
int count, uint32_t* colors) {
SkASSERT(count > 0 && colors != NULL);
SkASSERT(s.fFilterLevel != SkPaint::kNone_FilterLevel);
- SkASSERT(s.fBitmap->config() == SkBitmap::kARGB_8888_Config);
+ SkASSERT(kN32_SkColorType == s.fBitmap->colorType());
if (has_alpha) {
SkASSERT(s.fAlphaScale < 256);
} else {
@@ -417,9 +425,10 @@ void S32_generic_D32_filter_DX_SSSE3(const SkBitmapProcState& s,
const __m128i zero = _mm_setzero_si128();
__m128i alpha = _mm_setzero_si128();
- if (has_alpha)
+ if (has_alpha) {
// 8x(alpha)
alpha = _mm_set1_epi16(s.fAlphaScale);
+ }
if (sub_y == 0) {
// Unroll 4x, interleave bytes, use pmaddubsw (all_x is small)
@@ -578,7 +587,7 @@ void S32_generic_D32_filter_DXDY_SSSE3(const SkBitmapProcState& s,
int count, uint32_t* colors) {
SkASSERT(count > 0 && colors != NULL);
SkASSERT(s.fFilterLevel != SkPaint::kNone_FilterLevel);
- SkASSERT(s.fBitmap->config() == SkBitmap::kARGB_8888_Config);
+ SkASSERT(kN32_SkColorType == s.fBitmap->colorType());
if (has_alpha) {
SkASSERT(s.fAlphaScale < 256);
} else {
@@ -697,7 +706,7 @@ void S32_generic_D32_filter_DXDY_SSSE3(const SkBitmapProcState& s,
*colors++ = _mm_cvtsi128_si32(sum0);
}
}
-} // namepace
+} // namespace
void S32_opaque_D32_filter_DX_SSSE3(const SkBitmapProcState& s,
const uint32_t* xy,
@@ -722,3 +731,31 @@ void S32_alpha_D32_filter_DXDY_SSSE3(const SkBitmapProcState& s,
int count, uint32_t* colors) {
S32_generic_D32_filter_DXDY_SSSE3<true>(s, xy, count, colors);
}
+
+#else // !defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) || SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSSE3
+
+void S32_opaque_D32_filter_DX_SSSE3(const SkBitmapProcState& s,
+ const uint32_t* xy,
+ int count, uint32_t* colors) {
+ sk_throw();
+}
+
+void S32_alpha_D32_filter_DX_SSSE3(const SkBitmapProcState& s,
+ const uint32_t* xy,
+ int count, uint32_t* colors) {
+ sk_throw();
+}
+
+void S32_opaque_D32_filter_DXDY_SSSE3(const SkBitmapProcState& s,
+ const uint32_t* xy,
+ int count, uint32_t* colors) {
+ sk_throw();
+}
+
+void S32_alpha_D32_filter_DXDY_SSSE3(const SkBitmapProcState& s,
+ const uint32_t* xy,
+ int count, uint32_t* colors) {
+ sk_throw();
+}
+
+#endif
diff --git a/chromium/third_party/skia/src/opts/SkBitmapProcState_opts_SSSE3.h b/chromium/third_party/skia/src/opts/SkBitmapProcState_opts_SSSE3.h
index 176f2bfbe74..9fd074aacf2 100644
--- a/chromium/third_party/skia/src/opts/SkBitmapProcState_opts_SSSE3.h
+++ b/chromium/third_party/skia/src/opts/SkBitmapProcState_opts_SSSE3.h
@@ -5,6 +5,9 @@
* found in the LICENSE file.
*/
+#ifndef SkBitmapProcState_opts_SSSE3_DEFINED
+#define SkBitmapProcState_opts_SSSE3_DEFINED
+
#include "SkBitmapProcState.h"
void S32_opaque_D32_filter_DX_SSSE3(const SkBitmapProcState& s,
@@ -19,3 +22,5 @@ void S32_opaque_D32_filter_DXDY_SSSE3(const SkBitmapProcState& s,
void S32_alpha_D32_filter_DXDY_SSSE3(const SkBitmapProcState& s,
const uint32_t* xy,
int count, uint32_t* colors);
+
+#endif
diff --git a/chromium/third_party/skia/src/opts/SkBitmapProcState_opts_arm.cpp b/chromium/third_party/skia/src/opts/SkBitmapProcState_opts_arm.cpp
index 96fbebd4e19..ffa0ccfa8aa 100644
--- a/chromium/third_party/skia/src/opts/SkBitmapProcState_opts_arm.cpp
+++ b/chromium/third_party/skia/src/opts/SkBitmapProcState_opts_arm.cpp
@@ -15,7 +15,7 @@
#include "SkConvolver.h"
-#if SK_ARM_ARCH >= 6 && !defined(SK_CPU_BENDIAN)
+#if !defined(SK_CPU_ARM64) && SK_ARM_ARCH >= 6 && !defined(SK_CPU_BENDIAN)
void SI8_D16_nofilter_DX_arm(
const SkBitmapProcState& s,
const uint32_t* SK_RESTRICT xy,
@@ -186,7 +186,7 @@ void SI8_opaque_D32_nofilter_DX_arm(const SkBitmapProcState& s,
s.fBitmap->getColorTable()->unlockColors();
}
-#endif // SK_ARM_ARCH >= 6 && !defined(SK_CPU_BENDIAN)
+#endif // !defined(SK_CPU_ARM64) && SK_ARM_ARCH >= 6 && !defined(SK_CPU_BENDIAN)
///////////////////////////////////////////////////////////////////////////////
@@ -194,6 +194,7 @@ void SI8_opaque_D32_nofilter_DX_arm(const SkBitmapProcState& s,
otherwise the shader won't even look at the matrix/sampler
*/
void SkBitmapProcState::platformProcs() {
+#if !defined(SK_CPU_ARM64) && SK_ARM_ARCH >= 6 && !defined(SK_CPU_BENDIAN)
bool isOpaque = 256 == fAlphaScale;
bool justDx = false;
@@ -201,9 +202,8 @@ void SkBitmapProcState::platformProcs() {
justDx = true;
}
- switch (fBitmap->config()) {
- case SkBitmap::kIndex8_Config:
-#if SK_ARM_ARCH >= 6 && !defined(SK_CPU_BENDIAN)
+ switch (fBitmap->colorType()) {
+ case kIndex_8_SkColorType:
if (justDx && SkPaint::kNone_FilterLevel == fFilterLevel) {
#if 0 /* crashing on android device */
fSampleProc16 = SI8_D16_nofilter_DX_arm;
@@ -215,11 +215,11 @@ void SkBitmapProcState::platformProcs() {
fShaderProc32 = NULL;
}
}
-#endif
break;
default:
break;
}
+#endif
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/third_party/skia/src/opts/SkBlitMask_opts_arm.cpp b/chromium/third_party/skia/src/opts/SkBlitMask_opts_arm.cpp
index 2bf760313c1..11e172c0d1d 100644
--- a/chromium/third_party/skia/src/opts/SkBlitMask_opts_arm.cpp
+++ b/chromium/third_party/skia/src/opts/SkBlitMask_opts_arm.cpp
@@ -1,3 +1,9 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
#include "SkColor.h"
#include "SkColorPriv.h"
@@ -5,21 +11,24 @@
#include "SkUtilsArm.h"
#include "SkBlitMask_opts_arm_neon.h"
-SkBlitMask::ColorProc SkBlitMask::PlatformColorProcs(SkBitmap::Config dstConfig,
+SkBlitMask::ColorProc SkBlitMask::PlatformColorProcs(SkColorType dstCT,
SkMask::Format maskFormat,
SkColor color) {
#if SK_ARM_NEON_IS_NONE
return NULL;
#else
+/* ** This has been disabled until we can diagnose and fix the SIGILL generated
+ ** in the NEON code. See http://skbug.com/2067 for details.
#if SK_ARM_NEON_IS_DYNAMIC
if (!sk_cpu_arm_has_neon()) {
return NULL;
}
#endif
- if ((SkBitmap::kARGB_8888_Config == dstConfig) &&
+ if ((kN32_SkColorType == dstCT) &&
(SkMask::kA8_Format == maskFormat)) {
return D32_A8_Factory_neon(color);
}
+*/
#endif
// We don't need to handle the SkMask::kLCD16_Format case as the default
@@ -36,7 +45,7 @@ SkBlitMask::BlitLCD16RowProc SkBlitMask::PlatformBlitRowProcs16(bool isOpaque) {
}
}
-SkBlitMask::RowProc SkBlitMask::PlatformRowProcs(SkBitmap::Config dstConfig,
+SkBlitMask::RowProc SkBlitMask::PlatformRowProcs(SkColorType dstCT,
SkMask::Format maskFormat,
RowFlags flags) {
return NULL;
diff --git a/chromium/third_party/skia/src/opts/SkBlitMask_opts_none.cpp b/chromium/third_party/skia/src/opts/SkBlitMask_opts_none.cpp
index 0ad09193871..90f89a71292 100644
--- a/chromium/third_party/skia/src/opts/SkBlitMask_opts_none.cpp
+++ b/chromium/third_party/skia/src/opts/SkBlitMask_opts_none.cpp
@@ -1,7 +1,13 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
#include "SkBlitMask.h"
-SkBlitMask::ColorProc SkBlitMask::PlatformColorProcs(SkBitmap::Config dstConfig,
+SkBlitMask::ColorProc SkBlitMask::PlatformColorProcs(SkColorType dstCT,
SkMask::Format maskFormat,
SkColor color) {
return NULL;
@@ -11,7 +17,7 @@ SkBlitMask::BlitLCD16RowProc SkBlitMask::PlatformBlitRowProcs16(bool isOpaque) {
return NULL;
}
-SkBlitMask::RowProc SkBlitMask::PlatformRowProcs(SkBitmap::Config dstConfig,
+SkBlitMask::RowProc SkBlitMask::PlatformRowProcs(SkColorType dstCT,
SkMask::Format maskFormat,
RowFlags flags) {
return NULL;
diff --git a/chromium/third_party/skia/src/opts/SkBlitRect_opts_SSE2.cpp b/chromium/third_party/skia/src/opts/SkBlitRect_opts_SSE2.cpp
index 3cb2b9c6d09..d65a313dadf 100644
--- a/chromium/third_party/skia/src/opts/SkBlitRect_opts_SSE2.cpp
+++ b/chromium/third_party/skia/src/opts/SkBlitRect_opts_SSE2.cpp
@@ -5,15 +5,14 @@
* found in the LICENSE file.
*/
+#include <emmintrin.h>
#include "SkBlitRect_opts_SSE2.h"
#include "SkBlitRow.h"
#include "SkColorPriv.h"
-#include <emmintrin.h>
-
-/** Simple blitting of opaque rectangles less than 31 pixels wide:
- inlines and merges sections of Color32_SSE2 and sk_memset32_SSE2.
-*/
+/* Simple blitting of opaque rectangles less than 31 pixels wide:
+ * inlines and merges sections of Color32_SSE2 and sk_memset32_SSE2.
+ */
static void BlitRect32_OpaqueNarrow_SSE2(SkPMColor* SK_RESTRICT destination,
int width, int height,
size_t rowBytes, uint32_t color) {
@@ -42,12 +41,12 @@ static void BlitRect32_OpaqueNarrow_SSE2(SkPMColor* SK_RESTRICT destination,
}
}
-/**
- Fast blitting of opaque rectangles at least 31 pixels wide:
- inlines and merges sections of Color32_SSE2 and sk_memset32_SSE2.
- A 31 pixel rectangle is guaranteed to have at least one
- 16-pixel aligned span that can take advantage of mm_store.
-*/
+/*
+ * Fast blitting of opaque rectangles at least 31 pixels wide:
+ * inlines and merges sections of Color32_SSE2 and sk_memset32_SSE2.
+ * A 31 pixel rectangle is guaranteed to have at least one
+ * 16-pixel aligned span that can take advantage of mm_store.
+ */
static void BlitRect32_OpaqueWide_SSE2(SkPMColor* SK_RESTRICT destination,
int width, int height,
size_t rowBytes, uint32_t color) {
diff --git a/chromium/third_party/skia/src/opts/SkBlitRect_opts_SSE2.h b/chromium/third_party/skia/src/opts/SkBlitRect_opts_SSE2.h
index 4d2f74a4b1b..3d09f5c3abc 100644
--- a/chromium/third_party/skia/src/opts/SkBlitRect_opts_SSE2.h
+++ b/chromium/third_party/skia/src/opts/SkBlitRect_opts_SSE2.h
@@ -8,13 +8,11 @@
#ifndef SkBlitRect_opts_SSE2_DEFINED
#define SkBlitRect_opts_SSE2_DEFINED
-/*
- These functions' implementations copy sections of both
- SkBlitRow_opts_SSE2 and SkUtils_opts_SSE2.
-*/
-
#include "SkColor.h"
+/* These functions' implementations copy sections of both
+ * SkBlitRow_opts_SSE2 and SkUtils_opts_SSE2.
+ */
void ColorRect32_SSE2(SkPMColor* SK_RESTRICT dst,
int width, int height,
size_t rowBytes, uint32_t color);
diff --git a/chromium/third_party/skia/src/opts/SkBlitRow_opts_SSE2.cpp b/chromium/third_party/skia/src/opts/SkBlitRow_opts_SSE2.cpp
index f3d010e3bc4..391b24c8673 100644
--- a/chromium/third_party/skia/src/opts/SkBlitRow_opts_SSE2.cpp
+++ b/chromium/third_party/skia/src/opts/SkBlitRow_opts_SSE2.cpp
@@ -5,14 +5,14 @@
* found in the LICENSE file.
*/
-
-#include "SkBlitRow_opts_SSE2.h"
+#include <emmintrin.h>
#include "SkBitmapProcState_opts_SSE2.h"
+#include "SkBlitRow_opts_SSE2.h"
#include "SkColorPriv.h"
+#include "SkColor_opts_SSE2.h"
+#include "SkDither.h"
#include "SkUtils.h"
-#include <emmintrin.h>
-
/* SSE2 version of S32_Blend_BlitRow32()
* portable version is in core/SkBlitRow_D32.cpp
*/
@@ -177,7 +177,7 @@ void S32A_Opaque_BlitRow32_SSE2(SkPMColor* SK_RESTRICT dst,
d++;
count -= 4;
}
- #else
+#else
__m128i rb_mask = _mm_set1_epi32(0x00FF00FF);
__m128i c_256 = _mm_set1_epi16(0x0100); // 8 copies of 256 (16-bit)
while (count >= 4) {
@@ -340,7 +340,6 @@ void S32A_Blend_BlitRow32_SSE2(SkPMColor* SK_RESTRICT dst,
*/
void Color32_SSE2(SkPMColor dst[], const SkPMColor src[], int count,
SkPMColor color) {
-
if (count <= 0) {
return;
}
@@ -404,7 +403,7 @@ void Color32_SSE2(SkPMColor dst[], const SkPMColor src[], int count,
}
src = reinterpret_cast<const SkPMColor*>(s);
dst = reinterpret_cast<SkPMColor*>(d);
- }
+ }
while (count > 0) {
*dst = color + SkAlphaMulQ(*src, scale);
@@ -502,7 +501,7 @@ void SkARGB32_A8_BlitMask_SSE2(void* device, size_t dstRB, const void* maskPtr,
}
dst = reinterpret_cast<SkPMColor *>(d);
}
- while(count > 0) {
+ while (count > 0) {
*dst= SkBlendARGB32(color, *dst, *mask);
dst += 1;
mask++;
@@ -851,3 +850,512 @@ void SkBlitLCD16OpaqueRow_SSE2(SkPMColor dst[], const uint16_t mask[],
width--;
}
}
+
+/* SSE2 version of S32_D565_Opaque()
+ * portable version is in core/SkBlitRow_D16.cpp
+ */
+void S32_D565_Opaque_SSE2(uint16_t* SK_RESTRICT dst,
+ const SkPMColor* SK_RESTRICT src, int count,
+ U8CPU alpha, int /*x*/, int /*y*/) {
+ SkASSERT(255 == alpha);
+
+ if (count <= 0) {
+ return;
+ }
+
+ if (count >= 8) {
+ while (((size_t)dst & 0x0F) != 0) {
+ SkPMColor c = *src++;
+ SkPMColorAssert(c);
+
+ *dst++ = SkPixel32ToPixel16_ToU16(c);
+ count--;
+ }
+
+ const __m128i* s = reinterpret_cast<const __m128i*>(src);
+ __m128i* d = reinterpret_cast<__m128i*>(dst);
+ __m128i r16_mask = _mm_set1_epi32(SK_R16_MASK);
+ __m128i g16_mask = _mm_set1_epi32(SK_G16_MASK);
+ __m128i b16_mask = _mm_set1_epi32(SK_B16_MASK);
+
+ while (count >= 8) {
+ // Load 8 pixels of src.
+ __m128i src_pixel1 = _mm_loadu_si128(s++);
+ __m128i src_pixel2 = _mm_loadu_si128(s++);
+
+ // Calculate result r.
+ __m128i r1 = _mm_srli_epi32(src_pixel1,
+ SK_R32_SHIFT + (8 - SK_R16_BITS));
+ r1 = _mm_and_si128(r1, r16_mask);
+ __m128i r2 = _mm_srli_epi32(src_pixel2,
+ SK_R32_SHIFT + (8 - SK_R16_BITS));
+ r2 = _mm_and_si128(r2, r16_mask);
+ __m128i r = _mm_packs_epi32(r1, r2);
+
+ // Calculate result g.
+ __m128i g1 = _mm_srli_epi32(src_pixel1,
+ SK_G32_SHIFT + (8 - SK_G16_BITS));
+ g1 = _mm_and_si128(g1, g16_mask);
+ __m128i g2 = _mm_srli_epi32(src_pixel2,
+ SK_G32_SHIFT + (8 - SK_G16_BITS));
+ g2 = _mm_and_si128(g2, g16_mask);
+ __m128i g = _mm_packs_epi32(g1, g2);
+
+ // Calculate result b.
+ __m128i b1 = _mm_srli_epi32(src_pixel1,
+ SK_B32_SHIFT + (8 - SK_B16_BITS));
+ b1 = _mm_and_si128(b1, b16_mask);
+ __m128i b2 = _mm_srli_epi32(src_pixel2,
+ SK_B32_SHIFT + (8 - SK_B16_BITS));
+ b2 = _mm_and_si128(b2, b16_mask);
+ __m128i b = _mm_packs_epi32(b1, b2);
+
+ // Store 8 16-bit colors in dst.
+ __m128i d_pixel = SkPackRGB16_SSE2(r, g, b);
+ _mm_store_si128(d++, d_pixel);
+ count -= 8;
+ }
+ src = reinterpret_cast<const SkPMColor*>(s);
+ dst = reinterpret_cast<uint16_t*>(d);
+ }
+
+ if (count > 0) {
+ do {
+ SkPMColor c = *src++;
+ SkPMColorAssert(c);
+ *dst++ = SkPixel32ToPixel16_ToU16(c);
+ } while (--count != 0);
+ }
+}
+
+/* SSE2 version of S32A_D565_Opaque()
+ * portable version is in core/SkBlitRow_D16.cpp
+ */
+void S32A_D565_Opaque_SSE2(uint16_t* SK_RESTRICT dst,
+ const SkPMColor* SK_RESTRICT src,
+ int count, U8CPU alpha, int /*x*/, int /*y*/) {
+ SkASSERT(255 == alpha);
+
+ if (count <= 0) {
+ return;
+ }
+
+ if (count >= 8) {
+ // Make dst 16 bytes alignment
+ while (((size_t)dst & 0x0F) != 0) {
+ SkPMColor c = *src++;
+ if (c) {
+ *dst = SkSrcOver32To16(c, *dst);
+ }
+ dst += 1;
+ count--;
+ }
+
+ const __m128i* s = reinterpret_cast<const __m128i*>(src);
+ __m128i* d = reinterpret_cast<__m128i*>(dst);
+ __m128i var255 = _mm_set1_epi16(255);
+ __m128i r16_mask = _mm_set1_epi16(SK_R16_MASK);
+ __m128i g16_mask = _mm_set1_epi16(SK_G16_MASK);
+ __m128i b16_mask = _mm_set1_epi16(SK_B16_MASK);
+
+ while (count >= 8) {
+ // Load 8 pixels of src.
+ __m128i src_pixel1 = _mm_loadu_si128(s++);
+ __m128i src_pixel2 = _mm_loadu_si128(s++);
+
+ // Check whether src pixels are equal to 0 and get the highest bit
+ // of each byte of result, if src pixels are all zero, src_cmp1 and
+ // src_cmp2 will be 0xFFFF.
+ int src_cmp1 = _mm_movemask_epi8(_mm_cmpeq_epi16(src_pixel1,
+ _mm_setzero_si128()));
+ int src_cmp2 = _mm_movemask_epi8(_mm_cmpeq_epi16(src_pixel2,
+ _mm_setzero_si128()));
+ if (src_cmp1 == 0xFFFF && src_cmp2 == 0xFFFF) {
+ d++;
+ count -= 8;
+ continue;
+ }
+
+ // Load 8 pixels of dst.
+ __m128i dst_pixel = _mm_load_si128(d);
+
+ // Extract A from src.
+ __m128i sa1 = _mm_slli_epi32(src_pixel1, (24 - SK_A32_SHIFT));
+ sa1 = _mm_srli_epi32(sa1, 24);
+ __m128i sa2 = _mm_slli_epi32(src_pixel2, (24 - SK_A32_SHIFT));
+ sa2 = _mm_srli_epi32(sa2, 24);
+ __m128i sa = _mm_packs_epi32(sa1, sa2);
+
+ // Extract R from src.
+ __m128i sr1 = _mm_slli_epi32(src_pixel1, (24 - SK_R32_SHIFT));
+ sr1 = _mm_srli_epi32(sr1, 24);
+ __m128i sr2 = _mm_slli_epi32(src_pixel2, (24 - SK_R32_SHIFT));
+ sr2 = _mm_srli_epi32(sr2, 24);
+ __m128i sr = _mm_packs_epi32(sr1, sr2);
+
+ // Extract G from src.
+ __m128i sg1 = _mm_slli_epi32(src_pixel1, (24 - SK_G32_SHIFT));
+ sg1 = _mm_srli_epi32(sg1, 24);
+ __m128i sg2 = _mm_slli_epi32(src_pixel2, (24 - SK_G32_SHIFT));
+ sg2 = _mm_srli_epi32(sg2, 24);
+ __m128i sg = _mm_packs_epi32(sg1, sg2);
+
+ // Extract B from src.
+ __m128i sb1 = _mm_slli_epi32(src_pixel1, (24 - SK_B32_SHIFT));
+ sb1 = _mm_srli_epi32(sb1, 24);
+ __m128i sb2 = _mm_slli_epi32(src_pixel2, (24 - SK_B32_SHIFT));
+ sb2 = _mm_srli_epi32(sb2, 24);
+ __m128i sb = _mm_packs_epi32(sb1, sb2);
+
+ // Extract R G B from dst.
+ __m128i dr = _mm_srli_epi16(dst_pixel, SK_R16_SHIFT);
+ dr = _mm_and_si128(dr, r16_mask);
+ __m128i dg = _mm_srli_epi16(dst_pixel, SK_G16_SHIFT);
+ dg = _mm_and_si128(dg, g16_mask);
+ __m128i db = _mm_srli_epi16(dst_pixel, SK_B16_SHIFT);
+ db = _mm_and_si128(db, b16_mask);
+
+ __m128i isa = _mm_sub_epi16(var255, sa); // 255 -sa
+
+ // Calculate R G B of result.
+ // Original algorithm is in SkSrcOver32To16().
+ dr = _mm_add_epi16(sr, SkMul16ShiftRound_SSE2(dr, isa, SK_R16_BITS));
+ dr = _mm_srli_epi16(dr, 8 - SK_R16_BITS);
+ dg = _mm_add_epi16(sg, SkMul16ShiftRound_SSE2(dg, isa, SK_G16_BITS));
+ dg = _mm_srli_epi16(dg, 8 - SK_G16_BITS);
+ db = _mm_add_epi16(sb, SkMul16ShiftRound_SSE2(db, isa, SK_B16_BITS));
+ db = _mm_srli_epi16(db, 8 - SK_B16_BITS);
+
+ // Pack R G B into 16-bit color.
+ __m128i d_pixel = SkPackRGB16_SSE2(dr, dg, db);
+
+ // Store 8 16-bit colors in dst.
+ _mm_store_si128(d++, d_pixel);
+ count -= 8;
+ }
+
+ src = reinterpret_cast<const SkPMColor*>(s);
+ dst = reinterpret_cast<uint16_t*>(d);
+ }
+
+ if (count > 0) {
+ do {
+ SkPMColor c = *src++;
+ SkPMColorAssert(c);
+ if (c) {
+ *dst = SkSrcOver32To16(c, *dst);
+ }
+ dst += 1;
+ } while (--count != 0);
+ }
+}
+
+void S32_D565_Opaque_Dither_SSE2(uint16_t* SK_RESTRICT dst,
+ const SkPMColor* SK_RESTRICT src,
+ int count, U8CPU alpha, int x, int y) {
+ SkASSERT(255 == alpha);
+
+ if (count <= 0) {
+ return;
+ }
+
+ if (count >= 8) {
+ while (((size_t)dst & 0x0F) != 0) {
+ DITHER_565_SCAN(y);
+ SkPMColor c = *src++;
+ SkPMColorAssert(c);
+
+ unsigned dither = DITHER_VALUE(x);
+ *dst++ = SkDitherRGB32To565(c, dither);
+ DITHER_INC_X(x);
+ count--;
+ }
+
+ unsigned short dither_value[8];
+ __m128i dither;
+#ifdef ENABLE_DITHER_MATRIX_4X4
+ const uint8_t* dither_scan = gDitherMatrix_3Bit_4X4[(y) & 3];
+ dither_value[0] = dither_value[4] = dither_scan[(x) & 3];
+ dither_value[1] = dither_value[5] = dither_scan[(x + 1) & 3];
+ dither_value[2] = dither_value[6] = dither_scan[(x + 2) & 3];
+ dither_value[3] = dither_value[7] = dither_scan[(x + 3) & 3];
+#else
+ const uint16_t dither_scan = gDitherMatrix_3Bit_16[(y) & 3];
+ dither_value[0] = dither_value[4] = (dither_scan
+ >> (((x) & 3) << 2)) & 0xF;
+ dither_value[1] = dither_value[5] = (dither_scan
+ >> (((x + 1) & 3) << 2)) & 0xF;
+ dither_value[2] = dither_value[6] = (dither_scan
+ >> (((x + 2) & 3) << 2)) & 0xF;
+ dither_value[3] = dither_value[7] = (dither_scan
+ >> (((x + 3) & 3) << 2)) & 0xF;
+#endif
+ dither = _mm_loadu_si128((__m128i*) dither_value);
+
+ const __m128i* s = reinterpret_cast<const __m128i*>(src);
+ __m128i* d = reinterpret_cast<__m128i*>(dst);
+
+ while (count >= 8) {
+ // Load 8 pixels of src.
+ __m128i src_pixel1 = _mm_loadu_si128(s++);
+ __m128i src_pixel2 = _mm_loadu_si128(s++);
+
+ // Extract R from src.
+ __m128i sr1 = _mm_slli_epi32(src_pixel1, (24 - SK_R32_SHIFT));
+ sr1 = _mm_srli_epi32(sr1, 24);
+ __m128i sr2 = _mm_slli_epi32(src_pixel2, (24 - SK_R32_SHIFT));
+ sr2 = _mm_srli_epi32(sr2, 24);
+ __m128i sr = _mm_packs_epi32(sr1, sr2);
+
+ // SkDITHER_R32To565(sr, dither)
+ __m128i sr_offset = _mm_srli_epi16(sr, 5);
+ sr = _mm_add_epi16(sr, dither);
+ sr = _mm_sub_epi16(sr, sr_offset);
+ sr = _mm_srli_epi16(sr, SK_R32_BITS - SK_R16_BITS);
+
+ // Extract G from src.
+ __m128i sg1 = _mm_slli_epi32(src_pixel1, (24 - SK_G32_SHIFT));
+ sg1 = _mm_srli_epi32(sg1, 24);
+ __m128i sg2 = _mm_slli_epi32(src_pixel2, (24 - SK_G32_SHIFT));
+ sg2 = _mm_srli_epi32(sg2, 24);
+ __m128i sg = _mm_packs_epi32(sg1, sg2);
+
+ // SkDITHER_R32To565(sg, dither)
+ __m128i sg_offset = _mm_srli_epi16(sg, 6);
+ sg = _mm_add_epi16(sg, _mm_srli_epi16(dither, 1));
+ sg = _mm_sub_epi16(sg, sg_offset);
+ sg = _mm_srli_epi16(sg, SK_G32_BITS - SK_G16_BITS);
+
+ // Extract B from src.
+ __m128i sb1 = _mm_slli_epi32(src_pixel1, (24 - SK_B32_SHIFT));
+ sb1 = _mm_srli_epi32(sb1, 24);
+ __m128i sb2 = _mm_slli_epi32(src_pixel2, (24 - SK_B32_SHIFT));
+ sb2 = _mm_srli_epi32(sb2, 24);
+ __m128i sb = _mm_packs_epi32(sb1, sb2);
+
+ // SkDITHER_R32To565(sb, dither)
+ __m128i sb_offset = _mm_srli_epi16(sb, 5);
+ sb = _mm_add_epi16(sb, dither);
+ sb = _mm_sub_epi16(sb, sb_offset);
+ sb = _mm_srli_epi16(sb, SK_B32_BITS - SK_B16_BITS);
+
+ // Pack and store 16-bit dst pixel.
+ __m128i d_pixel = SkPackRGB16_SSE2(sr, sg, sb);
+ _mm_store_si128(d++, d_pixel);
+
+ count -= 8;
+ x += 8;
+ }
+
+ src = reinterpret_cast<const SkPMColor*>(s);
+ dst = reinterpret_cast<uint16_t*>(d);
+ }
+
+ if (count > 0) {
+ DITHER_565_SCAN(y);
+ do {
+ SkPMColor c = *src++;
+ SkPMColorAssert(c);
+
+ unsigned dither = DITHER_VALUE(x);
+ *dst++ = SkDitherRGB32To565(c, dither);
+ DITHER_INC_X(x);
+ } while (--count != 0);
+ }
+}
+
+/* SSE2 version of S32A_D565_Opaque_Dither()
+ * portable version is in core/SkBlitRow_D16.cpp
+ */
+void S32A_D565_Opaque_Dither_SSE2(uint16_t* SK_RESTRICT dst,
+ const SkPMColor* SK_RESTRICT src,
+ int count, U8CPU alpha, int x, int y) {
+ SkASSERT(255 == alpha);
+
+ if (count <= 0) {
+ return;
+ }
+
+ if (count >= 8) {
+ while (((size_t)dst & 0x0F) != 0) {
+ DITHER_565_SCAN(y);
+ SkPMColor c = *src++;
+ SkPMColorAssert(c);
+ if (c) {
+ unsigned a = SkGetPackedA32(c);
+
+ int d = SkAlphaMul(DITHER_VALUE(x), SkAlpha255To256(a));
+
+ unsigned sr = SkGetPackedR32(c);
+ unsigned sg = SkGetPackedG32(c);
+ unsigned sb = SkGetPackedB32(c);
+ sr = SkDITHER_R32_FOR_565(sr, d);
+ sg = SkDITHER_G32_FOR_565(sg, d);
+ sb = SkDITHER_B32_FOR_565(sb, d);
+
+ uint32_t src_expanded = (sg << 24) | (sr << 13) | (sb << 2);
+ uint32_t dst_expanded = SkExpand_rgb_16(*dst);
+ dst_expanded = dst_expanded * (SkAlpha255To256(255 - a) >> 3);
+ // now src and dst expanded are in g:11 r:10 x:1 b:10
+ *dst = SkCompact_rgb_16((src_expanded + dst_expanded) >> 5);
+ }
+ dst += 1;
+ DITHER_INC_X(x);
+ count--;
+ }
+
+ unsigned short dither_value[8];
+ __m128i dither, dither_cur;
+#ifdef ENABLE_DITHER_MATRIX_4X4
+ const uint8_t* dither_scan = gDitherMatrix_3Bit_4X4[(y) & 3];
+ dither_value[0] = dither_value[4] = dither_scan[(x) & 3];
+ dither_value[1] = dither_value[5] = dither_scan[(x + 1) & 3];
+ dither_value[2] = dither_value[6] = dither_scan[(x + 2) & 3];
+ dither_value[3] = dither_value[7] = dither_scan[(x + 3) & 3];
+#else
+ const uint16_t dither_scan = gDitherMatrix_3Bit_16[(y) & 3];
+ dither_value[0] = dither_value[4] = (dither_scan
+ >> (((x) & 3) << 2)) & 0xF;
+ dither_value[1] = dither_value[5] = (dither_scan
+ >> (((x + 1) & 3) << 2)) & 0xF;
+ dither_value[2] = dither_value[6] = (dither_scan
+ >> (((x + 2) & 3) << 2)) & 0xF;
+ dither_value[3] = dither_value[7] = (dither_scan
+ >> (((x + 3) & 3) << 2)) & 0xF;
+#endif
+ dither = _mm_loadu_si128((__m128i*) dither_value);
+
+ const __m128i* s = reinterpret_cast<const __m128i*>(src);
+ __m128i* d = reinterpret_cast<__m128i*>(dst);
+ __m128i var256 = _mm_set1_epi16(256);
+ __m128i r16_mask = _mm_set1_epi16(SK_R16_MASK);
+ __m128i g16_mask = _mm_set1_epi16(SK_G16_MASK);
+ __m128i b16_mask = _mm_set1_epi16(SK_B16_MASK);
+
+ while (count >= 8) {
+ // Load 8 pixels of src and dst.
+ __m128i src_pixel1 = _mm_loadu_si128(s++);
+ __m128i src_pixel2 = _mm_loadu_si128(s++);
+ __m128i dst_pixel = _mm_load_si128(d);
+
+ // Extract A from src.
+ __m128i sa1 = _mm_slli_epi32(src_pixel1, (24 - SK_A32_SHIFT));
+ sa1 = _mm_srli_epi32(sa1, 24);
+ __m128i sa2 = _mm_slli_epi32(src_pixel2, (24 - SK_A32_SHIFT));
+ sa2 = _mm_srli_epi32(sa2, 24);
+ __m128i sa = _mm_packs_epi32(sa1, sa2);
+
+ // Calculate current dither value.
+ dither_cur = _mm_mullo_epi16(dither,
+ _mm_add_epi16(sa, _mm_set1_epi16(1)));
+ dither_cur = _mm_srli_epi16(dither_cur, 8);
+
+ // Extract R from src.
+ __m128i sr1 = _mm_slli_epi32(src_pixel1, (24 - SK_R32_SHIFT));
+ sr1 = _mm_srli_epi32(sr1, 24);
+ __m128i sr2 = _mm_slli_epi32(src_pixel2, (24 - SK_R32_SHIFT));
+ sr2 = _mm_srli_epi32(sr2, 24);
+ __m128i sr = _mm_packs_epi32(sr1, sr2);
+
+ // SkDITHER_R32_FOR_565(sr, d)
+ __m128i sr_offset = _mm_srli_epi16(sr, 5);
+ sr = _mm_add_epi16(sr, dither_cur);
+ sr = _mm_sub_epi16(sr, sr_offset);
+
+ // Expand sr.
+ sr = _mm_slli_epi16(sr, 2);
+
+ // Extract G from src.
+ __m128i sg1 = _mm_slli_epi32(src_pixel1, (24 - SK_G32_SHIFT));
+ sg1 = _mm_srli_epi32(sg1, 24);
+ __m128i sg2 = _mm_slli_epi32(src_pixel2, (24 - SK_G32_SHIFT));
+ sg2 = _mm_srli_epi32(sg2, 24);
+ __m128i sg = _mm_packs_epi32(sg1, sg2);
+
+ // sg = SkDITHER_G32_FOR_565(sg, d).
+ __m128i sg_offset = _mm_srli_epi16(sg, 6);
+ sg = _mm_add_epi16(sg, _mm_srli_epi16(dither_cur, 1));
+ sg = _mm_sub_epi16(sg, sg_offset);
+
+ // Expand sg.
+ sg = _mm_slli_epi16(sg, 3);
+
+ // Extract B from src.
+ __m128i sb1 = _mm_slli_epi32(src_pixel1, (24 - SK_B32_SHIFT));
+ sb1 = _mm_srli_epi32(sb1, 24);
+ __m128i sb2 = _mm_slli_epi32(src_pixel2, (24 - SK_B32_SHIFT));
+ sb2 = _mm_srli_epi32(sb2, 24);
+ __m128i sb = _mm_packs_epi32(sb1, sb2);
+
+ // sb = SkDITHER_B32_FOR_565(sb, d).
+ __m128i sb_offset = _mm_srli_epi16(sb, 5);
+ sb = _mm_add_epi16(sb, dither_cur);
+ sb = _mm_sub_epi16(sb, sb_offset);
+
+ // Expand sb.
+ sb = _mm_slli_epi16(sb, 2);
+
+ // Extract R G B from dst.
+ __m128i dr = _mm_srli_epi16(dst_pixel, SK_R16_SHIFT);
+ dr = _mm_and_si128(dr, r16_mask);
+ __m128i dg = _mm_srli_epi16(dst_pixel, SK_G16_SHIFT);
+ dg = _mm_and_si128(dg, g16_mask);
+ __m128i db = _mm_srli_epi16(dst_pixel, SK_B16_SHIFT);
+ db = _mm_and_si128(db, b16_mask);
+
+ // SkAlpha255To256(255 - a) >> 3
+ __m128i isa = _mm_sub_epi16(var256, sa);
+ isa = _mm_srli_epi16(isa, 3);
+
+ dr = _mm_mullo_epi16(dr, isa);
+ dr = _mm_add_epi16(dr, sr);
+ dr = _mm_srli_epi16(dr, 5);
+
+ dg = _mm_mullo_epi16(dg, isa);
+ dg = _mm_add_epi16(dg, sg);
+ dg = _mm_srli_epi16(dg, 5);
+
+ db = _mm_mullo_epi16(db, isa);
+ db = _mm_add_epi16(db, sb);
+ db = _mm_srli_epi16(db, 5);
+
+ // Package and store dst pixel.
+ __m128i d_pixel = SkPackRGB16_SSE2(dr, dg, db);
+ _mm_store_si128(d++, d_pixel);
+
+ count -= 8;
+ x += 8;
+ }
+
+ src = reinterpret_cast<const SkPMColor*>(s);
+ dst = reinterpret_cast<uint16_t*>(d);
+ }
+
+ if (count > 0) {
+ DITHER_565_SCAN(y);
+ do {
+ SkPMColor c = *src++;
+ SkPMColorAssert(c);
+ if (c) {
+ unsigned a = SkGetPackedA32(c);
+
+ int d = SkAlphaMul(DITHER_VALUE(x), SkAlpha255To256(a));
+
+ unsigned sr = SkGetPackedR32(c);
+ unsigned sg = SkGetPackedG32(c);
+ unsigned sb = SkGetPackedB32(c);
+ sr = SkDITHER_R32_FOR_565(sr, d);
+ sg = SkDITHER_G32_FOR_565(sg, d);
+ sb = SkDITHER_B32_FOR_565(sb, d);
+
+ uint32_t src_expanded = (sg << 24) | (sr << 13) | (sb << 2);
+ uint32_t dst_expanded = SkExpand_rgb_16(*dst);
+ dst_expanded = dst_expanded * (SkAlpha255To256(255 - a) >> 3);
+ // now src and dst expanded are in g:11 r:10 x:1 b:10
+ *dst = SkCompact_rgb_16((src_expanded + dst_expanded) >> 5);
+ }
+ dst += 1;
+ DITHER_INC_X(x);
+ } while (--count != 0);
+ }
+}
diff --git a/chromium/third_party/skia/src/opts/SkBlitRow_opts_SSE2.h b/chromium/third_party/skia/src/opts/SkBlitRow_opts_SSE2.h
index b443ec7f213..29fd96e5e91 100644
--- a/chromium/third_party/skia/src/opts/SkBlitRow_opts_SSE2.h
+++ b/chromium/third_party/skia/src/opts/SkBlitRow_opts_SSE2.h
@@ -1,4 +1,3 @@
-
/*
* Copyright 2009 The Android Open Source Project
*
@@ -6,6 +5,8 @@
* found in the LICENSE file.
*/
+#ifndef SkBlitRow_opts_SSE2_DEFINED
+#define SkBlitRow_opts_SSE2_DEFINED
#include "SkBlitRow.h"
@@ -28,3 +29,18 @@ void SkBlitLCD16Row_SSE2(SkPMColor dst[], const uint16_t src[],
SkColor color, int width, SkPMColor);
void SkBlitLCD16OpaqueRow_SSE2(SkPMColor dst[], const uint16_t src[],
SkColor color, int width, SkPMColor opaqueDst);
+
+void S32_D565_Opaque_SSE2(uint16_t* SK_RESTRICT dst,
+ const SkPMColor* SK_RESTRICT src, int count,
+ U8CPU alpha, int /*x*/, int /*y*/);
+void S32A_D565_Opaque_SSE2(uint16_t* SK_RESTRICT dst,
+ const SkPMColor* SK_RESTRICT src,
+ int count, U8CPU alpha, int /*x*/, int /*y*/);
+void S32_D565_Opaque_Dither_SSE2(uint16_t* SK_RESTRICT dst,
+ const SkPMColor* SK_RESTRICT src,
+ int count, U8CPU alpha, int x, int y);
+void S32A_D565_Opaque_Dither_SSE2(uint16_t* SK_RESTRICT dst,
+ const SkPMColor* SK_RESTRICT src,
+ int count, U8CPU alpha, int x, int y);
+
+#endif
diff --git a/chromium/third_party/skia/src/opts/SkBlitRow_opts_arm.cpp b/chromium/third_party/skia/src/opts/SkBlitRow_opts_arm.cpp
index e8e544e9dcb..34b8564723c 100644
--- a/chromium/third_party/skia/src/opts/SkBlitRow_opts_arm.cpp
+++ b/chromium/third_party/skia/src/opts/SkBlitRow_opts_arm.cpp
@@ -12,8 +12,6 @@
#include "SkUtils.h"
#include "SkUtilsArm.h"
-#include "SkCachePreload_arm.h"
-
// Define USE_NEON_CODE to indicate that we need to build NEON routines
#define USE_NEON_CODE (!SK_ARM_NEON_IS_NONE)
@@ -376,3 +374,7 @@ SkBlitRow::Proc32 SkBlitRow::PlatformProcs32(unsigned flags) {
SkBlitRow::ColorProc SkBlitRow::PlatformColorProc() {
return SK_ARM_NEON_WRAP(Color32_arm);
}
+
+SkBlitRow::ColorRectProc PlatformColorRectProcFactory() {
+ return NULL;
+}
diff --git a/chromium/third_party/skia/src/opts/SkBlitRow_opts_arm_neon.cpp b/chromium/third_party/skia/src/opts/SkBlitRow_opts_arm_neon.cpp
index 672980d0d26..01a6a2aa745 100644
--- a/chromium/third_party/skia/src/opts/SkBlitRow_opts_arm_neon.cpp
+++ b/chromium/third_party/skia/src/opts/SkBlitRow_opts_arm_neon.cpp
@@ -14,10 +14,56 @@
#include "SkMathPriv.h"
#include "SkUtils.h"
-#include "SkCachePreload_arm.h"
#include "SkColor_opts_neon.h"
#include <arm_neon.h>
+#ifdef SK_CPU_ARM64
+static inline uint8x8x4_t sk_vld4_u8_arm64_3(const SkPMColor* SK_RESTRICT & src) {
+ uint8x8x4_t vsrc;
+ uint8x8_t vsrc_0, vsrc_1, vsrc_2;
+
+ asm (
+ "ld4 {v0.8b - v3.8b}, [%[src]], #32 \t\n"
+ "mov %[vsrc0].8b, v0.8b \t\n"
+ "mov %[vsrc1].8b, v1.8b \t\n"
+ "mov %[vsrc2].8b, v2.8b \t\n"
+ : [vsrc0] "=w" (vsrc_0), [vsrc1] "=w" (vsrc_1),
+ [vsrc2] "=w" (vsrc_2), [src] "+&r" (src)
+ : : "v0", "v1", "v2", "v3"
+ );
+
+ vsrc.val[0] = vsrc_0;
+ vsrc.val[1] = vsrc_1;
+ vsrc.val[2] = vsrc_2;
+
+ return vsrc;
+}
+
+static inline uint8x8x4_t sk_vld4_u8_arm64_4(const SkPMColor* SK_RESTRICT & src) {
+ uint8x8x4_t vsrc;
+ uint8x8_t vsrc_0, vsrc_1, vsrc_2, vsrc_3;
+
+ asm (
+ "ld4 {v0.8b - v3.8b}, [%[src]], #32 \t\n"
+ "mov %[vsrc0].8b, v0.8b \t\n"
+ "mov %[vsrc1].8b, v1.8b \t\n"
+ "mov %[vsrc2].8b, v2.8b \t\n"
+ "mov %[vsrc3].8b, v3.8b \t\n"
+ : [vsrc0] "=w" (vsrc_0), [vsrc1] "=w" (vsrc_1),
+ [vsrc2] "=w" (vsrc_2), [vsrc3] "=w" (vsrc_3),
+ [src] "+&r" (src)
+ : : "v0", "v1", "v2", "v3"
+ );
+
+ vsrc.val[0] = vsrc_0;
+ vsrc.val[1] = vsrc_1;
+ vsrc.val[2] = vsrc_2;
+ vsrc.val[3] = vsrc_3;
+
+ return vsrc;
+}
+#endif
+
void S32_D565_Opaque_neon(uint16_t* SK_RESTRICT dst,
const SkPMColor* SK_RESTRICT src, int count,
U8CPU alpha, int /*x*/, int /*y*/) {
@@ -28,7 +74,12 @@ void S32_D565_Opaque_neon(uint16_t* SK_RESTRICT dst,
uint16x8_t vdst;
// Load
+#ifdef SK_CPU_ARM64
+ vsrc = sk_vld4_u8_arm64_3(src);
+#else
vsrc = vld4_u8((uint8_t*)src);
+ src += 8;
+#endif
// Convert src to 565
vdst = SkPixel32ToPixel16_neon8(vsrc);
@@ -38,7 +89,6 @@ void S32_D565_Opaque_neon(uint16_t* SK_RESTRICT dst,
// Prepare next iteration
dst += 8;
- src += 8;
count -= 8;
};
@@ -52,6 +102,92 @@ void S32_D565_Opaque_neon(uint16_t* SK_RESTRICT dst,
};
}
+void S32_D565_Blend_neon(uint16_t* SK_RESTRICT dst,
+ const SkPMColor* SK_RESTRICT src, int count,
+ U8CPU alpha, int /*x*/, int /*y*/) {
+ SkASSERT(255 > alpha);
+
+ uint16x8_t vmask_blue, vscale;
+
+ // prepare constants
+ vscale = vdupq_n_u16(SkAlpha255To256(alpha));
+ vmask_blue = vmovq_n_u16(0x1F);
+
+ while (count >= 8) {
+ uint8x8x4_t vsrc;
+ uint16x8_t vdst, vdst_r, vdst_g, vdst_b;
+ uint16x8_t vres_r, vres_g, vres_b;
+
+ // Load src
+#ifdef SK_CPU_ARM64
+ vsrc = sk_vld4_u8_arm64_3(src);
+#else
+ {
+ register uint8x8_t d0 asm("d0");
+ register uint8x8_t d1 asm("d1");
+ register uint8x8_t d2 asm("d2");
+ register uint8x8_t d3 asm("d3");
+
+ asm (
+ "vld4.8 {d0-d3},[%[src]]!"
+ : "=w" (d0), "=w" (d1), "=w" (d2), "=w" (d3), [src] "+&r" (src)
+ :
+ );
+ vsrc.val[0] = d0;
+ vsrc.val[1] = d1;
+ vsrc.val[2] = d2;
+ }
+#endif
+
+ // Load and unpack dst
+ vdst = vld1q_u16(dst);
+ vdst_g = vshlq_n_u16(vdst, 5); // shift green to top of lanes
+ vdst_b = vandq_u16(vdst, vmask_blue); // extract blue
+ vdst_r = vshrq_n_u16(vdst, 6+5); // extract red
+ vdst_g = vshrq_n_u16(vdst_g, 5+5); // extract green
+
+ // Shift src to 565 range
+ vsrc.val[NEON_R] = vshr_n_u8(vsrc.val[NEON_R], 3);
+ vsrc.val[NEON_G] = vshr_n_u8(vsrc.val[NEON_G], 2);
+ vsrc.val[NEON_B] = vshr_n_u8(vsrc.val[NEON_B], 3);
+
+ // Scale src - dst
+ vres_r = vmovl_u8(vsrc.val[NEON_R]) - vdst_r;
+ vres_g = vmovl_u8(vsrc.val[NEON_G]) - vdst_g;
+ vres_b = vmovl_u8(vsrc.val[NEON_B]) - vdst_b;
+
+ vres_r = vshrq_n_u16(vres_r * vscale, 8);
+ vres_g = vshrq_n_u16(vres_g * vscale, 8);
+ vres_b = vshrq_n_u16(vres_b * vscale, 8);
+
+ vres_r += vdst_r;
+ vres_g += vdst_g;
+ vres_b += vdst_b;
+
+ // Combine
+ vres_b = vsliq_n_u16(vres_b, vres_g, 5); // insert green into blue
+ vres_b = vsliq_n_u16(vres_b, vres_r, 6+5); // insert red into green/blue
+
+ // Store
+ vst1q_u16(dst, vres_b);
+ dst += 8;
+ count -= 8;
+ }
+ if (count > 0) {
+ int scale = SkAlpha255To256(alpha);
+ do {
+ SkPMColor c = *src++;
+ SkPMColorAssert(c);
+ uint16_t d = *dst;
+ *dst++ = SkPackRGB16(
+ SkAlphaBlend(SkPacked32ToR16(c), SkGetPackedR16(d), scale),
+ SkAlphaBlend(SkPacked32ToG16(c), SkGetPackedG16(d), scale),
+ SkAlphaBlend(SkPacked32ToB16(c), SkGetPackedB16(d), scale));
+ } while (--count != 0);
+ }
+}
+
+#ifdef SK_CPU_ARM32
void S32A_D565_Opaque_neon(uint16_t* SK_RESTRICT dst,
const SkPMColor* SK_RESTRICT src, int count,
U8CPU alpha, int /*x*/, int /*y*/) {
@@ -229,114 +365,129 @@ void S32A_D565_Opaque_neon(uint16_t* SK_RESTRICT dst,
);
}
}
+#endif
+
+static inline uint16x8_t SkDiv255Round_neon8(uint16x8_t prod) {
+ prod += vdupq_n_u16(128);
+ prod += vshrq_n_u16(prod, 8);
+ return vshrq_n_u16(prod, 8);
+}
void S32A_D565_Blend_neon(uint16_t* SK_RESTRICT dst,
const SkPMColor* SK_RESTRICT src, int count,
U8CPU alpha, int /*x*/, int /*y*/) {
+ SkASSERT(255 > alpha);
- U8CPU alpha_for_asm = alpha;
-
- asm volatile (
- /* This code implements a Neon version of S32A_D565_Blend. The output differs from
- * the original in two respects:
- * 1. The results have a few mismatches compared to the original code. These mismatches
- * never exceed 1. It's possible to improve accuracy vs. a floating point
- * implementation by introducing rounding right shifts (vrshr) for the final stage.
- * Rounding is not present in the code below, because although results would be closer
- * to a floating point implementation, the number of mismatches compared to the
- * original code would be far greater.
- * 2. On certain inputs, the original code can overflow, causing colour channels to
- * mix. Although the Neon code can also overflow, it doesn't allow one colour channel
- * to affect another.
+ /* This code implements a Neon version of S32A_D565_Blend. The results have
+ * a few mismatches compared to the original code. These mismatches never
+ * exceed 1.
*/
-#if 1
- /* reflects SkAlpha255To256()'s change from a+a>>7 to a+1 */
- "add %[alpha], %[alpha], #1 \n\t" // adjust range of alpha 0-256
+ if (count >= 8) {
+ uint16x8_t valpha_max, vmask_blue;
+ uint8x8_t valpha;
+
+ // prepare constants
+ valpha_max = vmovq_n_u16(255);
+ valpha = vdup_n_u8(alpha);
+ vmask_blue = vmovq_n_u16(SK_B16_MASK);
+
+ do {
+ uint16x8_t vdst, vdst_r, vdst_g, vdst_b;
+ uint16x8_t vres_a, vres_r, vres_g, vres_b;
+ uint8x8x4_t vsrc;
+
+ // load pixels
+ vdst = vld1q_u16(dst);
+#ifdef SK_CPU_ARM64
+ vsrc = sk_vld4_u8_arm64_4(src);
#else
- "add %[alpha], %[alpha], %[alpha], lsr #7 \n\t" // adjust range of alpha 0-256
+#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 6))
+ asm (
+ "vld4.u8 %h[vsrc], [%[src]]!"
+ : [vsrc] "=w" (vsrc), [src] "+&r" (src)
+ : :
+ );
+#else
+ register uint8x8_t d0 asm("d0");
+ register uint8x8_t d1 asm("d1");
+ register uint8x8_t d2 asm("d2");
+ register uint8x8_t d3 asm("d3");
+
+ asm volatile (
+ "vld4.u8 {d0-d3},[%[src]]!;"
+ : "=w" (d0), "=w" (d1), "=w" (d2), "=w" (d3),
+ [src] "+&r" (src)
+ : :
+ );
+ vsrc.val[0] = d0;
+ vsrc.val[1] = d1;
+ vsrc.val[2] = d2;
+ vsrc.val[3] = d3;
#endif
- "vmov.u16 q3, #255 \n\t" // set up constant
- "movs r4, %[count], lsr #3 \n\t" // calc. count>>3
- "vmov.u16 d2[0], %[alpha] \n\t" // move alpha to Neon
- "beq 2f \n\t" // if count8 == 0, exit
- "vmov.u16 q15, #0x1f \n\t" // set up blue mask
-
- "1: \n\t"
- "vld1.u16 {d0, d1}, [%[dst]] \n\t" // load eight dst RGB565 pixels
- "subs r4, r4, #1 \n\t" // decrement loop counter
- "vld4.u8 {d24, d25, d26, d27}, [%[src]]! \n\t" // load eight src ABGR32 pixels
- // and deinterleave
-
- "vshl.u16 q9, q0, #5 \n\t" // shift green to top of lanes
- "vand q10, q0, q15 \n\t" // extract blue
- "vshr.u16 q8, q0, #11 \n\t" // extract red
- "vshr.u16 q9, q9, #10 \n\t" // extract green
- // dstrgb = {q8, q9, q10}
-
- "vshr.u8 d24, d24, #3 \n\t" // shift red to 565 range
- "vshr.u8 d25, d25, #2 \n\t" // shift green to 565 range
- "vshr.u8 d26, d26, #3 \n\t" // shift blue to 565 range
-
- "vmovl.u8 q11, d24 \n\t" // widen red to 16 bits
- "vmovl.u8 q12, d25 \n\t" // widen green to 16 bits
- "vmovl.u8 q14, d27 \n\t" // widen alpha to 16 bits
- "vmovl.u8 q13, d26 \n\t" // widen blue to 16 bits
- // srcrgba = {q11, q12, q13, q14}
-
- "vmul.u16 q2, q14, d2[0] \n\t" // sa * src_scale
- "vmul.u16 q11, q11, d2[0] \n\t" // red result = src_red * src_scale
- "vmul.u16 q12, q12, d2[0] \n\t" // grn result = src_grn * src_scale
- "vmul.u16 q13, q13, d2[0] \n\t" // blu result = src_blu * src_scale
-
- "vshr.u16 q2, q2, #8 \n\t" // sa * src_scale >> 8
- "vsub.u16 q2, q3, q2 \n\t" // 255 - (sa * src_scale >> 8)
- // dst_scale = q2
-
- "vmla.u16 q11, q8, q2 \n\t" // red result += dst_red * dst_scale
- "vmla.u16 q12, q9, q2 \n\t" // grn result += dst_grn * dst_scale
- "vmla.u16 q13, q10, q2 \n\t" // blu result += dst_blu * dst_scale
-
-#if 1
- // trying for a better match with SkDiv255Round(a)
- // C alg is: a+=128; (a+a>>8)>>8
- // we'll use just a rounding shift [q2 is available for scratch]
- "vrshr.u16 q11, q11, #8 \n\t" // shift down red
- "vrshr.u16 q12, q12, #8 \n\t" // shift down green
- "vrshr.u16 q13, q13, #8 \n\t" // shift down blue
+#endif // #ifdef SK_CPU_ARM64
+
+
+ // deinterleave dst
+ vdst_g = vshlq_n_u16(vdst, SK_R16_BITS); // shift green to top of lanes
+ vdst_b = vdst & vmask_blue; // extract blue
+ vdst_r = vshrq_n_u16(vdst, SK_R16_SHIFT); // extract red
+ vdst_g = vshrq_n_u16(vdst_g, SK_R16_BITS + SK_B16_BITS); // extract green
+
+ // shift src to 565
+ vsrc.val[NEON_R] = vshr_n_u8(vsrc.val[NEON_R], 8 - SK_R16_BITS);
+ vsrc.val[NEON_G] = vshr_n_u8(vsrc.val[NEON_G], 8 - SK_G16_BITS);
+ vsrc.val[NEON_B] = vshr_n_u8(vsrc.val[NEON_B], 8 - SK_B16_BITS);
+
+ // calc src * src_scale
+ vres_a = vmull_u8(vsrc.val[NEON_A], valpha);
+ vres_r = vmull_u8(vsrc.val[NEON_R], valpha);
+ vres_g = vmull_u8(vsrc.val[NEON_G], valpha);
+ vres_b = vmull_u8(vsrc.val[NEON_B], valpha);
+
+ // prepare dst_scale
+ vres_a = SkDiv255Round_neon8(vres_a);
+ vres_a = valpha_max - vres_a; // 255 - (sa * src_scale) / 255
+
+ // add dst * dst_scale to previous result
+ vres_r = vmlaq_u16(vres_r, vdst_r, vres_a);
+ vres_g = vmlaq_u16(vres_g, vdst_g, vres_a);
+ vres_b = vmlaq_u16(vres_b, vdst_b, vres_a);
+
+#ifdef S32A_D565_BLEND_EXACT
+ // It is possible to get exact results with this but it is slow,
+ // even slower than C code in some cases
+ vres_r = SkDiv255Round_neon8(vres_r);
+ vres_g = SkDiv255Round_neon8(vres_g);
+ vres_b = SkDiv255Round_neon8(vres_b);
#else
- // arm's original "truncating divide by 256"
- "vshr.u16 q11, q11, #8 \n\t" // shift down red
- "vshr.u16 q12, q12, #8 \n\t" // shift down green
- "vshr.u16 q13, q13, #8 \n\t" // shift down blue
+ vres_r = vrshrq_n_u16(vres_r, 8);
+ vres_g = vrshrq_n_u16(vres_g, 8);
+ vres_b = vrshrq_n_u16(vres_b, 8);
#endif
+ // pack result
+ vres_b = vsliq_n_u16(vres_b, vres_g, SK_G16_SHIFT); // insert green into blue
+ vres_b = vsliq_n_u16(vres_b, vres_r, SK_R16_SHIFT); // insert red into green/blue
- "vsli.u16 q13, q12, #5 \n\t" // insert green into blue
- "vsli.u16 q13, q11, #11 \n\t" // insert red into green/blue
- "vst1.16 {d26, d27}, [%[dst]]! \n\t" // write pixel back to dst, update ptr
-
- "bne 1b \n\t" // if counter != 0, loop
- "2: \n\t" // exit
-
- : [src] "+r" (src), [dst] "+r" (dst), [count] "+r" (count), [alpha] "+r" (alpha_for_asm)
- :
- : "cc", "memory", "r4", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"
- );
+ // store
+ vst1q_u16(dst, vres_b);
+ dst += 8;
+ count -= 8;
+ } while (count >= 8);
+ }
- count &= 7;
- if (count > 0) {
- do {
- SkPMColor sc = *src++;
- if (sc) {
- uint16_t dc = *dst;
- unsigned dst_scale = 255 - SkMulDiv255Round(SkGetPackedA32(sc), alpha);
- unsigned dr = SkMulS16(SkPacked32ToR16(sc), alpha) + SkMulS16(SkGetPackedR16(dc), dst_scale);
- unsigned dg = SkMulS16(SkPacked32ToG16(sc), alpha) + SkMulS16(SkGetPackedG16(dc), dst_scale);
- unsigned db = SkMulS16(SkPacked32ToB16(sc), alpha) + SkMulS16(SkGetPackedB16(dc), dst_scale);
- *dst = SkPackRGB16(SkDiv255Round(dr), SkDiv255Round(dg), SkDiv255Round(db));
- }
- dst += 1;
- } while (--count != 0);
+ // leftovers
+ while (count-- > 0) {
+ SkPMColor sc = *src++;
+ if (sc) {
+ uint16_t dc = *dst;
+ unsigned dst_scale = 255 - SkMulDiv255Round(SkGetPackedA32(sc), alpha);
+ unsigned dr = SkMulS16(SkPacked32ToR16(sc), alpha) + SkMulS16(SkGetPackedR16(dc), dst_scale);
+ unsigned dg = SkMulS16(SkPacked32ToG16(sc), alpha) + SkMulS16(SkGetPackedG16(dc), dst_scale);
+ unsigned db = SkMulS16(SkPacked32ToB16(sc), alpha) + SkMulS16(SkGetPackedB16(dc), dst_scale);
+ *dst = SkPackRGB16(SkDiv255Round(dr), SkDiv255Round(dg), SkDiv255Round(db));
+ }
+ dst += 1;
}
}
@@ -374,6 +525,7 @@ void S32_D565_Blend_Dither_neon(uint16_t *dst, const SkPMColor *src,
do {
+ uint8x8x4_t vsrc;
uint8x8_t vsrc_r, vsrc_g, vsrc_b;
uint8x8_t vsrc565_r, vsrc565_g, vsrc565_b;
uint16x8_t vsrc_dit_r, vsrc_dit_g, vsrc_dit_b;
@@ -384,6 +536,9 @@ void S32_D565_Blend_Dither_neon(uint16_t *dst, const SkPMColor *src,
int8x8_t vres8_r, vres8_g, vres8_b;
// Load source and add dither
+#ifdef SK_CPU_ARM64
+ vsrc = sk_vld4_u8_arm64_3(src);
+#else
{
register uint8x8_t d0 asm("d0");
register uint8x8_t d1 asm("d1");
@@ -391,17 +546,18 @@ void S32_D565_Blend_Dither_neon(uint16_t *dst, const SkPMColor *src,
register uint8x8_t d3 asm("d3");
asm (
- "vld4.8 {d0-d3},[%[src]]! /* r=%P0 g=%P1 b=%P2 a=%P3 */"
+ "vld4.8 {d0-d3},[%[src]]! "
: "=w" (d0), "=w" (d1), "=w" (d2), "=w" (d3), [src] "+&r" (src)
:
);
- vsrc_g = d1;
-#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
- vsrc_r = d2; vsrc_b = d0;
-#elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
- vsrc_r = d0; vsrc_b = d2;
-#endif
+ vsrc.val[0] = d0;
+ vsrc.val[1] = d1;
+ vsrc.val[2] = d2;
}
+#endif
+ vsrc_r = vsrc.val[NEON_R];
+ vsrc_g = vsrc.val[NEON_G];
+ vsrc_b = vsrc.val[NEON_B];
vsrc565_g = vshr_n_u8(vsrc_g, 6); // calc. green >> 6
vsrc565_r = vshr_n_u8(vsrc_r, 5); // calc. red >> 5
@@ -766,76 +922,67 @@ void S32_Blend_BlitRow32_neon(SkPMColor* SK_RESTRICT dst,
const SkPMColor* SK_RESTRICT src,
int count, U8CPU alpha) {
SkASSERT(alpha <= 255);
- if (count > 0) {
- uint16_t src_scale = SkAlpha255To256(alpha);
- uint16_t dst_scale = 256 - src_scale;
-
- /* run them N at a time through the NEON unit */
- /* note that each 1 is 4 bytes, each treated exactly the same,
- * so we can work under that guise. We *do* know that the src&dst
- * will be 32-bit aligned quantities, so we can specify that on
- * the load/store ops and do a neon 'reinterpret' to get us to
- * byte-sized (pun intended) pieces that we widen/multiply/shift
- * we're limited at 128 bits in the wide ops, which is 8x16bits
- * or a pair of 32 bit src/dsts.
- */
- /* we *could* manually unroll this loop so that we load 128 bits
- * (as a pair of 64s) from each of src and dst, processing them
- * in pieces. This might give us a little better management of
- * the memory latency, but my initial attempts here did not
- * produce an instruction stream that looked all that nice.
- */
-#define UNROLL 2
- while (count >= UNROLL) {
- uint8x8_t src_raw, dst_raw, dst_final;
- uint16x8_t src_wide, dst_wide;
- /* get 64 bits of src, widen it, multiply by src_scale */
- src_raw = vreinterpret_u8_u32(vld1_u32(src));
- src_wide = vmovl_u8(src_raw);
- /* gcc hoists vdupq_n_u16(), better than using vmulq_n_u16() */
- src_wide = vmulq_u16 (src_wide, vdupq_n_u16(src_scale));
+ if (count <= 0) {
+ return;
+ }
- /* ditto with dst */
- dst_raw = vreinterpret_u8_u32(vld1_u32(dst));
- dst_wide = vmovl_u8(dst_raw);
+ uint16_t src_scale = SkAlpha255To256(alpha);
+ uint16_t dst_scale = 256 - src_scale;
- /* combine add with dst multiply into mul-accumulate */
- dst_wide = vmlaq_u16(src_wide, dst_wide, vdupq_n_u16(dst_scale));
+ while (count >= 2) {
+ uint8x8_t vsrc, vdst, vres;
+ uint16x8_t vsrc_wide, vdst_wide;
- dst_final = vshrn_n_u16(dst_wide, 8);
- vst1_u32(dst, vreinterpret_u32_u8(dst_final));
+ /* These commented prefetches are a big win for count
+ * values > 64 on an A9 (Pandaboard) but hurt by 10% for count = 4.
+ * They also hurt a little (<5%) on an A15
+ */
+ //__builtin_prefetch(src+32);
+ //__builtin_prefetch(dst+32);
- src += UNROLL;
- dst += UNROLL;
- count -= UNROLL;
+ // Load
+ vsrc = vreinterpret_u8_u32(vld1_u32(src));
+ vdst = vreinterpret_u8_u32(vld1_u32(dst));
+
+ // Process src
+ vsrc_wide = vmovl_u8(vsrc);
+ vsrc_wide = vmulq_u16(vsrc_wide, vdupq_n_u16(src_scale));
+
+ // Process dst
+ vdst_wide = vmull_u8(vdst, vdup_n_u8(dst_scale));
+
+ // Combine
+ vres = vshrn_n_u16(vdst_wide, 8) + vshrn_n_u16(vsrc_wide, 8);
+
+ // Store
+ vst1_u32(dst, vreinterpret_u32_u8(vres));
+
+ src += 2;
+ dst += 2;
+ count -= 2;
}
- /* RBE: well, i don't like how gcc manages src/dst across the above
- * loop it's constantly calculating src+bias, dst+bias and it only
- * adjusts the real ones when we leave the loop. Not sure why
- * it's "hoisting down" (hoisting implies above in my lexicon ;))
- * the adjustments to src/dst/count, but it does...
- * (might be SSA-style internal logic...
- */
-#if UNROLL == 2
if (count == 1) {
- *dst = SkAlphaMulQ(*src, src_scale) + SkAlphaMulQ(*dst, dst_scale);
- }
-#else
- if (count > 0) {
- do {
- *dst = SkAlphaMulQ(*src, src_scale) + SkAlphaMulQ(*dst, dst_scale);
- src += 1;
- dst += 1;
- } while (--count > 0);
- }
-#endif
+ uint8x8_t vsrc = vdup_n_u8(0), vdst = vdup_n_u8(0), vres;
+ uint16x8_t vsrc_wide, vdst_wide;
-#undef UNROLL
+ // Load
+ vsrc = vreinterpret_u8_u32(vld1_lane_u32(src, vreinterpret_u32_u8(vsrc), 0));
+ vdst = vreinterpret_u8_u32(vld1_lane_u32(dst, vreinterpret_u32_u8(vdst), 0));
+
+ // Process
+ vsrc_wide = vmovl_u8(vsrc);
+ vsrc_wide = vmulq_u16(vsrc_wide, vdupq_n_u16(src_scale));
+ vdst_wide = vmull_u8(vdst, vdup_n_u8(dst_scale));
+ vres = vshrn_n_u16(vdst_wide, 8) + vshrn_n_u16(vsrc_wide, 8);
+
+ // Store
+ vst1_lane_u32(dst, vreinterpret_u32_u8(vres), 0);
}
}
+#ifdef SK_CPU_ARM32
void S32A_Blend_BlitRow32_neon(SkPMColor* SK_RESTRICT dst,
const SkPMColor* SK_RESTRICT src,
int count, U8CPU alpha) {
@@ -961,6 +1108,7 @@ static void showme16(char *str, void *p, int len)
SkDebugf("%s\n", buf);
}
#endif
+#endif // #ifdef SK_CPU_ARM32
void S32A_D565_Opaque_Dither_neon (uint16_t * SK_RESTRICT dst,
const SkPMColor* SK_RESTRICT src,
@@ -970,9 +1118,8 @@ void S32A_D565_Opaque_Dither_neon (uint16_t * SK_RESTRICT dst,
#define UNROLL 8
if (count >= UNROLL) {
- uint8x8_t dbase;
-#if defined(DEBUG_OPAQUE_DITHER)
+#if defined(DEBUG_OPAQUE_DITHER)
uint16_t tmpbuf[UNROLL];
int td[UNROLL];
int tdv[UNROLL];
@@ -983,35 +1130,37 @@ void S32A_D565_Opaque_Dither_neon (uint16_t * SK_RESTRICT dst,
int noisy = 0;
#endif
+ uint8x8_t dbase;
const uint8_t *dstart = &gDitherMatrix_Neon[(y&3)*12 + (x&3)];
dbase = vld1_u8(dstart);
do {
+ uint8x8x4_t vsrc;
uint8x8_t sr, sg, sb, sa, d;
uint16x8_t dst8, scale8, alpha8;
uint16x8_t dst_r, dst_g, dst_b;
-#if defined(DEBUG_OPAQUE_DITHER)
- /* calculate 8 elements worth into a temp buffer */
- {
- int my_y = y;
- int my_x = x;
- SkPMColor* my_src = (SkPMColor*)src;
- uint16_t* my_dst = dst;
- int i;
-
- DITHER_565_SCAN(my_y);
- for(i=0;i<UNROLL;i++) {
+#if defined(DEBUG_OPAQUE_DITHER)
+ // calculate 8 elements worth into a temp buffer
+ {
+ int my_y = y;
+ int my_x = x;
+ SkPMColor* my_src = (SkPMColor*)src;
+ uint16_t* my_dst = dst;
+ int i;
+
+ DITHER_565_SCAN(my_y);
+ for(i = 0; i < UNROLL; i++) {
SkPMColor c = *my_src++;
SkPMColorAssert(c);
if (c) {
unsigned a = SkGetPackedA32(c);
int d = SkAlphaMul(DITHER_VALUE(my_x), SkAlpha255To256(a));
- tdv[i] = DITHER_VALUE(my_x);
- ta[i] = a;
- tap[i] = SkAlpha255To256(a);
- td[i] = d;
+ tdv[i] = DITHER_VALUE(my_x);
+ ta[i] = a;
+ tap[i] = SkAlpha255To256(a);
+ td[i] = d;
unsigned sr = SkGetPackedR32(c);
unsigned sg = SkGetPackedG32(c);
@@ -1025,147 +1174,132 @@ void S32A_D565_Opaque_Dither_neon (uint16_t * SK_RESTRICT dst,
dst_expanded = dst_expanded * (SkAlpha255To256(255 - a) >> 3);
// now src and dst expanded are in g:11 r:10 x:1 b:10
tmpbuf[i] = SkCompact_rgb_16((src_expanded + dst_expanded) >> 5);
- td[i] = d;
-
+ td[i] = d;
} else {
- tmpbuf[i] = *my_dst;
- ta[i] = tdv[i] = td[i] = 0xbeef;
- }
- in_dst[i] = *my_dst;
+ tmpbuf[i] = *my_dst;
+ ta[i] = tdv[i] = td[i] = 0xbeef;
+ }
+ in_dst[i] = *my_dst;
my_dst += 1;
DITHER_INC_X(my_x);
- }
- }
+ }
+ }
#endif
- /* source is in ABGR */
+#ifdef SK_CPU_ARM64
+ vsrc = sk_vld4_u8_arm64_4(src);
+#else
{
register uint8x8_t d0 asm("d0");
register uint8x8_t d1 asm("d1");
register uint8x8_t d2 asm("d2");
register uint8x8_t d3 asm("d3");
- asm ("vld4.8 {d0-d3},[%4] /* r=%P0 g=%P1 b=%P2 a=%P3 */"
- : "=w" (d0), "=w" (d1), "=w" (d2), "=w" (d3)
- : "r" (src)
- );
- sr = d0; sg = d1; sb = d2; sa = d3;
+ asm ("vld4.8 {d0-d3},[%[src]]! "
+ : "=w" (d0), "=w" (d1), "=w" (d2), "=w" (d3), [src] "+r" (src)
+ :
+ );
+ vsrc.val[0] = d0;
+ vsrc.val[1] = d1;
+ vsrc.val[2] = d2;
+ vsrc.val[3] = d3;
}
-
- /* calculate 'd', which will be 0..7 */
- /* dbase[] is 0..7; alpha is 0..256; 16 bits suffice */
-#if defined(SK_BUILD_FOR_ANDROID)
- /* SkAlpha255To256() semantic a+1 vs a+a>>7 */
- alpha8 = vaddw_u8(vmovl_u8(sa), vdup_n_u8(1));
-#else
- alpha8 = vaddw_u8(vmovl_u8(sa), vshr_n_u8(sa, 7));
#endif
- alpha8 = vmulq_u16(alpha8, vmovl_u8(dbase));
- d = vshrn_n_u16(alpha8, 8); /* narrowing too */
+ sa = vsrc.val[NEON_A];
+ sr = vsrc.val[NEON_R];
+ sg = vsrc.val[NEON_G];
+ sb = vsrc.val[NEON_B];
- /* sr = sr - (sr>>5) + d */
+ /* calculate 'd', which will be 0..7
+ * dbase[] is 0..7; alpha is 0..256; 16 bits suffice
+ */
+ alpha8 = vmovl_u8(dbase);
+ alpha8 = vmlal_u8(alpha8, sa, dbase);
+ d = vshrn_n_u16(alpha8, 8); // narrowing too
+
+ // sr = sr - (sr>>5) + d
/* watching for 8-bit overflow. d is 0..7; risky range of
* sr is >248; and then (sr>>5) is 7 so it offsets 'd';
- * safe as long as we do ((sr-sr>>5) + d) */
+ * safe as long as we do ((sr-sr>>5) + d)
+ */
sr = vsub_u8(sr, vshr_n_u8(sr, 5));
sr = vadd_u8(sr, d);
- /* sb = sb - (sb>>5) + d */
+ // sb = sb - (sb>>5) + d
sb = vsub_u8(sb, vshr_n_u8(sb, 5));
sb = vadd_u8(sb, d);
- /* sg = sg - (sg>>6) + d>>1; similar logic for overflows */
+ // sg = sg - (sg>>6) + d>>1; similar logic for overflows
sg = vsub_u8(sg, vshr_n_u8(sg, 6));
sg = vadd_u8(sg, vshr_n_u8(d,1));
- /* need to pick up 8 dst's -- at 16 bits each, 128 bits */
+ // need to pick up 8 dst's -- at 16 bits each, 128 bits
dst8 = vld1q_u16(dst);
- dst_b = vandq_u16(dst8, vdupq_n_u16(0x001F));
- dst_g = vandq_u16(vshrq_n_u16(dst8,5), vdupq_n_u16(0x003F));
- dst_r = vshrq_n_u16(dst8,11); /* clearing hi bits */
-
- /* blend */
-#if 1
- /* SkAlpha255To256() semantic a+1 vs a+a>>7 */
- /* originally 255-sa + 1 */
+ dst_b = vandq_u16(dst8, vdupq_n_u16(SK_B16_MASK));
+ dst_g = vshrq_n_u16(vshlq_n_u16(dst8, SK_R16_BITS), SK_R16_BITS + SK_B16_BITS);
+ dst_r = vshrq_n_u16(dst8, SK_R16_SHIFT); // clearing hi bits
+
+ // blend
scale8 = vsubw_u8(vdupq_n_u16(256), sa);
-#else
- scale8 = vsubw_u8(vdupq_n_u16(255), sa);
- scale8 = vaddq_u16(scale8, vshrq_n_u16(scale8, 7));
-#endif
-#if 1
- /* combine the addq and mul, save 3 insns */
+ // combine the addq and mul, save 3 insns
scale8 = vshrq_n_u16(scale8, 3);
dst_b = vmlaq_u16(vshll_n_u8(sb,2), dst_b, scale8);
dst_g = vmlaq_u16(vshll_n_u8(sg,3), dst_g, scale8);
dst_r = vmlaq_u16(vshll_n_u8(sr,2), dst_r, scale8);
-#else
- /* known correct, but +3 insns over above */
- scale8 = vshrq_n_u16(scale8, 3);
- dst_b = vmulq_u16(dst_b, scale8);
- dst_g = vmulq_u16(dst_g, scale8);
- dst_r = vmulq_u16(dst_r, scale8);
-
- /* combine */
- /* NB: vshll widens, need to preserve those bits */
- dst_b = vaddq_u16(dst_b, vshll_n_u8(sb,2));
- dst_g = vaddq_u16(dst_g, vshll_n_u8(sg,3));
- dst_r = vaddq_u16(dst_r, vshll_n_u8(sr,2));
-#endif
- /* repack to store */
- dst8 = vandq_u16(vshrq_n_u16(dst_b, 5), vdupq_n_u16(0x001F));
+ // repack to store
+ dst8 = vshrq_n_u16(dst_b, 5);
dst8 = vsliq_n_u16(dst8, vshrq_n_u16(dst_g, 5), 5);
dst8 = vsliq_n_u16(dst8, vshrq_n_u16(dst_r,5), 11);
vst1q_u16(dst, dst8);
-#if defined(DEBUG_OPAQUE_DITHER)
- /* verify my 8 elements match the temp buffer */
- {
- int i, bad=0;
- static int invocation;
-
- for (i=0;i<UNROLL;i++)
- if (tmpbuf[i] != dst[i]) bad=1;
- if (bad) {
- SkDebugf("BAD S32A_D565_Opaque_Dither_neon(); invocation %d offset %d\n",
- invocation, offset);
- SkDebugf(" alpha 0x%x\n", alpha);
- for (i=0;i<UNROLL;i++)
- SkDebugf("%2d: %s %04x w %04x id %04x s %08x d %04x %04x %04x %04x\n",
- i, ((tmpbuf[i] != dst[i])?"BAD":"got"),
- dst[i], tmpbuf[i], in_dst[i], src[i], td[i], tdv[i], tap[i], ta[i]);
-
- showme16("alpha8", &alpha8, sizeof(alpha8));
- showme16("scale8", &scale8, sizeof(scale8));
- showme8("d", &d, sizeof(d));
- showme16("dst8", &dst8, sizeof(dst8));
- showme16("dst_b", &dst_b, sizeof(dst_b));
- showme16("dst_g", &dst_g, sizeof(dst_g));
- showme16("dst_r", &dst_r, sizeof(dst_r));
- showme8("sb", &sb, sizeof(sb));
- showme8("sg", &sg, sizeof(sg));
- showme8("sr", &sr, sizeof(sr));
-
- /* cop out */
- return;
- }
- offset += UNROLL;
- invocation++;
- }
-#endif
+#if defined(DEBUG_OPAQUE_DITHER)
+ // verify my 8 elements match the temp buffer
+ {
+ int i, bad=0;
+ static int invocation;
- dst += UNROLL;
- src += UNROLL;
+ for (i = 0; i < UNROLL; i++) {
+ if (tmpbuf[i] != dst[i]) {
+ bad=1;
+ }
+ }
+ if (bad) {
+ SkDebugf("BAD S32A_D565_Opaque_Dither_neon(); invocation %d offset %d\n",
+ invocation, offset);
+ SkDebugf(" alpha 0x%x\n", alpha);
+ for (i = 0; i < UNROLL; i++)
+ SkDebugf("%2d: %s %04x w %04x id %04x s %08x d %04x %04x %04x %04x\n",
+ i, ((tmpbuf[i] != dst[i])?"BAD":"got"), dst[i], tmpbuf[i],
+ in_dst[i], src[i-8], td[i], tdv[i], tap[i], ta[i]);
+
+ showme16("alpha8", &alpha8, sizeof(alpha8));
+ showme16("scale8", &scale8, sizeof(scale8));
+ showme8("d", &d, sizeof(d));
+ showme16("dst8", &dst8, sizeof(dst8));
+ showme16("dst_b", &dst_b, sizeof(dst_b));
+ showme16("dst_g", &dst_g, sizeof(dst_g));
+ showme16("dst_r", &dst_r, sizeof(dst_r));
+ showme8("sb", &sb, sizeof(sb));
+ showme8("sg", &sg, sizeof(sg));
+ showme8("sr", &sr, sizeof(sr));
+
+ return;
+ }
+ offset += UNROLL;
+ invocation++;
+ }
+#endif
+ dst += UNROLL;
count -= UNROLL;
- /* skip x += UNROLL, since it's unchanged mod-4 */
+ // skip x += UNROLL, since it's unchanged mod-4
} while (count >= UNROLL);
}
#undef UNROLL
- /* residuals */
+ // residuals
if (count > 0) {
DITHER_565_SCAN(y);
do {
@@ -1218,7 +1352,11 @@ void S32_D565_Opaque_Dither_neon(uint16_t* SK_RESTRICT dst,
uint8x8_t sr, sg, sb;
uint16x8_t dr, dg, db;
uint16x8_t dst8;
+ uint8x8x4_t vsrc;
+#ifdef SK_CPU_ARM64
+ vsrc = sk_vld4_u8_arm64_3(src);
+#else
{
register uint8x8_t d0 asm("d0");
register uint8x8_t d1 asm("d1");
@@ -1226,17 +1364,19 @@ void S32_D565_Opaque_Dither_neon(uint16_t* SK_RESTRICT dst,
register uint8x8_t d3 asm("d3");
asm (
- "vld4.8 {d0-d3},[%[src]]! /* r=%P0 g=%P1 b=%P2 a=%P3 */"
+ "vld4.8 {d0-d3},[%[src]]! "
: "=w" (d0), "=w" (d1), "=w" (d2), "=w" (d3), [src] "+&r" (src)
:
);
- sg = d1;
-#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
- sr = d2; sb = d0;
-#elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
- sr = d0; sb = d2;
-#endif
+ vsrc.val[0] = d0;
+ vsrc.val[1] = d1;
+ vsrc.val[2] = d2;
}
+#endif
+ sr = vsrc.val[NEON_R];
+ sg = vsrc.val[NEON_G];
+ sb = vsrc.val[NEON_B];
+
/* XXX: if we want to prefetch, hide it in the above asm()
* using the gcc __builtin_prefetch(), the prefetch will
* fall to the bottom of the loop -- it won't stick up
@@ -1321,84 +1461,88 @@ void Color32_arm_neon(SkPMColor* dst, const SkPMColor* src, int count,
unsigned colorA = SkGetPackedA32(color);
if (255 == colorA) {
sk_memset32(dst, color, count);
- } else {
- unsigned scale = 256 - SkAlpha255To256(colorA);
+ return;
+ }
- if (count >= 8) {
- // at the end of this assembly, count will have been decremented
- // to a negative value. That is, if count mod 8 = x, it will be
- // -8 +x coming out.
- asm volatile (
- PLD128(src, 0)
-
- "vdup.32 q0, %[color] \n\t"
-
- PLD128(src, 128)
-
- // scale numerical interval [0-255], so load as 8 bits
- "vdup.8 d2, %[scale] \n\t"
-
- PLD128(src, 256)
-
- "subs %[count], %[count], #8 \n\t"
-
- PLD128(src, 384)
-
- "Loop_Color32: \n\t"
-
- // load src color, 8 pixels, 4 64 bit registers
- // (and increment src).
- "vld1.32 {d4-d7}, [%[src]]! \n\t"
-
- PLD128(src, 384)
-
- // multiply long by scale, 64 bits at a time,
- // destination into a 128 bit register.
- "vmull.u8 q4, d4, d2 \n\t"
- "vmull.u8 q5, d5, d2 \n\t"
- "vmull.u8 q6, d6, d2 \n\t"
- "vmull.u8 q7, d7, d2 \n\t"
-
- // shift the 128 bit registers, containing the 16
- // bit scaled values back to 8 bits, narrowing the
- // results to 64 bit registers.
- "vshrn.i16 d8, q4, #8 \n\t"
- "vshrn.i16 d9, q5, #8 \n\t"
- "vshrn.i16 d10, q6, #8 \n\t"
- "vshrn.i16 d11, q7, #8 \n\t"
-
- // adding back the color, using 128 bit registers.
- "vadd.i8 q6, q4, q0 \n\t"
- "vadd.i8 q7, q5, q0 \n\t"
-
- // store back the 8 calculated pixels (2 128 bit
- // registers), and increment dst.
- "vst1.32 {d12-d15}, [%[dst]]! \n\t"
-
- "subs %[count], %[count], #8 \n\t"
- "bge Loop_Color32 \n\t"
- : [src] "+r" (src), [dst] "+r" (dst), [count] "+r" (count)
- : [color] "r" (color), [scale] "r" (scale)
- : "cc", "memory",
- "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
- "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15"
- );
- // At this point, if we went through the inline assembly, count is
- // a negative value:
- // if the value is -8, there is no pixel left to process.
- // if the value is -7, there is one pixel left to process
- // ...
- // And'ing it with 7 will give us the number of pixels
- // left to process.
- count = count & 0x7;
- }
+ unsigned scale = 256 - SkAlpha255To256(colorA);
- while (count > 0) {
- *dst = color + SkAlphaMulQ(*src, scale);
- src += 1;
- dst += 1;
- count--;
- }
+ if (count >= 8) {
+ uint32x4_t vcolor;
+ uint8x8_t vscale;
+
+ vcolor = vdupq_n_u32(color);
+
+ // scale numerical interval [0-255], so load as 8 bits
+ vscale = vdup_n_u8(scale);
+
+ do {
+ // load src color, 8 pixels, 4 64 bit registers
+ // (and increment src).
+ uint32x2x4_t vsrc;
+#if defined(SK_CPU_ARM32) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 6)))
+ asm (
+ "vld1.32 %h[vsrc], [%[src]]!"
+ : [vsrc] "=w" (vsrc), [src] "+r" (src)
+ : :
+ );
+#else // 64bit targets and Clang
+ vsrc.val[0] = vld1_u32(src);
+ vsrc.val[1] = vld1_u32(src+2);
+ vsrc.val[2] = vld1_u32(src+4);
+ vsrc.val[3] = vld1_u32(src+6);
+ src += 8;
+#endif
+
+ // multiply long by scale, 64 bits at a time,
+ // destination into a 128 bit register.
+ uint16x8x4_t vtmp;
+ vtmp.val[0] = vmull_u8(vreinterpret_u8_u32(vsrc.val[0]), vscale);
+ vtmp.val[1] = vmull_u8(vreinterpret_u8_u32(vsrc.val[1]), vscale);
+ vtmp.val[2] = vmull_u8(vreinterpret_u8_u32(vsrc.val[2]), vscale);
+ vtmp.val[3] = vmull_u8(vreinterpret_u8_u32(vsrc.val[3]), vscale);
+
+ // shift the 128 bit registers, containing the 16
+ // bit scaled values back to 8 bits, narrowing the
+ // results to 64 bit registers.
+ uint8x16x2_t vres;
+ vres.val[0] = vcombine_u8(
+ vshrn_n_u16(vtmp.val[0], 8),
+ vshrn_n_u16(vtmp.val[1], 8));
+ vres.val[1] = vcombine_u8(
+ vshrn_n_u16(vtmp.val[2], 8),
+ vshrn_n_u16(vtmp.val[3], 8));
+
+ // adding back the color, using 128 bit registers.
+ uint32x4x2_t vdst;
+ vdst.val[0] = vreinterpretq_u32_u8(vres.val[0] +
+ vreinterpretq_u8_u32(vcolor));
+ vdst.val[1] = vreinterpretq_u32_u8(vres.val[1] +
+ vreinterpretq_u8_u32(vcolor));
+
+ // store back the 8 calculated pixels (2 128 bit
+ // registers), and increment dst.
+#if defined(SK_CPU_ARM32) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 6)))
+ asm (
+ "vst1.32 %h[vdst], [%[dst]]!"
+ : [dst] "+r" (dst)
+ : [vdst] "w" (vdst)
+ : "memory"
+ );
+#else // 64bit targets and Clang
+ vst1q_u32(dst, vdst.val[0]);
+ vst1q_u32(dst+4, vdst.val[1]);
+ dst += 8;
+#endif
+ count -= 8;
+
+ } while (count >= 8);
+ }
+
+ while (count > 0) {
+ *dst = color + SkAlphaMulQ(*src, scale);
+ src += 1;
+ dst += 1;
+ count--;
}
}
@@ -1406,12 +1550,13 @@ void Color32_arm_neon(SkPMColor* dst, const SkPMColor* src, int count,
const SkBlitRow::Proc sk_blitrow_platform_565_procs_arm_neon[] = {
// no dither
- // NOTE: For the S32_D565_Blend function below, we don't have a special
- // version that assumes that each source pixel is opaque. But our
- // S32A is still faster than the default, so use it.
S32_D565_Opaque_neon,
- S32A_D565_Blend_neon, // really S32_D565_Blend
+ S32_D565_Blend_neon,
+#ifdef SK_CPU_ARM32
S32A_D565_Opaque_neon,
+#else
+ NULL,
+#endif
S32A_D565_Blend_neon,
// dither
@@ -1439,5 +1584,9 @@ const SkBlitRow::Proc32 sk_blitrow_platform_32_procs_arm_neon[] = {
#else
S32A_Opaque_BlitRow32_neon, // S32A_Opaque,
#endif
+#ifdef SK_CPU_ARM32
S32A_Blend_BlitRow32_neon // S32A_Blend
+#else
+ NULL
+#endif
};
diff --git a/chromium/third_party/skia/src/opts/SkBlitRow_opts_mips_dsp.cpp b/chromium/third_party/skia/src/opts/SkBlitRow_opts_mips_dsp.cpp
new file mode 100644
index 00000000000..30bb4c2701a
--- /dev/null
+++ b/chromium/third_party/skia/src/opts/SkBlitRow_opts_mips_dsp.cpp
@@ -0,0 +1,848 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkBlitRow.h"
+#include "SkBlitMask.h"
+#include "SkColorPriv.h"
+#include "SkDither.h"
+#include "SkMathPriv.h"
+
+static void S32_D565_Blend_mips_dsp(uint16_t* SK_RESTRICT dst,
+ const SkPMColor* SK_RESTRICT src, int count,
+ U8CPU alpha, int /*x*/, int /*y*/) {
+ register uint32_t t0, t1, t2, t3, t4, t5, t6;
+ register uint32_t s0, s1, s2, s4, s5, s6;
+
+ alpha += 1;
+ if (count >= 2) {
+ __asm__ volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "sll %[s4], %[alpha], 8 \n\t"
+ "or %[s4], %[s4], %[alpha] \n\t"
+ "repl.ph %[s5], 0x1f \n\t"
+ "repl.ph %[s6], 0x3f \n\t"
+ "1: \n\t"
+ "lw %[s2], 0(%[src]) \n\t"
+ "lw %[s1], 4(%[src]) \n\t"
+ "lwr %[s0], 0(%[dst]) \n\t"
+ "lwl %[s0], 3(%[dst]) \n\t"
+ "and %[t1], %[s0], %[s5] \n\t"
+ "shra.ph %[t0], %[s0], 5 \n\t"
+ "and %[t2], %[t0], %[s6] \n\t"
+#ifdef __MIPS_HAVE_DSPR2
+ "shrl.ph %[t3], %[s0], 11 \n\t"
+#else
+ "shra.ph %[t0], %[s0], 11 \n\t"
+ "and %[t3], %[t0], %[s5] \n\t"
+#endif
+ "precrq.ph.w %[t0], %[s1], %[s2] \n\t"
+ "shrl.qb %[t5], %[t0], 3 \n\t"
+ "and %[t4], %[t5], %[s5] \n\t"
+ "ins %[s2], %[s1], 16, 16 \n\t"
+ "preceu.ph.qbra %[t0], %[s2] \n\t"
+ "shrl.qb %[t6], %[t0], 3 \n\t"
+#ifdef __MIPS_HAVE_DSPR2
+ "shrl.ph %[t5], %[s2], 10 \n\t"
+#else
+ "shra.ph %[t0], %[s2], 10 \n\t"
+ "and %[t5], %[t0], %[s6] \n\t"
+#endif
+ "subu.qb %[t4], %[t4], %[t1] \n\t"
+ "subu.qb %[t5], %[t5], %[t2] \n\t"
+ "subu.qb %[t6], %[t6], %[t3] \n\t"
+ "muleu_s.ph.qbr %[t4], %[s4], %[t4] \n\t"
+ "muleu_s.ph.qbr %[t5], %[s4], %[t5] \n\t"
+ "muleu_s.ph.qbr %[t6], %[s4], %[t6] \n\t"
+ "addiu %[count], %[count], -2 \n\t"
+ "addiu %[src], %[src], 8 \n\t"
+ "shra.ph %[t4], %[t4], 8 \n\t"
+ "shra.ph %[t5], %[t5], 8 \n\t"
+ "shra.ph %[t6], %[t6], 8 \n\t"
+ "addu.qb %[t4], %[t4], %[t1] \n\t"
+ "addu.qb %[t5], %[t5], %[t2] \n\t"
+ "addu.qb %[t6], %[t6], %[t3] \n\t"
+ "andi %[s0], %[t4], 0xffff \n\t"
+ "andi %[t0], %[t5], 0xffff \n\t"
+ "sll %[t0], %[t0], 0x5 \n\t"
+ "or %[s0], %[s0], %[t0] \n\t"
+ "sll %[t0], %[t6], 0xb \n\t"
+ "or %[t0], %[t0], %[s0] \n\t"
+ "sh %[t0], 0(%[dst]) \n\t"
+ "srl %[s1], %[t4], 16 \n\t"
+ "srl %[t0], %[t5], 16 \n\t"
+ "sll %[t5], %[t0], 5 \n\t"
+ "or %[t0], %[t5], %[s1] \n\t"
+ "srl %[s0], %[t6], 16 \n\t"
+ "sll %[s2], %[s0], 0xb \n\t"
+ "or %[s1], %[s2], %[t0] \n\t"
+ "sh %[s1], 2(%[dst]) \n\t"
+ "bge %[count], 2, 1b \n\t"
+ " addiu %[dst], %[dst], 4 \n\t"
+ ".set pop \n\t"
+ : [t0]"=&r"(t0), [t1]"=&r"(t1), [t2]"=&r"(t2), [t3]"=&r"(t3),
+ [t4]"=&r"(t4), [t5]"=&r"(t5), [t6]"=&r"(t6), [s0]"=&r"(s0),
+ [s1]"=&r"(s1), [s2]"=&r"(s2), [s4]"=&r"(s4), [s5]"=&r"(s5),
+ [s6]"=&r"(s6), [count]"+r"(count), [dst]"+r"(dst),
+ [src]"+r"(src)
+ : [alpha]"r"(alpha)
+ : "memory", "hi", "lo"
+ );
+ }
+
+ if (count == 1) {
+ SkPMColor c = *src++;
+ SkPMColorAssert(c);
+ SkASSERT(SkGetPackedA32(c) == 255);
+ uint16_t d = *dst;
+ *dst++ = SkPackRGB16(SkAlphaBlend(SkPacked32ToR16(c), SkGetPackedR16(d), alpha),
+ SkAlphaBlend(SkPacked32ToG16(c), SkGetPackedG16(d), alpha),
+ SkAlphaBlend(SkPacked32ToB16(c), SkGetPackedB16(d), alpha));
+ }
+}
+
+static void S32A_D565_Opaque_Dither_mips_dsp(uint16_t* __restrict__ dst,
+ const SkPMColor* __restrict__ src,
+ int count, U8CPU alpha, int x, int y) {
+ __asm__ volatile (
+ "pref 0, 0(%[src]) \n\t"
+ "pref 1, 0(%[dst]) \n\t"
+ "pref 0, 32(%[src]) \n\t"
+ "pref 1, 32(%[dst]) \n\t"
+ :
+ : [src]"r"(src), [dst]"r"(dst)
+ : "memory"
+ );
+
+ register int32_t t0, t1, t2, t3, t4, t5, t6;
+ register int32_t t7, t8, t9, s0, s1, s2, s3;
+ const uint16_t dither_scan = gDitherMatrix_3Bit_16[(y) & 3];
+
+ if (count >= 2) {
+ __asm__ volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "li %[s1], 0x01010101 \n\t"
+ "li %[s2], -2017 \n\t"
+ "1: \n\t"
+ "bnez %[s3], 4f \n\t"
+ " li %[s3], 2 \n\t"
+ "pref 0, 64(%[src]) \n\t"
+ "pref 1, 64(%[dst]) \n\t"
+ "4: \n\t"
+ "addiu %[s3], %[s3], -1 \n\t"
+ "lw %[t1], 0(%[src]) \n\t"
+ "andi %[t3], %[x], 0x3 \n\t"
+ "addiu %[x], %[x], 1 \n\t"
+ "sll %[t4], %[t3], 2 \n\t"
+ "srav %[t5], %[dither_scan], %[t4] \n\t"
+ "andi %[t3], %[t5], 0xf \n\t"
+ "lw %[t2], 4(%[src]) \n\t"
+ "andi %[t4], %[x], 0x3 \n\t"
+ "sll %[t5], %[t4], 2 \n\t"
+ "srav %[t6], %[dither_scan], %[t5] \n\t"
+ "addiu %[x], %[x], 1 \n\t"
+ "ins %[t3], %[t6], 8, 4 \n\t"
+ "srl %[t4], %[t1], 24 \n\t"
+ "addiu %[t0], %[t4], 1 \n\t"
+ "srl %[t4], %[t2], 24 \n\t"
+ "addiu %[t5], %[t4], 1 \n\t"
+ "ins %[t0], %[t5], 16, 16 \n\t"
+ "muleu_s.ph.qbr %[t4], %[t3], %[t0] \n\t"
+ "preceu.ph.qbla %[t3], %[t4] \n\t"
+ "andi %[t4], %[t1], 0xff \n\t"
+ "ins %[t4], %[t2], 16, 8 \n\t"
+ "shrl.qb %[t5], %[t4], 5 \n\t"
+ "subu.qb %[t6], %[t3], %[t5] \n\t"
+ "addq.ph %[t5], %[t6], %[t4] \n\t"
+ "ext %[t4], %[t1], 8, 8 \n\t"
+ "srl %[t6], %[t2], 8 \n\t"
+ "ins %[t4], %[t6], 16, 8 \n\t"
+ "shrl.qb %[t6], %[t4], 6 \n\t"
+ "shrl.qb %[t7], %[t3], 1 \n\t"
+ "subu.qb %[t8], %[t7], %[t6] \n\t"
+ "addq.ph %[t6], %[t8], %[t4] \n\t"
+ "ext %[t4], %[t1], 16, 8 \n\t"
+ "srl %[t7], %[t2], 16 \n\t"
+ "ins %[t4], %[t7], 16, 8 \n\t"
+ "shrl.qb %[t7], %[t4], 5 \n\t"
+ "subu.qb %[t8], %[t3], %[t7] \n\t"
+ "addq.ph %[t7], %[t8], %[t4] \n\t"
+ "shll.ph %[t4], %[t7], 2 \n\t"
+ "andi %[t9], %[t4], 0xffff \n\t"
+ "srl %[s0], %[t4], 16 \n\t"
+ "andi %[t3], %[t6], 0xffff \n\t"
+ "srl %[t4], %[t6], 16 \n\t"
+ "andi %[t6], %[t5], 0xffff \n\t"
+ "srl %[t7], %[t5], 16 \n\t"
+ "subq.ph %[t5], %[s1], %[t0] \n\t"
+ "srl %[t0], %[t5], 3 \n\t"
+ "beqz %[t1], 3f \n\t"
+ " lhu %[t5], 0(%[dst]) \n\t"
+ "sll %[t1], %[t6], 13 \n\t"
+ "or %[t8], %[t9], %[t1] \n\t"
+ "sll %[t1], %[t3], 24 \n\t"
+ "or %[t9], %[t1], %[t8] \n\t"
+ "andi %[t3], %[t5], 0x7e0 \n\t"
+ "sll %[t6], %[t3], 0x10 \n\t"
+ "and %[t8], %[s2], %[t5] \n\t"
+ "or %[t5], %[t6], %[t8] \n\t"
+ "andi %[t6], %[t0], 0xff \n\t"
+ "mul %[t1], %[t6], %[t5] \n\t"
+ "addu %[t5], %[t1], %[t9] \n\t"
+ "srl %[t6], %[t5], 5 \n\t"
+ "and %[t5], %[s2], %[t6] \n\t"
+ "srl %[t8], %[t6], 16 \n\t"
+ "andi %[t6], %[t8], 0x7e0 \n\t"
+ "or %[t1], %[t5], %[t6] \n\t"
+ "sh %[t1], 0(%[dst]) \n\t"
+ "3: \n\t"
+ "beqz %[t2], 2f \n\t"
+ " lhu %[t5], 2(%[dst]) \n\t"
+ "sll %[t1], %[t7], 13 \n\t"
+ "or %[t8], %[s0], %[t1] \n\t"
+ "sll %[t1], %[t4], 24 \n\t"
+ "or %[t9], %[t1], %[t8] \n\t"
+ "andi %[t3], %[t5], 0x7e0 \n\t"
+ "sll %[t6], %[t3], 0x10 \n\t"
+ "and %[t8], %[s2], %[t5] \n\t"
+ "or %[t5], %[t6], %[t8] \n\t"
+ "srl %[t6], %[t0], 16 \n\t"
+ "mul %[t1], %[t6], %[t5] \n\t"
+ "addu %[t5], %[t1], %[t9] \n\t"
+ "srl %[t6], %[t5], 5 \n\t"
+ "and %[t5], %[s2], %[t6] \n\t"
+ "srl %[t8], %[t6], 16 \n\t"
+ "andi %[t6], %[t8], 0x7e0 \n\t"
+ "or %[t1], %[t5], %[t6] \n\t"
+ "sh %[t1], 2(%[dst]) \n\t"
+ "2: \n\t"
+ "addiu %[count], %[count], -2 \n\t"
+ "addiu %[src], %[src], 8 \n\t"
+ "addiu %[t1], %[count], -1 \n\t"
+ "bgtz %[t1], 1b \n\t"
+ " addiu %[dst], %[dst], 4 \n\t"
+ ".set pop \n\t"
+ : [src]"+r"(src), [count]"+r"(count), [dst]"+r"(dst), [x]"+r"(x),
+ [t0]"=&r"(t0), [t1]"=&r"(t1), [t2]"=&r"(t2), [t3]"=&r"(t3),
+ [t4]"=&r"(t4), [t5]"=&r"(t5), [t6]"=&r"(t6), [t7]"=&r"(t7),
+ [t8]"=&r"(t8), [t9]"=&r"(t9), [s0]"=&r"(s0), [s1]"=&r"(s1),
+ [s2]"=&r"(s2), [s3]"=&r"(s3)
+ : [dither_scan]"r"(dither_scan)
+ : "memory", "hi", "lo"
+ );
+ }
+
+ if (count == 1) {
+ SkPMColor c = *src++;
+ SkPMColorAssert(c);
+ if (c) {
+ unsigned a = SkGetPackedA32(c);
+ int d = SkAlphaMul(DITHER_VALUE(x), SkAlpha255To256(a));
+
+ unsigned sr = SkGetPackedR32(c);
+ unsigned sg = SkGetPackedG32(c);
+ unsigned sb = SkGetPackedB32(c);
+ sr = SkDITHER_R32_FOR_565(sr, d);
+ sg = SkDITHER_G32_FOR_565(sg, d);
+ sb = SkDITHER_B32_FOR_565(sb, d);
+
+ uint32_t src_expanded = (sg << 24) | (sr << 13) | (sb << 2);
+ uint32_t dst_expanded = SkExpand_rgb_16(*dst);
+ dst_expanded = dst_expanded * (SkAlpha255To256(255 - a) >> 3);
+ // now src and dst expanded are in g:11 r:10 x:1 b:10
+ *dst = SkCompact_rgb_16((src_expanded + dst_expanded) >> 5);
+ }
+ dst += 1;
+ DITHER_INC_X(x);
+ }
+}
+
+static void S32_D565_Opaque_Dither_mips_dsp(uint16_t* __restrict__ dst,
+ const SkPMColor* __restrict__ src,
+ int count, U8CPU alpha, int x, int y) {
+ uint16_t dither_scan = gDitherMatrix_3Bit_16[(y) & 3];
+ register uint32_t t0, t1, t2, t3, t4, t5;
+ register uint32_t t6, t7, t8, t9, s0;
+ int dither[4];
+ int i;
+
+ for (i = 0; i < 4; i++, x++) {
+ dither[i] = (dither_scan >> ((x & 3) << 2)) & 0xF;
+ }
+
+ __asm__ volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "li %[s0], 1 \n\t"
+ "2: \n\t"
+ "beqz %[count], 1f \n\t"
+ " nop \n\t"
+ "addiu %[t0], %[count], -1 \n\t"
+ "beqz %[t0], 1f \n\t"
+ " nop \n\t"
+ "beqz %[s0], 3f \n\t"
+ " nop \n\t"
+ "lw %[t0], 0(%[dither]) \n\t"
+ "lw %[t1], 4(%[dither]) \n\t"
+ "li %[s0], 0 \n\t"
+ "b 4f \n\t"
+ " nop \n\t"
+ "3: \n\t"
+ "lw %[t0], 8(%[dither]) \n\t"
+ "lw %[t1], 12(%[dither]) \n\t"
+ "li %[s0], 1 \n\t"
+ "4: \n\t"
+ "sll %[t2], %[t0], 16 \n\t"
+ "or %[t1], %[t2], %[t1] \n\t"
+ "lw %[t0], 0(%[src]) \n\t"
+ "lw %[t2], 4(%[src]) \n\t"
+ "precrq.ph.w %[t3], %[t0], %[t2] \n\t"
+ "preceu.ph.qbra %[t9], %[t3] \n\t"
+#ifdef __MIPS_HAVE_DSPR2
+ "append %[t0], %[t2], 16 \n\t"
+ "preceu.ph.qbra %[t4], %[t0] \n\t"
+ "preceu.ph.qbla %[t5], %[t0] \n\t"
+#else
+ "sll %[t6], %[t0], 16 \n\t"
+ "sll %[t7], %[t2], 16 \n\t"
+ "precrq.ph.w %[t8], %[t6], %[t7] \n\t"
+ "preceu.ph.qbra %[t4], %[t8] \n\t"
+ "preceu.ph.qbla %[t5], %[t8] \n\t"
+#endif
+ "addu.qb %[t0], %[t4], %[t1] \n\t"
+ "shra.ph %[t2], %[t4], 5 \n\t"
+ "subu.qb %[t3], %[t0], %[t2] \n\t"
+ "shra.ph %[t6], %[t3], 3 \n\t"
+ "addu.qb %[t0], %[t9], %[t1] \n\t"
+ "shra.ph %[t2], %[t9], 5 \n\t"
+ "subu.qb %[t3], %[t0], %[t2] \n\t"
+ "shra.ph %[t7], %[t3], 3 \n\t"
+ "shra.ph %[t0], %[t1], 1 \n\t"
+ "shra.ph %[t2], %[t5], 6 \n\t"
+ "addu.qb %[t3], %[t5], %[t0] \n\t"
+ "subu.qb %[t4], %[t3], %[t2] \n\t"
+ "shra.ph %[t8], %[t4], 2 \n\t"
+ "precrq.ph.w %[t0], %[t6], %[t7] \n\t"
+#ifdef __MIPS_HAVE_DSPR2
+ "append %[t6], %[t7], 16 \n\t"
+#else
+ "sll %[t6], %[t6], 16 \n\t"
+ "sll %[t2], %[t7], 16 \n\t"
+ "precrq.ph.w %[t6], %[t6], %[t2] \n\t"
+#endif
+ "sra %[t4], %[t8], 16 \n\t"
+ "andi %[t5], %[t8], 0xFF \n\t"
+ "sll %[t7], %[t4], 5 \n\t"
+ "sra %[t8], %[t0], 5 \n\t"
+ "or %[t9], %[t7], %[t8] \n\t"
+ "or %[t3], %[t9], %[t0] \n\t"
+ "andi %[t4], %[t3], 0xFFFF \n\t"
+ "sll %[t7], %[t5], 5 \n\t"
+ "sra %[t8], %[t6], 5 \n\t"
+ "or %[t9], %[t7], %[t8] \n\t"
+ "or %[t3], %[t9], %[t6] \n\t"
+ "and %[t7], %[t3], 0xFFFF \n\t"
+ "sh %[t4], 0(%[dst]) \n\t"
+ "sh %[t7], 2(%[dst]) \n\t"
+ "addiu %[count], %[count], -2 \n\t"
+ "addiu %[src], %[src], 8 \n\t"
+ "b 2b \n\t"
+ " addiu %[dst], %[dst], 4 \n\t"
+ "1: \n\t"
+ ".set pop \n\t"
+ : [dst]"+r"(dst), [src]"+r"(src), [count]"+r"(count),
+ [x]"+r"(x), [t0]"=&r"(t0), [t1]"=&r"(t1), [t2]"=&r"(t2),
+ [t3]"=&r"(t3), [t4]"=&r"(t4), [t5]"=&r"(t5), [t6]"=&r"(t6),
+ [t7]"=&r"(t7), [t8]"=&r"(t8), [t9]"=&r"(t9), [s0]"=&r"(s0)
+ : [dither] "r" (dither)
+ : "memory"
+ );
+
+ if (count == 1) {
+ SkPMColor c = *src++;
+ SkPMColorAssert(c); // only if DEBUG is turned on
+ SkASSERT(SkGetPackedA32(c) == 255);
+ unsigned dither = DITHER_VALUE(x);
+ *dst++ = SkDitherRGB32To565(c, dither);
+ }
+}
+
+static void S32_D565_Blend_Dither_mips_dsp(uint16_t* dst,
+ const SkPMColor* src,
+ int count, U8CPU alpha, int x, int y) {
+ register int32_t t0, t1, t2, t3, t4, t5, t6;
+ register int32_t s0, s1, s2, s3;
+ register int x1 = 0;
+ register uint32_t sc_mul;
+ register uint32_t sc_add;
+#ifdef ENABLE_DITHER_MATRIX_4X4
+ const uint8_t* dither_scan = gDitherMatrix_3Bit_4X4[(y) & 3];
+#else // ENABLE_DITHER_MATRIX_4X4
+ const uint16_t dither_scan = gDitherMatrix_3Bit_16[(y) & 3];
+#endif // ENABLE_DITHER_MATRIX_4X4
+ int dither[4];
+
+ for (int i = 0; i < 4; i++) {
+ dither[i] = (dither_scan >> ((x & 3) << 2)) & 0xF;
+ x += 1;
+ }
+ alpha += 1;
+ __asm__ volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "li %[t0], 0x100 \n\t"
+ "subu %[t0], %[t0], %[alpha] \n\t"
+ "replv.ph %[sc_mul], %[alpha] \n\t"
+ "beqz %[alpha], 1f \n\t"
+ " nop \n\t"
+ "replv.qb %[sc_add], %[t0] \n\t"
+ "b 2f \n\t"
+ " nop \n\t"
+ "1: \n\t"
+ "replv.qb %[sc_add], %[alpha] \n\t"
+ "2: \n\t"
+ "addiu %[t2], %[count], -1 \n\t"
+ "blez %[t2], 3f \n\t"
+ " nop \n\t"
+ "lw %[s0], 0(%[src]) \n\t"
+ "lw %[s1], 4(%[src]) \n\t"
+ "bnez %[x1], 4f \n\t"
+ " nop \n\t"
+ "lw %[t0], 0(%[dither]) \n\t"
+ "lw %[t1], 4(%[dither]) \n\t"
+ "li %[x1], 1 \n\t"
+ "b 5f \n\t"
+ " nop \n\t"
+ "4: \n\t"
+ "lw %[t0], 8(%[dither]) \n\t"
+ "lw %[t1], 12(%[dither]) \n\t"
+ "li %[x1], 0 \n\t"
+ "5: \n\t"
+ "sll %[t3], %[t0], 7 \n\t"
+ "sll %[t4], %[t1], 7 \n\t"
+#ifdef __MIPS_HAVE_DSPR2
+ "append %[t0], %[t1], 16 \n\t"
+#else
+ "sll %[t0], %[t0], 8 \n\t"
+ "sll %[t2], %[t1], 8 \n\t"
+ "precrq.qb.ph %[t0], %[t0], %[t2] \n\t"
+#endif
+ "precrq.qb.ph %[t1], %[t3], %[t4] \n\t"
+ "sll %[t5], %[s0], 8 \n\t"
+ "sll %[t6], %[s1], 8 \n\t"
+ "precrq.qb.ph %[t4], %[t5], %[t6] \n\t"
+ "precrq.qb.ph %[t6], %[s0], %[s1] \n\t"
+ "preceu.ph.qbla %[t5], %[t4] \n\t"
+ "preceu.ph.qbra %[t4], %[t4] \n\t"
+ "preceu.ph.qbra %[t6], %[t6] \n\t"
+ "lh %[t2], 0(%[dst]) \n\t"
+ "lh %[s1], 2(%[dst]) \n\t"
+#ifdef __MIPS_HAVE_DSPR2
+ "append %[t2], %[s1], 16 \n\t"
+#else
+ "sll %[s1], %[s1], 16 \n\t"
+ "packrl.ph %[t2], %[t2], %[s1] \n\t"
+#endif
+ "shra.ph %[s1], %[t2], 11 \n\t"
+ "and %[s1], %[s1], 0x1F001F \n\t"
+ "shra.ph %[s2], %[t2], 5 \n\t"
+ "and %[s2], %[s2], 0x3F003F \n\t"
+ "and %[s3], %[t2], 0x1F001F \n\t"
+ "shrl.qb %[t3], %[t4], 5 \n\t"
+ "addu.qb %[t4], %[t4], %[t0] \n\t"
+ "subu.qb %[t4], %[t4], %[t3] \n\t"
+ "shrl.qb %[t4], %[t4], 3 \n\t"
+ "shrl.qb %[t3], %[t5], 5 \n\t"
+ "addu.qb %[t5], %[t5], %[t0] \n\t"
+ "subu.qb %[t5], %[t5], %[t3] \n\t"
+ "shrl.qb %[t5], %[t5], 3 \n\t"
+ "shrl.qb %[t3], %[t6], 6 \n\t"
+ "addu.qb %[t6], %[t6], %[t1] \n\t"
+ "subu.qb %[t6], %[t6], %[t3] \n\t"
+ "shrl.qb %[t6], %[t6], 2 \n\t"
+ "cmpu.lt.qb %[t4], %[s1] \n\t"
+ "pick.qb %[s0], %[sc_add], $0 \n\t"
+ "addu.qb %[s0], %[s0], %[s1] \n\t"
+ "subu.qb %[t4], %[t4], %[s1] \n\t"
+ "muleu_s.ph.qbl %[t0], %[t4], %[sc_mul] \n\t"
+ "muleu_s.ph.qbr %[t1], %[t4], %[sc_mul] \n\t"
+ "precrq.qb.ph %[t4], %[t0], %[t1] \n\t"
+ "addu.qb %[t4], %[t4], %[s0] \n\t"
+ "cmpu.lt.qb %[t5], %[s3] \n\t"
+ "pick.qb %[s0], %[sc_add], $0 \n\t"
+ "addu.qb %[s0], %[s0], %[s3] \n\t"
+ "subu.qb %[t5], %[t5], %[s3] \n\t"
+ "muleu_s.ph.qbl %[t0], %[t5], %[sc_mul] \n\t"
+ "muleu_s.ph.qbr %[t1], %[t5], %[sc_mul] \n\t"
+ "precrq.qb.ph %[t5], %[t0], %[t1] \n\t"
+ "addu.qb %[t5], %[t5], %[s0] \n\t"
+ "cmpu.lt.qb %[t6], %[s2] \n\t"
+ "pick.qb %[s0], %[sc_add], $0 \n\t"
+ "addu.qb %[s0], %[s0], %[s2] \n\t"
+ "subu.qb %[t6], %[t6], %[s2] \n\t"
+ "muleu_s.ph.qbl %[t0], %[t6], %[sc_mul] \n\t"
+ "muleu_s.ph.qbr %[t1], %[t6], %[sc_mul] \n\t"
+ "precrq.qb.ph %[t6], %[t0], %[t1] \n\t"
+ "addu.qb %[t6], %[t6], %[s0] \n\t"
+ "shll.ph %[s1], %[t4], 11 \n\t"
+ "shll.ph %[t0], %[t6], 5 \n\t"
+ "or %[s0], %[s1], %[t0] \n\t"
+ "or %[s1], %[s0], %[t5] \n\t"
+ "srl %[t2], %[s1], 16 \n\t"
+ "and %[t3], %[s1], 0xFFFF \n\t"
+ "sh %[t2], 0(%[dst]) \n\t"
+ "sh %[t3], 2(%[dst]) \n\t"
+ "addiu %[src], %[src], 8 \n\t"
+ "addi %[count], %[count], -2 \n\t"
+ "b 2b \n\t"
+ " addu %[dst], %[dst], 4 \n\t"
+ "3: \n\t"
+ ".set pop \n\t"
+ : [src]"+r"(src), [dst]"+r"(dst), [count]"+r"(count),
+ [x1]"+r"(x1), [sc_mul]"=&r"(sc_mul), [sc_add]"=&r"(sc_add),
+ [t0]"=&r"(t0), [t1]"=&r"(t1), [t2]"=&r"(t2), [t3]"=&r"(t3),
+ [t4]"=&r"(t4), [t5]"=&r"(t5), [t6]"=&r"(t6), [s0]"=&r"(s0),
+ [s1]"=&r"(s1), [s2]"=&r"(s2), [s3]"=&r"(s3)
+ : [dither]"r"(dither), [alpha]"r"(alpha)
+ : "memory", "hi", "lo"
+ );
+
+ if(count == 1) {
+ SkPMColor c = *src++;
+ SkPMColorAssert(c);
+ SkASSERT(SkGetPackedA32(c) == 255);
+ DITHER_565_SCAN(y);
+ int dither = DITHER_VALUE(x);
+ int sr = SkGetPackedR32(c);
+ int sg = SkGetPackedG32(c);
+ int sb = SkGetPackedB32(c);
+ sr = SkDITHER_R32To565(sr, dither);
+ sg = SkDITHER_G32To565(sg, dither);
+ sb = SkDITHER_B32To565(sb, dither);
+
+ uint16_t d = *dst;
+ *dst++ = SkPackRGB16(SkAlphaBlend(sr, SkGetPackedR16(d), alpha),
+ SkAlphaBlend(sg, SkGetPackedG16(d), alpha),
+ SkAlphaBlend(sb, SkGetPackedB16(d), alpha));
+ DITHER_INC_X(x);
+ }
+}
+
+static void S32A_D565_Opaque_mips_dsp(uint16_t* __restrict__ dst,
+ const SkPMColor* __restrict__ src,
+ int count, U8CPU alpha, int x, int y) {
+
+ __asm__ volatile (
+ "pref 0, 0(%[src]) \n\t"
+ "pref 1, 0(%[dst]) \n\t"
+ "pref 0, 32(%[src]) \n\t"
+ "pref 1, 32(%[dst]) \n\t"
+ :
+ : [src]"r"(src), [dst]"r"(dst)
+ : "memory"
+ );
+
+ register uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8;
+ register uint32_t t16;
+ register uint32_t add_x10 = 0x100010;
+ register uint32_t add_x20 = 0x200020;
+ register uint32_t sa = 0xff00ff;
+
+ __asm__ volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "blez %[count], 1f \n\t"
+ " nop \n\t"
+ "2: \n\t"
+ "beqz %[count], 1f \n\t"
+ " nop \n\t"
+ "addiu %[t0], %[count], -1 \n\t"
+ "beqz %[t0], 1f \n\t"
+ " nop \n\t"
+ "bnez %[t16], 3f \n\t"
+ " nop \n\t"
+ "li %[t16], 2 \n\t"
+ "pref 0, 64(%[src]) \n\t"
+ "pref 1, 64(%[dst]) \n\t"
+ "3: \n\t"
+ "addiu %[t16], %[t16], -1 \n\t"
+ "lw %[t0], 0(%[src]) \n\t"
+ "lw %[t1], 4(%[src]) \n\t"
+ "precrq.ph.w %[t2], %[t0], %[t1] \n\t"
+ "preceu.ph.qbra %[t8], %[t2] \n\t"
+#ifdef __MIPS_HAVE_DSPR2
+ "append %[t0], %[t1], 16 \n\t"
+#else
+ "sll %[t0], %[t0], 16 \n\t"
+ "sll %[t6], %[t1], 16 \n\t"
+ "precrq.ph.w %[t0], %[t0], %[t6] \n\t"
+#endif
+ "preceu.ph.qbra %[t3], %[t0] \n\t"
+ "preceu.ph.qbla %[t4], %[t0] \n\t"
+ "preceu.ph.qbla %[t0], %[t2] \n\t"
+ "subq.ph %[t1], %[sa], %[t0] \n\t"
+ "sra %[t2], %[t1], 8 \n\t"
+ "or %[t5], %[t2], %[t1] \n\t"
+ "replv.ph %[t2], %[t5] \n\t"
+ "lh %[t0], 0(%[dst]) \n\t"
+ "lh %[t1], 2(%[dst]) \n\t"
+ "and %[t1], %[t1], 0xffff \n\t"
+#ifdef __MIPS_HAVE_DSPR2
+ "append %[t0], %[t1], 16 \n\t"
+#else
+ "sll %[t5], %[t0], 16 \n\t"
+ "or %[t0], %[t5], %[t1] \n\t"
+#endif
+ "and %[t1], %[t0], 0x1f001f \n\t"
+ "shra.ph %[t6], %[t0], 11 \n\t"
+ "and %[t6], %[t6], 0x1f001f \n\t"
+ "and %[t7], %[t0], 0x7e007e0 \n\t"
+ "shra.ph %[t5], %[t7], 5 \n\t"
+ "muleu_s.ph.qbl %[t0], %[t2], %[t6] \n\t"
+ "addq.ph %[t7], %[t0], %[add_x10] \n\t"
+ "shra.ph %[t6], %[t7], 5 \n\t"
+ "addq.ph %[t6], %[t7], %[t6] \n\t"
+ "shra.ph %[t0], %[t6], 5 \n\t"
+ "addq.ph %[t7], %[t0], %[t3] \n\t"
+ "shra.ph %[t6], %[t7], 3 \n\t"
+ "muleu_s.ph.qbl %[t0], %[t2], %[t1] \n\t"
+ "addq.ph %[t7], %[t0], %[add_x10] \n\t"
+ "shra.ph %[t0], %[t7], 5 \n\t"
+ "addq.ph %[t7], %[t7], %[t0] \n\t"
+ "shra.ph %[t0], %[t7], 5 \n\t"
+ "addq.ph %[t7], %[t0], %[t8] \n\t"
+ "shra.ph %[t3], %[t7], 3 \n\t"
+ "muleu_s.ph.qbl %[t0], %[t2], %[t5] \n\t"
+ "addq.ph %[t7], %[t0], %[add_x20] \n\t"
+ "shra.ph %[t0], %[t7], 6 \n\t"
+ "addq.ph %[t8], %[t7], %[t0] \n\t"
+ "shra.ph %[t0], %[t8], 6 \n\t"
+ "addq.ph %[t7], %[t0], %[t4] \n\t"
+ "shra.ph %[t8], %[t7], 2 \n\t"
+ "shll.ph %[t0], %[t8], 5 \n\t"
+ "shll.ph %[t1], %[t6], 11 \n\t"
+ "or %[t2], %[t0], %[t1] \n\t"
+ "or %[t3], %[t2], %[t3] \n\t"
+ "sra %[t4], %[t3], 16 \n\t"
+ "sh %[t4], 0(%[dst]) \n\t"
+ "sh %[t3], 2(%[dst]) \n\t"
+ "addiu %[count], %[count], -2 \n\t"
+ "addiu %[src], %[src], 8 \n\t"
+ "b 2b \n\t"
+ " addiu %[dst], %[dst], 4 \n\t"
+ "1: \n\t"
+ ".set pop \n\t"
+ : [dst]"+r"(dst), [src]"+r"(src), [count]"+r"(count),
+ [t16]"=&r"(t16), [t0]"=&r"(t0), [t1]"=&r"(t1), [t2]"=&r"(t2),
+ [t3]"=&r"(t3), [t4]"=&r"(t4), [t5]"=&r"(t5), [t6]"=&r"(t6),
+ [t7]"=&r"(t7), [t8]"=&r"(t8)
+ : [add_x10]"r"(add_x10), [add_x20]"r"(add_x20), [sa]"r"(sa)
+ : "memory", "hi", "lo"
+ );
+
+ if (count == 1) {
+ SkPMColor c = *src++;
+ SkPMColorAssert(c);
+ if (c) {
+ *dst = SkSrcOver32To16(c, *dst);
+ }
+ dst += 1;
+ }
+}
+
+static void S32A_D565_Blend_mips_dsp(uint16_t* SK_RESTRICT dst,
+ const SkPMColor* SK_RESTRICT src, int count,
+ U8CPU alpha, int /*x*/, int /*y*/) {
+ register uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9;
+ register uint32_t s0, s1, s2, s3;
+ register unsigned dst_scale = 0;
+
+ __asm__ volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "replv.qb %[t0], %[alpha] \n\t"
+ "repl.ph %[t6], 0x80 \n\t"
+ "repl.ph %[t7], 0xFF \n\t"
+ "1: \n\t"
+ "addiu %[t8], %[count], -1 \n\t"
+ "blez %[t8], 2f \n\t"
+ " nop \n\t"
+ "lw %[t8], 0(%[src]) \n\t"
+ "lw %[t9], 4(%[src]) \n\t"
+ "lh %[t4], 0(%[dst]) \n\t"
+ "lh %[t5], 2(%[dst]) \n\t"
+ "sll %[t5], %[t5], 16 \n\t"
+ "sll %[t2], %[t8], 8 \n\t"
+ "sll %[t3], %[t9], 8 \n\t"
+ "precrq.qb.ph %[t1], %[t2], %[t3] \n\t"
+ "precrq.qb.ph %[t3], %[t8], %[t9] \n\t"
+ "preceu.ph.qbla %[t8], %[t3] \n\t"
+ "muleu_s.ph.qbr %[s3], %[t0], %[t8] \n\t"
+ "preceu.ph.qbla %[t2], %[t1] \n\t"
+ "preceu.ph.qbra %[t1], %[t1] \n\t"
+ "preceu.ph.qbra %[t3], %[t3] \n\t"
+ "packrl.ph %[t9], %[t4], %[t5] \n\t"
+ "shra.ph %[s0], %[t9], 11 \n\t"
+ "and %[s0], %[s0], 0x1F001F \n\t"
+ "shra.ph %[s1], %[t9], 5 \n\t"
+ "and %[s1], %[s1], 0x3F003F \n\t"
+ "and %[s2], %[t9], 0x1F001F \n\t"
+ "addq.ph %[s3], %[s3], %[t6] \n\t"
+ "shra.ph %[t5], %[s3], 8 \n\t"
+ "and %[t5], %[t5], 0xFF00FF \n\t"
+ "addq.ph %[dst_scale], %[s3], %[t5] \n\t"
+ "shra.ph %[dst_scale], %[dst_scale], 8 \n\t"
+ "subq_s.ph %[dst_scale], %[t7], %[dst_scale] \n\t"
+ "sll %[dst_scale], %[dst_scale], 8 \n\t"
+ "precrq.qb.ph %[dst_scale], %[dst_scale], %[dst_scale] \n\t"
+ "shrl.qb %[t1], %[t1], 3 \n\t"
+ "shrl.qb %[t2], %[t2], 3 \n\t"
+ "shrl.qb %[t3], %[t3], 2 \n\t"
+ "muleu_s.ph.qbl %[t1], %[t0], %[t1] \n\t"
+ "muleu_s.ph.qbl %[t2], %[t0], %[t2] \n\t"
+ "muleu_s.ph.qbl %[t3], %[t0], %[t3] \n\t"
+ "muleu_s.ph.qbl %[t8], %[dst_scale], %[s0] \n\t"
+ "muleu_s.ph.qbl %[t9], %[dst_scale], %[s2] \n\t"
+ "muleu_s.ph.qbl %[t4], %[dst_scale], %[s1] \n\t"
+ "addq.ph %[t1], %[t1], %[t8] \n\t"
+ "addq.ph %[t2], %[t2], %[t9] \n\t"
+ "addq.ph %[t3], %[t3], %[t4] \n\t"
+ "addq.ph %[t8], %[t1], %[t6] \n\t"
+ "addq.ph %[t9], %[t2], %[t6] \n\t"
+ "addq.ph %[t4], %[t3], %[t6] \n\t"
+ "shra.ph %[t1], %[t8], 8 \n\t"
+ "addq.ph %[t1], %[t1], %[t8] \n\t"
+ "preceu.ph.qbla %[t1], %[t1] \n\t"
+ "shra.ph %[t2], %[t9], 8 \n\t"
+ "addq.ph %[t2], %[t2], %[t9] \n\t"
+ "preceu.ph.qbla %[t2], %[t2] \n\t"
+ "shra.ph %[t3], %[t4], 8 \n\t"
+ "addq.ph %[t3], %[t3], %[t4] \n\t"
+ "preceu.ph.qbla %[t3], %[t3] \n\t"
+ "shll.ph %[t8], %[t1], 11 \n\t"
+ "shll.ph %[t9], %[t3], 5 \n\t"
+ "or %[t8], %[t8], %[t9] \n\t"
+ "or %[s0], %[t8], %[t2] \n\t"
+ "srl %[t8], %[s0], 16 \n\t"
+ "and %[t9], %[s0], 0xFFFF \n\t"
+ "sh %[t8], 0(%[dst]) \n\t"
+ "sh %[t9], 2(%[dst]) \n\t"
+ "addiu %[src], %[src], 8 \n\t"
+ "addiu %[count], %[count], -2 \n\t"
+ "b 1b \n\t"
+ " addiu %[dst], %[dst], 4 \n\t"
+ "2: \n\t"
+ ".set pop \n\t"
+ : [src]"+r"(src), [dst]"+r"(dst), [count]"+r"(count),
+ [dst_scale]"+r"(dst_scale), [s0]"=&r"(s0), [s1]"=&r"(s1),
+ [s2]"=&r"(s2), [s3]"=&r"(s3), [t0]"=&r"(t0), [t1]"=&r"(t1),
+ [t2]"=&r"(t2), [t3]"=&r"(t3), [t4]"=&r"(t4), [t5]"=&r"(t5),
+ [t6]"=&r"(t6), [t7]"=&r"(t7), [t8]"=&r"(t8), [t9]"=&r"(t9)
+ : [alpha]"r"(alpha)
+ : "memory", "hi", "lo"
+ );
+
+ if (count == 1) {
+ SkPMColor sc = *src++;
+ SkPMColorAssert(sc);
+ if (sc) {
+ uint16_t dc = *dst;
+ unsigned dst_scale = 255 - SkMulDiv255Round(SkGetPackedA32(sc), alpha);
+ unsigned dr = SkMulS16(SkPacked32ToR16(sc), alpha) +
+ SkMulS16(SkGetPackedR16(dc), dst_scale);
+ unsigned dg = SkMulS16(SkPacked32ToG16(sc), alpha) +
+ SkMulS16(SkGetPackedG16(dc), dst_scale);
+ unsigned db = SkMulS16(SkPacked32ToB16(sc), alpha) +
+ SkMulS16(SkGetPackedB16(dc), dst_scale);
+ *dst = SkPackRGB16(SkDiv255Round(dr), SkDiv255Round(dg), SkDiv255Round(db));
+ }
+ dst += 1;
+ }
+}
+
+static void S32_Blend_BlitRow32_mips_dsp(SkPMColor* SK_RESTRICT dst,
+ const SkPMColor* SK_RESTRICT src,
+ int count, U8CPU alpha) {
+ register int32_t t0, t1, t2, t3, t4, t5, t6, t7;
+
+ __asm__ volatile (
+ ".set push \n\t"
+ ".set noreorder \n\t"
+ "li %[t2], 0x100 \n\t"
+ "addiu %[t0], %[alpha], 1 \n\t"
+ "subu %[t1], %[t2], %[t0] \n\t"
+ "replv.qb %[t7], %[t0] \n\t"
+ "replv.qb %[t6], %[t1] \n\t"
+ "1: \n\t"
+ "blez %[count], 2f \n\t"
+ "lw %[t0], 0(%[src]) \n\t"
+ "lw %[t1], 0(%[dst]) \n\t"
+ "preceu.ph.qbr %[t2], %[t0] \n\t"
+ "preceu.ph.qbl %[t3], %[t0] \n\t"
+ "preceu.ph.qbr %[t4], %[t1] \n\t"
+ "preceu.ph.qbl %[t5], %[t1] \n\t"
+ "muleu_s.ph.qbr %[t2], %[t7], %[t2] \n\t"
+ "muleu_s.ph.qbr %[t3], %[t7], %[t3] \n\t"
+ "muleu_s.ph.qbr %[t4], %[t6], %[t4] \n\t"
+ "muleu_s.ph.qbr %[t5], %[t6], %[t5] \n\t"
+ "addiu %[src], %[src], 4 \n\t"
+ "addiu %[count], %[count], -1 \n\t"
+ "precrq.qb.ph %[t0], %[t3], %[t2] \n\t"
+ "precrq.qb.ph %[t2], %[t5], %[t4] \n\t"
+ "addu %[t1], %[t0], %[t2] \n\t"
+ "sw %[t1], 0(%[dst]) \n\t"
+ "b 1b \n\t"
+ " addi %[dst], %[dst], 4 \n\t"
+ "2: \n\t"
+ ".set pop \n\t"
+ : [src]"+r"(src), [dst]"+r"(dst), [count]"+r"(count),
+ [t0]"=&r"(t0), [t1]"=&r"(t1), [t2]"=&r"(t2), [t3]"=&r"(t3),
+ [t4]"=&r"(t4), [t5]"=&r"(t5), [t6]"=&r"(t6), [t7]"=&r"(t7)
+ : [alpha]"r"(alpha)
+ : "memory", "hi", "lo"
+ );
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+const SkBlitRow::Proc platform_565_procs_mips_dsp[] = {
+ // no dither
+ NULL,
+ S32_D565_Blend_mips_dsp,
+ S32A_D565_Opaque_mips_dsp,
+ S32A_D565_Blend_mips_dsp,
+
+ // dither
+ S32_D565_Opaque_Dither_mips_dsp,
+ S32_D565_Blend_Dither_mips_dsp,
+ S32A_D565_Opaque_Dither_mips_dsp,
+ NULL,
+};
+
+static const SkBlitRow::Proc32 platform_32_procs_mips_dsp[] = {
+ NULL, // S32_Opaque,
+ S32_Blend_BlitRow32_mips_dsp, // S32_Blend,
+ NULL, // S32A_Opaque,
+ NULL, // S32A_Blend,
+};
+
+SkBlitRow::Proc SkBlitRow::PlatformProcs565(unsigned flags) {
+ return platform_565_procs_mips_dsp[flags];
+}
+
+SkBlitRow::Proc32 SkBlitRow::PlatformProcs32(unsigned flags) {
+ return platform_32_procs_mips_dsp[flags];
+}
+
+SkBlitRow::ColorRectProc PlatformColorRectProcFactory() {
+ return NULL;
+}
+
+SkBlitRow::ColorProc SkBlitRow::PlatformColorProc() {
+ return NULL;
+}
diff --git a/chromium/third_party/skia/src/opts/SkBlurImage_opts_SSE2.cpp b/chromium/third_party/skia/src/opts/SkBlurImage_opts_SSE2.cpp
index 93830d78b46..bbc6a66462e 100644
--- a/chromium/third_party/skia/src/opts/SkBlurImage_opts_SSE2.cpp
+++ b/chromium/third_party/skia/src/opts/SkBlurImage_opts_SSE2.cpp
@@ -5,36 +5,31 @@
* found in the LICENSE file.
*/
-
+#include <emmintrin.h>
#include "SkBitmap.h"
-#include "SkColorPriv.h"
#include "SkBlurImage_opts_SSE2.h"
+#include "SkColorPriv.h"
#include "SkRect.h"
-#include <emmintrin.h>
-
namespace {
-
enum BlurDirection {
kX, kY
};
-/**
- * Helper function to spread the components of a 32-bit integer into the
+/* Helper function to spread the components of a 32-bit integer into the
* lower 8 bits of each 32-bit element of an SSE register.
*/
-
inline __m128i expand(int a) {
- const __m128i zero = _mm_setzero_si128();
+ const __m128i zero = _mm_setzero_si128();
- // 0 0 0 0 0 0 0 0 0 0 0 0 A R G B
- __m128i result = _mm_cvtsi32_si128(a);
+ // 0 0 0 0 0 0 0 0 0 0 0 0 A R G B
+ __m128i result = _mm_cvtsi32_si128(a);
- // 0 0 0 0 0 0 0 0 0 A 0 R 0 G 0 B
- result = _mm_unpacklo_epi8(result, zero);
+ // 0 0 0 0 0 0 0 0 0 A 0 R 0 G 0 B
+ result = _mm_unpacklo_epi8(result, zero);
- // 0 0 0 A 0 0 0 R 0 0 0 G 0 0 0 B
- return _mm_unpacklo_epi16(result, zero);
+ // 0 0 0 A 0 0 0 R 0 0 0 G 0 0 0 B
+ return _mm_unpacklo_epi16(result, zero);
}
template<BlurDirection srcDirection, BlurDirection dstDirection>
diff --git a/chromium/third_party/skia/src/opts/SkBlurImage_opts_SSE2.h b/chromium/third_party/skia/src/opts/SkBlurImage_opts_SSE2.h
index c8deea4bb9c..db104bacf4f 100644
--- a/chromium/third_party/skia/src/opts/SkBlurImage_opts_SSE2.h
+++ b/chromium/third_party/skia/src/opts/SkBlurImage_opts_SSE2.h
@@ -5,9 +5,14 @@
* found in the LICENSE file.
*/
+#ifndef SkBlurImage_opts_SSE2_DEFINED
+#define SkBlurImage_opts_SSE2_DEFINED
+
#include "SkBlurImage_opts.h"
bool SkBoxBlurGetPlatformProcs_SSE2(SkBoxBlurProc* boxBlurX,
SkBoxBlurProc* boxBlurY,
SkBoxBlurProc* boxBlurXY,
SkBoxBlurProc* boxBlurYX);
+
+#endif
diff --git a/chromium/third_party/skia/src/opts/SkBlurImage_opts_arm.cpp b/chromium/third_party/skia/src/opts/SkBlurImage_opts_arm.cpp
new file mode 100644
index 00000000000..10d595afa59
--- /dev/null
+++ b/chromium/third_party/skia/src/opts/SkBlurImage_opts_arm.cpp
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2014 ARM Ltd.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkBlurImage_opts_neon.h"
+#include "SkUtilsArm.h"
+
+bool SkBoxBlurGetPlatformProcs(SkBoxBlurProc* boxBlurX,
+ SkBoxBlurProc* boxBlurY,
+ SkBoxBlurProc* boxBlurXY,
+ SkBoxBlurProc* boxBlurYX) {
+#if SK_ARM_NEON_IS_NONE
+ return false;
+#else
+#if SK_ARM_NEON_IS_DYNAMIC
+ if (!sk_cpu_arm_has_neon()) {
+ return false;
+ }
+#endif
+ return SkBoxBlurGetPlatformProcs_NEON(boxBlurX, boxBlurY, boxBlurXY, boxBlurYX);
+#endif
+}
diff --git a/chromium/third_party/skia/src/opts/SkBlurImage_opts_neon.cpp b/chromium/third_party/skia/src/opts/SkBlurImage_opts_neon.cpp
index 4e33d72d462..08187f3e55e 100644
--- a/chromium/third_party/skia/src/opts/SkBlurImage_opts_neon.cpp
+++ b/chromium/third_party/skia/src/opts/SkBlurImage_opts_neon.cpp
@@ -20,6 +20,86 @@ enum BlurDirection {
};
/**
+ * Helper function to load 2 pixels from diffent rows to a 8x8 NEON register
+ * and also pre-load pixels for future read
+ */
+template<BlurDirection srcDirection>
+inline uint8x8_t load_2_pixels(const SkPMColor* src, int srcStride) {
+ if (srcDirection == kX) {
+ uint32x2_t temp = vdup_n_u32(0);
+ // 10% faster by adding these 2 prefetches
+ SK_PREFETCH(src + 16);
+ SK_PREFETCH(src + srcStride + 16);
+ return vreinterpret_u8_u32(vld1_lane_u32(src + srcStride, vld1_lane_u32(src, temp, 0), 1));
+ } else {
+ return vld1_u8((uint8_t*)src);
+ }
+}
+
+/**
+ * Helper function to store the low 8-bits from a 16x8 NEON register to 2 rows
+ */
+template<BlurDirection dstDirection>
+inline void store_2_pixels(uint16x8_t result16x8, SkPMColor* dst, int dstStride) {
+ if (dstDirection == kX) {
+ uint32x2_t temp = vreinterpret_u32_u8(vmovn_u16(result16x8));
+ vst1_lane_u32(dst, temp, 0);
+ vst1_lane_u32(dst + dstStride, temp, 1);
+ } else {
+ uint8x8_t temp = vmovn_u16(result16x8);
+ vst1_u8((uint8_t*)dst, temp);
+ }
+}
+
+/**
+ * fast path for kernel size less than 128
+ */
+template<BlurDirection srcDirection, BlurDirection dstDirection>
+void SkDoubleRowBoxBlur_NEON(const SkPMColor** src, int srcStride, SkPMColor** dst, int kernelSize,
+ int leftOffset, int rightOffset, int width, int* height)
+{
+ const int rightBorder = SkMin32(rightOffset + 1, width);
+ const int srcStrideX = srcDirection == kX ? 1 : srcStride;
+ const int dstStrideX = dstDirection == kX ? 1 : *height;
+ const int srcStrideY = srcDirection == kX ? srcStride : 1;
+ const int dstStrideY = dstDirection == kX ? width : 1;
+ const uint16x8_t scale = vdupq_n_u16((1 << 15) / kernelSize);
+
+ for (; *height >= 2; *height -= 2) {
+ uint16x8_t sum = vdupq_n_u16(0);
+ const SkPMColor* p = *src;
+ for (int i = 0; i < rightBorder; i++) {
+ sum = vaddw_u8(sum,
+ load_2_pixels<srcDirection>(p, srcStride));
+ p += srcStrideX;
+ }
+
+ const SkPMColor* sptr = *src;
+ SkPMColor* dptr = *dst;
+ for (int x = 0; x < width; x++) {
+ // val = (sum * scale * 2 + 0x8000) >> 16
+ uint16x8_t resultPixels = vreinterpretq_u16_s16(vqrdmulhq_s16(
+ vreinterpretq_s16_u16(sum), vreinterpretq_s16_u16(scale)));
+ store_2_pixels<dstDirection>(resultPixels, dptr, width);
+
+ if (x >= leftOffset) {
+ sum = vsubw_u8(sum,
+ load_2_pixels<srcDirection>(sptr - leftOffset * srcStrideX, srcStride));
+ }
+ if (x + rightOffset + 1 < width) {
+ sum = vaddw_u8(sum,
+ load_2_pixels<srcDirection>(sptr + (rightOffset + 1) * srcStrideX, srcStride));
+ }
+ sptr += srcStrideX;
+ dptr += dstStrideX;
+ }
+ *src += srcStrideY * 2;
+ *dst += dstStrideY * 2;
+ }
+}
+
+
+/**
* Helper function to spread the components of a 32-bit integer into the
* lower 8 bits of each 16-bit element of a NEON register.
*/
@@ -42,7 +122,14 @@ void SkBoxBlur_NEON(const SkPMColor* src, int srcStride, SkPMColor* dst, int ker
const int dstStrideY = dstDirection == kX ? width : 1;
const uint32x4_t scale = vdupq_n_u32((1 << 24) / kernelSize);
const uint32x4_t half = vdupq_n_u32(1 << 23);
- for (int y = 0; y < height; ++y) {
+
+ if (kernelSize < 128)
+ {
+ SkDoubleRowBoxBlur_NEON<srcDirection, dstDirection>(&src, srcStride, &dst, kernelSize,
+ leftOffset, rightOffset, width, &height);
+ }
+
+ for (; height > 0; height--) {
uint32x4_t sum = vdupq_n_u32(0);
const SkPMColor* p = src;
for (int i = 0; i < rightBorder; ++i) {
@@ -77,8 +164,8 @@ void SkBoxBlur_NEON(const SkPMColor* src, int srcStride, SkPMColor* dst, int ker
sum = vaddw_u16(sum, expand(*r));
}
sptr += srcStrideX;
- if (srcDirection == kY) {
- SK_PREFETCH(sptr + (rightOffset + 1) * srcStrideX);
+ if (srcDirection == kX) {
+ SK_PREFETCH(sptr + (rightOffset + 16) * srcStrideX);
}
dptr += dstStrideX;
}
diff --git a/chromium/third_party/skia/src/opts/SkCachePreload_arm.h b/chromium/third_party/skia/src/opts/SkCachePreload_arm.h
deleted file mode 100644
index cff8c2a9b79..00000000000
--- a/chromium/third_party/skia/src/opts/SkCachePreload_arm.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2012 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#ifndef SkCachePreload_arm_DEFINED
-#define SkCachePreload_arm_DEFINED
-
-// This file defines macros for preload instructions for ARM. These macros
-// are designed to be embedded inside GNU inline assembly.
-// For the use of these macros, __ARM_USE_PLD needs to be enabled. The cache
-// line size also needs to be known (and needs to be contained inside
-// __ARM_CACHE_LINE_SIZE).
-#if defined(__ARM_USE_PLD)
-
-#define PLD(x, n) "pld [%["#x"], #("#n")]\n\t"
-
-#if __ARM_CACHE_LINE_SIZE == 32
- #define PLD64(x, n) PLD(x, n) PLD(x, (n) + 32)
-#elif __ARM_CACHE_LINE_SIZE == 64
- #define PLD64(x, n) PLD(x, n)
-#else
- #error "unknown __ARM_CACHE_LINE_SIZE."
-#endif
-#else
- // PLD is disabled, all macros become empty.
- #define PLD(x, n)
- #define PLD64(x, n)
-#endif
-
-#define PLD128(x, n) PLD64(x, n) PLD64(x, (n) + 64)
-
-#endif // SkCachePreload_arm_DEFINED
diff --git a/chromium/third_party/skia/src/opts/SkColor_opts_SSE2.h b/chromium/third_party/skia/src/opts/SkColor_opts_SSE2.h
new file mode 100644
index 00000000000..7e61d526b3b
--- /dev/null
+++ b/chromium/third_party/skia/src/opts/SkColor_opts_SSE2.h
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkColor_opts_SSE2_DEFINED
+#define SkColor_opts_SSE2_DEFINED
+
+#include <emmintrin.h>
+
+// Because no _mm_mul_epi32() in SSE2, we emulate it here.
+// Multiplies 4 32-bit integers from a by 4 32-bit intergers from b.
+// The 4 multiplication results should be represented within 32-bit
+// integers, otherwise they would be overflow.
+static inline __m128i Multiply32_SSE2(const __m128i& a, const __m128i& b) {
+ // Calculate results of a0 * b0 and a2 * b2.
+ __m128i r1 = _mm_mul_epu32(a, b);
+ // Calculate results of a1 * b1 and a3 * b3.
+ __m128i r2 = _mm_mul_epu32(_mm_srli_si128(a, 4), _mm_srli_si128(b, 4));
+ // Shuffle results to [63..0] and interleave the results.
+ __m128i r = _mm_unpacklo_epi32(_mm_shuffle_epi32(r1, _MM_SHUFFLE(0,0,2,0)),
+ _mm_shuffle_epi32(r2, _MM_SHUFFLE(0,0,2,0)));
+ return r;
+}
+
+static inline __m128i SkAlpha255To256_SSE2(const __m128i& alpha) {
+ return _mm_add_epi32(alpha, _mm_set1_epi32(1));
+}
+
+// See #define SkAlphaMulAlpha(a, b) SkMulDiv255Round(a, b) in SkXfermode.cpp.
+static inline __m128i SkAlphaMulAlpha_SSE2(const __m128i& a,
+ const __m128i& b) {
+ __m128i prod = _mm_mullo_epi16(a, b);
+ prod = _mm_add_epi32(prod, _mm_set1_epi32(128));
+ prod = _mm_add_epi32(prod, _mm_srli_epi32(prod, 8));
+ prod = _mm_srli_epi32(prod, 8);
+
+ return prod;
+}
+
+// Portable version SkAlphaMulQ is in SkColorPriv.h.
+static inline __m128i SkAlphaMulQ_SSE2(const __m128i& c, const __m128i& scale) {
+ __m128i mask = _mm_set1_epi32(0xFF00FF);
+ __m128i s = _mm_or_si128(_mm_slli_epi32(scale, 16), scale);
+
+ // uint32_t rb = ((c & mask) * scale) >> 8
+ __m128i rb = _mm_and_si128(mask, c);
+ rb = _mm_mullo_epi16(rb, s);
+ rb = _mm_srli_epi16(rb, 8);
+
+ // uint32_t ag = ((c >> 8) & mask) * scale
+ __m128i ag = _mm_srli_epi16(c, 8);
+ ag = _mm_and_si128(ag, mask);
+ ag = _mm_mullo_epi16(ag, s);
+
+ // (rb & mask) | (ag & ~mask)
+ rb = _mm_and_si128(mask, rb);
+ ag = _mm_andnot_si128(mask, ag);
+ return _mm_or_si128(rb, ag);
+}
+
+static inline __m128i SkGetPackedA32_SSE2(const __m128i& src) {
+ __m128i a = _mm_slli_epi32(src, (24 - SK_A32_SHIFT));
+ return _mm_srli_epi32(a, 24);
+}
+
+static inline __m128i SkGetPackedR32_SSE2(const __m128i& src) {
+ __m128i r = _mm_slli_epi32(src, (24 - SK_R32_SHIFT));
+ return _mm_srli_epi32(r, 24);
+}
+
+static inline __m128i SkGetPackedG32_SSE2(const __m128i& src) {
+ __m128i g = _mm_slli_epi32(src, (24 - SK_G32_SHIFT));
+ return _mm_srli_epi32(g, 24);
+}
+
+static inline __m128i SkGetPackedB32_SSE2(const __m128i& src) {
+ __m128i b = _mm_slli_epi32(src, (24 - SK_B32_SHIFT));
+ return _mm_srli_epi32(b, 24);
+}
+
+static inline __m128i SkMul16ShiftRound_SSE2(const __m128i& a,
+ const __m128i& b, int shift) {
+ __m128i prod = _mm_mullo_epi16(a, b);
+ prod = _mm_add_epi16(prod, _mm_set1_epi16(1 << (shift - 1)));
+ prod = _mm_add_epi16(prod, _mm_srli_epi16(prod, shift));
+ prod = _mm_srli_epi16(prod, shift);
+
+ return prod;
+}
+
+static inline __m128i SkPackRGB16_SSE2(const __m128i& r,
+ const __m128i& g, const __m128i& b) {
+ __m128i dr = _mm_slli_epi16(r, SK_R16_SHIFT);
+ __m128i dg = _mm_slli_epi16(g, SK_G16_SHIFT);
+ __m128i db = _mm_slli_epi16(b, SK_B16_SHIFT);
+
+ __m128i c = _mm_or_si128(dr, dg);
+ return _mm_or_si128(c, db);
+}
+
+static inline __m128i SkPackARGB32_SSE2(const __m128i& a, const __m128i& r,
+ const __m128i& g, const __m128i& b) {
+ __m128i da = _mm_slli_epi32(a, SK_A32_SHIFT);
+ __m128i dr = _mm_slli_epi32(r, SK_R32_SHIFT);
+ __m128i dg = _mm_slli_epi32(g, SK_G32_SHIFT);
+ __m128i db = _mm_slli_epi32(b, SK_B32_SHIFT);
+
+ __m128i c = _mm_or_si128(da, dr);
+ c = _mm_or_si128(c, dg);
+ return _mm_or_si128(c, db);
+}
+
+static inline __m128i SkPacked16ToR32_SSE2(const __m128i& src) {
+ __m128i r = _mm_srli_epi32(src, SK_R16_SHIFT);
+ r = _mm_and_si128(r, _mm_set1_epi32(SK_R16_MASK));
+ r = _mm_or_si128(_mm_slli_epi32(r, (8 - SK_R16_BITS)),
+ _mm_srli_epi32(r, (2 * SK_R16_BITS - 8)));
+
+ return r;
+}
+
+static inline __m128i SkPacked16ToG32_SSE2(const __m128i& src) {
+ __m128i g = _mm_srli_epi32(src, SK_G16_SHIFT);
+ g = _mm_and_si128(g, _mm_set1_epi32(SK_G16_MASK));
+ g = _mm_or_si128(_mm_slli_epi32(g, (8 - SK_G16_BITS)),
+ _mm_srli_epi32(g, (2 * SK_G16_BITS - 8)));
+
+ return g;
+}
+
+static inline __m128i SkPacked16ToB32_SSE2(const __m128i& src) {
+ __m128i b = _mm_srli_epi32(src, SK_B16_SHIFT);
+ b = _mm_and_si128(b, _mm_set1_epi32(SK_B16_MASK));
+ b = _mm_or_si128(_mm_slli_epi32(b, (8 - SK_B16_BITS)),
+ _mm_srli_epi32(b, (2 * SK_B16_BITS - 8)));
+
+ return b;
+}
+
+static inline __m128i SkPixel16ToPixel32_SSE2(const __m128i& src) {
+ __m128i r = SkPacked16ToR32_SSE2(src);
+ __m128i g = SkPacked16ToG32_SSE2(src);
+ __m128i b = SkPacked16ToB32_SSE2(src);
+
+ return SkPackARGB32_SSE2(_mm_set1_epi32(0xFF), r, g, b);
+}
+
+static inline __m128i SkPixel32ToPixel16_ToU16_SSE2(const __m128i& src_pixel1,
+ const __m128i& src_pixel2) {
+ // Calculate result r.
+ __m128i r1 = _mm_srli_epi32(src_pixel1,
+ SK_R32_SHIFT + (8 - SK_R16_BITS));
+ r1 = _mm_and_si128(r1, _mm_set1_epi32(SK_R16_MASK));
+ __m128i r2 = _mm_srli_epi32(src_pixel2,
+ SK_R32_SHIFT + (8 - SK_R16_BITS));
+ r2 = _mm_and_si128(r2, _mm_set1_epi32(SK_R16_MASK));
+ __m128i r = _mm_packs_epi32(r1, r2);
+
+ // Calculate result g.
+ __m128i g1 = _mm_srli_epi32(src_pixel1,
+ SK_G32_SHIFT + (8 - SK_G16_BITS));
+ g1 = _mm_and_si128(g1, _mm_set1_epi32(SK_G16_MASK));
+ __m128i g2 = _mm_srli_epi32(src_pixel2,
+ SK_G32_SHIFT + (8 - SK_G16_BITS));
+ g2 = _mm_and_si128(g2, _mm_set1_epi32(SK_G16_MASK));
+ __m128i g = _mm_packs_epi32(g1, g2);
+
+ // Calculate result b.
+ __m128i b1 = _mm_srli_epi32(src_pixel1,
+ SK_B32_SHIFT + (8 - SK_B16_BITS));
+ b1 = _mm_and_si128(b1, _mm_set1_epi32(SK_B16_MASK));
+ __m128i b2 = _mm_srli_epi32(src_pixel2,
+ SK_B32_SHIFT + (8 - SK_B16_BITS));
+ b2 = _mm_and_si128(b2, _mm_set1_epi32(SK_B16_MASK));
+ __m128i b = _mm_packs_epi32(b1, b2);
+
+ // Store 8 16-bit colors in dst.
+ __m128i d_pixel = SkPackRGB16_SSE2(r, g, b);
+
+ return d_pixel;
+}
+
+#endif // SkColor_opts_SSE2_DEFINED
diff --git a/chromium/third_party/skia/src/opts/SkMath_opts_SSE2.h b/chromium/third_party/skia/src/opts/SkMath_opts_SSE2.h
new file mode 100644
index 00000000000..2cc21afa0df
--- /dev/null
+++ b/chromium/third_party/skia/src/opts/SkMath_opts_SSE2.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkMath_opts_SSE2_DEFINED
+#define SkMath_opts_SSE2_DEFINED
+
+#include <emmintrin.h>
+
+// Because no _mm_div_epi32() in SSE2, we use float division to emulate.
+// When using this function, make sure a and b don't exceed float's precision.
+static inline __m128i shim_mm_div_epi32(const __m128i& a, const __m128i& b) {
+ __m128 x = _mm_cvtepi32_ps(a);
+ __m128 y = _mm_cvtepi32_ps(b);
+ return _mm_cvttps_epi32(_mm_div_ps(x, y));
+}
+
+// Portable version of SkSqrtBits is in SkMath.cpp.
+static inline __m128i SkSqrtBits_SSE2(const __m128i& x, int count) {
+ __m128i root = _mm_setzero_si128();
+ __m128i remHi = _mm_setzero_si128();
+ __m128i remLo = x;
+ __m128i one128 = _mm_set1_epi32(1);
+
+ do {
+ root = _mm_slli_epi32(root, 1);
+
+ remHi = _mm_or_si128(_mm_slli_epi32(remHi, 2),
+ _mm_srli_epi32(remLo, 30));
+ remLo = _mm_slli_epi32(remLo, 2);
+
+ __m128i testDiv = _mm_slli_epi32(root, 1);
+ testDiv = _mm_add_epi32(testDiv, _mm_set1_epi32(1));
+
+ __m128i cmp = _mm_cmplt_epi32(remHi, testDiv);
+ __m128i remHi1 = _mm_and_si128(cmp, remHi);
+ __m128i root1 = _mm_and_si128(cmp, root);
+ __m128i remHi2 = _mm_andnot_si128(cmp, _mm_sub_epi32(remHi, testDiv));
+ __m128i root2 = _mm_andnot_si128(cmp, _mm_add_epi32(root, one128));
+
+ remHi = _mm_or_si128(remHi1, remHi2);
+ root = _mm_or_si128(root1, root2);
+ } while (--count >= 0);
+
+ return root;
+}
+
+#endif // SkMath_opts_SSE2_DEFINED
diff --git a/chromium/third_party/skia/src/opts/SkMorphology_opts.h b/chromium/third_party/skia/src/opts/SkMorphology_opts.h
index e3ad853cf64..7ea7c546231 100644
--- a/chromium/third_party/skia/src/opts/SkMorphology_opts.h
+++ b/chromium/third_party/skia/src/opts/SkMorphology_opts.h
@@ -5,17 +5,10 @@
* found in the LICENSE file.
*/
-#include <SkColor.h>
+#ifndef SkMorphology_opts_DEFINED
+#define SkMorphology_opts_DEFINED
-/**
- * All morphology procs have the same signature: src is the source buffer, dst the
- * destination buffer, radius is the morphology radius, width and height are the bounds
- * of the destination buffer (in pixels), and srcStride and dstStride are the
- * number of pixels per row in each buffer. All buffers are 8888.
- */
-
-typedef void (*SkMorphologyProc)(const SkPMColor* src, SkPMColor* dst, int radius,
- int width, int height, int srcStride, int dstStride);
+#include <SkMorphologyImageFilter.h>
enum SkMorphologyProcType {
kDilateX_SkMorphologyProcType,
@@ -24,4 +17,6 @@ enum SkMorphologyProcType {
kErodeY_SkMorphologyProcType
};
-SkMorphologyProc SkMorphologyGetPlatformProc(SkMorphologyProcType type);
+SkMorphologyImageFilter::Proc SkMorphologyGetPlatformProc(SkMorphologyProcType type);
+
+#endif
diff --git a/chromium/third_party/skia/src/opts/SkMorphology_opts_SSE2.cpp b/chromium/third_party/skia/src/opts/SkMorphology_opts_SSE2.cpp
index b58fced2c12..e782950956a 100644
--- a/chromium/third_party/skia/src/opts/SkMorphology_opts_SSE2.cpp
+++ b/chromium/third_party/skia/src/opts/SkMorphology_opts_SSE2.cpp
@@ -5,12 +5,10 @@
* found in the LICENSE file.
*/
-
+#include <emmintrin.h>
#include "SkColorPriv.h"
#include "SkMorphology_opts_SSE2.h"
-#include <emmintrin.h>
-
/* SSE2 version of dilateX, dilateY, erodeX, erodeY.
* portable versions are in src/effects/SkMorphologyImageFilter.cpp.
*/
@@ -48,8 +46,12 @@ static void SkMorph_SSE2(const SkPMColor* src, SkPMColor* dst, int radius,
lp += srcStrideY;
up += srcStrideY;
}
- if (x >= radius) src += srcStrideX;
- if (x + radius < width - 1) upperSrc += srcStrideX;
+ if (x >= radius) {
+ src += srcStrideX;
+ }
+ if (x + radius < width - 1) {
+ upperSrc += srcStrideX;
+ }
dst += dstStrideX;
}
}
diff --git a/chromium/third_party/skia/src/opts/SkMorphology_opts_SSE2.h b/chromium/third_party/skia/src/opts/SkMorphology_opts_SSE2.h
index bd103e6eba9..bf5aa03b092 100644
--- a/chromium/third_party/skia/src/opts/SkMorphology_opts_SSE2.h
+++ b/chromium/third_party/skia/src/opts/SkMorphology_opts_SSE2.h
@@ -5,6 +5,11 @@
* found in the LICENSE file.
*/
+#ifndef SkMorphology_opts_SSE2_DEFINED
+#define SkMorphology_opts_SSE2_DEFINED
+
+#include "SkColor.h"
+
void SkDilateX_SSE2(const SkPMColor* src, SkPMColor* dst, int radius,
int width, int height, int srcStride, int dstStride);
void SkDilateY_SSE2(const SkPMColor* src, SkPMColor* dst, int radius,
@@ -13,3 +18,5 @@ void SkErodeX_SSE2(const SkPMColor* src, SkPMColor* dst, int radius,
int width, int height, int srcStride, int dstStride);
void SkErodeY_SSE2(const SkPMColor* src, SkPMColor* dst, int radius,
int width, int height, int srcStride, int dstStride);
+
+#endif
diff --git a/chromium/third_party/skia/src/opts/SkMorphology_opts_arm.cpp b/chromium/third_party/skia/src/opts/SkMorphology_opts_arm.cpp
new file mode 100644
index 00000000000..2bba4929c22
--- /dev/null
+++ b/chromium/third_party/skia/src/opts/SkMorphology_opts_arm.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2014 ARM Ltd.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkMorphology_opts.h"
+#include "SkMorphology_opts_neon.h"
+#include "SkUtilsArm.h"
+
+SkMorphologyImageFilter::Proc SkMorphologyGetPlatformProc(SkMorphologyProcType type) {
+#if SK_ARM_NEON_IS_NONE
+ return NULL;
+#else
+#if SK_ARM_NEON_IS_DYNAMIC
+ if (!sk_cpu_arm_has_neon()) {
+ return NULL;
+ }
+#endif
+ switch (type) {
+ case kDilateX_SkMorphologyProcType:
+ return SkDilateX_neon;
+ case kDilateY_SkMorphologyProcType:
+ return SkDilateY_neon;
+ case kErodeX_SkMorphologyProcType:
+ return SkErodeX_neon;
+ case kErodeY_SkMorphologyProcType:
+ return SkErodeY_neon;
+ default:
+ return NULL;
+ }
+#endif
+}
diff --git a/chromium/third_party/skia/src/opts/SkMorphology_opts_none.cpp b/chromium/third_party/skia/src/opts/SkMorphology_opts_none.cpp
index 66d58ba571f..ade261fc7d2 100644
--- a/chromium/third_party/skia/src/opts/SkMorphology_opts_none.cpp
+++ b/chromium/third_party/skia/src/opts/SkMorphology_opts_none.cpp
@@ -7,6 +7,6 @@
#include "SkMorphology_opts.h"
-SkMorphologyProc SkMorphologyGetPlatformProc(SkMorphologyProcType) {
+SkMorphologyImageFilter::Proc SkMorphologyGetPlatformProc(SkMorphologyProcType) {
return NULL;
}
diff --git a/chromium/third_party/skia/src/opts/SkUtils_opts_SSE2.cpp b/chromium/third_party/skia/src/opts/SkUtils_opts_SSE2.cpp
index e22044d39d3..bd2f9b29a44 100644
--- a/chromium/third_party/skia/src/opts/SkUtils_opts_SSE2.cpp
+++ b/chromium/third_party/skia/src/opts/SkUtils_opts_SSE2.cpp
@@ -1,4 +1,3 @@
-
/*
* Copyright 2009 The Android Open Source Project
*
@@ -6,7 +5,6 @@
* found in the LICENSE file.
*/
-
#include <emmintrin.h>
#include "SkUtils_opts_SSE2.h"
@@ -69,3 +67,33 @@ void sk_memset32_SSE2(uint32_t *dst, uint32_t value, int count)
--count;
}
}
+
+void sk_memcpy32_SSE2(uint32_t *dst, const uint32_t *src, int count)
+{
+ if (count >= 16) {
+ while (((size_t)dst) & 0x0F) {
+ *dst++ = *src++;
+ --count;
+ }
+ __m128i *dst128 = reinterpret_cast<__m128i*>(dst);
+ const __m128i *src128 = reinterpret_cast<const __m128i*>(src);
+ while (count >= 16) {
+ __m128i a = _mm_loadu_si128(src128++);
+ __m128i b = _mm_loadu_si128(src128++);
+ __m128i c = _mm_loadu_si128(src128++);
+ __m128i d = _mm_loadu_si128(src128++);
+
+ _mm_store_si128(dst128++, a);
+ _mm_store_si128(dst128++, b);
+ _mm_store_si128(dst128++, c);
+ _mm_store_si128(dst128++, d);
+ count -= 16;
+ }
+ dst = reinterpret_cast<uint32_t*>(dst128);
+ src = reinterpret_cast<const uint32_t*>(src128);
+ }
+ while (count > 0) {
+ *dst++ = *src++;
+ --count;
+ }
+}
diff --git a/chromium/third_party/skia/src/opts/SkUtils_opts_SSE2.h b/chromium/third_party/skia/src/opts/SkUtils_opts_SSE2.h
index ed24c1ffa40..009f01894b4 100644
--- a/chromium/third_party/skia/src/opts/SkUtils_opts_SSE2.h
+++ b/chromium/third_party/skia/src/opts/SkUtils_opts_SSE2.h
@@ -1,4 +1,3 @@
-
/*
* Copyright 2009 The Android Open Source Project
*
@@ -6,8 +5,13 @@
* found in the LICENSE file.
*/
+#ifndef SkUtils_opts_SSE2_DEFINED
+#define SkUtils_opts_SSE2_DEFINED
#include "SkTypes.h"
void sk_memset16_SSE2(uint16_t *dst, uint16_t value, int count);
void sk_memset32_SSE2(uint32_t *dst, uint32_t value, int count);
+void sk_memcpy32_SSE2(uint32_t *dst, const uint32_t *src, int count);
+
+#endif
diff --git a/chromium/third_party/skia/src/opts/SkUtils_opts_arm.cpp b/chromium/third_party/skia/src/opts/SkUtils_opts_arm.cpp
new file mode 100644
index 00000000000..b1c9d0aa93e
--- /dev/null
+++ b/chromium/third_party/skia/src/opts/SkUtils_opts_arm.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2014 ARM Ltd.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkUtils.h"
+#include "SkUtilsArm.h"
+
+#if defined(SK_CPU_LENDIAN) && !SK_ARM_NEON_IS_NONE
+extern "C" void memset16_neon(uint16_t dst[], uint16_t value, int count);
+extern "C" void memset32_neon(uint32_t dst[], uint32_t value, int count);
+#endif
+
+#if defined(SK_CPU_LENDIAN)
+extern "C" void arm_memset16(uint16_t* dst, uint16_t value, int count);
+extern "C" void arm_memset32(uint32_t* dst, uint32_t value, int count);
+#endif
+
+SkMemset16Proc SkMemset16GetPlatformProc() {
+ // FIXME: memset.arm.S is using syntax incompatible with XCode
+#if !defined(SK_CPU_LENDIAN) || defined(SK_BUILD_FOR_IOS)
+ return NULL;
+#elif SK_ARM_NEON_IS_DYNAMIC
+ if (sk_cpu_arm_has_neon()) {
+ return memset16_neon;
+ } else {
+ return arm_memset16;
+ }
+#elif SK_ARM_NEON_IS_ALWAYS
+ return memset16_neon;
+#else
+ return arm_memset16;
+#endif
+}
+
+SkMemset32Proc SkMemset32GetPlatformProc() {
+ // FIXME: memset.arm.S is using syntax incompatible with XCode
+#if !defined(SK_CPU_LENDIAN) || defined(SK_BUILD_FOR_IOS)
+ return NULL;
+#elif SK_ARM_NEON_IS_DYNAMIC
+ if (sk_cpu_arm_has_neon()) {
+ return memset32_neon;
+ } else {
+ return arm_memset32;
+ }
+#elif SK_ARM_NEON_IS_ALWAYS
+ return memset32_neon;
+#else
+ return arm_memset32;
+#endif
+}
+
+SkMemcpy32Proc SkMemcpy32GetPlatformProc() {
+ return NULL;
+}
diff --git a/chromium/third_party/skia/src/opts/SkUtils_opts_none.cpp b/chromium/third_party/skia/src/opts/SkUtils_opts_none.cpp
index 286f10d7e53..18f52496db4 100644
--- a/chromium/third_party/skia/src/opts/SkUtils_opts_none.cpp
+++ b/chromium/third_party/skia/src/opts/SkUtils_opts_none.cpp
@@ -16,3 +16,7 @@ SkMemset16Proc SkMemset16GetPlatformProc() {
SkMemset32Proc SkMemset32GetPlatformProc() {
return NULL;
}
+
+SkMemcpy32Proc SkMemcpy32GetPlatformProc() {
+ return NULL;
+}
diff --git a/chromium/third_party/skia/src/opts/SkXfermode_opts_SSE2.cpp b/chromium/third_party/skia/src/opts/SkXfermode_opts_SSE2.cpp
new file mode 100644
index 00000000000..94f9a4aea3b
--- /dev/null
+++ b/chromium/third_party/skia/src/opts/SkXfermode_opts_SSE2.cpp
@@ -0,0 +1,819 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkColorPriv.h"
+#include "SkColor_opts_SSE2.h"
+#include "SkMathPriv.h"
+#include "SkMath_opts_SSE2.h"
+#include "SkXfermode.h"
+#include "SkXfermode_opts_SSE2.h"
+#include "SkXfermode_proccoeff.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// 4 pixels SSE2 version functions
+////////////////////////////////////////////////////////////////////////////////
+
+static inline __m128i SkDiv255Round_SSE2(const __m128i& a) {
+ __m128i prod = _mm_add_epi32(a, _mm_set1_epi32(128)); // prod += 128;
+ prod = _mm_add_epi32(prod, _mm_srli_epi32(prod, 8)); // prod + (prod >> 8)
+ prod = _mm_srli_epi32(prod, 8); // >> 8
+
+ return prod;
+}
+
+static inline __m128i saturated_add_SSE2(const __m128i& a, const __m128i& b) {
+ __m128i sum = _mm_add_epi32(a, b);
+ __m128i cmp = _mm_cmpgt_epi32(sum, _mm_set1_epi32(255));
+
+ sum = _mm_or_si128(_mm_and_si128(cmp, _mm_set1_epi32(255)),
+ _mm_andnot_si128(cmp, sum));
+ return sum;
+}
+
+static inline __m128i clamp_signed_byte_SSE2(const __m128i& n) {
+ __m128i cmp1 = _mm_cmplt_epi32(n, _mm_setzero_si128());
+ __m128i cmp2 = _mm_cmpgt_epi32(n, _mm_set1_epi32(255));
+ __m128i ret = _mm_and_si128(cmp2, _mm_set1_epi32(255));
+
+ __m128i cmp = _mm_or_si128(cmp1, cmp2);
+ ret = _mm_or_si128(_mm_and_si128(cmp, ret), _mm_andnot_si128(cmp, n));
+
+ return ret;
+}
+
+static inline __m128i clamp_div255round_SSE2(const __m128i& prod) {
+ // test if > 0
+ __m128i cmp1 = _mm_cmpgt_epi32(prod, _mm_setzero_si128());
+ // test if < 255*255
+ __m128i cmp2 = _mm_cmplt_epi32(prod, _mm_set1_epi32(255*255));
+
+ __m128i ret = _mm_setzero_si128();
+
+ // if value >= 255*255, value = 255
+ ret = _mm_andnot_si128(cmp2, _mm_set1_epi32(255));
+
+ __m128i div = SkDiv255Round_SSE2(prod);
+
+ // test if > 0 && < 255*255
+ __m128i cmp = _mm_and_si128(cmp1, cmp2);
+
+ ret = _mm_or_si128(_mm_and_si128(cmp, div), _mm_andnot_si128(cmp, ret));
+
+ return ret;
+}
+
+static __m128i srcover_modeproc_SSE2(const __m128i& src, const __m128i& dst) {
+ __m128i isa = _mm_sub_epi32(_mm_set1_epi32(256), SkGetPackedA32_SSE2(src));
+ return _mm_add_epi32(src, SkAlphaMulQ_SSE2(dst, isa));
+}
+
+static __m128i dstover_modeproc_SSE2(const __m128i& src, const __m128i& dst) {
+ __m128i ida = _mm_sub_epi32(_mm_set1_epi32(256), SkGetPackedA32_SSE2(dst));
+ return _mm_add_epi32(dst, SkAlphaMulQ_SSE2(src, ida));
+}
+
+static __m128i srcin_modeproc_SSE2(const __m128i& src, const __m128i& dst) {
+ __m128i da = SkGetPackedA32_SSE2(dst);
+ return SkAlphaMulQ_SSE2(src, SkAlpha255To256_SSE2(da));
+}
+
+static __m128i dstin_modeproc_SSE2(const __m128i& src, const __m128i& dst) {
+ __m128i sa = SkGetPackedA32_SSE2(src);
+ return SkAlphaMulQ_SSE2(dst, SkAlpha255To256_SSE2(sa));
+}
+
+static __m128i srcout_modeproc_SSE2(const __m128i& src, const __m128i& dst) {
+ __m128i ida = _mm_sub_epi32(_mm_set1_epi32(256), SkGetPackedA32_SSE2(dst));
+ return SkAlphaMulQ_SSE2(src, ida);
+}
+
+static __m128i dstout_modeproc_SSE2(const __m128i& src, const __m128i& dst) {
+ __m128i isa = _mm_sub_epi32(_mm_set1_epi32(256), SkGetPackedA32_SSE2(src));
+ return SkAlphaMulQ_SSE2(dst, isa);
+}
+
+static __m128i srcatop_modeproc_SSE2(const __m128i& src, const __m128i& dst) {
+ __m128i sa = SkGetPackedA32_SSE2(src);
+ __m128i da = SkGetPackedA32_SSE2(dst);
+ __m128i isa = _mm_sub_epi32(_mm_set1_epi32(255), sa);
+
+ __m128i a = da;
+
+ __m128i r1 = SkAlphaMulAlpha_SSE2(da, SkGetPackedR32_SSE2(src));
+ __m128i r2 = SkAlphaMulAlpha_SSE2(isa, SkGetPackedR32_SSE2(dst));
+ __m128i r = _mm_add_epi32(r1, r2);
+
+ __m128i g1 = SkAlphaMulAlpha_SSE2(da, SkGetPackedG32_SSE2(src));
+ __m128i g2 = SkAlphaMulAlpha_SSE2(isa, SkGetPackedG32_SSE2(dst));
+ __m128i g = _mm_add_epi32(g1, g2);
+
+ __m128i b1 = SkAlphaMulAlpha_SSE2(da, SkGetPackedB32_SSE2(src));
+ __m128i b2 = SkAlphaMulAlpha_SSE2(isa, SkGetPackedB32_SSE2(dst));
+ __m128i b = _mm_add_epi32(b1, b2);
+
+ return SkPackARGB32_SSE2(a, r, g, b);
+}
+
+static __m128i dstatop_modeproc_SSE2(const __m128i& src, const __m128i& dst) {
+ __m128i sa = SkGetPackedA32_SSE2(src);
+ __m128i da = SkGetPackedA32_SSE2(dst);
+ __m128i ida = _mm_sub_epi32(_mm_set1_epi32(255), da);
+
+ __m128i a = sa;
+
+ __m128i r1 = SkAlphaMulAlpha_SSE2(ida, SkGetPackedR32_SSE2(src));
+ __m128i r2 = SkAlphaMulAlpha_SSE2(sa, SkGetPackedR32_SSE2(dst));
+ __m128i r = _mm_add_epi32(r1, r2);
+
+ __m128i g1 = SkAlphaMulAlpha_SSE2(ida, SkGetPackedG32_SSE2(src));
+ __m128i g2 = SkAlphaMulAlpha_SSE2(sa, SkGetPackedG32_SSE2(dst));
+ __m128i g = _mm_add_epi32(g1, g2);
+
+ __m128i b1 = SkAlphaMulAlpha_SSE2(ida, SkGetPackedB32_SSE2(src));
+ __m128i b2 = SkAlphaMulAlpha_SSE2(sa, SkGetPackedB32_SSE2(dst));
+ __m128i b = _mm_add_epi32(b1, b2);
+
+ return SkPackARGB32_SSE2(a, r, g, b);
+}
+
+static __m128i xor_modeproc_SSE2(const __m128i& src, const __m128i& dst) {
+ __m128i sa = SkGetPackedA32_SSE2(src);
+ __m128i da = SkGetPackedA32_SSE2(dst);
+ __m128i isa = _mm_sub_epi32(_mm_set1_epi32(255), sa);
+ __m128i ida = _mm_sub_epi32(_mm_set1_epi32(255), da);
+
+ __m128i a1 = _mm_add_epi32(sa, da);
+ __m128i a2 = SkAlphaMulAlpha_SSE2(sa, da);
+ a2 = _mm_slli_epi32(a2, 1);
+ __m128i a = _mm_sub_epi32(a1, a2);
+
+ __m128i r1 = SkAlphaMulAlpha_SSE2(ida, SkGetPackedR32_SSE2(src));
+ __m128i r2 = SkAlphaMulAlpha_SSE2(isa, SkGetPackedR32_SSE2(dst));
+ __m128i r = _mm_add_epi32(r1, r2);
+
+ __m128i g1 = SkAlphaMulAlpha_SSE2(ida, SkGetPackedG32_SSE2(src));
+ __m128i g2 = SkAlphaMulAlpha_SSE2(isa, SkGetPackedG32_SSE2(dst));
+ __m128i g = _mm_add_epi32(g1, g2);
+
+ __m128i b1 = SkAlphaMulAlpha_SSE2(ida, SkGetPackedB32_SSE2(src));
+ __m128i b2 = SkAlphaMulAlpha_SSE2(isa, SkGetPackedB32_SSE2(dst));
+ __m128i b = _mm_add_epi32(b1, b2);
+
+ return SkPackARGB32_SSE2(a, r, g, b);
+}
+
+static __m128i plus_modeproc_SSE2(const __m128i& src, const __m128i& dst) {
+ __m128i b = saturated_add_SSE2(SkGetPackedB32_SSE2(src),
+ SkGetPackedB32_SSE2(dst));
+ __m128i g = saturated_add_SSE2(SkGetPackedG32_SSE2(src),
+ SkGetPackedG32_SSE2(dst));
+ __m128i r = saturated_add_SSE2(SkGetPackedR32_SSE2(src),
+ SkGetPackedR32_SSE2(dst));
+ __m128i a = saturated_add_SSE2(SkGetPackedA32_SSE2(src),
+ SkGetPackedA32_SSE2(dst));
+ return SkPackARGB32_SSE2(a, r, g, b);
+}
+
+static __m128i modulate_modeproc_SSE2(const __m128i& src, const __m128i& dst) {
+ __m128i a = SkAlphaMulAlpha_SSE2(SkGetPackedA32_SSE2(src),
+ SkGetPackedA32_SSE2(dst));
+ __m128i r = SkAlphaMulAlpha_SSE2(SkGetPackedR32_SSE2(src),
+ SkGetPackedR32_SSE2(dst));
+ __m128i g = SkAlphaMulAlpha_SSE2(SkGetPackedG32_SSE2(src),
+ SkGetPackedG32_SSE2(dst));
+ __m128i b = SkAlphaMulAlpha_SSE2(SkGetPackedB32_SSE2(src),
+ SkGetPackedB32_SSE2(dst));
+ return SkPackARGB32_SSE2(a, r, g, b);
+}
+
+static inline __m128i SkMin32_SSE2(const __m128i& a, const __m128i& b) {
+ __m128i cmp = _mm_cmplt_epi32(a, b);
+ return _mm_or_si128(_mm_and_si128(cmp, a), _mm_andnot_si128(cmp, b));
+}
+
+static inline __m128i srcover_byte_SSE2(const __m128i& a, const __m128i& b) {
+ // a + b - SkAlphaMulAlpha(a, b);
+ return _mm_sub_epi32(_mm_add_epi32(a, b), SkAlphaMulAlpha_SSE2(a, b));
+
+}
+
+static inline __m128i blendfunc_multiply_byte_SSE2(const __m128i& sc, const __m128i& dc,
+ const __m128i& sa, const __m128i& da) {
+ // sc * (255 - da)
+ __m128i ret1 = _mm_sub_epi32(_mm_set1_epi32(255), da);
+ ret1 = _mm_mullo_epi16(sc, ret1);
+
+ // dc * (255 - sa)
+ __m128i ret2 = _mm_sub_epi32(_mm_set1_epi32(255), sa);
+ ret2 = _mm_mullo_epi16(dc, ret2);
+
+ // sc * dc
+ __m128i ret3 = _mm_mullo_epi16(sc, dc);
+
+ __m128i ret = _mm_add_epi32(ret1, ret2);
+ ret = _mm_add_epi32(ret, ret3);
+
+ return clamp_div255round_SSE2(ret);
+}
+
+static __m128i multiply_modeproc_SSE2(const __m128i& src, const __m128i& dst) {
+ __m128i sa = SkGetPackedA32_SSE2(src);
+ __m128i da = SkGetPackedA32_SSE2(dst);
+ __m128i a = srcover_byte_SSE2(sa, da);
+
+ __m128i sr = SkGetPackedR32_SSE2(src);
+ __m128i dr = SkGetPackedR32_SSE2(dst);
+ __m128i r = blendfunc_multiply_byte_SSE2(sr, dr, sa, da);
+
+ __m128i sg = SkGetPackedG32_SSE2(src);
+ __m128i dg = SkGetPackedG32_SSE2(dst);
+ __m128i g = blendfunc_multiply_byte_SSE2(sg, dg, sa, da);
+
+
+ __m128i sb = SkGetPackedB32_SSE2(src);
+ __m128i db = SkGetPackedB32_SSE2(dst);
+ __m128i b = blendfunc_multiply_byte_SSE2(sb, db, sa, da);
+
+ return SkPackARGB32_SSE2(a, r, g, b);
+}
+
+static __m128i screen_modeproc_SSE2(const __m128i& src, const __m128i& dst) {
+ __m128i a = srcover_byte_SSE2(SkGetPackedA32_SSE2(src),
+ SkGetPackedA32_SSE2(dst));
+ __m128i r = srcover_byte_SSE2(SkGetPackedR32_SSE2(src),
+ SkGetPackedR32_SSE2(dst));
+ __m128i g = srcover_byte_SSE2(SkGetPackedG32_SSE2(src),
+ SkGetPackedG32_SSE2(dst));
+ __m128i b = srcover_byte_SSE2(SkGetPackedB32_SSE2(src),
+ SkGetPackedB32_SSE2(dst));
+ return SkPackARGB32_SSE2(a, r, g, b);
+}
+
+// Portable version overlay_byte() is in SkXfermode.cpp.
+static inline __m128i overlay_byte_SSE2(const __m128i& sc, const __m128i& dc,
+ const __m128i& sa, const __m128i& da) {
+ __m128i ida = _mm_sub_epi32(_mm_set1_epi32(255), da);
+ __m128i tmp1 = _mm_mullo_epi16(sc, ida);
+ __m128i isa = _mm_sub_epi32(_mm_set1_epi32(255), sa);
+ __m128i tmp2 = _mm_mullo_epi16(dc, isa);
+ __m128i tmp = _mm_add_epi32(tmp1, tmp2);
+
+ __m128i cmp = _mm_cmpgt_epi32(_mm_slli_epi32(dc, 1), da);
+ __m128i rc1 = _mm_slli_epi32(sc, 1); // 2 * sc
+ rc1 = Multiply32_SSE2(rc1, dc); // *dc
+
+ __m128i rc2 = _mm_mullo_epi16(sa, da); // sa * da
+ __m128i tmp3 = _mm_slli_epi32(_mm_sub_epi32(da, dc), 1); // 2 * (da - dc)
+ tmp3 = Multiply32_SSE2(tmp3, _mm_sub_epi32(sa, sc)); // * (sa - sc)
+ rc2 = _mm_sub_epi32(rc2, tmp3);
+
+ __m128i rc = _mm_or_si128(_mm_andnot_si128(cmp, rc1),
+ _mm_and_si128(cmp, rc2));
+ return clamp_div255round_SSE2(_mm_add_epi32(rc, tmp));
+}
+
+static __m128i overlay_modeproc_SSE2(const __m128i& src, const __m128i& dst) {
+ __m128i sa = SkGetPackedA32_SSE2(src);
+ __m128i da = SkGetPackedA32_SSE2(dst);
+
+ __m128i a = srcover_byte_SSE2(sa, da);
+ __m128i r = overlay_byte_SSE2(SkGetPackedR32_SSE2(src),
+ SkGetPackedR32_SSE2(dst), sa, da);
+ __m128i g = overlay_byte_SSE2(SkGetPackedG32_SSE2(src),
+ SkGetPackedG32_SSE2(dst), sa, da);
+ __m128i b = overlay_byte_SSE2(SkGetPackedB32_SSE2(src),
+ SkGetPackedB32_SSE2(dst), sa, da);
+ return SkPackARGB32_SSE2(a, r, g, b);
+}
+
+static inline __m128i darken_byte_SSE2(const __m128i& sc, const __m128i& dc,
+ const __m128i& sa, const __m128i& da) {
+ __m128i sd = _mm_mullo_epi16(sc, da);
+ __m128i ds = _mm_mullo_epi16(dc, sa);
+
+ __m128i cmp = _mm_cmplt_epi32(sd, ds);
+
+ __m128i tmp = _mm_add_epi32(sc, dc);
+ __m128i ret1 = _mm_sub_epi32(tmp, SkDiv255Round_SSE2(ds));
+ __m128i ret2 = _mm_sub_epi32(tmp, SkDiv255Round_SSE2(sd));
+ __m128i ret = _mm_or_si128(_mm_and_si128(cmp, ret1),
+ _mm_andnot_si128(cmp, ret2));
+ return ret;
+}
+
+static __m128i darken_modeproc_SSE2(const __m128i& src, const __m128i& dst) {
+ __m128i sa = SkGetPackedA32_SSE2(src);
+ __m128i da = SkGetPackedA32_SSE2(dst);
+
+ __m128i a = srcover_byte_SSE2(sa, da);
+ __m128i r = darken_byte_SSE2(SkGetPackedR32_SSE2(src),
+ SkGetPackedR32_SSE2(dst), sa, da);
+ __m128i g = darken_byte_SSE2(SkGetPackedG32_SSE2(src),
+ SkGetPackedG32_SSE2(dst), sa, da);
+ __m128i b = darken_byte_SSE2(SkGetPackedB32_SSE2(src),
+ SkGetPackedB32_SSE2(dst), sa, da);
+ return SkPackARGB32_SSE2(a, r, g, b);
+}
+
+static inline __m128i lighten_byte_SSE2(const __m128i& sc, const __m128i& dc,
+ const __m128i& sa, const __m128i& da) {
+ __m128i sd = _mm_mullo_epi16(sc, da);
+ __m128i ds = _mm_mullo_epi16(dc, sa);
+
+ __m128i cmp = _mm_cmpgt_epi32(sd, ds);
+
+ __m128i tmp = _mm_add_epi32(sc, dc);
+ __m128i ret1 = _mm_sub_epi32(tmp, SkDiv255Round_SSE2(ds));
+ __m128i ret2 = _mm_sub_epi32(tmp, SkDiv255Round_SSE2(sd));
+ __m128i ret = _mm_or_si128(_mm_and_si128(cmp, ret1),
+ _mm_andnot_si128(cmp, ret2));
+ return ret;
+}
+
+static __m128i lighten_modeproc_SSE2(const __m128i& src, const __m128i& dst) {
+ __m128i sa = SkGetPackedA32_SSE2(src);
+ __m128i da = SkGetPackedA32_SSE2(dst);
+
+ __m128i a = srcover_byte_SSE2(sa, da);
+ __m128i r = lighten_byte_SSE2(SkGetPackedR32_SSE2(src),
+ SkGetPackedR32_SSE2(dst), sa, da);
+ __m128i g = lighten_byte_SSE2(SkGetPackedG32_SSE2(src),
+ SkGetPackedG32_SSE2(dst), sa, da);
+ __m128i b = lighten_byte_SSE2(SkGetPackedB32_SSE2(src),
+ SkGetPackedB32_SSE2(dst), sa, da);
+ return SkPackARGB32_SSE2(a, r, g, b);
+}
+
+static inline __m128i colordodge_byte_SSE2(const __m128i& sc, const __m128i& dc,
+ const __m128i& sa, const __m128i& da) {
+ __m128i diff = _mm_sub_epi32(sa, sc);
+ __m128i ida = _mm_sub_epi32(_mm_set1_epi32(255), da);
+ __m128i isa = _mm_sub_epi32(_mm_set1_epi32(255), sa);
+
+ // if (0 == dc)
+ __m128i cmp1 = _mm_cmpeq_epi32(dc, _mm_setzero_si128());
+ __m128i rc1 = _mm_and_si128(cmp1, SkAlphaMulAlpha_SSE2(sc, ida));
+
+ // else if (0 == diff)
+ __m128i cmp2 = _mm_cmpeq_epi32(diff, _mm_setzero_si128());
+ __m128i cmp = _mm_andnot_si128(cmp1, cmp2);
+ __m128i tmp1 = _mm_mullo_epi16(sa, da);
+ __m128i tmp2 = _mm_mullo_epi16(sc, ida);
+ __m128i tmp3 = _mm_mullo_epi16(dc, isa);
+ __m128i rc2 = _mm_add_epi32(tmp1, tmp2);
+ rc2 = _mm_add_epi32(rc2, tmp3);
+ rc2 = clamp_div255round_SSE2(rc2);
+ rc2 = _mm_and_si128(cmp, rc2);
+
+ // else
+ __m128i cmp3 = _mm_or_si128(cmp1, cmp2);
+ __m128i value = _mm_mullo_epi16(dc, sa);
+ diff = shim_mm_div_epi32(value, diff);
+
+ __m128i tmp4 = SkMin32_SSE2(da, diff);
+ tmp4 = Multiply32_SSE2(sa, tmp4);
+ __m128i rc3 = _mm_add_epi32(tmp4, tmp2);
+ rc3 = _mm_add_epi32(rc3, tmp3);
+ rc3 = clamp_div255round_SSE2(rc3);
+ rc3 = _mm_andnot_si128(cmp3, rc3);
+
+ __m128i rc = _mm_or_si128(rc1, rc2);
+ rc = _mm_or_si128(rc, rc3);
+
+ return rc;
+}
+
+static __m128i colordodge_modeproc_SSE2(const __m128i& src,
+ const __m128i& dst) {
+ __m128i sa = SkGetPackedA32_SSE2(src);
+ __m128i da = SkGetPackedA32_SSE2(dst);
+
+ __m128i a = srcover_byte_SSE2(sa, da);
+ __m128i r = colordodge_byte_SSE2(SkGetPackedR32_SSE2(src),
+ SkGetPackedR32_SSE2(dst), sa, da);
+ __m128i g = colordodge_byte_SSE2(SkGetPackedG32_SSE2(src),
+ SkGetPackedG32_SSE2(dst), sa, da);
+ __m128i b = colordodge_byte_SSE2(SkGetPackedB32_SSE2(src),
+ SkGetPackedB32_SSE2(dst), sa, da);
+ return SkPackARGB32_SSE2(a, r, g, b);
+}
+
+static inline __m128i colorburn_byte_SSE2(const __m128i& sc, const __m128i& dc,
+ const __m128i& sa, const __m128i& da) {
+ __m128i ida = _mm_sub_epi32(_mm_set1_epi32(255), da);
+ __m128i isa = _mm_sub_epi32(_mm_set1_epi32(255), sa);
+
+ // if (dc == da)
+ __m128i cmp1 = _mm_cmpeq_epi32(dc, da);
+ __m128i tmp1 = _mm_mullo_epi16(sa, da);
+ __m128i tmp2 = _mm_mullo_epi16(sc, ida);
+ __m128i tmp3 = _mm_mullo_epi16(dc, isa);
+ __m128i rc1 = _mm_add_epi32(tmp1, tmp2);
+ rc1 = _mm_add_epi32(rc1, tmp3);
+ rc1 = clamp_div255round_SSE2(rc1);
+ rc1 = _mm_and_si128(cmp1, rc1);
+
+ // else if (0 == sc)
+ __m128i cmp2 = _mm_cmpeq_epi32(sc, _mm_setzero_si128());
+ __m128i rc2 = SkAlphaMulAlpha_SSE2(dc, isa);
+ __m128i cmp = _mm_andnot_si128(cmp1, cmp2);
+ rc2 = _mm_and_si128(cmp, rc2);
+
+ // else
+ __m128i cmp3 = _mm_or_si128(cmp1, cmp2);
+ __m128i tmp4 = _mm_sub_epi32(da, dc);
+ tmp4 = Multiply32_SSE2(tmp4, sa);
+ tmp4 = shim_mm_div_epi32(tmp4, sc);
+
+ __m128i tmp5 = _mm_sub_epi32(da, SkMin32_SSE2(da, tmp4));
+ tmp5 = Multiply32_SSE2(sa, tmp5);
+ __m128i rc3 = _mm_add_epi32(tmp5, tmp2);
+ rc3 = _mm_add_epi32(rc3, tmp3);
+ rc3 = clamp_div255round_SSE2(rc3);
+ rc3 = _mm_andnot_si128(cmp3, rc3);
+
+ __m128i rc = _mm_or_si128(rc1, rc2);
+ rc = _mm_or_si128(rc, rc3);
+
+ return rc;
+}
+
+static __m128i colorburn_modeproc_SSE2(const __m128i& src, const __m128i& dst) {
+ __m128i sa = SkGetPackedA32_SSE2(src);
+ __m128i da = SkGetPackedA32_SSE2(dst);
+
+ __m128i a = srcover_byte_SSE2(sa, da);
+ __m128i r = colorburn_byte_SSE2(SkGetPackedR32_SSE2(src),
+ SkGetPackedR32_SSE2(dst), sa, da);
+ __m128i g = colorburn_byte_SSE2(SkGetPackedG32_SSE2(src),
+ SkGetPackedG32_SSE2(dst), sa, da);
+ __m128i b = colorburn_byte_SSE2(SkGetPackedB32_SSE2(src),
+ SkGetPackedB32_SSE2(dst), sa, da);
+ return SkPackARGB32_SSE2(a, r, g, b);
+}
+
+static inline __m128i hardlight_byte_SSE2(const __m128i& sc, const __m128i& dc,
+ const __m128i& sa, const __m128i& da) {
+ // if (2 * sc <= sa)
+ __m128i tmp1 = _mm_slli_epi32(sc, 1);
+ __m128i cmp1 = _mm_cmpgt_epi32(tmp1, sa);
+ __m128i rc1 = _mm_mullo_epi16(sc, dc); // sc * dc;
+ rc1 = _mm_slli_epi32(rc1, 1); // 2 * sc * dc
+ rc1 = _mm_andnot_si128(cmp1, rc1);
+
+ // else
+ tmp1 = _mm_mullo_epi16(sa, da);
+ __m128i tmp2 = Multiply32_SSE2(_mm_sub_epi32(da, dc),
+ _mm_sub_epi32(sa, sc));
+ tmp2 = _mm_slli_epi32(tmp2, 1);
+ __m128i rc2 = _mm_sub_epi32(tmp1, tmp2);
+ rc2 = _mm_and_si128(cmp1, rc2);
+
+ __m128i rc = _mm_or_si128(rc1, rc2);
+
+ __m128i ida = _mm_sub_epi32(_mm_set1_epi32(255), da);
+ tmp1 = _mm_mullo_epi16(sc, ida);
+ __m128i isa = _mm_sub_epi32(_mm_set1_epi32(255), sa);
+ tmp2 = _mm_mullo_epi16(dc, isa);
+ rc = _mm_add_epi32(rc, tmp1);
+ rc = _mm_add_epi32(rc, tmp2);
+ return clamp_div255round_SSE2(rc);
+}
+
+static __m128i hardlight_modeproc_SSE2(const __m128i& src, const __m128i& dst) {
+ __m128i sa = SkGetPackedA32_SSE2(src);
+ __m128i da = SkGetPackedA32_SSE2(dst);
+
+ __m128i a = srcover_byte_SSE2(sa, da);
+ __m128i r = hardlight_byte_SSE2(SkGetPackedR32_SSE2(src),
+ SkGetPackedR32_SSE2(dst), sa, da);
+ __m128i g = hardlight_byte_SSE2(SkGetPackedG32_SSE2(src),
+ SkGetPackedG32_SSE2(dst), sa, da);
+ __m128i b = hardlight_byte_SSE2(SkGetPackedB32_SSE2(src),
+ SkGetPackedB32_SSE2(dst), sa, da);
+ return SkPackARGB32_SSE2(a, r, g, b);
+}
+
+static __m128i sqrt_unit_byte_SSE2(const __m128i& n) {
+ return SkSqrtBits_SSE2(n, 15+4);
+}
+
+static inline __m128i softlight_byte_SSE2(const __m128i& sc, const __m128i& dc,
+ const __m128i& sa, const __m128i& da) {
+ __m128i tmp1, tmp2, tmp3;
+
+ // int m = da ? dc * 256 / da : 0;
+ __m128i cmp = _mm_cmpeq_epi32(da, _mm_setzero_si128());
+ __m128i m = _mm_slli_epi32(dc, 8);
+ __m128 x = _mm_cvtepi32_ps(m);
+ __m128 y = _mm_cvtepi32_ps(da);
+ m = _mm_cvttps_epi32(_mm_div_ps(x, y));
+ m = _mm_andnot_si128(cmp, m);
+
+ // if (2 * sc <= sa)
+ tmp1 = _mm_slli_epi32(sc, 1); // 2 * sc
+ __m128i cmp1 = _mm_cmpgt_epi32(tmp1, sa);
+ tmp1 = _mm_sub_epi32(tmp1, sa); // 2 * sc - sa
+ tmp2 = _mm_sub_epi32(_mm_set1_epi32(256), m); // 256 - m
+ tmp1 = Multiply32_SSE2(tmp1, tmp2);
+ tmp1 = _mm_srai_epi32(tmp1, 8);
+ tmp1 = _mm_add_epi32(sa, tmp1);
+ tmp1 = Multiply32_SSE2(dc, tmp1);
+ __m128i rc1 = _mm_andnot_si128(cmp1, tmp1);
+
+ // else if (4 * dc <= da)
+ tmp2 = _mm_slli_epi32(dc, 2); // dc * 4
+ __m128i cmp2 = _mm_cmpgt_epi32(tmp2, da);
+ __m128i i = _mm_slli_epi32(m, 2); // 4 * m
+ __m128i j = _mm_add_epi32(i, _mm_set1_epi32(256)); // 4 * m + 256
+ __m128i k = Multiply32_SSE2(i, j); // 4 * m * (4 * m + 256)
+ __m128i t = _mm_sub_epi32(m, _mm_set1_epi32(256)); // m - 256
+ i = Multiply32_SSE2(k, t); // 4 * m * (4 * m + 256) * (m - 256)
+ i = _mm_srai_epi32(i, 16); // >> 16
+ j = Multiply32_SSE2(_mm_set1_epi32(7), m); // 7 * m
+ tmp2 = _mm_add_epi32(i, j);
+ i = Multiply32_SSE2(dc, sa); // dc * sa
+ j = _mm_slli_epi32(sc, 1); // 2 * sc
+ j = _mm_sub_epi32(j, sa); // 2 * sc - sa
+ j = Multiply32_SSE2(da, j); // da * (2 * sc - sa)
+ tmp2 = Multiply32_SSE2(j, tmp2); // * tmp
+ tmp2 = _mm_srai_epi32(tmp2, 8); // >> 8
+ tmp2 = _mm_add_epi32(i, tmp2);
+ cmp = _mm_andnot_si128(cmp2, cmp1);
+ __m128i rc2 = _mm_and_si128(cmp, tmp2);
+ __m128i rc = _mm_or_si128(rc1, rc2);
+
+ // else
+ tmp3 = sqrt_unit_byte_SSE2(m);
+ tmp3 = _mm_sub_epi32(tmp3, m);
+ tmp3 = Multiply32_SSE2(j, tmp3); // j = da * (2 * sc - sa)
+ tmp3 = _mm_srai_epi32(tmp3, 8);
+ tmp3 = _mm_add_epi32(i, tmp3); // i = dc * sa
+ cmp = _mm_and_si128(cmp1, cmp2);
+ __m128i rc3 = _mm_and_si128(cmp, tmp3);
+ rc = _mm_or_si128(rc, rc3);
+
+ tmp1 = _mm_sub_epi32(_mm_set1_epi32(255), da); // 255 - da
+ tmp1 = _mm_mullo_epi16(sc, tmp1);
+ tmp2 = _mm_sub_epi32(_mm_set1_epi32(255), sa); // 255 - sa
+ tmp2 = _mm_mullo_epi16(dc, tmp2);
+ rc = _mm_add_epi32(rc, tmp1);
+ rc = _mm_add_epi32(rc, tmp2);
+ return clamp_div255round_SSE2(rc);
+}
+
+static __m128i softlight_modeproc_SSE2(const __m128i& src, const __m128i& dst) {
+ __m128i sa = SkGetPackedA32_SSE2(src);
+ __m128i da = SkGetPackedA32_SSE2(dst);
+
+ __m128i a = srcover_byte_SSE2(sa, da);
+ __m128i r = softlight_byte_SSE2(SkGetPackedR32_SSE2(src),
+ SkGetPackedR32_SSE2(dst), sa, da);
+ __m128i g = softlight_byte_SSE2(SkGetPackedG32_SSE2(src),
+ SkGetPackedG32_SSE2(dst), sa, da);
+ __m128i b = softlight_byte_SSE2(SkGetPackedB32_SSE2(src),
+ SkGetPackedB32_SSE2(dst), sa, da);
+ return SkPackARGB32_SSE2(a, r, g, b);
+}
+
+static inline __m128i difference_byte_SSE2(const __m128i& sc, const __m128i& dc,
+ const __m128i& sa, const __m128i& da) {
+ __m128i tmp1 = _mm_mullo_epi16(sc, da);
+ __m128i tmp2 = _mm_mullo_epi16(dc, sa);
+ __m128i tmp = SkMin32_SSE2(tmp1, tmp2);
+
+ __m128i ret1 = _mm_add_epi32(sc, dc);
+ __m128i ret2 = _mm_slli_epi32(SkDiv255Round_SSE2(tmp), 1);
+ __m128i ret = _mm_sub_epi32(ret1, ret2);
+
+ ret = clamp_signed_byte_SSE2(ret);
+ return ret;
+}
+
+static __m128i difference_modeproc_SSE2(const __m128i& src,
+ const __m128i& dst) {
+ __m128i sa = SkGetPackedA32_SSE2(src);
+ __m128i da = SkGetPackedA32_SSE2(dst);
+
+ __m128i a = srcover_byte_SSE2(sa, da);
+ __m128i r = difference_byte_SSE2(SkGetPackedR32_SSE2(src),
+ SkGetPackedR32_SSE2(dst), sa, da);
+ __m128i g = difference_byte_SSE2(SkGetPackedG32_SSE2(src),
+ SkGetPackedG32_SSE2(dst), sa, da);
+ __m128i b = difference_byte_SSE2(SkGetPackedB32_SSE2(src),
+ SkGetPackedB32_SSE2(dst), sa, da);
+ return SkPackARGB32_SSE2(a, r, g, b);
+}
+
+static inline __m128i exclusion_byte_SSE2(const __m128i& sc, const __m128i& dc,
+ const __m128i&, __m128i&) {
+ __m128i tmp1 = _mm_mullo_epi16(_mm_set1_epi32(255), sc); // 255 * sc
+ __m128i tmp2 = _mm_mullo_epi16(_mm_set1_epi32(255), dc); // 255 * dc
+ tmp1 = _mm_add_epi32(tmp1, tmp2);
+ tmp2 = _mm_mullo_epi16(sc, dc); // sc * dc
+ tmp2 = _mm_slli_epi32(tmp2, 1); // 2 * sc * dc
+
+ __m128i r = _mm_sub_epi32(tmp1, tmp2);
+ return clamp_div255round_SSE2(r);
+}
+
+static __m128i exclusion_modeproc_SSE2(const __m128i& src, const __m128i& dst) {
+ __m128i sa = SkGetPackedA32_SSE2(src);
+ __m128i da = SkGetPackedA32_SSE2(dst);
+
+ __m128i a = srcover_byte_SSE2(sa, da);
+ __m128i r = exclusion_byte_SSE2(SkGetPackedR32_SSE2(src),
+ SkGetPackedR32_SSE2(dst), sa, da);
+ __m128i g = exclusion_byte_SSE2(SkGetPackedG32_SSE2(src),
+ SkGetPackedG32_SSE2(dst), sa, da);
+ __m128i b = exclusion_byte_SSE2(SkGetPackedB32_SSE2(src),
+ SkGetPackedB32_SSE2(dst), sa, da);
+ return SkPackARGB32_SSE2(a, r, g, b);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+typedef __m128i (*SkXfermodeProcSIMD)(const __m128i& src, const __m128i& dst);
+
+extern SkXfermodeProcSIMD gSSE2XfermodeProcs[];
+
+SkSSE2ProcCoeffXfermode::SkSSE2ProcCoeffXfermode(SkReadBuffer& buffer)
+ : INHERITED(buffer) {
+ fProcSIMD = reinterpret_cast<void*>(gSSE2XfermodeProcs[this->getMode()]);
+ buffer.validate(fProcSIMD != NULL);
+}
+
+void SkSSE2ProcCoeffXfermode::xfer32(SkPMColor dst[], const SkPMColor src[],
+ int count, const SkAlpha aa[]) const {
+ SkASSERT(dst && src && count >= 0);
+
+ SkXfermodeProc proc = this->getProc();
+ SkXfermodeProcSIMD procSIMD = reinterpret_cast<SkXfermodeProcSIMD>(fProcSIMD);
+ SkASSERT(procSIMD != NULL);
+
+ if (NULL == aa) {
+ if (count >= 4) {
+ while (((size_t)dst & 0x0F) != 0) {
+ *dst = proc(*src, *dst);
+ dst++;
+ src++;
+ count--;
+ }
+
+ const __m128i* s = reinterpret_cast<const __m128i*>(src);
+ __m128i* d = reinterpret_cast<__m128i*>(dst);
+
+ while (count >= 4) {
+ __m128i src_pixel = _mm_loadu_si128(s++);
+ __m128i dst_pixel = _mm_load_si128(d);
+
+ dst_pixel = procSIMD(src_pixel, dst_pixel);
+ _mm_store_si128(d++, dst_pixel);
+ count -= 4;
+ }
+
+ src = reinterpret_cast<const SkPMColor*>(s);
+ dst = reinterpret_cast<SkPMColor*>(d);
+ }
+
+ for (int i = count - 1; i >= 0; --i) {
+ *dst = proc(*src, *dst);
+ dst++;
+ src++;
+ }
+ } else {
+ for (int i = count - 1; i >= 0; --i) {
+ unsigned a = aa[i];
+ if (0 != a) {
+ SkPMColor dstC = dst[i];
+ SkPMColor C = proc(src[i], dstC);
+ if (a != 0xFF) {
+ C = SkFourByteInterp(C, dstC, a);
+ }
+ dst[i] = C;
+ }
+ }
+ }
+}
+
+void SkSSE2ProcCoeffXfermode::xfer16(uint16_t dst[], const SkPMColor src[],
+ int count, const SkAlpha aa[]) const {
+ SkASSERT(dst && src && count >= 0);
+
+ SkXfermodeProc proc = this->getProc();
+ SkXfermodeProcSIMD procSIMD = reinterpret_cast<SkXfermodeProcSIMD>(fProcSIMD);
+ SkASSERT(procSIMD != NULL);
+
+ if (NULL == aa) {
+ if (count >= 8) {
+ while (((size_t)dst & 0x0F) != 0) {
+ SkPMColor dstC = SkPixel16ToPixel32(*dst);
+ *dst = SkPixel32ToPixel16_ToU16(proc(*src, dstC));
+ dst++;
+ src++;
+ count--;
+ }
+
+ const __m128i* s = reinterpret_cast<const __m128i*>(src);
+ __m128i* d = reinterpret_cast<__m128i*>(dst);
+
+ while (count >= 8) {
+ __m128i src_pixel1 = _mm_loadu_si128(s++);
+ __m128i src_pixel2 = _mm_loadu_si128(s++);
+ __m128i dst_pixel = _mm_load_si128(d);
+
+ __m128i dst_pixel1 = _mm_unpacklo_epi16(dst_pixel, _mm_setzero_si128());
+ __m128i dst_pixel2 = _mm_unpackhi_epi16(dst_pixel, _mm_setzero_si128());
+
+ __m128i dstC1 = SkPixel16ToPixel32_SSE2(dst_pixel1);
+ __m128i dstC2 = SkPixel16ToPixel32_SSE2(dst_pixel2);
+
+ dst_pixel1 = procSIMD(src_pixel1, dstC1);
+ dst_pixel2 = procSIMD(src_pixel2, dstC2);
+ dst_pixel = SkPixel32ToPixel16_ToU16_SSE2(dst_pixel1, dst_pixel2);
+
+ _mm_store_si128(d++, dst_pixel);
+ count -= 8;
+ }
+
+ src = reinterpret_cast<const SkPMColor*>(s);
+ dst = reinterpret_cast<uint16_t*>(d);
+ }
+
+ for (int i = count - 1; i >= 0; --i) {
+ SkPMColor dstC = SkPixel16ToPixel32(*dst);
+ *dst = SkPixel32ToPixel16_ToU16(proc(*src, dstC));
+ dst++;
+ src++;
+ }
+ } else {
+ for (int i = count - 1; i >= 0; --i) {
+ unsigned a = aa[i];
+ if (0 != a) {
+ SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
+ SkPMColor C = proc(src[i], dstC);
+ if (0xFF != a) {
+ C = SkFourByteInterp(C, dstC, a);
+ }
+ dst[i] = SkPixel32ToPixel16_ToU16(C);
+ }
+ }
+ }
+}
+
+#ifndef SK_IGNORE_TO_STRING
+void SkSSE2ProcCoeffXfermode::toString(SkString* str) const {
+ this->INHERITED::toString(str);
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+
+// 4 pixels modeprocs with SSE2
+SkXfermodeProcSIMD gSSE2XfermodeProcs[] = {
+ NULL, // kClear_Mode
+ NULL, // kSrc_Mode
+ NULL, // kDst_Mode
+ srcover_modeproc_SSE2,
+ dstover_modeproc_SSE2,
+ srcin_modeproc_SSE2,
+ dstin_modeproc_SSE2,
+ srcout_modeproc_SSE2,
+ dstout_modeproc_SSE2,
+ srcatop_modeproc_SSE2,
+ dstatop_modeproc_SSE2,
+ xor_modeproc_SSE2,
+ plus_modeproc_SSE2,
+ modulate_modeproc_SSE2,
+ screen_modeproc_SSE2,
+
+ overlay_modeproc_SSE2,
+ darken_modeproc_SSE2,
+ lighten_modeproc_SSE2,
+ colordodge_modeproc_SSE2,
+ colorburn_modeproc_SSE2,
+ hardlight_modeproc_SSE2,
+ softlight_modeproc_SSE2,
+ difference_modeproc_SSE2,
+ exclusion_modeproc_SSE2,
+ multiply_modeproc_SSE2,
+
+ NULL, // kHue_Mode
+ NULL, // kSaturation_Mode
+ NULL, // kColor_Mode
+ NULL, // kLuminosity_Mode
+};
+
+SkProcCoeffXfermode* SkPlatformXfermodeFactory_impl_SSE2(const ProcCoeff& rec,
+ SkXfermode::Mode mode) {
+ void* procSIMD = reinterpret_cast<void*>(gSSE2XfermodeProcs[mode]);
+
+ if (procSIMD != NULL) {
+ return SkNEW_ARGS(SkSSE2ProcCoeffXfermode, (rec, mode, procSIMD));
+ }
+ return NULL;
+}
diff --git a/chromium/third_party/skia/src/opts/SkXfermode_opts_SSE2.h b/chromium/third_party/skia/src/opts/SkXfermode_opts_SSE2.h
new file mode 100644
index 00000000000..bfc143937a8
--- /dev/null
+++ b/chromium/third_party/skia/src/opts/SkXfermode_opts_SSE2.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkXfermode_opts_SSE2_DEFINED
+#define SkXfermode_opts_SSE2_DEFINED
+
+#include "SkTypes.h"
+#include "SkXfermode_proccoeff.h"
+
+class SK_API SkSSE2ProcCoeffXfermode : public SkProcCoeffXfermode {
+public:
+ SkSSE2ProcCoeffXfermode(const ProcCoeff& rec, SkXfermode::Mode mode,
+ void* procSIMD)
+ : INHERITED(rec, mode), fProcSIMD(procSIMD) {}
+
+ virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
+ const SkAlpha aa[]) const SK_OVERRIDE;
+ virtual void xfer16(uint16_t dst[], const SkPMColor src[],
+ int count, const SkAlpha aa[]) const SK_OVERRIDE;
+
+ SK_TO_STRING_OVERRIDE()
+ SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSSE2ProcCoeffXfermode)
+
+private:
+ SkSSE2ProcCoeffXfermode(SkReadBuffer& buffer);
+
+ void* fProcSIMD;
+ typedef SkProcCoeffXfermode INHERITED;
+};
+
+SkProcCoeffXfermode* SkPlatformXfermodeFactory_impl_SSE2(const ProcCoeff& rec,
+ SkXfermode::Mode mode);
+
+#endif // SkXfermode_opts_SSE2_DEFINED
diff --git a/chromium/third_party/skia/src/opts/SkXfermode_opts_arm_neon.cpp b/chromium/third_party/skia/src/opts/SkXfermode_opts_arm_neon.cpp
index 6a79b737263..70e92af66bc 100644
--- a/chromium/third_party/skia/src/opts/SkXfermode_opts_arm_neon.cpp
+++ b/chromium/third_party/skia/src/opts/SkXfermode_opts_arm_neon.cpp
@@ -41,8 +41,13 @@ static inline uint16x8_t SkAlphaMulAlpha_neon8_16(uint8x8_t color, uint8x8_t alp
static inline uint8x8_t SkDiv255Round_neon8_32_8(int32x4_t p1, int32x4_t p2) {
uint16x8_t tmp;
+#ifdef SK_CPU_ARM64
+ tmp = vmovn_high_u32(vmovn_u32(vreinterpretq_u32_s32(p1)),
+ vreinterpretq_u32_s32(p2));
+#else
tmp = vcombine_u16(vmovn_u32(vreinterpretq_u32_s32(p1)),
vmovn_u32(vreinterpretq_u32_s32(p2)));
+#endif
tmp += vdupq_n_u16(128);
tmp += vshrq_n_u16(tmp, 8);
@@ -66,7 +71,11 @@ static inline uint8x8_t clamp_div255round_simd8_32(int32x4_t val1, int32x4_t val
// Test if <= 0
cmp1 = vcleq_s32(val1, vdupq_n_s32(0));
cmp2 = vcleq_s32(val2, vdupq_n_s32(0));
+#ifdef SK_CPU_ARM64
+ cmp16 = vmovn_high_u32(vmovn_u32(cmp1), cmp2);
+#else
cmp16 = vcombine_u16(vmovn_u32(cmp1), vmovn_u32(cmp2));
+#endif
cmp8_1 = vmovn_u16(cmp16);
// Init to zero
@@ -75,7 +84,11 @@ static inline uint8x8_t clamp_div255round_simd8_32(int32x4_t val1, int32x4_t val
// Test if >= 255*255
cmp1 = vcgeq_s32(val1, vdupq_n_s32(255*255));
cmp2 = vcgeq_s32(val2, vdupq_n_s32(255*255));
+#ifdef SK_CPU_ARM64
+ cmp16 = vmovn_high_u32(vmovn_u32(cmp1), cmp2);
+#else
cmp16 = vcombine_u16(vmovn_u32(cmp1), vmovn_u32(cmp2));
+#endif
cmp8 = vmovn_u16(cmp16);
// Insert 255 where true
@@ -409,11 +422,19 @@ static inline uint8x8_t overlay_hardlight_color(uint8x8_t sc, uint8x8_t dc,
if (overlay) {
dc2 = vshll_n_u8(dc, 1);
scdc2_1 = vmull_u16(vget_low_u16(dc2), vget_low_u16(vmovl_u8(sc)));
+#ifdef SK_CPU_ARM64
+ scdc2_2 = vmull_high_u16(dc2, vmovl_u8(sc));
+#else
scdc2_2 = vmull_u16(vget_high_u16(dc2), vget_high_u16(vmovl_u8(sc)));
+#endif
} else {
sc2 = vshll_n_u8(sc, 1);
scdc2_1 = vmull_u16(vget_low_u16(sc2), vget_low_u16(vmovl_u8(dc)));
+#ifdef SK_CPU_ARM64
+ scdc2_2 = vmull_high_u16(sc2, vmovl_u8(dc));
+#else
scdc2_2 = vmull_u16(vget_high_u16(sc2), vget_high_u16(vmovl_u8(dc)));
+#endif
}
// Calc COM
@@ -421,12 +442,20 @@ static inline uint8x8_t overlay_hardlight_color(uint8x8_t sc, uint8x8_t dc,
com1 = vreinterpretq_s32_u32(
vmull_u16(vget_low_u16(const255), vget_low_u16(sc_plus_dc)));
com2 = vreinterpretq_s32_u32(
+#ifdef SK_CPU_ARM64
+ vmull_high_u16(const255, sc_plus_dc));
+#else
vmull_u16(vget_high_u16(const255), vget_high_u16(sc_plus_dc)));
+#endif
// Calc SUB
int32x4_t sub1, sub2;
sub1 = vreinterpretq_s32_u32(vaddl_u16(vget_low_u16(scda), vget_low_u16(dcsa)));
+#ifdef SK_CPU_ARM64
+ sub2 = vreinterpretq_s32_u32(vaddl_high_u16(scda, dcsa));
+#else
sub2 = vreinterpretq_s32_u32(vaddl_u16(vget_high_u16(scda), vget_high_u16(dcsa)));
+#endif
sub1 = vsubq_s32(sub1, vreinterpretq_s32_u32(scdc2_1));
sub2 = vsubq_s32(sub2, vreinterpretq_s32_u32(scdc2_2));
@@ -444,10 +473,14 @@ static inline uint8x8_t overlay_hardlight_color(uint8x8_t sc, uint8x8_t dc,
int32x4_t val2_1, val2_2;
uint32x4_t cmp1, cmp2;
- cmp1 = vmovl_u16(vget_low_u16(cmp));
- cmp1 |= vshlq_n_u32(cmp1, 16);
- cmp2 = vmovl_u16(vget_high_u16(cmp));
- cmp2 |= vshlq_n_u32(cmp2, 16);
+ // Doing a signed lengthening allows to save a few instructions
+ // thanks to sign extension.
+ cmp1 = vreinterpretq_u32_s32(vmovl_s16(vreinterpret_s16_u16(vget_low_u16(cmp))));
+#ifdef SK_CPU_ARM64
+ cmp2 = vreinterpretq_u32_s32(vmovl_high_s16(vreinterpretq_s16_u16(cmp)));
+#else
+ cmp2 = vreinterpretq_u32_s32(vmovl_s16(vreinterpret_s16_u16(vget_high_u16(cmp))));
+#endif
// Calc COM - SUB
val1_1 = com1 - sub1;
@@ -458,7 +491,11 @@ static inline uint8x8_t overlay_hardlight_color(uint8x8_t sc, uint8x8_t dc,
val2_2 = com2 + sub2;
val2_1 = vsubq_s32(val2_1, vreinterpretq_s32_u32(vmovl_u16(vget_low_u16(sada))));
+#ifdef SK_CPU_ARM64
+ val2_2 = vsubq_s32(val2_2, vreinterpretq_s32_u32(vmovl_high_u16(sada)));
+#else
val2_2 = vsubq_s32(val2_2, vreinterpretq_s32_u32(vmovl_u16(vget_high_u16(sada))));
+#endif
// Insert where needed
val1_1 = vbslq_s32(cmp1, val1_1, val2_1);
@@ -628,11 +665,19 @@ static inline uint8x8_t exclusion_color(uint8x8_t sc, uint8x8_t dc,
term1_1 = vreinterpretq_s32_u32(
vmull_u16(vget_low_u16(const255), vget_low_u16(sc_plus_dc)));
term1_2 = vreinterpretq_s32_u32(
+#ifdef SK_CPU_ARM64
+ vmull_high_u16(const255, sc_plus_dc));
+#else
vmull_u16(vget_high_u16(const255), vget_high_u16(sc_plus_dc)));
+#endif
/* Calc the second term */
term2_1 = vreinterpretq_s32_u32(vshll_n_u16(vget_low_u16(scdc), 1));
+#ifdef SK_CPU_ARM64
+ term2_2 = vreinterpretq_s32_u32(vshll_high_n_u16(scdc, 1));
+#else
term2_2 = vreinterpretq_s32_u32(vshll_n_u16(vget_high_u16(scdc), 1));
+#endif
return clamp_div255round_simd8_32(term1_1 - term2_1, term1_2 - term2_2);
}
@@ -661,10 +706,18 @@ static inline uint8x8_t blendfunc_multiply_color(uint8x8_t sc, uint8x8_t dc,
scdc = vmull_u8(sc, dc);
val1 = vaddl_u16(vget_low_u16(t1), vget_low_u16(t2));
+#ifdef SK_CPU_ARM64
+ val2 = vaddl_high_u16(t1, t2);
+#else
val2 = vaddl_u16(vget_high_u16(t1), vget_high_u16(t2));
+#endif
val1 = vaddw_u16(val1, vget_low_u16(scdc));
+#ifdef SK_CPU_ARM64
+ val2 = vaddw_high_u16(val2, scdc);
+#else
val2 = vaddw_u16(val2, vget_high_u16(scdc));
+#endif
return clamp_div255round_simd8_32(
vreinterpretq_s32_u32(val1), vreinterpretq_s32_u32(val2));
@@ -690,7 +743,7 @@ typedef uint8x8x4_t (*SkXfermodeProcSIMD)(uint8x8x4_t src, uint8x8x4_t dst);
extern SkXfermodeProcSIMD gNEONXfermodeProcs[];
-SkNEONProcCoeffXfermode::SkNEONProcCoeffXfermode(SkFlattenableReadBuffer& buffer)
+SkNEONProcCoeffXfermode::SkNEONProcCoeffXfermode(SkReadBuffer& buffer)
: INHERITED(buffer) {
fProcSIMD = reinterpret_cast<void*>(gNEONXfermodeProcs[this->getMode()]);
}
@@ -708,6 +761,10 @@ void SkNEONProcCoeffXfermode::xfer32(SkPMColor dst[], const SkPMColor src[],
while (count >= 8) {
uint8x8x4_t vsrc, vdst, vres;
+#ifdef SK_CPU_ARM64
+ vsrc = vld4_u8((uint8_t*)src);
+ vdst = vld4_u8((uint8_t*)dst);
+#else
#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 6))
asm volatile (
"vld4.u8 %h[vsrc], [%[src]]! \t\n"
@@ -740,6 +797,7 @@ void SkNEONProcCoeffXfermode::xfer32(SkPMColor dst[], const SkPMColor src[],
vsrc.val[2] = d2; vdst.val[2] = d6;
vsrc.val[3] = d3; vdst.val[3] = d7;
#endif
+#endif // #ifdef SK_CPU_ARM64
vres = procSIMD(vsrc, vdst);
@@ -747,6 +805,9 @@ void SkNEONProcCoeffXfermode::xfer32(SkPMColor dst[], const SkPMColor src[],
count -= 8;
dst += 8;
+#ifdef SK_CPU_ARM64
+ src += 8;
+#endif
}
// Leftovers
for (int i = 0; i < count; i++) {
@@ -783,6 +844,9 @@ void SkNEONProcCoeffXfermode::xfer16(uint16_t* SK_RESTRICT dst,
vdst = vld1q_u16(dst);
+#ifdef SK_CPU_ARM64
+ vsrc = vld4_u8((uint8_t*)src);
+#else
#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 6))
asm volatile (
"vld4.u8 %h[vsrc], [%[src]]! \t\n"
@@ -806,6 +870,7 @@ void SkNEONProcCoeffXfermode::xfer16(uint16_t* SK_RESTRICT dst,
vsrc.val[2] = d2;
vsrc.val[3] = d3;
#endif
+#endif // #ifdef SK_CPU_ARM64
vdst32 = SkPixel16ToPixel32_neon8(vdst);
vres = procSIMD(vsrc, vdst32);
@@ -815,6 +880,9 @@ void SkNEONProcCoeffXfermode::xfer16(uint16_t* SK_RESTRICT dst,
count -= 8;
dst += 8;
+#ifdef SK_CPU_ARM64
+ src += 8;
+#endif
}
for (int i = 0; i < count; i++) {
SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
@@ -835,7 +903,7 @@ void SkNEONProcCoeffXfermode::xfer16(uint16_t* SK_RESTRICT dst,
}
}
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
void SkNEONProcCoeffXfermode::toString(SkString* str) const {
this->INHERITED::toString(str);
}
diff --git a/chromium/third_party/skia/src/opts/SkXfermode_opts_arm_neon.h b/chromium/third_party/skia/src/opts/SkXfermode_opts_arm_neon.h
index a8d438195eb..8f3aaaea9d9 100644
--- a/chromium/third_party/skia/src/opts/SkXfermode_opts_arm_neon.h
+++ b/chromium/third_party/skia/src/opts/SkXfermode_opts_arm_neon.h
@@ -14,11 +14,11 @@ public:
virtual void xfer16(uint16_t* SK_RESTRICT dst, const SkPMColor* SK_RESTRICT src,
int count, const SkAlpha* SK_RESTRICT aa) const SK_OVERRIDE;
- SK_DEVELOPER_TO_STRING()
+ SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkNEONProcCoeffXfermode)
private:
- SkNEONProcCoeffXfermode(SkFlattenableReadBuffer& buffer);
+ SkNEONProcCoeffXfermode(SkReadBuffer& buffer);
// void* is used to avoid pulling arm_neon.h in the core and having to build
// it with -mfpu=neon.
diff --git a/chromium/third_party/skia/src/opts/opts_check_SSE2.cpp b/chromium/third_party/skia/src/opts/opts_check_SSE2.cpp
deleted file mode 100644
index aaf6b2ef824..00000000000
--- a/chromium/third_party/skia/src/opts/opts_check_SSE2.cpp
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Copyright 2009 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkBitmapProcState_opts_SSE2.h"
-#include "SkBitmapProcState_opts_SSSE3.h"
-#include "SkBitmapFilter_opts_SSE2.h"
-#include "SkBlitMask.h"
-#include "SkBlitRow.h"
-#include "SkBlitRect_opts_SSE2.h"
-#include "SkBlitRow_opts_SSE2.h"
-#include "SkBlurImage_opts_SSE2.h"
-#include "SkUtils_opts_SSE2.h"
-#include "SkUtils.h"
-#include "SkMorphology_opts.h"
-#include "SkMorphology_opts_SSE2.h"
-
-#include "SkRTConf.h"
-
-#if defined(_MSC_VER) && defined(_WIN64)
-#include <intrin.h>
-#endif
-
-/* This file must *not* be compiled with -msse or -msse2, otherwise
- gcc may generate sse2 even for scalar ops (and thus give an invalid
- instruction on Pentium3 on the code below). Only files named *_SSE2.cpp
- in this directory should be compiled with -msse2. */
-
-
-#ifdef _MSC_VER
-static inline void getcpuid(int info_type, int info[4]) {
-#if defined(_WIN64)
- __cpuid(info, info_type);
-#else
- __asm {
- mov eax, [info_type]
- cpuid
- mov edi, [info]
- mov [edi], eax
- mov [edi+4], ebx
- mov [edi+8], ecx
- mov [edi+12], edx
- }
-#endif
-}
-#else
-#if defined(__x86_64__)
-static inline void getcpuid(int info_type, int info[4]) {
- asm volatile (
- "cpuid \n\t"
- : "=a"(info[0]), "=b"(info[1]), "=c"(info[2]), "=d"(info[3])
- : "a"(info_type)
- );
-}
-#else
-static inline void getcpuid(int info_type, int info[4]) {
- // We save and restore ebx, so this code can be compatible with -fPIC
- asm volatile (
- "pushl %%ebx \n\t"
- "cpuid \n\t"
- "movl %%ebx, %1 \n\t"
- "popl %%ebx \n\t"
- : "=a"(info[0]), "=r"(info[1]), "=c"(info[2]), "=d"(info[3])
- : "a"(info_type)
- );
-}
-#endif
-#endif
-
-#if defined(__x86_64__) || defined(_WIN64) || SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
-/* All x86_64 machines have SSE2, or we know it's supported at compile time, so don't even bother checking. */
-static inline bool hasSSE2() {
- return true;
-}
-#else
-
-static inline bool hasSSE2() {
- int cpu_info[4] = { 0 };
- getcpuid(1, cpu_info);
- return (cpu_info[3] & (1<<26)) != 0;
-}
-#endif
-
-#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSSE3
-/* If we know SSSE3 is supported at compile time, don't even bother checking. */
-static inline bool hasSSSE3() {
- return true;
-}
-#else
-
-static inline bool hasSSSE3() {
- int cpu_info[4] = { 0 };
- getcpuid(1, cpu_info);
- return (cpu_info[2] & 0x200) != 0;
-}
-#endif
-
-static bool cachedHasSSE2() {
- static bool gHasSSE2 = hasSSE2();
- return gHasSSE2;
-}
-
-static bool cachedHasSSSE3() {
- static bool gHasSSSE3 = hasSSSE3();
- return gHasSSSE3;
-}
-
-SK_CONF_DECLARE( bool, c_hqfilter_sse, "bitmap.filter.highQualitySSE", false, "Use SSE optimized version of high quality image filters");
-
-void SkBitmapProcState::platformConvolutionProcs(SkConvolutionProcs* procs) {
- if (cachedHasSSE2()) {
- procs->fExtraHorizontalReads = 3;
- procs->fConvolveVertically = &convolveVertically_SSE2;
- procs->fConvolve4RowsHorizontally = &convolve4RowsHorizontally_SSE2;
- procs->fConvolveHorizontally = &convolveHorizontally_SSE2;
- procs->fApplySIMDPadding = &applySIMDPadding_SSE2;
- }
-}
-
-void SkBitmapProcState::platformProcs() {
- if (cachedHasSSSE3()) {
- if (fSampleProc32 == S32_opaque_D32_filter_DX) {
- fSampleProc32 = S32_opaque_D32_filter_DX_SSSE3;
- } else if (fSampleProc32 == S32_alpha_D32_filter_DX) {
- fSampleProc32 = S32_alpha_D32_filter_DX_SSSE3;
- }
-
- if (fSampleProc32 == S32_opaque_D32_filter_DXDY) {
- fSampleProc32 = S32_opaque_D32_filter_DXDY_SSSE3;
- } else if (fSampleProc32 == S32_alpha_D32_filter_DXDY) {
- fSampleProc32 = S32_alpha_D32_filter_DXDY_SSSE3;
- }
- } else if (cachedHasSSE2()) {
- if (fSampleProc32 == S32_opaque_D32_filter_DX) {
- fSampleProc32 = S32_opaque_D32_filter_DX_SSE2;
- } else if (fSampleProc32 == S32_alpha_D32_filter_DX) {
- fSampleProc32 = S32_alpha_D32_filter_DX_SSE2;
- }
-
- if (fSampleProc16 == S32_D16_filter_DX) {
- fSampleProc16 = S32_D16_filter_DX_SSE2;
- }
- }
-
- if (cachedHasSSSE3() || cachedHasSSE2()) {
- if (fMatrixProc == ClampX_ClampY_filter_scale) {
- fMatrixProc = ClampX_ClampY_filter_scale_SSE2;
- } else if (fMatrixProc == ClampX_ClampY_nofilter_scale) {
- fMatrixProc = ClampX_ClampY_nofilter_scale_SSE2;
- }
-
- if (fMatrixProc == ClampX_ClampY_filter_affine) {
- fMatrixProc = ClampX_ClampY_filter_affine_SSE2;
- } else if (fMatrixProc == ClampX_ClampY_nofilter_affine) {
- fMatrixProc = ClampX_ClampY_nofilter_affine_SSE2;
- }
- if (c_hqfilter_sse) {
- if (fShaderProc32 == highQualityFilter32) {
- fShaderProc32 = highQualityFilter_SSE2;
- }
- }
- }
-}
-
-static SkBlitRow::Proc32 platform_32_procs[] = {
- NULL, // S32_Opaque,
- S32_Blend_BlitRow32_SSE2, // S32_Blend,
- S32A_Opaque_BlitRow32_SSE2, // S32A_Opaque
- S32A_Blend_BlitRow32_SSE2, // S32A_Blend,
-};
-
-SkBlitRow::Proc SkBlitRow::PlatformProcs565(unsigned flags) {
- return NULL;
-}
-
-SkBlitRow::ColorProc SkBlitRow::PlatformColorProc() {
- if (cachedHasSSE2()) {
- return Color32_SSE2;
- } else {
- return NULL;
- }
-}
-
-SkBlitRow::Proc32 SkBlitRow::PlatformProcs32(unsigned flags) {
- if (cachedHasSSE2()) {
- return platform_32_procs[flags];
- } else {
- return NULL;
- }
-}
-
-
-SkBlitMask::ColorProc SkBlitMask::PlatformColorProcs(SkBitmap::Config dstConfig,
- SkMask::Format maskFormat,
- SkColor color) {
- if (SkMask::kA8_Format != maskFormat) {
- return NULL;
- }
-
- ColorProc proc = NULL;
- if (cachedHasSSE2()) {
- switch (dstConfig) {
- case SkBitmap::kARGB_8888_Config:
- // The SSE2 version is not (yet) faster for black, so we check
- // for that.
- if (SK_ColorBLACK != color) {
- proc = SkARGB32_A8_BlitMask_SSE2;
- }
- break;
- default:
- break;
- }
- }
- return proc;
-}
-
-SkBlitMask::BlitLCD16RowProc SkBlitMask::PlatformBlitRowProcs16(bool isOpaque) {
- if (cachedHasSSE2()) {
- if (isOpaque) {
- return SkBlitLCD16OpaqueRow_SSE2;
- } else {
- return SkBlitLCD16Row_SSE2;
- }
- } else {
- return NULL;
- }
-
-}
-SkBlitMask::RowProc SkBlitMask::PlatformRowProcs(SkBitmap::Config dstConfig,
- SkMask::Format maskFormat,
- RowFlags flags) {
- return NULL;
-}
-
-SkMemset16Proc SkMemset16GetPlatformProc() {
- if (cachedHasSSE2()) {
- return sk_memset16_SSE2;
- } else {
- return NULL;
- }
-}
-
-SkMemset32Proc SkMemset32GetPlatformProc() {
- if (cachedHasSSE2()) {
- return sk_memset32_SSE2;
- } else {
- return NULL;
- }
-}
-
-SkMorphologyProc SkMorphologyGetPlatformProc(SkMorphologyProcType type) {
- if (!cachedHasSSE2()) {
- return NULL;
- }
- switch (type) {
- case kDilateX_SkMorphologyProcType:
- return SkDilateX_SSE2;
- case kDilateY_SkMorphologyProcType:
- return SkDilateY_SSE2;
- case kErodeX_SkMorphologyProcType:
- return SkErodeX_SSE2;
- case kErodeY_SkMorphologyProcType:
- return SkErodeY_SSE2;
- default:
- return NULL;
- }
-}
-
-bool SkBoxBlurGetPlatformProcs(SkBoxBlurProc* boxBlurX,
- SkBoxBlurProc* boxBlurY,
- SkBoxBlurProc* boxBlurXY,
- SkBoxBlurProc* boxBlurYX) {
-#ifdef SK_DISABLE_BLUR_DIVISION_OPTIMIZATION
- return false;
-#else
- if (!cachedHasSSE2()) {
- return false;
- }
- return SkBoxBlurGetPlatformProcs_SSE2(boxBlurX, boxBlurY, boxBlurXY, boxBlurYX);
-#endif
-}
-
-SkBlitRow::ColorRectProc PlatformColorRectProcFactory(); // suppress warning
-
-SkBlitRow::ColorRectProc PlatformColorRectProcFactory() {
- if (cachedHasSSE2()) {
- return ColorRect32_SSE2;
- } else {
- return NULL;
- }
-}
diff --git a/chromium/third_party/skia/src/opts/opts_check_arm.cpp b/chromium/third_party/skia/src/opts/opts_check_arm.cpp
deleted file mode 100644
index 3a322aa0e9b..00000000000
--- a/chromium/third_party/skia/src/opts/opts_check_arm.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-/***************************************************************************
- * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
- * Copyright 2006-2010, The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- ***************************************************************************/
-
-/* Changes:
- * 2011-04-01 ARM
- * Merged the functions from src/opts/opts_check_arm_neon.cpp
- * Modified to return ARM version of memset16 and memset32 if no neon
- * available in the core
- */
-
-#include "SkBlitRow.h"
-#include "SkUtils.h"
-
-#include "SkUtilsArm.h"
-#include "SkMorphology_opts.h"
-#include "SkMorphology_opts_neon.h"
-#include "SkBlurImage_opts_neon.h"
-
-#if defined(SK_CPU_LENDIAN) && !SK_ARM_NEON_IS_NONE
-extern "C" void memset16_neon(uint16_t dst[], uint16_t value, int count);
-extern "C" void memset32_neon(uint32_t dst[], uint32_t value, int count);
-#endif
-
-#if defined(SK_CPU_LENDIAN)
-extern "C" void arm_memset16(uint16_t* dst, uint16_t value, int count);
-extern "C" void arm_memset32(uint32_t* dst, uint32_t value, int count);
-#endif
-
-SkMemset16Proc SkMemset16GetPlatformProc() {
- // FIXME: memset.arm.S is using syntax incompatible with XCode
-#if !defined(SK_CPU_LENDIAN) || defined(SK_BUILD_FOR_IOS)
- return NULL;
-#elif SK_ARM_NEON_IS_DYNAMIC
- if (sk_cpu_arm_has_neon()) {
- return memset16_neon;
- } else {
- return arm_memset16;
- }
-#elif SK_ARM_NEON_IS_ALWAYS
- return memset16_neon;
-#else
- return arm_memset16;
-#endif
-}
-
-SkMemset32Proc SkMemset32GetPlatformProc() {
- // FIXME: memset.arm.S is using syntax incompatible with XCode
-#if !defined(SK_CPU_LENDIAN) || defined(SK_BUILD_FOR_IOS)
- return NULL;
-#elif SK_ARM_NEON_IS_DYNAMIC
- if (sk_cpu_arm_has_neon()) {
- return memset32_neon;
- } else {
- return arm_memset32;
- }
-#elif SK_ARM_NEON_IS_ALWAYS
- return memset32_neon;
-#else
- return arm_memset32;
-#endif
-}
-
-SkBlitRow::ColorRectProc PlatformColorRectProcFactory() {
- return NULL;
-}
-
-SkMorphologyProc SkMorphologyGetPlatformProc(SkMorphologyProcType type) {
-#if SK_ARM_NEON_IS_NONE
- return NULL;
-#else
-#if SK_ARM_NEON_IS_DYNAMIC
- if (!sk_cpu_arm_has_neon()) {
- return NULL;
- }
-#endif
- switch (type) {
- case kDilateX_SkMorphologyProcType:
- return SkDilateX_neon;
- case kDilateY_SkMorphologyProcType:
- return SkDilateY_neon;
- case kErodeX_SkMorphologyProcType:
- return SkErodeX_neon;
- case kErodeY_SkMorphologyProcType:
- return SkErodeY_neon;
- default:
- return NULL;
- }
-#endif
-}
-
-bool SkBoxBlurGetPlatformProcs(SkBoxBlurProc* boxBlurX,
- SkBoxBlurProc* boxBlurY,
- SkBoxBlurProc* boxBlurXY,
- SkBoxBlurProc* boxBlurYX) {
-#if SK_ARM_NEON_IS_NONE
- return false;
-#else
-#if SK_ARM_NEON_IS_DYNAMIC
- if (!sk_cpu_arm_has_neon()) {
- return false;
- }
-#endif
- return SkBoxBlurGetPlatformProcs_NEON(boxBlurX, boxBlurY, boxBlurXY, boxBlurYX);
-#endif
-}
diff --git a/chromium/third_party/skia/src/opts/opts_check_x86.cpp b/chromium/third_party/skia/src/opts/opts_check_x86.cpp
new file mode 100644
index 00000000000..6af47729cd0
--- /dev/null
+++ b/chromium/third_party/skia/src/opts/opts_check_x86.cpp
@@ -0,0 +1,379 @@
+/*
+ * Copyright 2009 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkBitmapFilter_opts_SSE2.h"
+#include "SkBitmapProcState_opts_SSE2.h"
+#include "SkBitmapProcState_opts_SSSE3.h"
+#include "SkBlitMask.h"
+#include "SkBlitRect_opts_SSE2.h"
+#include "SkBlitRow.h"
+#include "SkBlitRow_opts_SSE2.h"
+#include "SkBlurImage_opts_SSE2.h"
+#include "SkMorphology_opts.h"
+#include "SkMorphology_opts_SSE2.h"
+#include "SkRTConf.h"
+#include "SkUtils.h"
+#include "SkUtils_opts_SSE2.h"
+#include "SkXfermode.h"
+#include "SkXfermode_proccoeff.h"
+
+#if defined(_MSC_VER) && defined(_WIN64)
+#include <intrin.h>
+#endif
+
+/* This file must *not* be compiled with -msse or any other optional SIMD
+ extension, otherwise gcc may generate SIMD instructions even for scalar ops
+ (and thus give an invalid instruction on Pentium3 on the code below).
+ For example, only files named *_SSE2.cpp in this directory should be
+ compiled with -msse2 or higher. */
+
+
+/* Function to get the CPU SSE-level in runtime, for different compilers. */
+#ifdef _MSC_VER
+static inline void getcpuid(int info_type, int info[4]) {
+#if defined(_WIN64)
+ __cpuid(info, info_type);
+#else
+ __asm {
+ mov eax, [info_type]
+ cpuid
+ mov edi, [info]
+ mov [edi], eax
+ mov [edi+4], ebx
+ mov [edi+8], ecx
+ mov [edi+12], edx
+ }
+#endif
+}
+#elif defined(__x86_64__)
+static inline void getcpuid(int info_type, int info[4]) {
+ asm volatile (
+ "cpuid \n\t"
+ : "=a"(info[0]), "=b"(info[1]), "=c"(info[2]), "=d"(info[3])
+ : "a"(info_type)
+ );
+}
+#else
+static inline void getcpuid(int info_type, int info[4]) {
+ // We save and restore ebx, so this code can be compatible with -fPIC
+ asm volatile (
+ "pushl %%ebx \n\t"
+ "cpuid \n\t"
+ "movl %%ebx, %1 \n\t"
+ "popl %%ebx \n\t"
+ : "=a"(info[0]), "=r"(info[1]), "=c"(info[2]), "=d"(info[3])
+ : "a"(info_type)
+ );
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+
+/* Fetch the SIMD level directly from the CPU, at run-time.
+ * Only checks the levels needed by the optimizations in this file.
+ */
+static int get_SIMD_level() {
+ int cpu_info[4] = { 0 };
+
+ getcpuid(1, cpu_info);
+ if ((cpu_info[2] & (1<<20)) != 0) {
+ return SK_CPU_SSE_LEVEL_SSE42;
+ } else if ((cpu_info[2] & (1<<9)) != 0) {
+ return SK_CPU_SSE_LEVEL_SSSE3;
+ } else if ((cpu_info[3] & (1<<26)) != 0) {
+ return SK_CPU_SSE_LEVEL_SSE2;
+ } else {
+ return 0;
+ }
+}
+
+/* Verify that the requested SIMD level is supported in the build.
+ * If not, check if the platform supports it.
+ */
+static inline bool supports_simd(int minLevel) {
+#if defined(SK_CPU_SSE_LEVEL)
+ if (minLevel <= SK_CPU_SSE_LEVEL) {
+ return true;
+ } else
+#endif
+ {
+#if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK)
+ /* For the Android framework we should always know at compile time if the device
+ * we are building for supports SSSE3. The one exception to this rule is on the
+ * emulator where we are compiled without the -mssse3 option (so we have no
+ * SSSE3 procs) but can be run on a host machine that supports SSSE3
+ * instructions. So for that particular case we disable our SSSE3 options.
+ */
+ return false;
+#else
+ static int gSIMDLevel = get_SIMD_level();
+ return (minLevel <= gSIMDLevel);
+#endif
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SK_CONF_DECLARE( bool, c_hqfilter_sse, "bitmap.filter.highQualitySSE", false, "Use SSE optimized version of high quality image filters");
+
+void SkBitmapProcState::platformConvolutionProcs(SkConvolutionProcs* procs) {
+ if (supports_simd(SK_CPU_SSE_LEVEL_SSE2)) {
+ procs->fExtraHorizontalReads = 3;
+ procs->fConvolveVertically = &convolveVertically_SSE2;
+ procs->fConvolve4RowsHorizontally = &convolve4RowsHorizontally_SSE2;
+ procs->fConvolveHorizontally = &convolveHorizontally_SSE2;
+ procs->fApplySIMDPadding = &applySIMDPadding_SSE2;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void SkBitmapProcState::platformProcs() {
+ /* Every optimization in the function requires at least SSE2 */
+ if (!supports_simd(SK_CPU_SSE_LEVEL_SSE2)) {
+ return;
+ }
+
+ /* Check fSampleProc32 */
+ if (fSampleProc32 == S32_opaque_D32_filter_DX) {
+ if (supports_simd(SK_CPU_SSE_LEVEL_SSSE3)) {
+ fSampleProc32 = S32_opaque_D32_filter_DX_SSSE3;
+ } else {
+ fSampleProc32 = S32_opaque_D32_filter_DX_SSE2;
+ }
+ } else if (fSampleProc32 == S32_opaque_D32_filter_DXDY) {
+ if (supports_simd(SK_CPU_SSE_LEVEL_SSSE3)) {
+ fSampleProc32 = S32_opaque_D32_filter_DXDY_SSSE3;
+ }
+ } else if (fSampleProc32 == S32_alpha_D32_filter_DX) {
+ if (supports_simd(SK_CPU_SSE_LEVEL_SSSE3)) {
+ fSampleProc32 = S32_alpha_D32_filter_DX_SSSE3;
+ } else {
+ fSampleProc32 = S32_alpha_D32_filter_DX_SSE2;
+ }
+ } else if (fSampleProc32 == S32_alpha_D32_filter_DXDY) {
+ if (supports_simd(SK_CPU_SSE_LEVEL_SSSE3)) {
+ fSampleProc32 = S32_alpha_D32_filter_DXDY_SSSE3;
+ }
+ }
+
+ /* Check fSampleProc16 */
+ if (fSampleProc16 == S32_D16_filter_DX) {
+ fSampleProc16 = S32_D16_filter_DX_SSE2;
+ }
+
+ /* Check fMatrixProc */
+ if (fMatrixProc == ClampX_ClampY_filter_scale) {
+ fMatrixProc = ClampX_ClampY_filter_scale_SSE2;
+ } else if (fMatrixProc == ClampX_ClampY_nofilter_scale) {
+ fMatrixProc = ClampX_ClampY_nofilter_scale_SSE2;
+ } else if (fMatrixProc == ClampX_ClampY_filter_affine) {
+ fMatrixProc = ClampX_ClampY_filter_affine_SSE2;
+ } else if (fMatrixProc == ClampX_ClampY_nofilter_affine) {
+ fMatrixProc = ClampX_ClampY_nofilter_affine_SSE2;
+ }
+
+ /* Check fShaderProc32 */
+ if (c_hqfilter_sse) {
+ if (fShaderProc32 == highQualityFilter32) {
+ fShaderProc32 = highQualityFilter_SSE2;
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+static SkBlitRow::Proc platform_16_procs[] = {
+ S32_D565_Opaque_SSE2, // S32_D565_Opaque
+ NULL, // S32_D565_Blend
+ S32A_D565_Opaque_SSE2, // S32A_D565_Opaque
+ NULL, // S32A_D565_Blend
+ S32_D565_Opaque_Dither_SSE2, // S32_D565_Opaque_Dither
+ NULL, // S32_D565_Blend_Dither
+ S32A_D565_Opaque_Dither_SSE2, // S32A_D565_Opaque_Dither
+ NULL, // S32A_D565_Blend_Dither
+};
+
+SkBlitRow::Proc SkBlitRow::PlatformProcs565(unsigned flags) {
+ if (supports_simd(SK_CPU_SSE_LEVEL_SSE2)) {
+ return platform_16_procs[flags];
+ } else {
+ return NULL;
+ }
+}
+
+static SkBlitRow::Proc32 platform_32_procs[] = {
+ NULL, // S32_Opaque,
+ S32_Blend_BlitRow32_SSE2, // S32_Blend,
+ S32A_Opaque_BlitRow32_SSE2, // S32A_Opaque
+ S32A_Blend_BlitRow32_SSE2, // S32A_Blend,
+};
+
+SkBlitRow::Proc32 SkBlitRow::PlatformProcs32(unsigned flags) {
+ if (supports_simd(SK_CPU_SSE_LEVEL_SSE2)) {
+ return platform_32_procs[flags];
+ } else {
+ return NULL;
+ }
+}
+
+SkBlitRow::ColorProc SkBlitRow::PlatformColorProc() {
+ if (supports_simd(SK_CPU_SSE_LEVEL_SSE2)) {
+ return Color32_SSE2;
+ } else {
+ return NULL;
+ }
+}
+
+SkBlitRow::ColorRectProc PlatformColorRectProcFactory(); // suppress warning
+
+SkBlitRow::ColorRectProc PlatformColorRectProcFactory() {
+/* Return NULL for now, since the optimized path in ColorRect32_SSE2 is disabled.
+ if (supports_simd(SK_CPU_SSE_LEVEL_SSE2)) {
+ return ColorRect32_SSE2;
+ } else {
+ return NULL;
+ }
+*/
+ return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SkBlitMask::ColorProc SkBlitMask::PlatformColorProcs(SkColorType dstCT,
+ SkMask::Format maskFormat,
+ SkColor color) {
+ if (SkMask::kA8_Format != maskFormat) {
+ return NULL;
+ }
+
+ ColorProc proc = NULL;
+ if (supports_simd(SK_CPU_SSE_LEVEL_SSE2)) {
+ switch (dstCT) {
+ case kN32_SkColorType:
+ // The SSE2 version is not (yet) faster for black, so we check
+ // for that.
+ if (SK_ColorBLACK != color) {
+ proc = SkARGB32_A8_BlitMask_SSE2;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return proc;
+}
+
+SkBlitMask::BlitLCD16RowProc SkBlitMask::PlatformBlitRowProcs16(bool isOpaque) {
+ if (supports_simd(SK_CPU_SSE_LEVEL_SSE2)) {
+ if (isOpaque) {
+ return SkBlitLCD16OpaqueRow_SSE2;
+ } else {
+ return SkBlitLCD16Row_SSE2;
+ }
+ } else {
+ return NULL;
+ }
+
+}
+
+SkBlitMask::RowProc SkBlitMask::PlatformRowProcs(SkColorType, SkMask::Format, RowFlags) {
+ return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SkMemset16Proc SkMemset16GetPlatformProc() {
+ if (supports_simd(SK_CPU_SSE_LEVEL_SSE2)) {
+ return sk_memset16_SSE2;
+ } else {
+ return NULL;
+ }
+}
+
+SkMemset32Proc SkMemset32GetPlatformProc() {
+ if (supports_simd(SK_CPU_SSE_LEVEL_SSE2)) {
+ return sk_memset32_SSE2;
+ } else {
+ return NULL;
+ }
+}
+
+SkMemcpy32Proc SkMemcpy32GetPlatformProc() {
+ if (supports_simd(SK_CPU_SSE_LEVEL_SSE2)) {
+ return sk_memcpy32_SSE2;
+ } else {
+ return NULL;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SkMorphologyImageFilter::Proc SkMorphologyGetPlatformProc(SkMorphologyProcType type) {
+ if (!supports_simd(SK_CPU_SSE_LEVEL_SSE2)) {
+ return NULL;
+ }
+ switch (type) {
+ case kDilateX_SkMorphologyProcType:
+ return SkDilateX_SSE2;
+ case kDilateY_SkMorphologyProcType:
+ return SkDilateY_SSE2;
+ case kErodeX_SkMorphologyProcType:
+ return SkErodeX_SSE2;
+ case kErodeY_SkMorphologyProcType:
+ return SkErodeY_SSE2;
+ default:
+ return NULL;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+bool SkBoxBlurGetPlatformProcs(SkBoxBlurProc* boxBlurX,
+ SkBoxBlurProc* boxBlurY,
+ SkBoxBlurProc* boxBlurXY,
+ SkBoxBlurProc* boxBlurYX) {
+#ifdef SK_DISABLE_BLUR_DIVISION_OPTIMIZATION
+ return false;
+#else
+ if (!supports_simd(SK_CPU_SSE_LEVEL_SSE2)) {
+ return false;
+ }
+ return SkBoxBlurGetPlatformProcs_SSE2(boxBlurX, boxBlurY, boxBlurXY, boxBlurYX);
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+extern SkProcCoeffXfermode* SkPlatformXfermodeFactory_impl_SSE2(const ProcCoeff& rec,
+ SkXfermode::Mode mode);
+
+SkProcCoeffXfermode* SkPlatformXfermodeFactory_impl(const ProcCoeff& rec,
+ SkXfermode::Mode mode);
+
+SkProcCoeffXfermode* SkPlatformXfermodeFactory_impl(const ProcCoeff& rec,
+ SkXfermode::Mode mode) {
+ return NULL;
+}
+
+SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec,
+ SkXfermode::Mode mode);
+
+SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec,
+ SkXfermode::Mode mode) {
+ if (supports_simd(SK_CPU_SSE_LEVEL_SSE2)) {
+ return SkPlatformXfermodeFactory_impl_SSE2(rec, mode);
+ } else {
+ return SkPlatformXfermodeFactory_impl(rec, mode);
+ }
+}
+
+SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode);
+
+SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode) {
+ return NULL;
+}
diff --git a/chromium/third_party/skia/src/pathops/SkAddIntersections.cpp b/chromium/third_party/skia/src/pathops/SkAddIntersections.cpp
index 035a50e4aa9..52e751bd08d 100644
--- a/chromium/third_party/skia/src/pathops/SkAddIntersections.cpp
+++ b/chromium/third_party/skia/src/pathops/SkAddIntersections.cpp
@@ -397,6 +397,7 @@ bool AddIntersectTs(SkOpContour* test, SkOpContour* next) {
SkASSERT(ts[0][pt] >= 0 && ts[0][pt] <= 1);
SkASSERT(ts[1][pt] >= 0 && ts[1][pt] <= 1);
SkPoint point = ts.pt(pt).asSkPoint();
+ wt.alignTPt(wn, swap, pt, &ts, &point);
int testTAt = wt.addT(wn, point, ts[swap][pt]);
int nextTAt = wn.addT(wt, point, ts[!swap][pt]);
wt.addOtherT(testTAt, ts[!swap][pt], nextTAt);
@@ -424,8 +425,8 @@ void AddSelfIntersectTs(SkOpContour* test) {
SkASSERT(ts[0][0] >= 0 && ts[0][0] <= 1);
SkASSERT(ts[1][0] >= 0 && ts[1][0] <= 1);
SkPoint point = ts.pt(0).asSkPoint();
- int testTAt = wt.addSelfT(wt, point, ts[0][0]);
- int nextTAt = wt.addT(wt, point, ts[1][0]);
+ int testTAt = wt.addSelfT(point, ts[0][0]);
+ int nextTAt = wt.addSelfT(point, ts[1][0]);
wt.addOtherT(testTAt, ts[1][0], nextTAt);
wt.addOtherT(nextTAt, ts[0][0], testTAt);
} while (wt.advance());
@@ -437,6 +438,10 @@ void CoincidenceCheck(SkTArray<SkOpContour*, true>* contourList, int total) {
int contourCount = (*contourList).count();
for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
SkOpContour* contour = (*contourList)[cIndex];
+ contour->resolveNearCoincidence();
+ }
+ for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
+ SkOpContour* contour = (*contourList)[cIndex];
contour->addCoincidentPoints();
}
for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
diff --git a/chromium/third_party/skia/src/pathops/SkDCubicIntersection.cpp b/chromium/third_party/skia/src/pathops/SkDCubicIntersection.cpp
index bb734e19da7..9d83242eda6 100644
--- a/chromium/third_party/skia/src/pathops/SkDCubicIntersection.cpp
+++ b/chromium/third_party/skia/src/pathops/SkDCubicIntersection.cpp
@@ -134,7 +134,10 @@ static void intersect(const SkDCubic& cubic1, double t1s, double t1e, const SkDC
}
}
} else {
- double offset = precisionScale / 16; // FIME: const is arbitrary: test, refine
+/*for random cubics, 16 below catches 99.997% of the intersections. To test for the remaining 0.003%
+ look for nearly coincident curves. and check each 1/16th section.
+*/
+ double offset = precisionScale / 16; // FIXME: const is arbitrary: test, refine
double c1Bottom = tIdx == 0 ? 0 :
(t1Start + (t1 - t1Start) * locals[0][tIdx - 1] + to1) / 2;
double c1Min = SkTMax(c1Bottom, to1 - offset);
@@ -300,15 +303,39 @@ bool SkIntersections::cubicExactEnd(const SkDCubic& cubic1, bool start, const Sk
continue;
}
if (swap) {
- insert(testT, impTs[0][index], tmpLine[0]);
+ cubicInsert(testT, impTs[0][index], tmpLine[0], cubic2, cubic1);
} else {
- insert(impTs[0][index], testT, tmpLine[0]);
+ cubicInsert(impTs[0][index], testT, tmpLine[0], cubic1, cubic2);
}
return true;
}
return false;
}
+
+void SkIntersections::cubicInsert(double one, double two, const SkDPoint& pt,
+ const SkDCubic& cubic1, const SkDCubic& cubic2) {
+ for (int index = 0; index < fUsed; ++index) {
+ if (fT[0][index] == one) {
+ double oldTwo = fT[1][index];
+ if (oldTwo == two) {
+ return;
+ }
+ SkDPoint mid = cubic2.ptAtT((oldTwo + two) / 2);
+ if (mid.approximatelyEqual(fPt[index])) {
+ return;
+ }
+ }
+ if (fT[1][index] == two) {
+ SkDPoint mid = cubic1.ptAtT((fT[0][index] + two) / 2);
+ if (mid.approximatelyEqual(fPt[index])) {
+ return;
+ }
+ }
+ }
+ insert(one, two, pt);
+}
+
void SkIntersections::cubicNearEnd(const SkDCubic& cubic1, bool start, const SkDCubic& cubic2,
const SkDRect& bounds2) {
SkDLine line;
@@ -368,11 +395,15 @@ void SkIntersections::cubicNearEnd(const SkDCubic& cubic1, bool start, const SkD
double tMin2 = SkTMax(tVals[tIdx] - LINE_FRACTION, 0.0);
double tMax2 = SkTMin(tVals[tLast] + LINE_FRACTION, 1.0);
int lastUsed = used();
- ::intersect(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, *this);
+ if (start ? tMax1 < tMin2 : tMax2 < tMin1) {
+ ::intersect(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, *this);
+ }
if (lastUsed == used()) {
tMin2 = SkTMax(tVals[tIdx] - (1.0 / SkDCubic::gPrecisionUnit), 0.0);
tMax2 = SkTMin(tVals[tLast] + (1.0 / SkDCubic::gPrecisionUnit), 1.0);
- ::intersect(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, *this);
+ if (start ? tMax1 < tMin2 : tMax2 < tMin1) {
+ ::intersect(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, *this);
+ }
}
tIdx = tLast + 1;
} while (tIdx < tVals.count());
@@ -418,6 +449,9 @@ static bool only_end_pts_in_common(const SkDCubic& c1, const SkDCubic& c2) {
}
double adj = endPt[oppTest]->fX - origX;
double opp = endPt[oppTest]->fY - origY;
+ if (adj == 0 && opp == 0) { // if the other point equals the test point, ignore it
+ continue;
+ }
double sign = (c1[oddMan].fY - origY) * adj - (c1[oddMan].fX - origX) * opp;
if (approximately_zero(sign)) {
goto tryNextHalfPlane;
@@ -491,7 +525,18 @@ int SkIntersections::intersect(const SkDCubic& c1, const SkDCubic& c2) {
cubicNearEnd(c1, false, c2, c2Bounds);
}
if (!(exactEndBits & 8)) {
+ if (selfIntersect && fUsed) {
+ return fUsed;
+ }
cubicNearEnd(c1, true, c2, c2Bounds);
+ if (selfIntersect && fUsed && ((approximately_less_than_zero(fT[0][0])
+ && approximately_less_than_zero(fT[1][0]))
+ || (approximately_greater_than_one(fT[0][0])
+ && approximately_greater_than_one(fT[1][0])))) {
+ SkASSERT(fUsed == 1);
+ fUsed = 0;
+ return fUsed;
+ }
}
if (!selfIntersect) {
SkDRect c1Bounds;
@@ -517,7 +562,7 @@ int SkIntersections::intersect(const SkDCubic& c1, const SkDCubic& c2) {
if (compCount) {
int exactCount = used();
if (exactCount == 0) {
- set(i);
+ *this = i;
} else {
// at least one is exact or near, and at least one was computed. Eliminate duplicates
for (int exIdx = 0; exIdx < exactCount; ++exIdx) {
@@ -636,11 +681,17 @@ int SkIntersections::intersect(const SkDCubic& c) {
if (c.endsAreExtremaInXOrY()) {
return false;
}
+ // OPTIMIZATION: could quick reject if neither end point tangent ray intersected the line
+ // segment formed by the opposite end point to the control point
(void) intersect(c, c);
if (used() > 0) {
- SkASSERT(used() == 1);
- if (fT[0][0] > fT[1][0]) {
- swapPts();
+ if (approximately_equal_double(fT[0][0], fT[1][0])) {
+ fUsed = 0;
+ } else {
+ SkASSERT(used() == 1);
+ if (fT[0][0] > fT[1][0]) {
+ swapPts();
+ }
}
}
return used();
diff --git a/chromium/third_party/skia/src/pathops/SkDCubicLineIntersection.cpp b/chromium/third_party/skia/src/pathops/SkDCubicLineIntersection.cpp
index abbc4e32b22..696c42e835a 100644
--- a/chromium/third_party/skia/src/pathops/SkDCubicLineIntersection.cpp
+++ b/chromium/third_party/skia/src/pathops/SkDCubicLineIntersection.cpp
@@ -97,13 +97,27 @@ public:
int intersectRay(double roots[3]) {
double adj = fLine[1].fX - fLine[0].fX;
double opp = fLine[1].fY - fLine[0].fY;
- SkDCubic r;
+ SkDCubic c;
for (int n = 0; n < 4; ++n) {
- r[n].fX = (fCubic[n].fY - fLine[0].fY) * adj - (fCubic[n].fX - fLine[0].fX) * opp;
+ c[n].fX = (fCubic[n].fY - fLine[0].fY) * adj - (fCubic[n].fX - fLine[0].fX) * opp;
}
double A, B, C, D;
- SkDCubic::Coefficients(&r[0].fX, &A, &B, &C, &D);
- return SkDCubic::RootsValidT(A, B, C, D, roots);
+ SkDCubic::Coefficients(&c[0].fX, &A, &B, &C, &D);
+ int count = SkDCubic::RootsValidT(A, B, C, D, roots);
+ for (int index = 0; index < count; ++index) {
+ SkDPoint calcPt = c.ptAtT(roots[index]);
+ if (!approximately_zero(calcPt.fX)) {
+ for (int n = 0; n < 4; ++n) {
+ c[n].fY = (fCubic[n].fY - fLine[0].fY) * opp
+ + (fCubic[n].fX - fLine[0].fX) * adj;
+ }
+ double extremeTs[6];
+ int extrema = SkDCubic::FindExtrema(c[0].fX, c[1].fX, c[2].fX, c[3].fX, extremeTs);
+ count = c.searchRoots(extremeTs, extrema, 0, SkDCubic::kXAxis, roots);
+ break;
+ }
+ }
+ return count;
}
int intersect() {
@@ -146,11 +160,21 @@ public:
return fIntersections->used();
}
- int horizontalIntersect(double axisIntercept, double roots[3]) {
+ static int HorizontalIntersect(const SkDCubic& c, double axisIntercept, double roots[3]) {
double A, B, C, D;
- SkDCubic::Coefficients(&fCubic[0].fY, &A, &B, &C, &D);
+ SkDCubic::Coefficients(&c[0].fY, &A, &B, &C, &D);
D -= axisIntercept;
- return SkDCubic::RootsValidT(A, B, C, D, roots);
+ int count = SkDCubic::RootsValidT(A, B, C, D, roots);
+ for (int index = 0; index < count; ++index) {
+ SkDPoint calcPt = c.ptAtT(roots[index]);
+ if (!approximately_equal(calcPt.fY, axisIntercept)) {
+ double extremeTs[6];
+ int extrema = SkDCubic::FindExtrema(c[0].fY, c[1].fY, c[2].fY, c[3].fY, extremeTs);
+ count = c.searchRoots(extremeTs, extrema, axisIntercept, SkDCubic::kYAxis, roots);
+ break;
+ }
+ }
+ return count;
}
int horizontalIntersect(double axisIntercept, double left, double right, bool flipped) {
@@ -158,11 +182,13 @@ public:
if (fAllowNear) {
addNearHorizontalEndPoints(left, right, axisIntercept);
}
- double rootVals[3];
- int roots = horizontalIntersect(axisIntercept, rootVals);
- for (int index = 0; index < roots; ++index) {
- double cubicT = rootVals[index];
- SkDPoint pt = fCubic.ptAtT(cubicT);
+ double roots[3];
+ int count = HorizontalIntersect(fCubic, axisIntercept, roots);
+ for (int index = 0; index < count; ++index) {
+ double cubicT = roots[index];
+ SkDPoint pt;
+ pt.fX = fCubic.ptAtT(cubicT).fX;
+ pt.fY = axisIntercept;
double lineT = (pt.fX - left) / (right - left);
if (pinTs(&cubicT, &lineT, &pt, kPointInitialized)) {
fIntersections->insert(cubicT, lineT, pt);
@@ -174,11 +200,21 @@ public:
return fIntersections->used();
}
- int verticalIntersect(double axisIntercept, double roots[3]) {
+ static int VerticalIntersect(const SkDCubic& c, double axisIntercept, double roots[3]) {
double A, B, C, D;
- SkDCubic::Coefficients(&fCubic[0].fX, &A, &B, &C, &D);
+ SkDCubic::Coefficients(&c[0].fX, &A, &B, &C, &D);
D -= axisIntercept;
- return SkDCubic::RootsValidT(A, B, C, D, roots);
+ int count = SkDCubic::RootsValidT(A, B, C, D, roots);
+ for (int index = 0; index < count; ++index) {
+ SkDPoint calcPt = c.ptAtT(roots[index]);
+ if (!approximately_equal(calcPt.fX, axisIntercept)) {
+ double extremeTs[6];
+ int extrema = SkDCubic::FindExtrema(c[0].fX, c[1].fX, c[2].fX, c[3].fX, extremeTs);
+ count = c.searchRoots(extremeTs, extrema, axisIntercept, SkDCubic::kXAxis, roots);
+ break;
+ }
+ }
+ return count;
}
int verticalIntersect(double axisIntercept, double top, double bottom, bool flipped) {
@@ -186,11 +222,13 @@ public:
if (fAllowNear) {
addNearVerticalEndPoints(top, bottom, axisIntercept);
}
- double rootVals[3];
- int roots = verticalIntersect(axisIntercept, rootVals);
- for (int index = 0; index < roots; ++index) {
- double cubicT = rootVals[index];
- SkDPoint pt = fCubic.ptAtT(cubicT);
+ double roots[3];
+ int count = VerticalIntersect(fCubic, axisIntercept, roots);
+ for (int index = 0; index < count; ++index) {
+ double cubicT = roots[index];
+ SkDPoint pt;
+ pt.fX = axisIntercept;
+ pt.fY = fCubic.ptAtT(cubicT).fY;
double lineT = (pt.fY - top) / (bottom - top);
if (pinTs(&cubicT, &lineT, &pt, kPointInitialized)) {
fIntersections->insert(cubicT, lineT, pt);
@@ -223,7 +261,7 @@ public:
if (fIntersections->hasT(cubicT)) {
continue;
}
- double lineT = fLine.nearPoint(fCubic[cIndex]);
+ double lineT = fLine.nearPoint(fCubic[cIndex], NULL);
if (lineT < 0) {
continue;
}
@@ -302,10 +340,17 @@ public:
}
double cT = *cubicT = SkPinT(*cubicT);
double lT = *lineT = SkPinT(*lineT);
+ SkDPoint lPt = fLine.ptAtT(lT);
+ SkDPoint cPt = fCubic.ptAtT(cT);
+ if (!lPt.moreRoughlyEqual(cPt)) {
+ return false;
+ }
+ // FIXME: if points are roughly equal but not approximately equal, need to do
+ // a binary search like quad/quad intersection to find more precise t values
if (lT == 0 || lT == 1 || (ptSet == kPointUninitialized && cT != 0 && cT != 1)) {
- *pt = fLine.ptAtT(lT);
+ *pt = lPt;
} else if (ptSet == kPointUninitialized) {
- *pt = fCubic.ptAtT(cT);
+ *pt = cPt;
}
SkPoint gridPt = pt->asSkPoint();
if (gridPt == fLine[0].asSkPoint()) {
diff --git a/chromium/third_party/skia/src/pathops/SkDCubicToQuads.cpp b/chromium/third_party/skia/src/pathops/SkDCubicToQuads.cpp
index 3cf63f31d02..a28564d4c2c 100644
--- a/chromium/third_party/skia/src/pathops/SkDCubicToQuads.cpp
+++ b/chromium/third_party/skia/src/pathops/SkDCubicToQuads.cpp
@@ -20,7 +20,6 @@ If this is a degree-elevated cubic, then both equations will give the same answe
P1 = -1/4 Q0 + 3/4 Q1 + 3/4 Q2 - 1/4 Q3
-
SkDCubic defined by: P1/2 - anchor points, C1/C2 control points
|x| is the euclidean norm of x
mid-point approx of cubic: a quad that shares the same anchors with the cubic and has the
@@ -136,17 +135,16 @@ void SkDCubic::toQuadraticTs(double precision, SkTArray<double, true>* ts) const
memmove(inflectT, &inflectT[1], sizeof(inflectT[0]) * --inflections);
}
int start = 0;
- do {
- int next = start + 1;
- if (next >= inflections) {
- break;
- }
+ int next = 1;
+ while (next < inflections) {
if (!approximately_equal(inflectT[start], inflectT[next])) {
++start;
+ ++next;
continue;
}
memmove(&inflectT[start], &inflectT[next], sizeof(inflectT[0]) * (--inflections - start));
- } while (true);
+ }
+
while (inflections && approximately_greater_than_one(inflectT[inflections - 1])) {
--inflections;
}
diff --git a/chromium/third_party/skia/src/pathops/SkDLineIntersection.cpp b/chromium/third_party/skia/src/pathops/SkDLineIntersection.cpp
index f10b4404046..9ae01071739 100644
--- a/chromium/third_party/skia/src/pathops/SkDLineIntersection.cpp
+++ b/chromium/third_party/skia/src/pathops/SkDLineIntersection.cpp
@@ -76,6 +76,12 @@ int SkIntersections::intersectRay(const SkDLine& a, const SkDLine& b) {
SkDVector ab0 = a[0] - b[0];
double numerA = ab0.fY * bLen.fX - bLen.fY * ab0.fX;
double numerB = ab0.fY * aLen.fX - aLen.fY * ab0.fX;
+#if 0
+ if (!between(0, numerA, denom) || !between(0, numerB, denom)) {
+ fUsed = 0;
+ return 0;
+ }
+#endif
numerA /= denom;
numerB /= denom;
int used;
@@ -148,15 +154,52 @@ int SkIntersections::intersect(const SkDLine& a, const SkDLine& b) {
computePoints(a, 1);
}
}
+/* Allow tracking that both sets of end points are near each other -- the lines are entirely
+ coincident -- even when the end points are not exactly the same.
+ Mark this as a 'wild card' for the end points, so that either point is considered totally
+ coincident. Then, avoid folding the lines over each other, but allow either end to mate
+ to the next set of lines.
+ */
if (fAllowNear || !unparallel) {
- for (int iA = 0; iA < 2; ++iA) {
- if ((t = b.nearPoint(a[iA])) >= 0) {
- insert(iA, t, a[iA]);
- }
+ double aNearB[2];
+ double bNearA[2];
+ bool aNotB[2] = {false, false};
+ bool bNotA[2] = {false, false};
+ int nearCount = 0;
+ for (int index = 0; index < 2; ++index) {
+ aNearB[index] = t = b.nearPoint(a[index], &aNotB[index]);
+ nearCount += t >= 0;
+ bNearA[index] = t = a.nearPoint(b[index], &bNotA[index]);
+ nearCount += t >= 0;
}
- for (int iB = 0; iB < 2; ++iB) {
- if ((t = a.nearPoint(b[iB])) >= 0) {
- insert(t, iB, b[iB]);
+ if (nearCount > 0) {
+ for (int iA = 0; iA < 2; ++iA) {
+ if (!aNotB[iA]) {
+ continue;
+ }
+ int nearer = aNearB[iA] > 0.5;
+ if (!bNotA[nearer]) {
+ continue;
+ }
+ SkASSERT(a[iA] != b[nearer]);
+ SkASSERT(iA == (bNearA[nearer] > 0.5));
+ fNearlySame[iA] = true;
+ insertNear(iA, nearer, a[iA], b[nearer]);
+ aNearB[iA] = -1;
+ bNearA[nearer] = -1;
+ nearCount -= 2;
+ }
+ if (nearCount > 0) {
+ for (int iA = 0; iA < 2; ++iA) {
+ if (aNearB[iA] >= 0) {
+ insert(iA, aNearB[iA], a[iA]);
+ }
+ }
+ for (int iB = 0; iB < 2; ++iB) {
+ if (bNearA[iB] >= 0) {
+ insert(bNearA[iB], iB, b[iB]);
+ }
+ }
}
}
}
@@ -198,7 +241,7 @@ int SkIntersections::horizontal(const SkDLine& line, double y) {
int SkIntersections::horizontal(const SkDLine& line, double left, double right,
double y, bool flipped) {
- fMax = 2;
+ fMax = 3; // clean up parallel at the end will limit the result to 2 at the most
// see if end points intersect the opposite line
double t;
const SkDPoint leftPt = { left, y };
@@ -234,12 +277,12 @@ int SkIntersections::horizontal(const SkDLine& line, double left, double right,
}
}
if (fAllowNear || result == 2) {
- if ((t = line.nearPoint(leftPt)) >= 0) {
+ if ((t = line.nearPoint(leftPt, NULL)) >= 0) {
insert(t, (double) flipped, leftPt);
}
if (left != right) {
const SkDPoint rightPt = { right, y };
- if ((t = line.nearPoint(rightPt)) >= 0) {
+ if ((t = line.nearPoint(rightPt, NULL)) >= 0) {
insert(t, (double) !flipped, rightPt);
}
for (int index = 0; index < 2; ++index) {
@@ -286,7 +329,7 @@ int SkIntersections::vertical(const SkDLine& line, double x) {
int SkIntersections::vertical(const SkDLine& line, double top, double bottom,
double x, bool flipped) {
- fMax = 2;
+ fMax = 3; // cleanup parallel lines will bring this back line
// see if end points intersect the opposite line
double t;
SkDPoint topPt = { x, top };
@@ -322,12 +365,12 @@ int SkIntersections::vertical(const SkDLine& line, double top, double bottom,
}
}
if (fAllowNear || result == 2) {
- if ((t = line.nearPoint(topPt)) >= 0) {
+ if ((t = line.nearPoint(topPt, NULL)) >= 0) {
insert(t, (double) flipped, topPt);
}
if (top != bottom) {
SkDPoint bottomPt = { x, bottom };
- if ((t = line.nearPoint(bottomPt)) >= 0) {
+ if ((t = line.nearPoint(bottomPt, NULL)) >= 0) {
insert(t, (double) !flipped, bottomPt);
}
for (int index = 0; index < 2; ++index) {
@@ -338,6 +381,7 @@ int SkIntersections::vertical(const SkDLine& line, double top, double bottom,
}
}
cleanUpParallelLines(result == 2);
+ SkASSERT(fUsed <= 2);
return fUsed;
}
diff --git a/chromium/third_party/skia/src/pathops/SkDQuadIntersection.cpp b/chromium/third_party/skia/src/pathops/SkDQuadIntersection.cpp
index 685a01f70fc..5a8bafcdc56 100644
--- a/chromium/third_party/skia/src/pathops/SkDQuadIntersection.cpp
+++ b/chromium/third_party/skia/src/pathops/SkDQuadIntersection.cpp
@@ -4,7 +4,6 @@
// The downside of this approach is that early rejects are difficult to come by.
// http://planetmath.org/encyclopedia/GaloisTheoreticDerivationOfTheQuarticFormula.html#step
-
#include "SkDQuadImplicit.h"
#include "SkIntersections.h"
#include "SkPathOpsLine.h"
@@ -159,10 +158,13 @@ static bool is_linear_inner(const SkDQuad& q1, double t1s, double t1e, const SkD
int roots = rootTs.intersect(q2, *testLines[index]);
for (int idx2 = 0; idx2 < roots; ++idx2) {
double t = rootTs[0][idx2];
-#ifdef SK_DEBUG
+#if 0 // def SK_DEBUG // FIXME : accurate for error = 16, error of 17.5 seen
+// {{{136.08723965397621, 1648.2814535211637}, {593.49031197259478, 1190.8784277439891}, {593.49031197259478, 544.0128173828125}}}
+// {{{-968.181396484375, 544.0128173828125}, {592.2825927734375, 870.552490234375}, {593.435302734375, 557.8828125}}}
+
SkDPoint qPt = q2.ptAtT(t);
SkDPoint lPt = testLines[index]->ptAtT(rootTs[1][idx2]);
- SkASSERT(qPt.approximatelyPEqual(lPt));
+ SkASSERT(qPt.approximatelyDEqual(lPt));
#endif
if (approximately_negative(t - t2s) || approximately_positive(t - t2e)) {
continue;
@@ -305,10 +307,10 @@ static bool binary_search(const SkDQuad& quad1, const SkDQuad& quad2, double* t1
#endif
return true;
}
- if (calcMask & (1 << 0)) t1[0] = quad1.ptAtT(*t1Seed - tStep);
- if (calcMask & (1 << 2)) t1[2] = quad1.ptAtT(*t1Seed + tStep);
- if (calcMask & (1 << 3)) t2[0] = quad2.ptAtT(*t2Seed - tStep);
- if (calcMask & (1 << 5)) t2[2] = quad2.ptAtT(*t2Seed + tStep);
+ if (calcMask & (1 << 0)) t1[0] = quad1.ptAtT(SkTMax(0., *t1Seed - tStep));
+ if (calcMask & (1 << 2)) t1[2] = quad1.ptAtT(SkTMin(1., *t1Seed + tStep));
+ if (calcMask & (1 << 3)) t2[0] = quad2.ptAtT(SkTMax(0., *t2Seed - tStep));
+ if (calcMask & (1 << 5)) t2[2] = quad2.ptAtT(SkTMin(1., *t2Seed + tStep));
double dist[3][3];
// OPTIMIZE: using calcMask value permits skipping some distance calcuations
// if prior loop's results are moved to correct slot for reuse
@@ -383,7 +385,7 @@ static void lookNearEnd(const SkDQuad& q1, const SkDQuad& q2, int testT,
impTs.intersectRay(q1, tmpLine);
for (int index = 0; index < impTs.used(); ++index) {
SkDPoint realPt = impTs.pt(index);
- if (!tmpLine[0].approximatelyEqual(realPt)) {
+ if (!tmpLine[0].approximatelyPEqual(realPt)) {
continue;
}
if (swap) {
@@ -420,7 +422,7 @@ int SkIntersections::intersect(const SkDQuad& q1, const SkDQuad& q2) {
swapped.setMax(fMax);
if (is_linear(q2, q1, &swapped)) {
swapped.swapPts();
- set(swapped);
+ *this = swapped;
return fUsed;
}
SkIntersections copyI(*this);
diff --git a/chromium/third_party/skia/src/pathops/SkDQuadLineIntersection.cpp b/chromium/third_party/skia/src/pathops/SkDQuadLineIntersection.cpp
index bae003c1842..ef8edb02cda 100644
--- a/chromium/third_party/skia/src/pathops/SkDQuadLineIntersection.cpp
+++ b/chromium/third_party/skia/src/pathops/SkDQuadLineIntersection.cpp
@@ -86,7 +86,6 @@ Thus, if the slope of the line tends towards vertical, we use:
C = ( (a ) - g'*(d ) - h' )
*/
-
class LineQuadraticIntersections {
public:
enum PinTPoint {
@@ -99,7 +98,7 @@ public:
, fLine(l)
, fIntersections(i)
, fAllowNear(true) {
- i->setMax(2);
+ i->setMax(3); // allow short partial coincidence plus discrete intersection
}
void allowNear(bool allow) {
@@ -239,7 +238,7 @@ protected:
if (fIntersections->hasT(quadT)) {
continue;
}
- double lineT = fLine.nearPoint(fQuad[qIndex]);
+ double lineT = fLine.nearPoint(fQuad[qIndex], NULL);
if (lineT < 0) {
continue;
}
@@ -311,10 +310,10 @@ protected:
}
bool pinTs(double* quadT, double* lineT, SkDPoint* pt, PinTPoint ptSet) {
- if (!approximately_one_or_less(*lineT)) {
+ if (!approximately_one_or_less_double(*lineT)) {
return false;
}
- if (!approximately_zero_or_more(*lineT)) {
+ if (!approximately_zero_or_more_double(*lineT)) {
return false;
}
double qT = *quadT = SkPinT(*quadT);
@@ -325,14 +324,21 @@ protected:
*pt = fQuad.ptAtT(qT);
}
SkPoint gridPt = pt->asSkPoint();
- if (gridPt == fLine[0].asSkPoint()) {
+ if (SkDPoint::ApproximatelyEqual(gridPt, fLine[0].asSkPoint())) {
+ *pt = fLine[0];
*lineT = 0;
- } else if (gridPt == fLine[1].asSkPoint()) {
+ } else if (SkDPoint::ApproximatelyEqual(gridPt, fLine[1].asSkPoint())) {
+ *pt = fLine[1];
*lineT = 1;
}
+ if (fIntersections->used() > 0 && approximately_equal((*fIntersections)[1][0], *lineT)) {
+ return false;
+ }
if (gridPt == fQuad[0].asSkPoint()) {
+ *pt = fQuad[0];
*quadT = 0;
} else if (gridPt == fQuad[2].asSkPoint()) {
+ *pt = fQuad[2];
*quadT = 1;
}
return true;
@@ -345,44 +351,6 @@ private:
bool fAllowNear;
};
-// utility for pairs of coincident quads
-static double horizontalIntersect(const SkDQuad& quad, const SkDPoint& pt) {
- LineQuadraticIntersections q(quad, *(static_cast<SkDLine*>(0)),
- static_cast<SkIntersections*>(0));
- double rootVals[2];
- int roots = q.horizontalIntersect(pt.fY, rootVals);
- for (int index = 0; index < roots; ++index) {
- double t = rootVals[index];
- SkDPoint qPt = quad.ptAtT(t);
- if (AlmostEqualUlps(qPt.fX, pt.fX)) {
- return t;
- }
- }
- return -1;
-}
-
-static double verticalIntersect(const SkDQuad& quad, const SkDPoint& pt) {
- LineQuadraticIntersections q(quad, *(static_cast<SkDLine*>(0)),
- static_cast<SkIntersections*>(0));
- double rootVals[2];
- int roots = q.verticalIntersect(pt.fX, rootVals);
- for (int index = 0; index < roots; ++index) {
- double t = rootVals[index];
- SkDPoint qPt = quad.ptAtT(t);
- if (AlmostEqualUlps(qPt.fY, pt.fY)) {
- return t;
- }
- }
- return -1;
-}
-
-double SkIntersections::Axial(const SkDQuad& q1, const SkDPoint& p, bool vertical) {
- if (vertical) {
- return verticalIntersect(q1, p);
- }
- return horizontalIntersect(q1, p);
-}
-
int SkIntersections::horizontal(const SkDQuad& quad, double left, double right, double y,
bool flipped) {
SkDLine line = {{{ left, y }, { right, y }}};
diff --git a/chromium/third_party/skia/src/pathops/SkIntersectionHelper.h b/chromium/third_party/skia/src/pathops/SkIntersectionHelper.h
index fa1aa697c29..3569c934de1 100644
--- a/chromium/third_party/skia/src/pathops/SkIntersectionHelper.h
+++ b/chromium/third_party/skia/src/pathops/SkIntersectionHelper.h
@@ -46,14 +46,19 @@ public:
return fContour->addT(fIndex, other.fContour, other.fIndex, pt, newT);
}
- int addSelfT(const SkIntersectionHelper& other, const SkPoint& pt, double newT) {
- return fContour->addSelfT(fIndex, other.fContour, other.fIndex, pt, newT);
+ int addSelfT(const SkPoint& pt, double newT) {
+ return fContour->addSelfT(fIndex, pt, newT);
}
bool advance() {
return ++fIndex < fLast;
}
+ void alignTPt(SkIntersectionHelper& other, bool swap, int index,
+ SkIntersections* ts, SkPoint* point) {
+ fContour->alignTPt(fIndex, other.fContour, other.fIndex, swap, index, ts, point);
+ }
+
SkScalar bottom() const {
return bounds().fBottom;
}
@@ -141,20 +146,10 @@ public:
return y() != pts()[0].fY;
}
-#ifdef SK_DEBUG
- void dump() {
- SkDPoint::dump(pts()[0]);
- SkDPoint::dump(pts()[1]);
- if (verb() >= SkPath::kQuad_Verb) {
- SkDPoint::dump(pts()[2]);
- }
- if (verb() >= SkPath::kCubic_Verb) {
- SkDPoint::dump(pts()[3]);
- }
- }
-#endif
-
private:
+ // utility callable by the user from the debugger when the implementation code is linked in
+ void dump() const;
+
SkOpContour* fContour;
int fIndex;
int fLast;
diff --git a/chromium/third_party/skia/src/pathops/SkIntersections.cpp b/chromium/third_party/skia/src/pathops/SkIntersections.cpp
index 53cd6feb433..56eba2717b7 100644
--- a/chromium/third_party/skia/src/pathops/SkIntersections.cpp
+++ b/chromium/third_party/skia/src/pathops/SkIntersections.cpp
@@ -103,6 +103,7 @@ int SkIntersections::insert(double one, double two, const SkDPoint& pt) {
int remaining = fUsed - index;
if (remaining > 0) {
memmove(&fPt[index + 1], &fPt[index], sizeof(fPt[0]) * remaining);
+ memmove(&fPt2[index + 1], &fPt2[index], sizeof(fPt2[0]) * remaining);
memmove(&fT[0][index + 1], &fT[0][index], sizeof(fT[0][0]) * remaining);
memmove(&fT[1][index + 1], &fT[1][index], sizeof(fT[1][0]) * remaining);
int clearMask = ~((1 << index) - 1);
@@ -116,6 +117,15 @@ int SkIntersections::insert(double one, double two, const SkDPoint& pt) {
return index;
}
+void SkIntersections::insertNear(double one, double two, const SkDPoint& pt1, const SkDPoint& pt2) {
+ SkASSERT(one == 0 || one == 1);
+ SkASSERT(two == 0 || two == 1);
+ SkASSERT(pt1 != pt2);
+ SkASSERT(fNearlySame[(int) one]);
+ (void) insert(one, two, pt1);
+ fPt2[one ? fUsed - 1 : 0] = pt2;
+}
+
void SkIntersections::insertCoincident(double one, double two, const SkDPoint& pt) {
int index = insertSwap(one, two, pt);
int bit = 1 << index;
@@ -152,26 +162,13 @@ void SkIntersections::quickRemoveOne(int index, int replace) {
}
}
-#if 0
-void SkIntersections::remove(double one, double two, const SkDPoint& startPt,
- const SkDPoint& endPt) {
- for (int index = fUsed - 1; index >= 0; --index) {
- if (!(fIsCoincident[0] & (1 << index)) && (between(one, fT[fSwap][index], two)
- || startPt.approximatelyEqual(fPt[index])
- || endPt.approximatelyEqual(fPt[index]))) {
- SkASSERT(fUsed > 0);
- removeOne(index);
- }
- }
-}
-#endif
-
void SkIntersections::removeOne(int index) {
int remaining = --fUsed - index;
if (remaining <= 0) {
return;
}
memmove(&fPt[index], &fPt[index + 1], sizeof(fPt[0]) * remaining);
+ memmove(&fPt2[index], &fPt2[index + 1], sizeof(fPt2[0]) * remaining);
memmove(&fT[0][index], &fT[0][index + 1], sizeof(fT[0][0]) * remaining);
memmove(&fT[1][index], &fT[1][index + 1], sizeof(fT[1][0]) * remaining);
SkASSERT(fIsCoincident[0] == 0);
diff --git a/chromium/third_party/skia/src/pathops/SkIntersections.h b/chromium/third_party/skia/src/pathops/SkIntersections.h
index 0e3fcd1173f..0186b3797d5 100644
--- a/chromium/third_party/skia/src/pathops/SkIntersections.h
+++ b/chromium/third_party/skia/src/pathops/SkIntersections.h
@@ -21,8 +21,10 @@ public:
#endif
{
sk_bzero(fPt, sizeof(fPt));
+ sk_bzero(fPt2, sizeof(fPt2));
sk_bzero(fT, sizeof(fT));
sk_bzero(fIsCoincident, sizeof(fIsCoincident));
+ sk_bzero(fNearlySame, sizeof(fNearlySame));
reset();
fMax = 0; // require that the caller set the max
}
@@ -37,16 +39,6 @@ public:
};
TArray operator[](int n) const { return TArray(fT[n]); }
- void set(const SkIntersections& i) {
- memcpy(fPt, i.fPt, sizeof(fPt));
- memcpy(fT, i.fT, sizeof(fT));
- memcpy(fIsCoincident, i.fIsCoincident, sizeof(fIsCoincident));
- fUsed = i.fUsed;
- fMax = i.fMax;
- fSwap = i.fSwap;
- SkDEBUGCODE(fDepth = i.fDepth);
- }
-
void allowNear(bool nearAllowed) {
fAllowNear = nearAllowed;
}
@@ -140,10 +132,19 @@ public:
return intersect(aLine, bLine);
}
+ bool nearlySame(int index) const {
+ SkASSERT(index == 0 || index == 1);
+ return fNearlySame[index];
+ }
+
const SkDPoint& pt(int index) const {
return fPt[index];
}
+ const SkDPoint& pt2(int index) const {
+ return fPt2[index];
+ }
+
int quadHorizontal(const SkPoint a[3], SkScalar left, SkScalar right, SkScalar y,
bool flipped) {
SkDQuad quad;
@@ -164,7 +165,7 @@ public:
quad.set(a);
SkDLine line;
line.set(b);
- fMax = 2;
+ fMax = 3; // 2; permit small coincident segment + non-coincident intersection
return intersect(quad, line);
}
@@ -177,12 +178,16 @@ public:
return intersect(aQuad, bQuad);
}
- // leaves flip, swap, max alone
+ // leaves swap, max alone
void reset() {
fAllowNear = true;
fUsed = 0;
}
+ void set(bool swap, int tIndex, double t) {
+ fT[(int) swap][tIndex] = t;
+ }
+
void setMax(int max) {
fMax = max;
}
@@ -210,9 +215,10 @@ public:
}
void append(const SkIntersections& );
- static double Axial(const SkDQuad& , const SkDPoint& , bool vertical);
void cleanUpCoincidence();
int coincidentUsed() const;
+ void cubicInsert(double one, double two, const SkDPoint& pt, const SkDCubic& c1,
+ const SkDCubic& c2);
int cubicRay(const SkPoint pts[4], const SkDLine& line);
void flip();
int horizontal(const SkDLine&, double y);
@@ -224,7 +230,7 @@ public:
int horizontal(const SkDCubic&, double left, double right, double y, double tRange[3]);
// FIXME : does not respect swap
int insert(double one, double two, const SkDPoint& pt);
- void insertNear(double one, double two, const SkDPoint& pt);
+ void insertNear(double one, double two, const SkDPoint& pt1, const SkDPoint& pt2);
// start if index == 0 : end if index == 1
void insertCoincident(double one, double two, const SkDPoint& pt);
int intersect(const SkDLine&, const SkDLine&);
@@ -266,12 +272,12 @@ private:
void cubicNearEnd(const SkDCubic& cubic1, bool start, const SkDCubic& cubic2, const SkDRect& );
void cleanUpParallelLines(bool parallel);
void computePoints(const SkDLine& line, int used);
- // used by addCoincident to remove ordinary intersections in range
- // void remove(double one, double two, const SkDPoint& startPt, const SkDPoint& endPt);
SkDPoint fPt[9]; // FIXME: since scans store points as SkPoint, this should also
+ SkDPoint fPt2[9]; // used by nearly same to store alternate intersection point
double fT[2][9];
uint16_t fIsCoincident[2]; // bit set for each curve's coincident T
+ bool fNearlySame[2]; // true if end points nearly match
unsigned char fUsed;
unsigned char fMax;
bool fAllowNear;
diff --git a/chromium/third_party/skia/src/pathops/SkLineParameters.h b/chromium/third_party/skia/src/pathops/SkLineParameters.h
index 04074854a8f..92343c691bd 100644
--- a/chromium/third_party/skia/src/pathops/SkLineParameters.h
+++ b/chromium/third_party/skia/src/pathops/SkLineParameters.h
@@ -24,48 +24,50 @@
class SkLineParameters {
public:
- void cubicEndPoints(const SkDCubic& pts) {
+ bool cubicEndPoints(const SkDCubic& pts) {
int endIndex = 1;
cubicEndPoints(pts, 0, endIndex);
if (dy() != 0) {
- return;
+ return true;
}
if (dx() == 0) {
cubicEndPoints(pts, 0, ++endIndex);
SkASSERT(endIndex == 2);
if (dy() != 0) {
- return;
+ return true;
}
if (dx() == 0) {
cubicEndPoints(pts, 0, ++endIndex); // line
SkASSERT(endIndex == 3);
- return;
+ return false;
}
}
+ // FIXME: after switching to round sort, remove bumping fA
if (dx() < 0) { // only worry about y bias when breaking cw/ccw tie
- return;
+ return true;
}
// if cubic tangent is on x axis, look at next control point to break tie
// control point may be approximate, so it must move significantly to account for error
if (NotAlmostEqualUlps(pts[0].fY, pts[++endIndex].fY)) {
if (pts[0].fY > pts[endIndex].fY) {
- a = DBL_EPSILON; // push it from 0 to slightly negative (y() returns -a)
+ fA = DBL_EPSILON; // push it from 0 to slightly negative (y() returns -a)
}
- return;
+ return true;
}
if (endIndex == 3) {
- return;
+ return true;
}
SkASSERT(endIndex == 2);
if (pts[0].fY > pts[3].fY) {
- a = DBL_EPSILON; // push it from 0 to slightly negative (y() returns -a)
+ fA = DBL_EPSILON; // push it from 0 to slightly negative (y() returns -a)
}
+ return true;
}
void cubicEndPoints(const SkDCubic& pts, int s, int e) {
- a = pts[s].fY - pts[e].fY;
- b = pts[e].fX - pts[s].fX;
- c = pts[s].fX * pts[e].fY - pts[e].fX * pts[s].fY;
+ fA = pts[s].fY - pts[e].fY;
+ fB = pts[e].fX - pts[s].fX;
+ fC = pts[s].fX * pts[e].fY - pts[e].fX * pts[s].fY;
}
double cubicPart(const SkDCubic& part) {
@@ -77,32 +79,34 @@ public:
}
void lineEndPoints(const SkDLine& pts) {
- a = pts[0].fY - pts[1].fY;
- b = pts[1].fX - pts[0].fX;
- c = pts[0].fX * pts[1].fY - pts[1].fX * pts[0].fY;
+ fA = pts[0].fY - pts[1].fY;
+ fB = pts[1].fX - pts[0].fX;
+ fC = pts[0].fX * pts[1].fY - pts[1].fX * pts[0].fY;
}
- void quadEndPoints(const SkDQuad& pts) {
+ bool quadEndPoints(const SkDQuad& pts) {
quadEndPoints(pts, 0, 1);
if (dy() != 0) {
- return;
+ return true;
}
if (dx() == 0) {
quadEndPoints(pts, 0, 2);
- return;
+ return false;
}
if (dx() < 0) { // only worry about y bias when breaking cw/ccw tie
- return;
+ return true;
}
+ // FIXME: after switching to round sort, remove this
if (pts[0].fY > pts[2].fY) {
- a = DBL_EPSILON;
+ fA = DBL_EPSILON;
}
+ return true;
}
void quadEndPoints(const SkDQuad& pts, int s, int e) {
- a = pts[s].fY - pts[e].fY;
- b = pts[e].fX - pts[s].fX;
- c = pts[s].fX * pts[e].fY - pts[e].fX * pts[s].fY;
+ fA = pts[s].fY - pts[e].fY;
+ fB = pts[e].fX - pts[s].fX;
+ fC = pts[s].fX * pts[e].fY - pts[e].fX * pts[s].fY;
}
double quadPart(const SkDQuad& part) {
@@ -111,19 +115,19 @@ public:
}
double normalSquared() const {
- return a * a + b * b;
+ return fA * fA + fB * fB;
}
bool normalize() {
double normal = sqrt(normalSquared());
if (approximately_zero(normal)) {
- a = b = c = 0;
+ fA = fB = fC = 0;
return false;
}
double reciprocal = 1 / normal;
- a *= reciprocal;
- b *= reciprocal;
- c *= reciprocal;
+ fA *= reciprocal;
+ fB *= reciprocal;
+ fC *= reciprocal;
return true;
}
@@ -131,7 +135,7 @@ public:
double oneThird = 1 / 3.0;
for (int index = 0; index < 4; ++index) {
distance[index].fX = index * oneThird;
- distance[index].fY = a * pts[index].fX + b * pts[index].fY + c;
+ distance[index].fY = fA * pts[index].fX + fB * pts[index].fY + fC;
}
}
@@ -139,33 +143,33 @@ public:
double oneHalf = 1 / 2.0;
for (int index = 0; index < 3; ++index) {
distance[index].fX = index * oneHalf;
- distance[index].fY = a * pts[index].fX + b * pts[index].fY + c;
+ distance[index].fY = fA * pts[index].fX + fB * pts[index].fY + fC;
}
}
double controlPtDistance(const SkDCubic& pts, int index) const {
SkASSERT(index == 1 || index == 2);
- return a * pts[index].fX + b * pts[index].fY + c;
+ return fA * pts[index].fX + fB * pts[index].fY + fC;
}
double controlPtDistance(const SkDQuad& pts) const {
- return a * pts[1].fX + b * pts[1].fY + c;
+ return fA * pts[1].fX + fB * pts[1].fY + fC;
}
double pointDistance(const SkDPoint& pt) const {
- return a * pt.fX + b * pt.fY + c;
+ return fA * pt.fX + fB * pt.fY + fC;
}
double dx() const {
- return b;
+ return fB;
}
double dy() const {
- return -a;
+ return -fA;
}
private:
- double a;
- double b;
- double c;
+ double fA;
+ double fB;
+ double fC;
};
diff --git a/chromium/third_party/skia/src/pathops/SkOpAngle.cpp b/chromium/third_party/skia/src/pathops/SkOpAngle.cpp
index 742a161f6c4..894758cfe81 100644
--- a/chromium/third_party/skia/src/pathops/SkOpAngle.cpp
+++ b/chromium/third_party/skia/src/pathops/SkOpAngle.cpp
@@ -12,19 +12,14 @@
#if DEBUG_ANGLE
#include "SkString.h"
-
-static const char funcName[] = "SkOpSegment::operator<";
-static const int bugChar = strlen(funcName) + 1;
#endif
/* Angles are sorted counterclockwise. The smallest angle has a positive x and the smallest
positive y. The largest angle has a positive x and a zero y. */
#if DEBUG_ANGLE
- static bool CompareResult(SkString* bugOut, const char* append, bool compare) {
- bugOut->appendf("%s", append);
- bugOut->writable_str()[bugChar] = "><"[compare];
- SkDebugf("%s\n", bugOut->c_str());
+ static bool CompareResult(SkString* bugOut, int append, bool compare) {
+ SkDebugf("%s %c %d\n", bugOut->c_str(), compare ? 'T' : 'F', append);
return compare;
}
@@ -33,7 +28,197 @@ static const int bugChar = strlen(funcName) + 1;
#define COMPARE_RESULT(append, compare) compare
#endif
-bool SkOpAngle::calcSlop(double x, double y, double rx, double ry, bool* result) const{
+/* quarter angle values for sector
+
+31 x > 0, y == 0 horizontal line (to the right)
+0 x > 0, y == epsilon quad/cubic horizontal tangent eventually going +y
+1 x > 0, y > 0, x > y nearer horizontal angle
+2 x + e == y quad/cubic 45 going horiz
+3 x > 0, y > 0, x == y 45 angle
+4 x == y + e quad/cubic 45 going vert
+5 x > 0, y > 0, x < y nearer vertical angle
+6 x == epsilon, y > 0 quad/cubic vertical tangent eventually going +x
+7 x == 0, y > 0 vertical line (to the top)
+
+ 8 7 6
+ 9 | 5
+ 10 | 4
+ 11 | 3
+ 12 \ | / 2
+ 13 | 1
+ 14 | 0
+ 15 --------------+------------- 31
+ 16 | 30
+ 17 | 29
+ 18 / | \ 28
+ 19 | 27
+ 20 | 26
+ 21 | 25
+ 22 23 24
+*/
+
+// return true if lh < this < rh
+bool SkOpAngle::after(const SkOpAngle* test) const {
+ const SkOpAngle& lh = *test;
+ const SkOpAngle& rh = *lh.fNext;
+ SkASSERT(&lh != &rh);
+#if DEBUG_ANGLE
+ SkString bugOut;
+ bugOut.printf("%s [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g"
+ " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g"
+ " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g ", __FUNCTION__,
+ lh.fSegment->debugID(), lh.debugID(), lh.fSectorStart, lh.fSectorEnd,
+ lh.fSegment->t(lh.fStart), lh.fSegment->t(lh.fEnd),
+ fSegment->debugID(), debugID(), fSectorStart, fSectorEnd, fSegment->t(fStart),
+ fSegment->t(fEnd),
+ rh.fSegment->debugID(), rh.debugID(), rh.fSectorStart, rh.fSectorEnd,
+ rh.fSegment->t(rh.fStart), rh.fSegment->t(rh.fEnd));
+#endif
+ if (lh.fComputeSector && !const_cast<SkOpAngle&>(lh).computeSector()) {
+ return COMPARE_RESULT(1, true);
+ }
+ if (fComputeSector && !const_cast<SkOpAngle*>(this)->computeSector()) {
+ return COMPARE_RESULT(2, true);
+ }
+ if (rh.fComputeSector && !const_cast<SkOpAngle&>(rh).computeSector()) {
+ return COMPARE_RESULT(3, true);
+ }
+#if DEBUG_ANGLE // reset bugOut with computed sectors
+ bugOut.printf("%s [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g"
+ " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g"
+ " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g ", __FUNCTION__,
+ lh.fSegment->debugID(), lh.debugID(), lh.fSectorStart, lh.fSectorEnd,
+ lh.fSegment->t(lh.fStart), lh.fSegment->t(lh.fEnd),
+ fSegment->debugID(), debugID(), fSectorStart, fSectorEnd, fSegment->t(fStart),
+ fSegment->t(fEnd),
+ rh.fSegment->debugID(), rh.debugID(), rh.fSectorStart, rh.fSectorEnd,
+ rh.fSegment->t(rh.fStart), rh.fSegment->t(rh.fEnd));
+#endif
+ bool ltrOverlap = (lh.fSectorMask | rh.fSectorMask) & fSectorMask;
+ bool lrOverlap = lh.fSectorMask & rh.fSectorMask;
+ int lrOrder; // set to -1 if either order works
+ if (!lrOverlap) { // no lh/rh sector overlap
+ if (!ltrOverlap) { // no lh/this/rh sector overlap
+ return COMPARE_RESULT(4, (lh.fSectorEnd > rh.fSectorStart)
+ ^ (fSectorStart > lh.fSectorEnd) ^ (fSectorStart > rh.fSectorStart));
+ }
+ int lrGap = (rh.fSectorStart - lh.fSectorStart + 32) & 0x1f;
+ /* A tiny change can move the start +/- 4. The order can only be determined if
+ lr gap is not 12 to 20 or -12 to -20.
+ -31 ..-21 1
+ -20 ..-12 -1
+ -11 .. -1 0
+ 0 shouldn't get here
+ 11 .. 1 1
+ 12 .. 20 -1
+ 21 .. 31 0
+ */
+ lrOrder = lrGap > 20 ? 0 : lrGap > 11 ? -1 : 1;
+ } else {
+ lrOrder = (int) lh.orderable(rh);
+ if (!ltrOverlap) {
+ return COMPARE_RESULT(5, !lrOrder);
+ }
+ }
+ int ltOrder;
+ SkASSERT((lh.fSectorMask & fSectorMask) || (rh.fSectorMask & fSectorMask));
+ if (lh.fSectorMask & fSectorMask) {
+ ltOrder = (int) lh.orderable(*this);
+ } else {
+ int ltGap = (fSectorStart - lh.fSectorStart + 32) & 0x1f;
+ ltOrder = ltGap > 20 ? 0 : ltGap > 11 ? -1 : 1;
+ }
+ int trOrder;
+ if (rh.fSectorMask & fSectorMask) {
+ trOrder = (int) orderable(rh);
+ } else {
+ int trGap = (rh.fSectorStart - fSectorStart + 32) & 0x1f;
+ trOrder = trGap > 20 ? 0 : trGap > 11 ? -1 : 1;
+ }
+ if (lrOrder >= 0 && ltOrder >= 0 && trOrder >= 0) {
+ return COMPARE_RESULT(7, lrOrder ? (ltOrder & trOrder) : (ltOrder | trOrder));
+ }
+ SkASSERT(lrOrder >= 0 || ltOrder >= 0 || trOrder >= 0);
+// There's not enough information to sort. Get the pairs of angles in opposite planes.
+// If an order is < 0, the pair is already in an opposite plane. Check the remaining pairs.
+ // FIXME : once all variants are understood, rewrite this more simply
+ if (ltOrder == 0 && lrOrder == 0) {
+ SkASSERT(trOrder < 0);
+ // FIXME : once this is verified to work, remove one opposite angle call
+ SkDEBUGCODE(bool lrOpposite = lh.oppositePlanes(rh));
+ bool ltOpposite = lh.oppositePlanes(*this);
+ SkASSERT(lrOpposite != ltOpposite);
+ return COMPARE_RESULT(8, ltOpposite);
+ } else if (ltOrder == 1 && trOrder == 0) {
+ SkASSERT(lrOrder < 0);
+ SkDEBUGCODE(bool ltOpposite = lh.oppositePlanes(*this));
+ bool trOpposite = oppositePlanes(rh);
+ SkASSERT(ltOpposite != trOpposite);
+ return COMPARE_RESULT(9, trOpposite);
+ } else if (lrOrder == 1 && trOrder == 1) {
+ SkASSERT(ltOrder < 0);
+ SkDEBUGCODE(bool trOpposite = oppositePlanes(rh));
+ bool lrOpposite = lh.oppositePlanes(rh);
+ SkASSERT(lrOpposite != trOpposite);
+ return COMPARE_RESULT(10, lrOpposite);
+ }
+ if (lrOrder < 0) {
+ if (ltOrder < 0) {
+ return COMPARE_RESULT(11, trOrder);
+ }
+ return COMPARE_RESULT(12, ltOrder);
+ }
+ return COMPARE_RESULT(13, !lrOrder);
+}
+
+// given a line, see if the opposite curve's convex hull is all on one side
+// returns -1=not on one side 0=this CW of test 1=this CCW of test
+int SkOpAngle::allOnOneSide(const SkOpAngle& test) const {
+ SkASSERT(!fIsCurve);
+ SkASSERT(test.fIsCurve);
+ const SkDPoint& origin = test.fCurvePart[0];
+ SkVector line;
+ if (fSegment->verb() == SkPath::kLine_Verb) {
+ const SkPoint* linePts = fSegment->pts();
+ int lineStart = fStart < fEnd ? 0 : 1;
+ line = linePts[lineStart ^ 1] - linePts[lineStart];
+ } else {
+ SkPoint shortPts[2] = { fCurvePart[0].asSkPoint(), fCurvePart[1].asSkPoint() };
+ line = shortPts[1] - shortPts[0];
+ }
+ float crosses[3];
+ SkPath::Verb testVerb = test.fSegment->verb();
+ int iMax = SkPathOpsVerbToPoints(testVerb);
+// SkASSERT(origin == test.fCurveHalf[0]);
+ const SkDCubic& testCurve = test.fCurvePart;
+// do {
+ for (int index = 1; index <= iMax; ++index) {
+ float xy1 = (float) (line.fX * (testCurve[index].fY - origin.fY));
+ float xy2 = (float) (line.fY * (testCurve[index].fX - origin.fX));
+ crosses[index - 1] = AlmostEqualUlps(xy1, xy2) ? 0 : xy1 - xy2;
+ }
+ if (crosses[0] * crosses[1] < 0) {
+ return -1;
+ }
+ if (SkPath::kCubic_Verb == testVerb) {
+ if (crosses[0] * crosses[2] < 0 || crosses[1] * crosses[2] < 0) {
+ return -1;
+ }
+ }
+ if (crosses[0]) {
+ return crosses[0] < 0;
+ }
+ if (crosses[1]) {
+ return crosses[1] < 0;
+ }
+ if (SkPath::kCubic_Verb == testVerb && crosses[2]) {
+ return crosses[2] < 0;
+ }
+ fUnorderable = true;
+ return -1;
+}
+
+bool SkOpAngle::calcSlop(double x, double y, double rx, double ry, bool* result) const {
double absX = fabs(x);
double absY = fabs(y);
double length = absX < absY ? absX / 2 + absY : absX + absY / 2;
@@ -59,280 +244,782 @@ bool SkOpAngle::calcSlop(double x, double y, double rx, double ry, bool* result)
return *result == less2;
}
-/*
-for quads and cubics, set up a parameterized line (e.g. LineParameters )
-for points [0] to [1]. See if point [2] is on that line, or on one side
-or the other. If it both quads' end points are on the same side, choose
-the shorter tangent. If the tangents are equal, choose the better second
-tangent angle
+bool SkOpAngle::checkCrossesZero() const {
+ int start = SkTMin(fSectorStart, fSectorEnd);
+ int end = SkTMax(fSectorStart, fSectorEnd);
+ bool crossesZero = end - start > 16;
+ return crossesZero;
+}
-FIXME: maybe I could set up LineParameters lazily
-*/
-bool SkOpAngle::operator<(const SkOpAngle& rh) const { // this/lh: left-hand; rh: right-hand
- double y = dy();
- double ry = rh.dy();
-#if DEBUG_ANGLE
- SkString bugOut;
- bugOut.printf("%s _ id=%d segId=%d tStart=%1.9g tEnd=%1.9g"
- " | id=%d segId=%d tStart=%1.9g tEnd=%1.9g ", funcName,
- fID, fSegment->debugID(), fSegment->t(fStart), fSegment->t(fEnd),
- rh.fID, rh.fSegment->debugID(), rh.fSegment->t(rh.fStart), rh.fSegment->t(rh.fEnd));
-#endif
- double y_ry = y * ry;
- if (y_ry < 0) { // if y's are opposite signs, we can do a quick return
- return COMPARE_RESULT("1 y * ry < 0", y < 0);
- }
- // at this point, both y's must be the same sign, or one (or both) is zero
- double x = dx();
- double rx = rh.dx();
- if (x * rx < 0) { // if x's are opposite signs, use y to determine first or second half
- if (y < 0 && ry < 0) { // if y's are negative, lh x is smaller if positive
- return COMPARE_RESULT("2 x_rx < 0 && y < 0 ...", x > 0);
- }
- if (y >= 0 && ry >= 0) { // if y's are zero or positive, lh x is smaller if negative
- return COMPARE_RESULT("3 x_rx < 0 && y >= 0 ...", x < 0);
- }
- SkASSERT((y == 0) ^ (ry == 0)); // if one y is zero and one is negative, neg y is smaller
- return COMPARE_RESULT("4 x_rx < 0 && y == 0 ...", y < 0);
- }
- // at this point, both x's must be the same sign, or one (or both) is zero
- if (y_ry == 0) { // if either y is zero
- if (y + ry < 0) { // if the other y is less than zero, it must be smaller
- return COMPARE_RESULT("5 y_ry == 0 && y + ry < 0", y < 0);
- }
- if (y + ry > 0) { // if a y is greater than zero and an x is positive, non zero is smaller
- return COMPARE_RESULT("6 y_ry == 0 && y + ry > 0", (x + rx > 0) ^ (y == 0));
- }
- // at this point, both y's are zero, so lines are coincident or one is degenerate
- SkASSERT(x * rx != 0); // and a degenerate line should haven't gotten this far
- }
- // see if either curve can be lengthened before trying the tangent
- if (fSegment->other(fEnd) != rh.fSegment // tangents not absolutely identical
- && rh.fSegment->other(rh.fEnd) != fSegment
- && y != -DBL_EPSILON
- && ry != -DBL_EPSILON) { // and not intersecting
- SkOpAngle longer = *this;
- SkOpAngle rhLonger = rh;
- if ((longer.lengthen(rh) | rhLonger.lengthen(*this)) // lengthen both
- && (fUnorderable || !longer.fUnorderable)
- && (rh.fUnorderable || !rhLonger.fUnorderable)) {
-#if DEBUG_ANGLE
- bugOut.prepend(" ");
-#endif
- return COMPARE_RESULT("10 longer.lengthen(rh) ...", longer < rhLonger);
+bool SkOpAngle::checkParallel(const SkOpAngle& rh) const {
+ SkDVector scratch[2];
+ const SkDVector* sweep, * tweep;
+ if (!fUnorderedSweep) {
+ sweep = fSweep;
+ } else {
+ scratch[0] = fCurvePart[1] - fCurvePart[0];
+ sweep = &scratch[0];
+ }
+ if (!rh.fUnorderedSweep) {
+ tweep = rh.fSweep;
+ } else {
+ scratch[1] = rh.fCurvePart[1] - rh.fCurvePart[0];
+ tweep = &scratch[1];
+ }
+ double s0xt0 = sweep->crossCheck(*tweep);
+ if (tangentsDiverge(rh, s0xt0)) {
+ return s0xt0 < 0;
+ }
+ SkDVector m0 = fSegment->dPtAtT(midT()) - fCurvePart[0];
+ SkDVector m1 = rh.fSegment->dPtAtT(rh.midT()) - rh.fCurvePart[0];
+ double m0xm1 = m0.crossCheck(m1);
+ if (m0xm1 == 0) {
+ fUnorderable = true;
+ rh.fUnorderable = true;
+ return true;
+ }
+ return m0xm1 < 0;
+}
+
+// the original angle is too short to get meaningful sector information
+// lengthen it until it is long enough to be meaningful or leave it unset if lengthening it
+// would cause it to intersect one of the adjacent angles
+bool SkOpAngle::computeSector() {
+ if (fComputedSector) {
+ // FIXME: logically, this should return !fUnorderable, but doing so breaks testQuadratic51
+ // -- but in general, this code may not work so this may be the least of problems
+ // adding the bang fixes testQuads46x in release, however
+ return !fUnorderable;
+ }
+ SkASSERT(fSegment->verb() != SkPath::kLine_Verb && small());
+ fComputedSector = true;
+ int step = fStart < fEnd ? 1 : -1;
+ int limit = step > 0 ? fSegment->count() : -1;
+ int checkEnd = fEnd;
+ do {
+// advance end
+ const SkOpSpan& span = fSegment->span(checkEnd);
+ const SkOpSegment* other = span.fOther;
+ int oCount = other->count();
+ for (int oIndex = 0; oIndex < oCount; ++oIndex) {
+ const SkOpSpan& oSpan = other->span(oIndex);
+ if (oSpan.fOther != fSegment) {
+ continue;
+ }
+ if (oSpan.fOtherIndex == checkEnd) {
+ continue;
+ }
+ if (!approximately_equal(oSpan.fOtherT, span.fT)) {
+ continue;
+ }
+ goto recomputeSector;
}
+ checkEnd += step;
+ } while (checkEnd != limit);
+recomputeSector:
+ if (checkEnd == fEnd || checkEnd - step == fEnd) {
+ fUnorderable = true;
+ return false;
}
- SkPath::Verb verb = fSegment->verb();
- SkPath::Verb rVerb = rh.fSegment->verb();
- if (y_ry != 0) { // if they aren't coincident, look for a stable cross product
- // at this point, y's are the same sign, neither is zero
- // and x's are the same sign, or one (or both) is zero
- double x_ry = x * ry;
- double rx_y = rx * y;
- if (!fComputed && !rh.fComputed) {
- if (!SkDLine::NearRay(x, y, rx, ry) && x_ry != rx_y) {
- return COMPARE_RESULT("7 !fComputed && !rh.fComputed", x_ry < rx_y);
+ int saveEnd = fEnd;
+ fComputedEnd = fEnd = checkEnd - step;
+ setSpans();
+ setSector();
+ fEnd = saveEnd;
+ return !fUnorderable;
+}
+
+// returns -1 if overlaps 0 if no overlap cw 1 if no overlap ccw
+int SkOpAngle::convexHullOverlaps(const SkOpAngle& rh) const {
+ const SkDVector* sweep = fSweep;
+ const SkDVector* tweep = rh.fSweep;
+ double s0xs1 = sweep[0].crossCheck(sweep[1]);
+ double s0xt0 = sweep[0].crossCheck(tweep[0]);
+ double s1xt0 = sweep[1].crossCheck(tweep[0]);
+ bool tBetweenS = s0xs1 > 0 ? s0xt0 > 0 && s1xt0 < 0 : s0xt0 < 0 && s1xt0 > 0;
+ double s0xt1 = sweep[0].crossCheck(tweep[1]);
+ double s1xt1 = sweep[1].crossCheck(tweep[1]);
+ tBetweenS |= s0xs1 > 0 ? s0xt1 > 0 && s1xt1 < 0 : s0xt1 < 0 && s1xt1 > 0;
+ double t0xt1 = tweep[0].crossCheck(tweep[1]);
+ if (tBetweenS) {
+ return -1;
+ }
+ if ((s0xt0 == 0 && s1xt1 == 0) || (s1xt0 == 0 && s0xt1 == 0)) { // s0 to s1 equals t0 to t1
+ return -1;
+ }
+ bool sBetweenT = t0xt1 > 0 ? s0xt0 < 0 && s0xt1 > 0 : s0xt0 > 0 && s0xt1 < 0;
+ sBetweenT |= t0xt1 > 0 ? s1xt0 < 0 && s1xt1 > 0 : s1xt0 > 0 && s1xt1 < 0;
+ if (sBetweenT) {
+ return -1;
+ }
+ // if all of the sweeps are in the same half plane, then the order of any pair is enough
+ if (s0xt0 >= 0 && s0xt1 >= 0 && s1xt0 >= 0 && s1xt1 >= 0) {
+ return 0;
+ }
+ if (s0xt0 <= 0 && s0xt1 <= 0 && s1xt0 <= 0 && s1xt1 <= 0) {
+ return 1;
+ }
+ // if the outside sweeps are greater than 180 degress:
+ // first assume the inital tangents are the ordering
+ // if the midpoint direction matches the inital order, that is enough
+ SkDVector m0 = fSegment->dPtAtT(midT()) - fCurvePart[0];
+ SkDVector m1 = rh.fSegment->dPtAtT(rh.midT()) - rh.fCurvePart[0];
+ double m0xm1 = m0.crossCheck(m1);
+ if (s0xt0 > 0 && m0xm1 > 0) {
+ return 0;
+ }
+ if (s0xt0 < 0 && m0xm1 < 0) {
+ return 1;
+ }
+ if (tangentsDiverge(rh, s0xt0)) {
+ return s0xt0 < 0;
+ }
+ return m0xm1 < 0;
+}
+
+// OPTIMIZATION: longest can all be either lazily computed here or precomputed in setup
+double SkOpAngle::distEndRatio(double dist) const {
+ double longest = 0;
+ const SkOpSegment& segment = *this->segment();
+ int ptCount = SkPathOpsVerbToPoints(segment.verb());
+ const SkPoint* pts = segment.pts();
+ for (int idx1 = 0; idx1 <= ptCount - 1; ++idx1) {
+ for (int idx2 = idx1 + 1; idx2 <= ptCount; ++idx2) {
+ if (idx1 == idx2) {
+ continue;
}
- if (fSide2 == 0 && rh.fSide2 == 0) {
- return COMPARE_RESULT("7a !fComputed && !rh.fComputed", x_ry < rx_y);
+ SkDVector v;
+ v.set(pts[idx2] - pts[idx1]);
+ double lenSq = v.lengthSquared();
+ longest = SkTMax(longest, lenSq);
+ }
+ }
+ return sqrt(longest) / dist;
+}
+
+bool SkOpAngle::endsIntersect(const SkOpAngle& rh) const {
+ SkPath::Verb lVerb = fSegment->verb();
+ SkPath::Verb rVerb = rh.fSegment->verb();
+ int lPts = SkPathOpsVerbToPoints(lVerb);
+ int rPts = SkPathOpsVerbToPoints(rVerb);
+ SkDLine rays[] = {{{fCurvePart[0], rh.fCurvePart[rPts]}},
+ {{fCurvePart[0], fCurvePart[lPts]}}};
+ if (rays[0][1] == rays[1][1]) {
+ return checkParallel(rh);
+ }
+ double smallTs[2] = {-1, -1};
+ bool limited[2] = {false, false};
+ for (int index = 0; index < 2; ++index) {
+ const SkOpSegment& segment = index ? *rh.fSegment : *fSegment;
+ SkIntersections i;
+ (*CurveIntersectRay[index ? rPts : lPts])(segment.pts(), rays[index], &i);
+// SkASSERT(i.used() >= 1);
+// if (i.used() <= 1) {
+// continue;
+// }
+ double tStart = segment.t(index ? rh.fStart : fStart);
+ double tEnd = segment.t(index ? rh.fComputedEnd : fComputedEnd);
+ bool testAscends = index ? rh.fStart < rh.fComputedEnd : fStart < fComputedEnd;
+ double t = testAscends ? 0 : 1;
+ for (int idx2 = 0; idx2 < i.used(); ++idx2) {
+ double testT = i[0][idx2];
+ if (!approximately_between_orderable(tStart, testT, tEnd)) {
+ continue;
}
- } else {
- // if the vector was a result of subdividing a curve, see if it is stable
- bool sloppy1 = x_ry < rx_y;
- bool sloppy2 = !sloppy1;
- if ((!fComputed || calcSlop(x, y, rx, ry, &sloppy1))
- && (!rh.fComputed || rh.calcSlop(rx, ry, x, y, &sloppy2))
- && sloppy1 != sloppy2) {
- return COMPARE_RESULT("8 CalcSlop(x, y ...", sloppy1);
+ if (approximately_equal_orderable(tStart, testT)) {
+ continue;
}
+ smallTs[index] = t = testAscends ? SkTMax(t, testT) : SkTMin(t, testT);
+ limited[index] = approximately_equal_orderable(t, tEnd);
}
}
- if (fSide2 * rh.fSide2 == 0) { // one is zero
-#if DEBUG_ANGLE
- if (fSide2 == rh.fSide2 && y_ry) { // both is zero; coincidence was undetected
- SkDebugf("%s coincidence!\n", __FUNCTION__);
+#if 0
+ if (smallTs[0] < 0 && smallTs[1] < 0) { // if neither ray intersects, do endpoint sort
+ double m0xm1 = 0;
+ if (lVerb == SkPath::kLine_Verb) {
+ SkASSERT(rVerb != SkPath::kLine_Verb);
+ SkDVector m0 = rays[1][1] - fCurvePart[0];
+ SkDPoint endPt;
+ endPt.set(rh.fSegment->pts()[rh.fStart < rh.fEnd ? rPts : 0]);
+ SkDVector m1 = endPt - fCurvePart[0];
+ m0xm1 = m0.crossCheck(m1);
}
+ if (rVerb == SkPath::kLine_Verb) {
+ SkDPoint endPt;
+ endPt.set(fSegment->pts()[fStart < fEnd ? lPts : 0]);
+ SkDVector m0 = endPt - fCurvePart[0];
+ SkDVector m1 = rays[0][1] - fCurvePart[0];
+ m0xm1 = m0.crossCheck(m1);
+ }
+ if (m0xm1 != 0) {
+ return m0xm1 < 0;
+ }
+ }
#endif
- return COMPARE_RESULT("9a fSide2 * rh.fSide2 == 0 ...", fSide2 < rh.fSide2);
- }
- // at this point, the initial tangent line is nearly coincident
- // see if edges curl away from each other
- if (fSide * rh.fSide < 0 && (!approximately_zero(fSide) || !approximately_zero(rh.fSide))) {
- return COMPARE_RESULT("9b fSide * rh.fSide < 0 ...", fSide < rh.fSide);
- }
- if (fUnsortable || rh.fUnsortable) {
- // even with no solution, return a stable sort
- return COMPARE_RESULT("11 fUnsortable || rh.fUnsortable", this < &rh);
- }
- if ((verb == SkPath::kLine_Verb && approximately_zero(y) && approximately_zero(x))
- || (rVerb == SkPath::kLine_Verb
- && approximately_zero(ry) && approximately_zero(rx))) {
- // See general unsortable comment below. This case can happen when
- // one line has a non-zero change in t but no change in x and y.
- fUnsortable = true;
- return COMPARE_RESULT("12 verb == SkPath::kLine_Verb ...", this < &rh);
- }
- if (fSegment->isTiny(this) || rh.fSegment->isTiny(&rh)) {
- fUnsortable = true;
- return COMPARE_RESULT("13 verb == fSegment->isTiny(this) ...", this < &rh);
- }
- SkASSERT(verb >= SkPath::kQuad_Verb);
- SkASSERT(rVerb >= SkPath::kQuad_Verb);
- // FIXME: until I can think of something better, project a ray from the
- // end of the shorter tangent to midway between the end points
- // through both curves and use the resulting angle to sort
- // FIXME: some of this setup can be moved to set() if it works, or cached if it's expensive
- double len = fTangentPart.normalSquared();
- double rlen = rh.fTangentPart.normalSquared();
- SkDLine ray;
- SkIntersections i, ri;
- int roots, rroots;
- bool flip = false;
- bool useThis;
- bool leftLessThanRight = fSide > 0;
- do {
- useThis = (len < rlen) ^ flip;
- const SkDCubic& part = useThis ? fCurvePart : rh.fCurvePart;
- SkPath::Verb partVerb = useThis ? verb : rVerb;
- ray[0] = partVerb == SkPath::kCubic_Verb && part[0].approximatelyEqual(part[1]) ?
- part[2] : part[1];
- ray[1] = SkDPoint::Mid(part[0], part[SkPathOpsVerbToPoints(partVerb)]);
- SkASSERT(ray[0] != ray[1]);
- roots = (i.*CurveRay[SkPathOpsVerbToPoints(verb)])(fSegment->pts(), ray);
- rroots = (ri.*CurveRay[SkPathOpsVerbToPoints(rVerb)])(rh.fSegment->pts(), ray);
- } while ((roots == 0 || rroots == 0) && (flip ^= true));
- if (roots == 0 || rroots == 0) {
- // FIXME: we don't have a solution in this case. The interim solution
- // is to mark the edges as unsortable, exclude them from this and
- // future computations, and allow the returned path to be fragmented
- fUnsortable = true;
- return COMPARE_RESULT("roots == 0 || rroots == 0", this < &rh);
- }
- SkASSERT(fSide != 0 && rh.fSide != 0);
- if (fSide * rh.fSide < 0) {
- fUnsortable = true;
- return COMPARE_RESULT("14 fSide * rh.fSide < 0", this < &rh);
- }
- SkDPoint lLoc;
- double best = SK_ScalarInfinity;
-#if DEBUG_SORT
- SkDebugf("lh=%d rh=%d use-lh=%d ray={{%1.9g,%1.9g}, {%1.9g,%1.9g}} %c\n",
- fSegment->debugID(), rh.fSegment->debugID(), useThis, ray[0].fX, ray[0].fY,
- ray[1].fX, ray[1].fY, "-+"[fSide > 0]);
-#endif
- for (int index = 0; index < roots; ++index) {
- SkDPoint loc = i.pt(index);
- SkDVector dxy = loc - ray[0];
- double dist = dxy.lengthSquared();
-#if DEBUG_SORT
- SkDebugf("best=%1.9g dist=%1.9g loc={%1.9g,%1.9g} dxy={%1.9g,%1.9g}\n",
- best, dist, loc.fX, loc.fY, dxy.fX, dxy.fY);
-#endif
- if (best > dist) {
- lLoc = loc;
- best = dist;
- }
- }
- flip = false;
- SkDPoint rLoc;
- for (int index = 0; index < rroots; ++index) {
- rLoc = ri.pt(index);
- SkDVector dxy = rLoc - ray[0];
- double dist = dxy.lengthSquared();
-#if DEBUG_SORT
- SkDebugf("best=%1.9g dist=%1.9g %c=(fSide < 0) rLoc={%1.9g,%1.9g} dxy={%1.9g,%1.9g}\n",
- best, dist, "><"[fSide < 0], rLoc.fX, rLoc.fY, dxy.fX, dxy.fY);
-#endif
- if (best > dist) {
- flip = true;
+ bool sRayLonger = false;
+ SkDVector sCept = {0, 0};
+ double sCeptT = -1;
+ int sIndex = -1;
+ bool useIntersect = false;
+ for (int index = 0; index < 2; ++index) {
+ if (smallTs[index] < 0) {
+ continue;
+ }
+ const SkOpSegment& segment = index ? *rh.fSegment : *fSegment;
+ const SkDPoint& dPt = segment.dPtAtT(smallTs[index]);
+ SkDVector cept = dPt - rays[index][0];
+ // If this point is on the curve, it should have been detected earlier by ordinary
+ // curve intersection. This may be hard to determine in general, but for lines,
+ // the point could be close to or equal to its end, but shouldn't be near the start.
+ if ((index ? lPts : rPts) == 1) {
+ SkDVector total = rays[index][1] - rays[index][0];
+ if (cept.lengthSquared() * 2 < total.lengthSquared()) {
+ continue;
+ }
+ }
+ SkDVector end = rays[index][1] - rays[index][0];
+ if (cept.fX * end.fX < 0 || cept.fY * end.fY < 0) {
+ continue;
+ }
+ double rayDist = cept.length();
+ double endDist = end.length();
+ bool rayLonger = rayDist > endDist;
+ if (limited[0] && limited[1] && rayLonger) {
+ useIntersect = true;
+ sRayLonger = rayLonger;
+ sCept = cept;
+ sCeptT = smallTs[index];
+ sIndex = index;
break;
}
+ double delta = fabs(rayDist - endDist);
+ double minX, minY, maxX, maxY;
+ minX = minY = SK_ScalarInfinity;
+ maxX = maxY = -SK_ScalarInfinity;
+ const SkDCubic& curve = index ? rh.fCurvePart : fCurvePart;
+ int ptCount = index ? rPts : lPts;
+ for (int idx2 = 0; idx2 <= ptCount; ++idx2) {
+ minX = SkTMin(minX, curve[idx2].fX);
+ minY = SkTMin(minY, curve[idx2].fY);
+ maxX = SkTMax(maxX, curve[idx2].fX);
+ maxY = SkTMax(maxY, curve[idx2].fY);
+ }
+ double maxWidth = SkTMax(maxX - minX, maxY - minY);
+ delta /= maxWidth;
+ if (delta > 1e-4 && (useIntersect ^= true)) { // FIXME: move this magic number
+ sRayLonger = rayLonger;
+ sCept = cept;
+ sCeptT = smallTs[index];
+ sIndex = index;
+ }
}
- if (flip) {
- leftLessThanRight = !leftLessThanRight;
+ if (useIntersect) {
+ const SkDCubic& curve = sIndex ? rh.fCurvePart : fCurvePart;
+ const SkOpSegment& segment = sIndex ? *rh.fSegment : *fSegment;
+ double tStart = segment.t(sIndex ? rh.fStart : fStart);
+ SkDVector mid = segment.dPtAtT(tStart + (sCeptT - tStart) / 2) - curve[0];
+ double septDir = mid.crossCheck(sCept);
+ if (!septDir) {
+ return checkParallel(rh);
+ }
+ return sRayLonger ^ (sIndex == 0) ^ (septDir < 0);
+ } else {
+ return checkParallel(rh);
}
- return COMPARE_RESULT("15 leftLessThanRight", leftLessThanRight);
+}
+
+// Most of the time, the first one can be found trivially by detecting the smallest sector value.
+// If all angles have the same sector value, actual sorting is required.
+const SkOpAngle* SkOpAngle::findFirst() const {
+ const SkOpAngle* best = this;
+ int bestStart = SkTMin(fSectorStart, fSectorEnd);
+ const SkOpAngle* angle = this;
+ while ((angle = angle->fNext) != this) {
+ int angleEnd = SkTMax(angle->fSectorStart, angle->fSectorEnd);
+ if (angleEnd < bestStart) {
+ return angle; // we wrapped around
+ }
+ int angleStart = SkTMin(angle->fSectorStart, angle->fSectorEnd);
+ if (bestStart > angleStart) {
+ best = angle;
+ bestStart = angleStart;
+ }
+ }
+ // back up to the first possible angle
+ const SkOpAngle* firstBest = best;
+ angle = best;
+ int bestEnd = SkTMax(best->fSectorStart, best->fSectorEnd);
+ while ((angle = angle->previous()) != firstBest) {
+ if (angle->fStop) {
+ break;
+ }
+ int angleStart = SkTMin(angle->fSectorStart, angle->fSectorEnd);
+ // angles that are smaller by one aren't necessary better, since the larger may be a line
+ // and the smaller may be a curve that curls to the other side of the line.
+ if (bestEnd + 1 < angleStart) {
+ return best;
+ }
+ best = angle;
+ bestEnd = SkTMax(angle->fSectorStart, angle->fSectorEnd);
+ }
+ // in the case where all angles are nearly in the same sector, check the order to find the best
+ firstBest = best;
+ angle = best;
+ do {
+ angle = angle->fNext;
+ if (angle->fStop) {
+ return firstBest;
+ }
+ bool orderable = best->orderable(*angle); // note: may return an unorderable angle
+ if (orderable == 0) {
+ return angle;
+ }
+ best = angle;
+ } while (angle != firstBest);
+ // if the angles are equally ordered, fall back on the initial tangent
+ bool foundBelow = false;
+ while ((angle = angle->fNext)) {
+ SkDVector scratch[2];
+ const SkDVector* sweep;
+ if (!angle->fUnorderedSweep) {
+ sweep = angle->fSweep;
+ } else {
+ scratch[0] = angle->fCurvePart[1] - angle->fCurvePart[0];
+ sweep = &scratch[0];
+ }
+ bool isAbove = sweep->fY <= 0;
+ if (isAbove && foundBelow) {
+ return angle;
+ }
+ foundBelow |= !isAbove;
+ if (angle == firstBest) {
+ return NULL; // should not loop around
+ }
+ }
+ SkASSERT(0); // should never get here
+ return NULL;
+}
+
+/* y<0 y==0 y>0 x<0 x==0 x>0 xy<0 xy==0 xy>0
+ 0 x x x
+ 1 x x x
+ 2 x x x
+ 3 x x x
+ 4 x x x
+ 5 x x x
+ 6 x x x
+ 7 x x x
+ 8 x x x
+ 9 x x x
+ 10 x x x
+ 11 x x x
+ 12 x x x
+ 13 x x x
+ 14 x x x
+ 15 x x x
+*/
+int SkOpAngle::findSector(SkPath::Verb verb, double x, double y) const {
+ double absX = fabs(x);
+ double absY = fabs(y);
+ double xy = SkPath::kLine_Verb == verb || !AlmostEqualUlps(absX, absY) ? absX - absY : 0;
+ // If there are four quadrants and eight octants, and since the Latin for sixteen is sedecim,
+ // one could coin the term sedecimant for a space divided into 16 sections.
+ // http://english.stackexchange.com/questions/133688/word-for-something-partitioned-into-16-parts
+ static const int sedecimant[3][3][3] = {
+ // y<0 y==0 y>0
+ // x<0 x==0 x>0 x<0 x==0 x>0 x<0 x==0 x>0
+ {{ 4, 3, 2}, { 7, -1, 15}, {10, 11, 12}}, // abs(x) < abs(y)
+ {{ 5, -1, 1}, {-1, -1, -1}, { 9, -1, 13}}, // abs(x) == abs(y)
+ {{ 6, 3, 0}, { 7, -1, 15}, { 8, 11, 14}}, // abs(x) > abs(y)
+ };
+ int sector = sedecimant[(xy >= 0) + (xy > 0)][(y >= 0) + (y > 0)][(x >= 0) + (x > 0)] * 2 + 1;
+ SkASSERT(SkPath::kLine_Verb == verb || sector >= 0);
+ return sector;
+}
+
+// OPTIMIZE: if this loops to only one other angle, after first compare fails, insert on other side
+// OPTIMIZE: return where insertion succeeded. Then, start next insertion on opposite side
+void SkOpAngle::insert(SkOpAngle* angle) {
+ if (angle->fNext) {
+ if (loopCount() >= angle->loopCount()) {
+ if (!merge(angle)) {
+ return;
+ }
+ } else if (fNext) {
+ if (!angle->merge(this)) {
+ return;
+ }
+ } else {
+ angle->insert(this);
+ }
+ return;
+ }
+ bool singleton = NULL == fNext;
+ if (singleton) {
+ fNext = this;
+ }
+ SkOpAngle* next = fNext;
+ if (next->fNext == this) {
+ if (angle->overlap(*this)) {
+ return;
+ }
+ if (singleton || angle->after(this)) {
+ this->fNext = angle;
+ angle->fNext = next;
+ } else {
+ next->fNext = angle;
+ angle->fNext = this;
+ }
+ debugValidateNext();
+ return;
+ }
+ SkOpAngle* last = this;
+ do {
+ SkASSERT(last->fNext == next);
+ if (angle->overlap(*last) || angle->overlap(*next)) {
+ return;
+ }
+ if (angle->after(last)) {
+ last->fNext = angle;
+ angle->fNext = next;
+ debugValidateNext();
+ return;
+ }
+ last = next;
+ next = next->fNext;
+ if (last == this && next->fUnorderable) {
+ fUnorderable = true;
+ return;
+ }
+ SkASSERT(last != this);
+ } while (true);
}
bool SkOpAngle::isHorizontal() const {
- return dy() == 0 && fSegment->verb() == SkPath::kLine_Verb;
+ return !fIsCurve && fSweep[0].fY == 0;
}
-// lengthen cannot cross opposite angle
-bool SkOpAngle::lengthen(const SkOpAngle& opp) {
- if (fSegment->other(fEnd) == opp.fSegment) {
- return false;
+SkOpSpan* SkOpAngle::lastMarked() const {
+ if (fLastMarked) {
+ if (fLastMarked->fChased) {
+ return NULL;
+ }
+ fLastMarked->fChased = true;
}
- // FIXME: make this a while loop instead and make it as large as possible?
- int newEnd = fEnd;
- if (fStart < fEnd ? ++newEnd < fSegment->count() : --newEnd >= 0) {
- fEnd = newEnd;
- setSpans();
- return true;
+ return fLastMarked;
+}
+
+bool SkOpAngle::loopContains(const SkOpAngle& test) const {
+ if (!fNext) {
+ return false;
}
+ const SkOpAngle* first = this;
+ const SkOpAngle* loop = this;
+ const SkOpSegment* tSegment = test.fSegment;
+ double tStart = tSegment->span(test.fStart).fT;
+ double tEnd = tSegment->span(test.fEnd).fT;
+ do {
+ const SkOpSegment* lSegment = loop->fSegment;
+ // FIXME : use precisely_equal ? or compare points exactly ?
+ if (lSegment != tSegment) {
+ continue;
+ }
+ double lStart = lSegment->span(loop->fStart).fT;
+ if (lStart != tEnd) {
+ continue;
+ }
+ double lEnd = lSegment->span(loop->fEnd).fT;
+ if (lEnd == tStart) {
+ return true;
+ }
+ } while ((loop = loop->fNext) != first);
return false;
}
+int SkOpAngle::loopCount() const {
+ int count = 0;
+ const SkOpAngle* first = this;
+ const SkOpAngle* next = this;
+ do {
+ next = next->fNext;
+ ++count;
+ } while (next && next != first);
+ return count;
+}
+
+// OPTIMIZATION: can this be done better in after when angles are sorted?
+void SkOpAngle::markStops() {
+ SkOpAngle* angle = this;
+ int lastEnd = SkTMax(fSectorStart, fSectorEnd);
+ do {
+ angle = angle->fNext;
+ int angleStart = SkTMin(angle->fSectorStart, angle->fSectorEnd);
+ // angles that are smaller by one aren't necessary better, since the larger may be a line
+ // and the smaller may be a curve that curls to the other side of the line.
+ if (lastEnd + 1 < angleStart) {
+ angle->fStop = true;
+ }
+ lastEnd = SkTMax(angle->fSectorStart, angle->fSectorEnd);
+ } while (angle != this);
+}
+
+bool SkOpAngle::merge(SkOpAngle* angle) {
+ SkASSERT(fNext);
+ SkASSERT(angle->fNext);
+ SkOpAngle* working = angle;
+ do {
+ if (this == working) {
+ return false;
+ }
+ working = working->fNext;
+ } while (working != angle);
+ do {
+ SkOpAngle* next = working->fNext;
+ working->fNext = NULL;
+ insert(working);
+ working = next;
+ } while (working != angle);
+ // it's likely that a pair of the angles are unorderable
+#if DEBUG_ANGLE
+ SkOpAngle* last = angle;
+ working = angle->fNext;
+ do {
+ SkASSERT(last->fNext == working);
+ last->fNext = working->fNext;
+ SkASSERT(working->after(last));
+ last->fNext = working;
+ last = working;
+ working = working->fNext;
+ } while (last != angle);
+#endif
+ debugValidateNext();
+ return true;
+}
+
+double SkOpAngle::midT() const {
+ return (fSegment->t(fStart) + fSegment->t(fEnd)) / 2;
+}
+
+bool SkOpAngle::oppositePlanes(const SkOpAngle& rh) const {
+ int startSpan = abs(rh.fSectorStart - fSectorStart);
+ return startSpan >= 8;
+}
+
+bool SkOpAngle::orderable(const SkOpAngle& rh) const {
+ int result;
+ if (!fIsCurve) {
+ if (!rh.fIsCurve) {
+ double leftX = fTangentHalf.dx();
+ double leftY = fTangentHalf.dy();
+ double rightX = rh.fTangentHalf.dx();
+ double rightY = rh.fTangentHalf.dy();
+ double x_ry = leftX * rightY;
+ double rx_y = rightX * leftY;
+ if (x_ry == rx_y) {
+ if (leftX * rightX < 0 || leftY * rightY < 0) {
+ return true; // exactly 180 degrees apart
+ }
+ goto unorderable;
+ }
+ SkASSERT(x_ry != rx_y); // indicates an undetected coincidence -- worth finding earlier
+ return x_ry < rx_y;
+ }
+ if ((result = allOnOneSide(rh)) >= 0) {
+ return result;
+ }
+ if (fUnorderable || approximately_zero(rh.fSide)) {
+ goto unorderable;
+ }
+ } else if (!rh.fIsCurve) {
+ if ((result = rh.allOnOneSide(*this)) >= 0) {
+ return !result;
+ }
+ if (rh.fUnorderable || approximately_zero(fSide)) {
+ goto unorderable;
+ }
+ }
+ if ((result = convexHullOverlaps(rh)) >= 0) {
+ return result;
+ }
+ return endsIntersect(rh);
+unorderable:
+ fUnorderable = true;
+ rh.fUnorderable = true;
+ return true;
+}
+
+bool SkOpAngle::overlap(const SkOpAngle& other) const {
+ int min = SkTMin(fStart, fEnd);
+ const SkOpSpan& span = fSegment->span(min);
+ const SkOpSegment* oSeg = other.fSegment;
+ int oMin = SkTMin(other.fStart, other.fEnd);
+ const SkOpSpan& oSpan = oSeg->span(oMin);
+ if (!span.fSmall && !oSpan.fSmall) {
+ return false;
+ }
+ if (fSegment->span(fStart).fPt != oSeg->span(other.fStart).fPt) {
+ return false;
+ }
+ // see if small span is contained by opposite span
+ return span.fSmall ? oSeg->containsPt(fSegment->span(fEnd).fPt, other.fEnd, other.fStart)
+ : fSegment->containsPt(oSeg->span(other.fEnd).fPt, fEnd, fStart);
+}
+
+// OPTIMIZE: if this shows up in a profile, add a previous pointer
+// as is, this should be rarely called
+SkOpAngle* SkOpAngle::previous() const {
+ SkOpAngle* last = fNext;
+ do {
+ SkOpAngle* next = last->fNext;
+ if (next == this) {
+ return last;
+ }
+ last = next;
+ } while (true);
+}
+
void SkOpAngle::set(const SkOpSegment* segment, int start, int end) {
fSegment = segment;
fStart = start;
- fEnd = end;
+ fComputedEnd = fEnd = end;
+ fNext = NULL;
+ fComputeSector = fComputedSector = false;
+ fStop = false;
setSpans();
+ setSector();
+}
+
+void SkOpAngle::setCurveHullSweep() {
+ fUnorderedSweep = false;
+ fSweep[0] = fCurvePart[1] - fCurvePart[0];
+ if (SkPath::kLine_Verb == fSegment->verb()) {
+ fSweep[1] = fSweep[0];
+ return;
+ }
+ fSweep[1] = fCurvePart[2] - fCurvePart[0];
+ if (SkPath::kCubic_Verb != fSegment->verb()) {
+ if (!fSweep[0].fX && !fSweep[0].fY) {
+ fSweep[0] = fSweep[1];
+ }
+ return;
+ }
+ SkDVector thirdSweep = fCurvePart[3] - fCurvePart[0];
+ if (fSweep[0].fX == 0 && fSweep[0].fY == 0) {
+ fSweep[0] = fSweep[1];
+ fSweep[1] = thirdSweep;
+ if (fSweep[0].fX == 0 && fSweep[0].fY == 0) {
+ fSweep[0] = fSweep[1];
+ fCurvePart[1] = fCurvePart[3];
+ fIsCurve = false;
+ }
+ return;
+ }
+ double s1x3 = fSweep[0].crossCheck(thirdSweep);
+ double s3x2 = thirdSweep.crossCheck(fSweep[1]);
+ if (s1x3 * s3x2 >= 0) { // if third vector is on or between first two vectors
+ return;
+ }
+ double s2x1 = fSweep[1].crossCheck(fSweep[0]);
+ // FIXME: If the sweep of the cubic is greater than 180 degrees, we're in trouble
+ // probably such wide sweeps should be artificially subdivided earlier so that never happens
+ SkASSERT(s1x3 * s2x1 < 0 || s1x3 * s3x2 < 0);
+ if (s3x2 * s2x1 < 0) {
+ SkASSERT(s2x1 * s1x3 > 0);
+ fSweep[0] = fSweep[1];
+ fUnorderedSweep = true;
+ }
+ fSweep[1] = thirdSweep;
+}
+
+void SkOpAngle::setSector() {
+ SkPath::Verb verb = fSegment->verb();
+ if (SkPath::kLine_Verb != verb && small()) {
+ fSectorStart = fSectorEnd = -1;
+ fSectorMask = 0;
+ fComputeSector = true; // can't determine sector until segment length can be found
+ return;
+ }
+ fSectorStart = findSector(verb, fSweep[0].fX, fSweep[0].fY);
+ if (!fIsCurve) { // if it's a line or line-like, note that both sectors are the same
+ SkASSERT(fSectorStart >= 0);
+ fSectorEnd = fSectorStart;
+ fSectorMask = 1 << fSectorStart;
+ return;
+ }
+ SkASSERT(SkPath::kLine_Verb != verb);
+ fSectorEnd = findSector(verb, fSweep[1].fX, fSweep[1].fY);
+ if (fSectorEnd == fSectorStart) {
+ SkASSERT((fSectorStart & 3) != 3); // if the sector has no span, it can't be an exact angle
+ fSectorMask = 1 << fSectorStart;
+ return;
+ }
+ bool crossesZero = checkCrossesZero();
+ int start = SkTMin(fSectorStart, fSectorEnd);
+ bool curveBendsCCW = (fSectorStart == start) ^ crossesZero;
+ // bump the start and end of the sector span if they are on exact compass points
+ if ((fSectorStart & 3) == 3) {
+ fSectorStart = (fSectorStart + (curveBendsCCW ? 1 : 31)) & 0x1f;
+ }
+ if ((fSectorEnd & 3) == 3) {
+ fSectorEnd = (fSectorEnd + (curveBendsCCW ? 31 : 1)) & 0x1f;
+ }
+ crossesZero = checkCrossesZero();
+ start = SkTMin(fSectorStart, fSectorEnd);
+ int end = SkTMax(fSectorStart, fSectorEnd);
+ if (!crossesZero) {
+ fSectorMask = (unsigned) -1 >> (31 - end + start) << start;
+ } else {
+ fSectorMask = (unsigned) -1 >> (31 - start) | (-1 << end);
+ }
}
void SkOpAngle::setSpans() {
fUnorderable = fSegment->isTiny(this);
fLastMarked = NULL;
- fUnsortable = false;
const SkPoint* pts = fSegment->pts();
- if (fSegment->verb() != SkPath::kLine_Verb) {
- fComputed = fSegment->subDivide(fStart, fEnd, &fCurvePart);
- fSegment->subDivide(fStart, fStart < fEnd ? fSegment->count() - 1 : 0, &fCurveHalf);
- }
- // FIXME: slight errors in subdivision cause sort trouble later on. As an experiment, try
- // rounding the curve part to float precision here
- // fCurvePart.round(fSegment->verb());
- switch (fSegment->verb()) {
+ SkDEBUGCODE(fCurvePart[2].fX = fCurvePart[2].fY = fCurvePart[3].fX = fCurvePart[3].fY
+ = SK_ScalarNaN);
+ fSegment->subDivide(fStart, fEnd, &fCurvePart);
+ setCurveHullSweep();
+ const SkPath::Verb verb = fSegment->verb();
+ if (verb != SkPath::kLine_Verb
+ && !(fIsCurve = fSweep[0].crossCheck(fSweep[1]) != 0)) {
+ SkDLine lineHalf;
+ lineHalf[0].set(fCurvePart[0].asSkPoint());
+ lineHalf[1].set(fCurvePart[SkPathOpsVerbToPoints(verb)].asSkPoint());
+ fTangentHalf.lineEndPoints(lineHalf);
+ fSide = 0;
+ }
+ switch (verb) {
case SkPath::kLine_Verb: {
SkASSERT(fStart != fEnd);
- fCurvePart[0].set(pts[fStart > fEnd]);
- fCurvePart[1].set(pts[fStart < fEnd]);
- fComputed = false;
- // OPTIMIZATION: for pure line compares, we never need fTangentPart.c
- fTangentPart.lineEndPoints(*SkTCast<SkDLine*>(&fCurvePart));
+ const SkPoint& cP1 = pts[fStart < fEnd];
+ SkDLine lineHalf;
+ lineHalf[0].set(fSegment->span(fStart).fPt);
+ lineHalf[1].set(cP1);
+ fTangentHalf.lineEndPoints(lineHalf);
fSide = 0;
- fSide2 = 0;
- } break;
+ fIsCurve = false;
+ } return;
case SkPath::kQuad_Verb: {
- fSide2 = -fTangentHalf.quadPart(*SkTCast<SkDQuad*>(&fCurveHalf));
- SkDQuad& quad = *SkTCast<SkDQuad*>(&fCurvePart);
- fTangentPart.quadEndPoints(quad);
- fSide = -fTangentPart.pointDistance(fCurvePart[2]); // not normalized -- compare sign only
- if (fComputed && dx() > 0 && approximately_zero(dy())) {
- SkDCubic origCurve; // can't use segment's curve in place since it may be flipped
- int last = fSegment->count() - 1;
- fSegment->subDivide(fStart < fEnd ? 0 : last, fStart < fEnd ? last : 0, &origCurve);
- SkLineParameters origTan;
- origTan.quadEndPoints(*SkTCast<SkDQuad*>(&origCurve));
- if (origTan.dx() <= 0
- || (dy() != origTan.dy() && dy() * origTan.dy() <= 0)) { // signs match?
- fUnorderable = true;
- return;
- }
- }
+ SkLineParameters tangentPart;
+ SkDQuad& quad2 = *SkTCast<SkDQuad*>(&fCurvePart);
+ (void) tangentPart.quadEndPoints(quad2);
+ fSide = -tangentPart.pointDistance(fCurvePart[2]); // not normalized -- compare sign only
} break;
case SkPath::kCubic_Verb: {
- double startT = fSegment->t(fStart);
- fSide2 = -fTangentHalf.cubicPart(fCurveHalf);
- fTangentPart.cubicEndPoints(fCurvePart);
+ SkLineParameters tangentPart;
+ (void) tangentPart.cubicPart(fCurvePart);
+ fSide = -tangentPart.pointDistance(fCurvePart[3]);
double testTs[4];
// OPTIMIZATION: keep inflections precomputed with cubic segment?
int testCount = SkDCubic::FindInflections(pts, testTs);
+ double startT = fSegment->t(fStart);
double endT = fSegment->t(fEnd);
double limitT = endT;
int index;
for (index = 0; index < testCount; ++index) {
- if (!between(startT, testTs[index], limitT)) {
+ if (!::between(startT, testTs[index], limitT)) {
testTs[index] = -1;
}
}
@@ -354,82 +1041,86 @@ void SkOpAngle::setSpans() {
}
// OPTIMIZE: could avoid call for t == startT, endT
SkDPoint pt = dcubic_xy_at_t(pts, testT);
- double testSide = fTangentPart.pointDistance(pt);
+ SkLineParameters tangentPart;
+ tangentPart.cubicEndPoints(fCurvePart);
+ double testSide = tangentPart.pointDistance(pt);
if (fabs(bestSide) < fabs(testSide)) {
bestSide = testSide;
}
}
fSide = -bestSide; // compare sign only
- SkASSERT(fSide == 0 || fSide2 != 0);
- if (fComputed && dx() > 0 && approximately_zero(dy())) {
- SkDCubic origCurve; // can't use segment's curve in place since it may be flipped
- int last = fSegment->count() - 1;
- fSegment->subDivide(fStart < fEnd ? 0 : last, fStart < fEnd ? last : 0, &origCurve);
- SkDCubicPair split = origCurve.chopAt(startT);
- SkLineParameters splitTan;
- splitTan.cubicEndPoints(fStart < fEnd ? split.second() : split.first());
- if (splitTan.dx() <= 0) {
- fUnorderable = true;
- fUnsortable = fSegment->isTiny(this);
- return;
- }
- // if one is < 0 and the other is >= 0
- if (dy() * splitTan.dy() < 0) {
- fUnorderable = true;
- fUnsortable = fSegment->isTiny(this);
- return;
- }
- }
} break;
default:
SkASSERT(0);
}
- if ((fUnsortable = approximately_zero(dx()) && approximately_zero(dy()))) {
- return;
- }
- if (fSegment->verb() == SkPath::kLine_Verb) {
- return;
+}
+
+bool SkOpAngle::small() const {
+ int min = SkMin32(fStart, fEnd);
+ int max = SkMax32(fStart, fEnd);
+ for (int index = min; index < max; ++index) {
+ const SkOpSpan& mSpan = fSegment->span(index);
+ if (!mSpan.fSmall) {
+ return false;
+ }
}
- SkASSERT(fStart != fEnd);
- int smaller = SkMin32(fStart, fEnd);
- int larger = SkMax32(fStart, fEnd);
- while (smaller < larger && fSegment->span(smaller).fTiny) {
- ++smaller;
- }
- if (precisely_equal(fSegment->span(smaller).fT, fSegment->span(larger).fT)) {
- #if DEBUG_UNSORTABLE
- SkPoint iPt = fSegment->xyAtT(fStart);
- SkPoint ePt = fSegment->xyAtT(fEnd);
- SkDebugf("%s all tiny unsortable [%d] (%1.9g,%1.9g) [%d] (%1.9g,%1.9g)\n", __FUNCTION__,
- fStart, iPt.fX, iPt.fY, fEnd, ePt.fX, ePt.fY);
- #endif
- fUnsortable = true;
- return;
+ return true;
+}
+
+bool SkOpAngle::tangentsDiverge(const SkOpAngle& rh, double s0xt0) const {
+ if (s0xt0 == 0) {
+ return false;
}
- fUnsortable = fStart < fEnd ? fSegment->span(smaller).fUnsortableStart
- : fSegment->span(larger).fUnsortableEnd;
-#if DEBUG_UNSORTABLE
- if (fUnsortable) {
- SkPoint iPt = fSegment->xyAtT(smaller);
- SkPoint ePt = fSegment->xyAtT(larger);
- SkDebugf("%s unsortable [%d] (%1.9g,%1.9g) [%d] (%1.9g,%1.9g)\n", __FUNCTION__,
- smaller, iPt.fX, iPt.fY, fEnd, ePt.fX, ePt.fY);
+ // if the ctrl tangents are not nearly parallel, use them
+ // solve for opposite direction displacement scale factor == m
+ // initial dir = v1.cross(v2) == v2.x * v1.y - v2.y * v1.x
+ // displacement of q1[1] : dq1 = { -m * v1.y, m * v1.x } + q1[1]
+ // straight angle when : v2.x * (dq1.y - q1[0].y) == v2.y * (dq1.x - q1[0].x)
+ // v2.x * (m * v1.x + v1.y) == v2.y * (-m * v1.y + v1.x)
+ // - m * (v2.x * v1.x + v2.y * v1.y) == v2.x * v1.y - v2.y * v1.x
+ // m = (v2.y * v1.x - v2.x * v1.y) / (v2.x * v1.x + v2.y * v1.y)
+ // m = v1.cross(v2) / v1.dot(v2)
+ const SkDVector* sweep = fSweep;
+ const SkDVector* tweep = rh.fSweep;
+ double s0dt0 = sweep[0].dot(tweep[0]);
+ if (!s0dt0) {
+ return true;
}
+ SkASSERT(s0dt0 != 0);
+ double m = s0xt0 / s0dt0;
+ double sDist = sweep[0].length() * m;
+ double tDist = tweep[0].length() * m;
+ bool useS = fabs(sDist) < fabs(tDist);
+ double mFactor = fabs(useS ? distEndRatio(sDist) : rh.distEndRatio(tDist));
+ return mFactor < 5000; // empirically found limit
+}
+
+SkOpAngleSet::SkOpAngleSet()
+ : fAngles(NULL)
+#if DEBUG_ANGLE
+ , fCount(0)
#endif
- return;
-}
-
-#ifdef SK_DEBUG
-void SkOpAngle::dump() const {
- const SkOpSpan& spanStart = fSegment->span(fStart);
- const SkOpSpan& spanEnd = fSegment->span(fEnd);
- const SkOpSpan& spanMin = fStart < fEnd ? spanStart : spanEnd;
- SkDebugf("id=%d (%1.9g,%1.9g) start=%d (%1.9g) end=%d (%1.9g) sumWind=",
- fSegment->debugID(), fSegment->xAtT(fStart), fSegment->yAtT(fStart),
- fStart, spanStart.fT, fEnd, spanEnd.fT);
- SkPathOpsDebug::WindingPrintf(spanMin.fWindSum);
- SkDebugf(" oppWind=");
- SkPathOpsDebug::WindingPrintf(spanMin.fOppSum),
- SkDebugf(" done=%d\n", spanMin.fDone);
+{
+}
+
+SkOpAngleSet::~SkOpAngleSet() {
+ SkDELETE(fAngles);
}
+
+SkOpAngle& SkOpAngleSet::push_back() {
+ if (!fAngles) {
+ fAngles = SkNEW_ARGS(SkChunkAlloc, (2));
+ }
+ void* ptr = fAngles->allocThrow(sizeof(SkOpAngle));
+ SkOpAngle* angle = (SkOpAngle*) ptr;
+#if DEBUG_ANGLE
+ angle->setID(++fCount);
#endif
+ return *angle;
+}
+
+void SkOpAngleSet::reset() {
+ if (fAngles) {
+ fAngles->reset();
+ }
+}
diff --git a/chromium/third_party/skia/src/pathops/SkOpAngle.h b/chromium/third_party/skia/src/pathops/SkOpAngle.h
index 583f5ec8b39..63d378d73ce 100644
--- a/chromium/third_party/skia/src/pathops/SkOpAngle.h
+++ b/chromium/third_party/skia/src/pathops/SkOpAngle.h
@@ -7,9 +7,8 @@
#ifndef SkOpAngle_DEFINED
#define SkOpAngle_DEFINED
+#include "SkChunkAlloc.h"
#include "SkLineParameters.h"
-#include "SkPath.h"
-#include "SkPathOpsCubic.h"
class SkOpSegment;
struct SkOpSpan;
@@ -26,28 +25,31 @@ public:
kBinaryOpp,
};
- bool operator<(const SkOpAngle& rh) const;
- bool calcSlop(double x, double y, double rx, double ry, bool* result) const;
-
- double dx() const {
- return fTangentPart.dx();
+ int end() const {
+ return fEnd;
}
- double dy() const {
- return fTangentPart.dy();
- }
+ const SkOpAngle* findFirst() const;
- int end() const {
- return fEnd;
+ bool inLoop() const {
+ return !!fNext;
}
+ void insert(SkOpAngle* );
bool isHorizontal() const;
-
- SkOpSpan* lastMarked() const {
- return fLastMarked;
+ SkOpSpan* lastMarked() const;
+ bool loopContains(const SkOpAngle& ) const;
+ int loopCount() const;
+ void markStops();
+ bool merge(SkOpAngle* );
+
+ SkOpAngle* next() const {
+ return fNext;
}
+ SkOpAngle* previous() const;
+
void set(const SkOpSegment* segment, int start, int end);
void setLastMarked(SkOpSpan* marked) {
@@ -62,6 +64,8 @@ public:
return SkSign32(fStart - fEnd);
}
+ bool small() const;
+
int start() const {
return fStart;
}
@@ -70,43 +74,96 @@ public:
return fUnorderable;
}
- bool unsortable() const {
- return fUnsortable;
- }
-
-#ifdef SK_DEBUG
- void dump() const;
+ // available to testing only
+#if DEBUG_SORT
+ void debugLoop() const; // called by code during run
+#endif
+#if DEBUG_ANGLE
+ void debugSameAs(const SkOpAngle* compare) const;
#endif
+ void dump() const;
+ void dumpLoop() const;
+ void dumpTo(const SkOpSegment* fromSeg, const SkOpAngle* ) const;
#if DEBUG_ANGLE
+ int debugID() const { return fID; }
+
void setID(int id) {
fID = id;
}
+#else
+ int debugID() const { return 0; }
+#endif
+
+#if DEBUG_VALIDATE
+ void debugValidateLoop() const;
#endif
private:
- bool lengthen(const SkOpAngle& );
+ bool after(const SkOpAngle* test) const;
+ int allOnOneSide(const SkOpAngle& test) const;
+ bool calcSlop(double x, double y, double rx, double ry, bool* result) const;
+ bool checkCrossesZero() const;
+ bool checkParallel(const SkOpAngle& ) const;
+ bool computeSector();
+ int convexHullOverlaps(const SkOpAngle& ) const;
+ double distEndRatio(double dist) const;
+ int findSector(SkPath::Verb verb, double x, double y) const;
+ bool endsIntersect(const SkOpAngle& ) const;
+ double midT() const;
+ bool oppositePlanes(const SkOpAngle& rh) const;
+ bool orderable(const SkOpAngle& rh) const; // false == this < rh ; true == this > rh
+ bool overlap(const SkOpAngle& test) const;
+ void setCurveHullSweep();
+ void setSector();
void setSpans();
+ bool tangentsDiverge(const SkOpAngle& rh, double s0xt0) const;
SkDCubic fCurvePart; // the curve from start to end
- SkDCubic fCurveHalf; // the curve from start to 1 or 0
double fSide;
- double fSide2;
- SkLineParameters fTangentPart;
- SkLineParameters fTangentHalf;
+ SkLineParameters fTangentHalf; // used only to sort a pair of lines or line-like sections
const SkOpSegment* fSegment;
+ SkOpAngle* fNext;
SkOpSpan* fLastMarked;
+ SkDVector fSweep[2];
int fStart;
int fEnd;
- bool fComputed; // tangent is computed, may contain some error
- // if subdividing a quad or cubic causes the tangent to go from the maximum angle to the
- // minimum, mark it unorderable. It still can be sorted, which is good enough for find-top
- // but can't be ordered, and therefore can't be used to compute winding
- bool fUnorderable;
- mutable bool fUnsortable; // this alone is editable by the less than operator
+ int fComputedEnd;
+ int fSectorMask;
+ int8_t fSectorStart; // in 32nds of a circle
+ int8_t fSectorEnd;
+ bool fIsCurve;
+ bool fStop; // set if ordered angle is greater than the previous
+ mutable bool fUnorderable; // this is editable by orderable()
+ bool fUnorderedSweep; // set when a cubic's first control point between the sweep vectors
+ bool fComputeSector;
+ bool fComputedSector;
+
#if DEBUG_ANGLE
int fID;
#endif
+#if DEBUG_VALIDATE
+ void debugValidateNext() const; // in debug builds, verify that angle loop is uncorrupted
+#else
+ void debugValidateNext() const {}
+#endif
+ void dumpOne(bool showFunc) const; // available to testing only
+ void dumpPartials() const; // utility to be called by user from debugger
+ friend class PathOpsAngleTester;
+};
+
+class SkOpAngleSet {
+public:
+ SkOpAngleSet();
+ ~SkOpAngleSet();
+ SkOpAngle& push_back();
+ void reset();
+private:
+ void dump() const; // utility to be called by user from debugger
+#if DEBUG_ANGLE
+ int fCount;
+#endif
+ SkChunkAlloc* fAngles;
};
#endif
diff --git a/chromium/third_party/skia/src/pathops/SkOpContour.cpp b/chromium/third_party/skia/src/pathops/SkOpContour.cpp
index 874de381b19..5ef702d4c10 100644
--- a/chromium/third_party/skia/src/pathops/SkOpContour.cpp
+++ b/chromium/third_party/skia/src/pathops/SkOpContour.cpp
@@ -28,8 +28,14 @@ bool SkOpContour::addCoincident(int index, SkOpContour* other, int otherIndex,
coincidence.fTs[swap][1] = ts[0][1];
coincidence.fTs[!swap][0] = ts[1][0];
coincidence.fTs[!swap][1] = ts[1][1];
- coincidence.fPts[0] = pt0;
- coincidence.fPts[1] = pt1;
+ coincidence.fPts[swap][0] = pt0;
+ coincidence.fPts[swap][1] = pt1;
+ bool nearStart = ts.nearlySame(0);
+ bool nearEnd = ts.nearlySame(1);
+ coincidence.fPts[!swap][0] = nearStart ? ts.pt2(0).asSkPoint() : pt0;
+ coincidence.fPts[!swap][1] = nearEnd ? ts.pt2(1).asSkPoint() : pt1;
+ coincidence.fNearly[0] = nearStart;
+ coincidence.fNearly[1] = nearEnd;
return true;
}
@@ -93,28 +99,31 @@ void SkOpContour::addCoincidentPoints() {
cancelers ^= true;
}
SkASSERT(!approximately_negative(oEndT - oStartT));
+ const SkPoint& startPt = coincidence.fPts[0][startSwapped];
if (cancelers) {
// make sure startT and endT have t entries
- const SkPoint& startPt = coincidence.fPts[startSwapped];
if (startT > 0 || oEndT < 1
|| thisOne.isMissing(startT, startPt) || other.isMissing(oEndT, startPt)) {
- thisOne.addTPair(startT, &other, oEndT, true, startPt);
+ thisOne.addTPair(startT, &other, oEndT, true, startPt,
+ coincidence.fPts[1][startSwapped]);
}
- const SkPoint& oStartPt = coincidence.fPts[oStartSwapped];
+ const SkPoint& oStartPt = coincidence.fPts[1][oStartSwapped];
if (oStartT > 0 || endT < 1
|| thisOne.isMissing(endT, oStartPt) || other.isMissing(oStartT, oStartPt)) {
- other.addTPair(oStartT, &thisOne, endT, true, oStartPt);
+ other.addTPair(oStartT, &thisOne, endT, true, oStartPt,
+ coincidence.fPts[0][oStartSwapped]);
}
} else {
- const SkPoint& startPt = coincidence.fPts[startSwapped];
if (startT > 0 || oStartT > 0
|| thisOne.isMissing(startT, startPt) || other.isMissing(oStartT, startPt)) {
- thisOne.addTPair(startT, &other, oStartT, true, startPt);
+ thisOne.addTPair(startT, &other, oStartT, true, startPt,
+ coincidence.fPts[1][startSwapped]);
}
- const SkPoint& oEndPt = coincidence.fPts[!oStartSwapped];
+ const SkPoint& oEndPt = coincidence.fPts[1][!oStartSwapped];
if (endT < 1 || oEndT < 1
|| thisOne.isMissing(endT, oEndPt) || other.isMissing(oEndT, oEndPt)) {
- other.addTPair(oEndT, &thisOne, endT, true, oEndPt);
+ other.addTPair(oEndT, &thisOne, endT, true, oEndPt,
+ coincidence.fPts[0][!oStartSwapped]);
}
}
#if DEBUG_CONCIDENT
@@ -122,6 +131,32 @@ void SkOpContour::addCoincidentPoints() {
other.debugShowTs("o");
#endif
}
+ // if there are multiple pairs of coincidence that share an edge, see if the opposite
+ // are also coincident
+ for (int index = 0; index < count - 1; ++index) {
+ const SkCoincidence& coincidence = fCoincidences[index];
+ int thisIndex = coincidence.fSegments[0];
+ SkOpContour* otherContour = coincidence.fOther;
+ int otherIndex = coincidence.fSegments[1];
+ for (int idx2 = 1; idx2 < count; ++idx2) {
+ const SkCoincidence& innerCoin = fCoincidences[idx2];
+ int innerThisIndex = innerCoin.fSegments[0];
+ if (thisIndex == innerThisIndex) {
+ checkCoincidentPair(coincidence, 1, innerCoin, 1, false);
+ }
+ if (this == otherContour && otherIndex == innerThisIndex) {
+ checkCoincidentPair(coincidence, 0, innerCoin, 1, false);
+ }
+ SkOpContour* innerOtherContour = innerCoin.fOther;
+ innerThisIndex = innerCoin.fSegments[1];
+ if (this == innerOtherContour && thisIndex == innerThisIndex) {
+ checkCoincidentPair(coincidence, 1, innerCoin, 0, false);
+ }
+ if (otherContour == innerOtherContour && otherIndex == innerThisIndex) {
+ checkCoincidentPair(coincidence, 0, innerCoin, 0, false);
+ }
+ }
+ }
}
bool SkOpContour::addPartialCoincident(int index, SkOpContour* other, int otherIndex,
@@ -143,8 +178,84 @@ bool SkOpContour::addPartialCoincident(int index, SkOpContour* other, int otherI
coincidence.fTs[swap][1] = ts[0][ptIndex + 1];
coincidence.fTs[!swap][0] = ts[1][ptIndex];
coincidence.fTs[!swap][1] = ts[1][ptIndex + 1];
- coincidence.fPts[0] = pt0;
- coincidence.fPts[1] = pt1;
+ coincidence.fPts[0][0] = coincidence.fPts[1][0] = pt0;
+ coincidence.fPts[0][1] = coincidence.fPts[1][1] = pt1;
+ coincidence.fNearly[0] = 0;
+ coincidence.fNearly[1] = 0;
+ return true;
+}
+
+void SkOpContour::align(const SkOpSegment::AlignedSpan& aligned, bool swap,
+ SkCoincidence* coincidence) {
+ for (int idx2 = 0; idx2 < 2; ++idx2) {
+ if (coincidence->fPts[0][idx2] == aligned.fOldPt
+ && coincidence->fTs[swap][idx2] == aligned.fOldT) {
+ SkASSERT(SkDPoint::RoughlyEqual(coincidence->fPts[0][idx2], aligned.fPt));
+ coincidence->fPts[0][idx2] = aligned.fPt;
+ SkASSERT(way_roughly_equal(coincidence->fTs[swap][idx2], aligned.fT));
+ coincidence->fTs[swap][idx2] = aligned.fT;
+ }
+ }
+}
+
+void SkOpContour::alignCoincidence(const SkOpSegment::AlignedSpan& aligned,
+ SkTArray<SkCoincidence, true>* coincidences) {
+ int count = coincidences->count();
+ for (int index = 0; index < count; ++index) {
+ SkCoincidence& coincidence = (*coincidences)[index];
+ int thisIndex = coincidence.fSegments[0];
+ const SkOpSegment* thisOne = &fSegments[thisIndex];
+ const SkOpContour* otherContour = coincidence.fOther;
+ int otherIndex = coincidence.fSegments[1];
+ const SkOpSegment* other = &otherContour->fSegments[otherIndex];
+ if (thisOne == aligned.fOther1 && other == aligned.fOther2) {
+ align(aligned, false, &coincidence);
+ } else if (thisOne == aligned.fOther2 && other == aligned.fOther1) {
+ align(aligned, true, &coincidence);
+ }
+ }
+}
+
+void SkOpContour::alignTPt(int segmentIndex, const SkOpContour* other, int otherIndex,
+ bool swap, int tIndex, SkIntersections* ts, SkPoint* point) const {
+ int zeroPt;
+ if ((zeroPt = alignT(swap, tIndex, ts)) >= 0) {
+ alignPt(segmentIndex, point, zeroPt);
+ }
+ if ((zeroPt = other->alignT(!swap, tIndex, ts)) >= 0) {
+ other->alignPt(otherIndex, point, zeroPt);
+ }
+}
+
+void SkOpContour::alignPt(int index, SkPoint* point, int zeroPt) const {
+ const SkOpSegment& segment = fSegments[index];
+ if (0 == zeroPt) {
+ *point = segment.pts()[0];
+ } else {
+ *point = segment.pts()[SkPathOpsVerbToPoints(segment.verb())];
+ }
+}
+
+int SkOpContour::alignT(bool swap, int tIndex, SkIntersections* ts) const {
+ double tVal = (*ts)[swap][tIndex];
+ if (tVal != 0 && precisely_zero(tVal)) {
+ ts->set(swap, tIndex, 0);
+ return 0;
+ }
+ if (tVal != 1 && precisely_equal(tVal, 1)) {
+ ts->set(swap, tIndex, 1);
+ return 1;
+ }
+ return -1;
+}
+
+bool SkOpContour::calcAngles() {
+ int segmentCount = fSegments.count();
+ for (int test = 0; test < segmentCount; ++test) {
+ if (!fSegments[test].calcAngles()) {
+ return false;
+ }
+ }
return true;
}
@@ -170,7 +281,187 @@ void SkOpContour::calcPartialCoincidentWinding() {
#endif
for (int index = 0; index < count; ++index) {
SkCoincidence& coincidence = fPartialCoincidences[index];
- calcCommonCoincidentWinding(coincidence);
+ calcCommonCoincidentWinding(coincidence);
+ }
+ // if there are multiple pairs of partial coincidence that share an edge, see if the opposite
+ // are also coincident
+ for (int index = 0; index < count - 1; ++index) {
+ const SkCoincidence& coincidence = fPartialCoincidences[index];
+ int thisIndex = coincidence.fSegments[0];
+ SkOpContour* otherContour = coincidence.fOther;
+ int otherIndex = coincidence.fSegments[1];
+ for (int idx2 = 1; idx2 < count; ++idx2) {
+ const SkCoincidence& innerCoin = fPartialCoincidences[idx2];
+ int innerThisIndex = innerCoin.fSegments[0];
+ if (thisIndex == innerThisIndex) {
+ checkCoincidentPair(coincidence, 1, innerCoin, 1, true);
+ }
+ if (this == otherContour && otherIndex == innerThisIndex) {
+ checkCoincidentPair(coincidence, 0, innerCoin, 1, true);
+ }
+ SkOpContour* innerOtherContour = innerCoin.fOther;
+ innerThisIndex = innerCoin.fSegments[1];
+ if (this == innerOtherContour && thisIndex == innerThisIndex) {
+ checkCoincidentPair(coincidence, 1, innerCoin, 0, true);
+ }
+ if (otherContour == innerOtherContour && otherIndex == innerThisIndex) {
+ checkCoincidentPair(coincidence, 0, innerCoin, 0, true);
+ }
+ }
+ }
+}
+
+void SkOpContour::checkCoincidentPair(const SkCoincidence& oneCoin, int oneIdx,
+ const SkCoincidence& twoCoin, int twoIdx, bool partial) {
+ SkASSERT((oneIdx ? this : oneCoin.fOther) == (twoIdx ? this : twoCoin.fOther));
+ SkASSERT(oneCoin.fSegments[!oneIdx] == twoCoin.fSegments[!twoIdx]);
+ // look for common overlap
+ double min = SK_ScalarMax;
+ double max = SK_ScalarMin;
+ double min1 = oneCoin.fTs[!oneIdx][0];
+ double max1 = oneCoin.fTs[!oneIdx][1];
+ double min2 = twoCoin.fTs[!twoIdx][0];
+ double max2 = twoCoin.fTs[!twoIdx][1];
+ bool cancelers = (min1 < max1) != (min2 < max2);
+ if (min1 > max1) {
+ SkTSwap(min1, max1);
+ }
+ if (min2 > max2) {
+ SkTSwap(min2, max2);
+ }
+ if (between(min1, min2, max1)) {
+ min = min2;
+ }
+ if (between(min1, max2, max1)) {
+ max = max2;
+ }
+ if (between(min2, min1, max2)) {
+ min = SkTMin(min, min1);
+ }
+ if (between(min2, max1, max2)) {
+ max = SkTMax(max, max1);
+ }
+ if (min >= max) {
+ return; // no overlap
+ }
+ // look to see if opposite are different segments
+ int seg1Index = oneCoin.fSegments[oneIdx];
+ int seg2Index = twoCoin.fSegments[twoIdx];
+ if (seg1Index == seg2Index) {
+ return;
+ }
+ SkOpContour* contour1 = oneIdx ? oneCoin.fOther : this;
+ SkOpContour* contour2 = twoIdx ? twoCoin.fOther : this;
+ SkOpSegment* segment1 = &contour1->fSegments[seg1Index];
+ SkOpSegment* segment2 = &contour2->fSegments[seg2Index];
+ // find opposite t value ranges corresponding to reference min/max range
+ const SkOpContour* refContour = oneIdx ? this : oneCoin.fOther;
+ const int refSegIndex = oneCoin.fSegments[!oneIdx];
+ const SkOpSegment* refSegment = &refContour->fSegments[refSegIndex];
+ int seg1Start = segment1->findOtherT(min, refSegment);
+ int seg1End = segment1->findOtherT(max, refSegment);
+ int seg2Start = segment2->findOtherT(min, refSegment);
+ int seg2End = segment2->findOtherT(max, refSegment);
+ // if the opposite pairs already contain min/max, we're done
+ if (seg1Start >= 0 && seg1End >= 0 && seg2Start >= 0 && seg2End >= 0) {
+ return;
+ }
+ double loEnd = SkTMin(min1, min2);
+ double hiEnd = SkTMax(max1, max2);
+ // insert the missing coincident point(s)
+ double missingT1 = -1;
+ double otherT1 = -1;
+ if (seg1Start < 0) {
+ if (seg2Start < 0) {
+ return;
+ }
+ missingT1 = segment1->calcMissingTStart(refSegment, loEnd, min, max, hiEnd,
+ segment2, seg1End);
+ if (missingT1 < 0) {
+ return;
+ }
+ const SkOpSpan* missingSpan = &segment2->span(seg2Start);
+ otherT1 = missingSpan->fT;
+ } else if (seg2Start < 0) {
+ SkASSERT(seg1Start >= 0);
+ missingT1 = segment2->calcMissingTStart(refSegment, loEnd, min, max, hiEnd,
+ segment1, seg2End);
+ if (missingT1 < 0) {
+ return;
+ }
+ const SkOpSpan* missingSpan = &segment1->span(seg1Start);
+ otherT1 = missingSpan->fT;
+ }
+ SkPoint missingPt1;
+ SkOpSegment* addTo1 = NULL;
+ SkOpSegment* addOther1 = seg1Start < 0 ? segment2 : segment1;
+ int minTIndex = refSegment->findExactT(min, addOther1);
+ SkASSERT(minTIndex >= 0);
+ if (missingT1 >= 0) {
+ missingPt1 = refSegment->span(minTIndex).fPt;
+ addTo1 = seg1Start < 0 ? segment1 : segment2;
+ }
+ double missingT2 = -1;
+ double otherT2 = -1;
+ if (seg1End < 0) {
+ if (seg2End < 0) {
+ return;
+ }
+ missingT2 = segment1->calcMissingTEnd(refSegment, loEnd, min, max, hiEnd,
+ segment2, seg1Start);
+ if (missingT2 < 0) {
+ return;
+ }
+ const SkOpSpan* missingSpan = &segment2->span(seg2End);
+ otherT2 = missingSpan->fT;
+ } else if (seg2End < 0) {
+ SkASSERT(seg1End >= 0);
+ missingT2 = segment2->calcMissingTEnd(refSegment, loEnd, min, max, hiEnd,
+ segment1, seg2Start);
+ if (missingT2 < 0) {
+ return;
+ }
+ const SkOpSpan* missingSpan = &segment1->span(seg1End);
+ otherT2 = missingSpan->fT;
+ }
+ SkPoint missingPt2;
+ SkOpSegment* addTo2 = NULL;
+ SkOpSegment* addOther2 = seg1End < 0 ? segment2 : segment1;
+ int maxTIndex = refSegment->findExactT(max, addOther2);
+ SkASSERT(maxTIndex >= 0);
+ if (missingT2 >= 0) {
+ missingPt2 = refSegment->span(maxTIndex).fPt;
+ addTo2 = seg1End < 0 ? segment1 : segment2;
+ }
+ if (missingT1 >= 0) {
+ addTo1->pinT(missingPt1, &missingT1);
+ addTo1->addTPair(missingT1, addOther1, otherT1, false, missingPt1);
+ } else {
+ SkASSERT(minTIndex >= 0);
+ missingPt1 = refSegment->span(minTIndex).fPt;
+ }
+ if (missingT2 >= 0) {
+ addTo2->pinT(missingPt2, &missingT2);
+ addTo2->addTPair(missingT2, addOther2, otherT2, false, missingPt2);
+ } else {
+ SkASSERT(minTIndex >= 0);
+ missingPt2 = refSegment->span(maxTIndex).fPt;
+ }
+ if (!partial) {
+ return;
+ }
+ if (cancelers) {
+ if (missingT1 >= 0) {
+ addTo1->addTCancel(missingPt1, missingPt2, addOther1);
+ } else {
+ addTo2->addTCancel(missingPt1, missingPt2, addOther2);
+ }
+ } else if (missingT1 >= 0) {
+ addTo1->addTCoincident(missingPt1, missingPt2, addTo1 == addTo2 ? missingT2 : otherT2,
+ addOther1);
+ } else {
+ addTo2->addTCoincident(missingPt2, missingPt1, addTo2 == addTo1 ? missingT1 : otherT1,
+ addOther2);
}
}
@@ -186,9 +477,15 @@ void SkOpContour::joinCoincidence(const SkTArray<SkCoincidence, true>& coinciden
const SkCoincidence& coincidence = coincidences[index];
int thisIndex = coincidence.fSegments[0];
SkOpSegment& thisOne = fSegments[thisIndex];
+ if (thisOne.done()) {
+ continue;
+ }
SkOpContour* otherContour = coincidence.fOther;
int otherIndex = coincidence.fSegments[1];
SkOpSegment& other = otherContour->fSegments[otherIndex];
+ if (other.done()) {
+ continue;
+ }
double startT = coincidence.fTs[0][0];
double endT = coincidence.fTs[0][1];
if (startT == endT) { // this can happen in very large compares
@@ -201,9 +498,12 @@ void SkOpContour::joinCoincidence(const SkTArray<SkCoincidence, true>& coinciden
}
bool swapStart = startT > endT;
bool swapOther = oStartT > oEndT;
+ const SkPoint* startPt = &coincidence.fPts[0][0];
+ const SkPoint* endPt = &coincidence.fPts[0][1];
if (swapStart) {
- SkTSwap<double>(startT, endT);
- SkTSwap<double>(oStartT, oEndT);
+ SkTSwap(startT, endT);
+ SkTSwap(oStartT, oEndT);
+ SkTSwap(startPt, endPt);
}
bool cancel = swapOther != swapStart;
int step = swapStart ? -1 : 1;
@@ -212,23 +512,27 @@ void SkOpContour::joinCoincidence(const SkTArray<SkCoincidence, true>& coinciden
if (partial ? startT != 0 || oMatchStart != 0 : (startT == 0) != (oMatchStart == 0)) {
bool added = false;
if (oMatchStart != 0) {
- added = thisOne.joinCoincidence(&other, oMatchStart, oStep, cancel);
+ const SkPoint& oMatchStartPt = cancel ? *endPt : *startPt;
+ added = thisOne.joinCoincidence(&other, oMatchStart, oMatchStartPt, oStep, cancel);
}
if (!cancel && startT != 0 && !added) {
- (void) other.joinCoincidence(&thisOne, startT, step, cancel);
+ (void) other.joinCoincidence(&thisOne, startT, *startPt, step, cancel);
}
}
double oMatchEnd = cancel ? oStartT : oEndT;
if (partial ? endT != 1 || oMatchEnd != 1 : (endT == 1) != (oMatchEnd == 1)) {
bool added = false;
if (cancel && endT != 1 && !added) {
- (void) other.joinCoincidence(&thisOne, endT, -step, cancel);
+ (void) other.joinCoincidence(&thisOne, endT, *endPt, -step, cancel);
}
}
}
}
void SkOpContour::calcCommonCoincidentWinding(const SkCoincidence& coincidence) {
+ if (coincidence.fNearly[0] && coincidence.fNearly[1]) {
+ return;
+ }
int thisIndex = coincidence.fSegments[0];
SkOpSegment& thisOne = fSegments[thisIndex];
if (thisOne.done()) {
@@ -242,8 +546,8 @@ void SkOpContour::calcCommonCoincidentWinding(const SkCoincidence& coincidence)
}
double startT = coincidence.fTs[0][0];
double endT = coincidence.fTs[0][1];
- const SkPoint* startPt = &coincidence.fPts[0];
- const SkPoint* endPt = &coincidence.fPts[1];
+ const SkPoint* startPt = &coincidence.fPts[0][0];
+ const SkPoint* endPt = &coincidence.fPts[0][1];
bool cancelers;
if ((cancelers = startT > endT)) {
SkTSwap<double>(startT, endT);
@@ -277,6 +581,64 @@ void SkOpContour::calcCommonCoincidentWinding(const SkCoincidence& coincidence)
#endif
}
+void SkOpContour::resolveNearCoincidence() {
+ int count = fCoincidences.count();
+ for (int index = 0; index < count; ++index) {
+ SkCoincidence& coincidence = fCoincidences[index];
+ if (!coincidence.fNearly[0] || !coincidence.fNearly[1]) {
+ continue;
+ }
+ int thisIndex = coincidence.fSegments[0];
+ SkOpSegment& thisOne = fSegments[thisIndex];
+ SkOpContour* otherContour = coincidence.fOther;
+ int otherIndex = coincidence.fSegments[1];
+ SkOpSegment& other = otherContour->fSegments[otherIndex];
+ if ((thisOne.done() || other.done()) && thisOne.complete() && other.complete()) {
+ // OPTIMIZATION: remove from coincidence array
+ continue;
+ }
+ #if DEBUG_CONCIDENT
+ thisOne.debugShowTs("-");
+ other.debugShowTs("o");
+ #endif
+ double startT = coincidence.fTs[0][0];
+ double endT = coincidence.fTs[0][1];
+ bool cancelers;
+ if ((cancelers = startT > endT)) {
+ SkTSwap<double>(startT, endT);
+ }
+ if (startT == endT) { // if span is very large, the smaller may have collapsed to nothing
+ if (endT <= 1 - FLT_EPSILON) {
+ endT += FLT_EPSILON;
+ SkASSERT(endT <= 1);
+ } else {
+ startT -= FLT_EPSILON;
+ SkASSERT(startT >= 0);
+ }
+ }
+ SkASSERT(!approximately_negative(endT - startT));
+ double oStartT = coincidence.fTs[1][0];
+ double oEndT = coincidence.fTs[1][1];
+ if (oStartT > oEndT) {
+ SkTSwap<double>(oStartT, oEndT);
+ cancelers ^= true;
+ }
+ SkASSERT(!approximately_negative(oEndT - oStartT));
+ if (cancelers) {
+ thisOne.blindCancel(coincidence, &other);
+ } else {
+ thisOne.blindCoincident(coincidence, &other);
+ }
+ }
+}
+
+void SkOpContour::sortAngles() {
+ int segmentCount = fSegments.count();
+ for (int test = 0; test < segmentCount; ++test) {
+ fSegments[test].sortAngles();
+ }
+}
+
void SkOpContour::sortSegments() {
int segmentCount = fSegments.count();
fSortedSegments.push_back_n(segmentCount);
@@ -312,7 +674,7 @@ void SkOpContour::topSortableSegment(const SkPoint& topLeft, SkPoint* bestXY,
continue;
}
fDone = false;
- SkPoint testXY = testSegment->activeLeftTop(true, NULL);
+ SkPoint testXY = testSegment->activeLeftTop(NULL);
if (*topStart) {
if (testXY.fY < topLeft.fY) {
continue;
diff --git a/chromium/third_party/skia/src/pathops/SkOpContour.h b/chromium/third_party/skia/src/pathops/SkOpContour.h
index 8cedab4cb1e..d1b3cd0179d 100644
--- a/chromium/third_party/skia/src/pathops/SkOpContour.h
+++ b/chromium/third_party/skia/src/pathops/SkOpContour.h
@@ -10,6 +10,10 @@
#include "SkOpSegment.h"
#include "SkTArray.h"
+#if defined(SK_DEBUG) || !FORCE_RELEASE
+#include "SkThread.h"
+#endif
+
class SkIntersections;
class SkOpContour;
class SkPathWriter;
@@ -18,15 +22,16 @@ struct SkCoincidence {
SkOpContour* fOther;
int fSegments[2];
double fTs[2][2];
- SkPoint fPts[2];
+ SkPoint fPts[2][2];
+ int fNearly[2];
};
class SkOpContour {
public:
SkOpContour() {
reset();
-#ifdef SK_DEBUG
- fID = ++SkPathOpsDebug::gContourID;
+#if defined(SK_DEBUG) || !FORCE_RELEASE
+ fID = sk_atomic_inc(&SkPathOpsDebug::gContourID);
#endif
}
@@ -77,18 +82,51 @@ public:
return fSegments[segIndex].addT(&other->fSegments[otherIndex], pt, newT);
}
- int addSelfT(int segIndex, SkOpContour* other, int otherIndex, const SkPoint& pt, double newT) {
+ int addSelfT(int segIndex, const SkPoint& pt, double newT) {
setContainsIntercepts();
- return fSegments[segIndex].addSelfT(&other->fSegments[otherIndex], pt, newT);
+ return fSegments[segIndex].addSelfT(pt, newT);
+ }
+
+ void align(const SkOpSegment::AlignedSpan& aligned, bool swap, SkCoincidence* coincidence);
+ void alignCoincidence(const SkOpSegment::AlignedSpan& aligned,
+ SkTArray<SkCoincidence, true>* coincidences);
+
+ void alignCoincidence(const SkOpSegment::AlignedSpan& aligned) {
+ alignCoincidence(aligned, &fCoincidences);
+ alignCoincidence(aligned, &fPartialCoincidences);
+ }
+
+ void alignMultiples(SkTDArray<SkOpSegment::AlignedSpan>* aligned) {
+ int segmentCount = fSegments.count();
+ for (int sIndex = 0; sIndex < segmentCount; ++sIndex) {
+ SkOpSegment& segment = fSegments[sIndex];
+ if (segment.hasMultiples()) {
+ segment.alignMultiples(aligned);
+ }
+ }
}
+ void alignTPt(int segmentIndex, const SkOpContour* other, int otherIndex,
+ bool swap, int tIndex, SkIntersections* ts, SkPoint* point) const;
+
const SkPathOpsBounds& bounds() const {
return fBounds;
}
+ bool calcAngles();
void calcCoincidentWinding();
void calcPartialCoincidentWinding();
+ void checkDuplicates() {
+ int segmentCount = fSegments.count();
+ for (int sIndex = 0; sIndex < segmentCount; ++sIndex) {
+ SkOpSegment& segment = fSegments[sIndex];
+ if (segment.count() > 2) {
+ segment.checkDuplicates();
+ }
+ }
+ }
+
void checkEnds() {
if (!fContainsCurves) {
return;
@@ -106,6 +144,28 @@ public:
}
}
+ void checkMultiples() {
+ int segmentCount = fSegments.count();
+ for (int sIndex = 0; sIndex < segmentCount; ++sIndex) {
+ SkOpSegment& segment = fSegments[sIndex];
+ if (segment.count() > 2) {
+ segment.checkMultiples();
+ fMultiples |= segment.hasMultiples();
+ }
+ }
+ }
+
+ void checkSmall() {
+ int segmentCount = fSegments.count();
+ for (int sIndex = 0; sIndex < segmentCount; ++sIndex) {
+ SkOpSegment& segment = fSegments[sIndex];
+ // OPTIMIZATION : skip segments that are done?
+ if (segment.hasSmall()) {
+ segment.checkSmall();
+ }
+ }
+ }
+
// if same point has different T values, choose a common T
void checkTiny() {
int segmentCount = fSegments.count();
@@ -113,7 +173,10 @@ public:
return;
}
for (int sIndex = 0; sIndex < segmentCount; ++sIndex) {
- fSegments[sIndex].checkTiny();
+ SkOpSegment& segment = fSegments[sIndex];
+ if (segment.hasTiny()) {
+ segment.checkTiny();
+ }
}
}
@@ -151,6 +214,10 @@ public:
}
}
+ bool hasMultiples() const {
+ return fMultiples;
+ }
+
void joinCoincidence() {
joinCoincidence(fCoincidences, false);
joinCoincidence(fPartialCoincidences, true);
@@ -165,9 +232,11 @@ public:
void reset() {
fSegments.reset();
fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax);
- fContainsCurves = fContainsCubics = fContainsIntercepts = fDone = false;
+ fContainsCurves = fContainsCubics = fContainsIntercepts = fDone = fMultiples = false;
}
+ void resolveNearCoincidence();
+
SkTArray<SkOpSegment>& segments() {
return fSegments;
}
@@ -192,6 +261,7 @@ public:
fXor = isXor;
}
+ void sortAngles();
void sortSegments();
const SkPoint& start() const {
@@ -242,8 +312,22 @@ public:
static void debugShowWindingValues(const SkTArray<SkOpContour*, true>& contourList);
#endif
+ // available to test routines only
+ void dump() const;
+ void dumpAngles() const;
+ void dumpCoincidence(const SkCoincidence& ) const;
+ void dumpCoincidences() const;
+ void dumpPt(int ) const;
+ void dumpPts() const;
+ void dumpSpan(int ) const;
+ void dumpSpans() const;
+
private:
+ void alignPt(int index, SkPoint* point, int zeroPt) const;
+ int alignT(bool swap, int tIndex, SkIntersections* ts) const;
void calcCommonCoincidentWinding(const SkCoincidence& );
+ void checkCoincidentPair(const SkCoincidence& oneCoin, int oneIdx,
+ const SkCoincidence& twoCoin, int twoIdx, bool partial);
void joinCoincidence(const SkTArray<SkCoincidence, true>& , bool partial);
void setBounds();
@@ -258,11 +342,15 @@ private:
bool fContainsCubics;
bool fContainsCurves;
bool fDone;
+ bool fMultiples; // set if some segment has multiple identical intersections with other curves
bool fOperand; // true for the second argument to a binary operator
bool fXor;
bool fOppXor;
-#ifdef SK_DEBUG
+#if defined(SK_DEBUG) || !FORCE_RELEASE
+ int debugID() const { return fID; }
int fID;
+#else
+ int debugID() const { return -1; }
#endif
};
diff --git a/chromium/third_party/skia/src/pathops/SkOpEdgeBuilder.cpp b/chromium/third_party/skia/src/pathops/SkOpEdgeBuilder.cpp
index ae72e293850..31a446b32b3 100644
--- a/chromium/third_party/skia/src/pathops/SkOpEdgeBuilder.cpp
+++ b/chromium/third_party/skia/src/pathops/SkOpEdgeBuilder.cpp
@@ -13,10 +13,6 @@ void SkOpEdgeBuilder::init() {
fOperand = false;
fXorMask[0] = fXorMask[1] = (fPath->getFillType() & 1) ? kEvenOdd_PathOpsMask
: kWinding_PathOpsMask;
-#ifdef SK_DEBUG
- SkPathOpsDebug::gContourID = 0;
- SkPathOpsDebug::gSegmentID = 0;
-#endif
fUnparseable = false;
fSecondHalf = preFetch();
}
diff --git a/chromium/third_party/skia/src/pathops/SkOpSegment.cpp b/chromium/third_party/skia/src/pathops/SkOpSegment.cpp
index 00963403b7b..4e8b5d28d9d 100644
--- a/chromium/third_party/skia/src/pathops/SkOpSegment.cpp
+++ b/chromium/third_party/skia/src/pathops/SkOpSegment.cpp
@@ -5,6 +5,7 @@
* found in the LICENSE file.
*/
#include "SkIntersections.h"
+#include "SkOpContour.h"
#include "SkOpSegment.h"
#include "SkPathWriter.h"
#include "SkTSort.h"
@@ -20,8 +21,8 @@ static const bool gUnaryActiveEdge[2][2] = {
static const bool gActiveEdge[kXOR_PathOp + 1][2][2][2][2] = {
// miFrom=0 miFrom=1
-// miTo=0 miTo=1 miTo=0 miTo=1
-// suFrom=0 1 suFrom=0 1 suFrom=0 1 suFrom=0 1
+// miTo=0 miTo=1 miTo=0 miTo=1
+// suFrom=0 1 suFrom=0 1 suFrom=0 1 suFrom=0 1
// suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1
{{{{F, F}, {F, F}}, {{T, F}, {T, F}}}, {{{T, T}, {F, F}}, {{F, T}, {T, F}}}}, // mi - su
{{{{F, F}, {F, F}}, {{F, T}, {F, T}}}, {{{F, F}, {T, T}}, {{F, T}, {T, F}}}}, // mi & su
@@ -37,22 +38,22 @@ enum {
kMissingSpanCount = 4, // FIXME: determine what this should be
};
-// note that this follows the same logic flow as build angles
-bool SkOpSegment::activeAngle(int index, int* done, SkTArray<SkOpAngle, true>* angles) {
- if (activeAngleInner(index, done, angles)) {
- return true;
+const SkOpAngle* SkOpSegment::activeAngle(int index, int* start, int* end, bool* done,
+ bool* sortable) const {
+ if (const SkOpAngle* result = activeAngleInner(index, start, end, done, sortable)) {
+ return result;
}
double referenceT = fTs[index].fT;
int lesser = index;
while (--lesser >= 0
&& (precisely_negative(referenceT - fTs[lesser].fT) || fTs[lesser].fTiny)) {
- if (activeAngleOther(lesser, done, angles)) {
- return true;
+ if (const SkOpAngle* result = activeAngleOther(lesser, start, end, done, sortable)) {
+ return result;
}
}
do {
- if (activeAngleOther(index, done, angles)) {
- return true;
+ if (const SkOpAngle* result = activeAngleOther(index, start, end, done, sortable)) {
+ return result;
}
if (++index == fTs.count()) {
break;
@@ -62,64 +63,68 @@ bool SkOpSegment::activeAngle(int index, int* done, SkTArray<SkOpAngle, true>* a
continue;
}
} while (precisely_negative(fTs[index].fT - referenceT));
- return false;
-}
-
-bool SkOpSegment::activeAngleOther(int index, int* done, SkTArray<SkOpAngle, true>* angles) {
- SkOpSpan* span = &fTs[index];
- SkOpSegment* other = span->fOther;
- int oIndex = span->fOtherIndex;
- return other->activeAngleInner(oIndex, done, angles);
+ return NULL;
}
-bool SkOpSegment::activeAngleInner(int index, int* done, SkTArray<SkOpAngle, true>* angles) {
+const SkOpAngle* SkOpSegment::activeAngleInner(int index, int* start, int* end, bool* done,
+ bool* sortable) const {
int next = nextExactSpan(index, 1);
if (next > 0) {
- SkOpSpan& upSpan = fTs[index];
+ const SkOpSpan& upSpan = fTs[index];
if (upSpan.fWindValue || upSpan.fOppValue) {
- addAngle(angles, index, next);
- if (upSpan.fDone || upSpan.fUnsortableEnd) {
- (*done)++;
- } else if (upSpan.fWindSum != SK_MinS32) {
- return true;
+ if (*end < 0) {
+ *start = index;
+ *end = next;
+ }
+ if (!upSpan.fDone) {
+ if (upSpan.fWindSum != SK_MinS32) {
+ return spanToAngle(index, next);
+ }
+ *done = false;
}
- } else if (!upSpan.fDone) {
- upSpan.fDone = true;
- fDoneSpans++;
+ } else {
+ SkASSERT(upSpan.fDone);
}
}
int prev = nextExactSpan(index, -1);
// edge leading into junction
if (prev >= 0) {
- SkOpSpan& downSpan = fTs[prev];
+ const SkOpSpan& downSpan = fTs[prev];
if (downSpan.fWindValue || downSpan.fOppValue) {
- addAngle(angles, index, prev);
- if (downSpan.fDone) {
- (*done)++;
- } else if (downSpan.fWindSum != SK_MinS32) {
- return true;
+ if (*end < 0) {
+ *start = index;
+ *end = prev;
+ }
+ if (!downSpan.fDone) {
+ if (downSpan.fWindSum != SK_MinS32) {
+ return spanToAngle(index, prev);
+ }
+ *done = false;
}
- } else if (!downSpan.fDone) {
- downSpan.fDone = true;
- fDoneSpans++;
+ } else {
+ SkASSERT(downSpan.fDone);
}
}
- return false;
+ return NULL;
+}
+
+const SkOpAngle* SkOpSegment::activeAngleOther(int index, int* start, int* end, bool* done,
+ bool* sortable) const {
+ const SkOpSpan* span = &fTs[index];
+ SkOpSegment* other = span->fOther;
+ int oIndex = span->fOtherIndex;
+ return other->activeAngleInner(oIndex, start, end, done, sortable);
}
-SkPoint SkOpSegment::activeLeftTop(bool onlySortable, int* firstT) const {
+SkPoint SkOpSegment::activeLeftTop(int* firstT) const {
SkASSERT(!done());
SkPoint topPt = {SK_ScalarMax, SK_ScalarMax};
int count = fTs.count();
// see if either end is not done since we want smaller Y of the pair
bool lastDone = true;
- bool lastUnsortable = false;
double lastT = -1;
for (int index = 0; index < count; ++index) {
const SkOpSpan& span = fTs[index];
- if (onlySortable && (span.fUnsortableStart || lastUnsortable)) {
- goto next;
- }
if (span.fDone && lastDone) {
goto next;
}
@@ -148,7 +153,6 @@ SkPoint SkOpSegment::activeLeftTop(bool onlySortable, int* firstT) const {
}
next:
lastDone = span.fDone;
- lastUnsortable = span.fUnsortableEnd;
}
return topPt;
}
@@ -159,34 +163,33 @@ bool SkOpSegment::activeOp(int index, int endIndex, int xorMiMask, int xorSuMask
if (fOperand) {
SkTSwap<int>(sumMiWinding, sumSuWinding);
}
- int maxWinding, sumWinding, oppMaxWinding, oppSumWinding;
- return activeOp(xorMiMask, xorSuMask, index, endIndex, op, &sumMiWinding, &sumSuWinding,
- &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding);
+ return activeOp(xorMiMask, xorSuMask, index, endIndex, op, &sumMiWinding, &sumSuWinding);
}
bool SkOpSegment::activeOp(int xorMiMask, int xorSuMask, int index, int endIndex, SkPathOp op,
- int* sumMiWinding, int* sumSuWinding,
- int* maxWinding, int* sumWinding, int* oppMaxWinding, int* oppSumWinding) {
+ int* sumMiWinding, int* sumSuWinding) {
+ int maxWinding, sumWinding, oppMaxWinding, oppSumWinding;
setUpWindings(index, endIndex, sumMiWinding, sumSuWinding,
- maxWinding, sumWinding, oppMaxWinding, oppSumWinding);
+ &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding);
bool miFrom;
bool miTo;
bool suFrom;
bool suTo;
if (operand()) {
- miFrom = (*oppMaxWinding & xorMiMask) != 0;
- miTo = (*oppSumWinding & xorMiMask) != 0;
- suFrom = (*maxWinding & xorSuMask) != 0;
- suTo = (*sumWinding & xorSuMask) != 0;
+ miFrom = (oppMaxWinding & xorMiMask) != 0;
+ miTo = (oppSumWinding & xorMiMask) != 0;
+ suFrom = (maxWinding & xorSuMask) != 0;
+ suTo = (sumWinding & xorSuMask) != 0;
} else {
- miFrom = (*maxWinding & xorMiMask) != 0;
- miTo = (*sumWinding & xorMiMask) != 0;
- suFrom = (*oppMaxWinding & xorSuMask) != 0;
- suTo = (*oppSumWinding & xorSuMask) != 0;
+ miFrom = (maxWinding & xorMiMask) != 0;
+ miTo = (sumWinding & xorMiMask) != 0;
+ suFrom = (oppMaxWinding & xorSuMask) != 0;
+ suTo = (oppSumWinding & xorSuMask) != 0;
}
bool result = gActiveEdge[op][miFrom][miTo][suFrom][suTo];
#if DEBUG_ACTIVE_OP
- SkDebugf("%s op=%s miFrom=%d miTo=%d suFrom=%d suTo=%d result=%d\n", __FUNCTION__,
+ SkDebugf("%s id=%d t=%1.9g tEnd=%1.9g op=%s miFrom=%d miTo=%d suFrom=%d suTo=%d result=%d\n",
+ __FUNCTION__, debugID(), span(index).fT, span(endIndex).fT,
SkPathOpsDebug::kPathOpStr[op], miFrom, miTo, suFrom, suTo, result);
#endif
return result;
@@ -194,24 +197,18 @@ bool SkOpSegment::activeOp(int xorMiMask, int xorSuMask, int index, int endIndex
bool SkOpSegment::activeWinding(int index, int endIndex) {
int sumWinding = updateWinding(endIndex, index);
- int maxWinding;
- return activeWinding(index, endIndex, &maxWinding, &sumWinding);
+ return activeWinding(index, endIndex, &sumWinding);
}
-bool SkOpSegment::activeWinding(int index, int endIndex, int* maxWinding, int* sumWinding) {
- setUpWinding(index, endIndex, maxWinding, sumWinding);
- bool from = *maxWinding != 0;
+bool SkOpSegment::activeWinding(int index, int endIndex, int* sumWinding) {
+ int maxWinding;
+ setUpWinding(index, endIndex, &maxWinding, sumWinding);
+ bool from = maxWinding != 0;
bool to = *sumWinding != 0;
bool result = gUnaryActiveEdge[from][to];
return result;
}
-void SkOpSegment::addAngle(SkTArray<SkOpAngle, true>* anglesPtr, int start, int end) const {
- SkASSERT(start != end);
- SkOpAngle& angle = anglesPtr->push_back();
- angle.set(this, start, end);
-}
-
void SkOpSegment::addCancelOutsides(const SkPoint& startPt, const SkPoint& endPt,
SkOpSegment* other) {
int tIndex = -1;
@@ -299,10 +296,36 @@ void SkOpSegment::addCoinOutsides(const SkPoint& startPt, const SkPoint& endPt,
do {
++tIndex;
} while (startPt != fTs[tIndex].fPt);
+ int ttIndex = tIndex;
+ bool checkOtherTMatch = false;
+ do {
+ const SkOpSpan& span = fTs[ttIndex];
+ if (startPt != span.fPt) {
+ break;
+ }
+ if (span.fOther == other && span.fPt == startPt) {
+ checkOtherTMatch = true;
+ break;
+ }
+ } while (++ttIndex < count());
do {
++oIndex;
} while (startPt != other->fTs[oIndex].fPt);
- if (tIndex > 0 || oIndex > 0 || fOperand != other->fOperand) {
+ bool skipAdd = false;
+ if (checkOtherTMatch) {
+ int ooIndex = oIndex;
+ do {
+ const SkOpSpan& oSpan = other->fTs[ooIndex];
+ if (startPt != oSpan.fPt) {
+ break;
+ }
+ if (oSpan.fT == fTs[ttIndex].fOtherT) {
+ skipAdd = true;
+ break;
+ }
+ } while (++ooIndex < other->count());
+ }
+ if ((tIndex > 0 || oIndex > 0 || fOperand != other->fOperand) && !skipAdd) {
addTPair(fTs[tIndex].fT, other, other->fTs[oIndex].fT, false, startPt);
}
SkPoint nextPt = startPt;
@@ -311,16 +334,19 @@ void SkOpSegment::addCoinOutsides(const SkPoint& startPt, const SkPoint& endPt,
do {
workPt = &fTs[++tIndex].fPt;
} while (nextPt == *workPt);
+ const SkPoint* oWorkPt;
do {
- workPt = &other->fTs[++oIndex].fPt;
- } while (nextPt == *workPt);
+ oWorkPt = &other->fTs[++oIndex].fPt;
+ } while (nextPt == *oWorkPt);
nextPt = *workPt;
double tStart = fTs[tIndex].fT;
double oStart = other->fTs[oIndex].fT;
if (tStart == 1 && oStart == 1 && fOperand == other->fOperand) {
break;
}
- addTPair(tStart, other, oStart, false, nextPt);
+ if (*workPt == *oWorkPt) {
+ addTPair(tStart, other, oStart, false, nextPt);
+ }
} while (endPt != nextPt);
}
@@ -378,6 +404,29 @@ void SkOpSegment::addCurveTo(int start, int end, SkPathWriter* path, bool active
// return ePtr[SkPathOpsVerbToPoints(fVerb)];
}
+void SkOpSegment::addEndSpan(int endIndex) {
+ int spanCount = fTs.count();
+ int startIndex = endIndex - 1;
+ while (fTs[startIndex].fT == 1 || fTs[startIndex].fTiny) {
+ ++startIndex;
+ SkASSERT(startIndex < spanCount - 1);
+ ++endIndex;
+ }
+ SkOpAngle& angle = fAngles.push_back();
+ angle.set(this, spanCount - 1, startIndex);
+#if DEBUG_ANGLE
+ debugCheckPointsEqualish(endIndex, spanCount);
+#endif
+ setFromAngle(endIndex, &angle);
+}
+
+void SkOpSegment::setFromAngle(int endIndex, SkOpAngle* angle) {
+ int spanCount = fTs.count();
+ do {
+ fTs[endIndex].fFromAngle = angle;
+ } while (++endIndex < spanCount);
+}
+
void SkOpSegment::addLine(const SkPoint pts[2], bool operand, bool evenOdd) {
init(pts, SkPath::kLine_Verb, operand, evenOdd);
fBounds.set(pts, 2);
@@ -400,6 +449,95 @@ void SkOpSegment::addQuad(const SkPoint pts[3], bool operand, bool evenOdd) {
fBounds.setQuadBounds(pts);
}
+SkOpAngle* SkOpSegment::addSingletonAngleDown(SkOpSegment** otherPtr, SkOpAngle** anglePtr) {
+ int spanIndex = count() - 1;
+ int startIndex = nextExactSpan(spanIndex, -1);
+ SkASSERT(startIndex >= 0);
+ SkOpAngle& angle = fAngles.push_back();
+ *anglePtr = &angle;
+ angle.set(this, spanIndex, startIndex);
+ setFromAngle(spanIndex, &angle);
+ SkOpSegment* other;
+ int oStartIndex, oEndIndex;
+ do {
+ const SkOpSpan& span = fTs[spanIndex];
+ SkASSERT(span.fT > 0);
+ other = span.fOther;
+ oStartIndex = span.fOtherIndex;
+ oEndIndex = other->nextExactSpan(oStartIndex, 1);
+ if (oEndIndex > 0 && other->span(oStartIndex).fWindValue) {
+ break;
+ }
+ oEndIndex = oStartIndex;
+ oStartIndex = other->nextExactSpan(oEndIndex, -1);
+ --spanIndex;
+ } while (oStartIndex < 0 || !other->span(oStartIndex).fWindSum);
+ SkOpAngle& oAngle = other->fAngles.push_back();
+ oAngle.set(other, oStartIndex, oEndIndex);
+ other->setToAngle(oEndIndex, &oAngle);
+ *otherPtr = other;
+ return &oAngle;
+}
+
+SkOpAngle* SkOpSegment::addSingletonAngleUp(SkOpSegment** otherPtr, SkOpAngle** anglePtr) {
+ int endIndex = nextExactSpan(0, 1);
+ SkASSERT(endIndex > 0);
+ SkOpAngle& angle = fAngles.push_back();
+ *anglePtr = &angle;
+ angle.set(this, 0, endIndex);
+ setToAngle(endIndex, &angle);
+ int spanIndex = 0;
+ SkOpSegment* other;
+ int oStartIndex, oEndIndex;
+ do {
+ const SkOpSpan& span = fTs[spanIndex];
+ SkASSERT(span.fT < 1);
+ other = span.fOther;
+ oEndIndex = span.fOtherIndex;
+ oStartIndex = other->nextExactSpan(oEndIndex, -1);
+ if (oStartIndex >= 0 && other->span(oStartIndex).fWindValue) {
+ break;
+ }
+ oStartIndex = oEndIndex;
+ oEndIndex = other->nextExactSpan(oStartIndex, 1);
+ ++spanIndex;
+ } while (oEndIndex < 0 || !other->span(oStartIndex).fWindValue);
+ SkOpAngle& oAngle = other->fAngles.push_back();
+ oAngle.set(other, oEndIndex, oStartIndex);
+ other->setFromAngle(oEndIndex, &oAngle);
+ *otherPtr = other;
+ return &oAngle;
+}
+
+SkOpAngle* SkOpSegment::addSingletonAngles(int step) {
+ SkOpSegment* other;
+ SkOpAngle* angle, * otherAngle;
+ if (step > 0) {
+ otherAngle = addSingletonAngleUp(&other, &angle);
+ } else {
+ otherAngle = addSingletonAngleDown(&other, &angle);
+ }
+ angle->insert(otherAngle);
+ return angle;
+}
+
+void SkOpSegment::addStartSpan(int endIndex) {
+ int index = 0;
+ SkOpAngle& angle = fAngles.push_back();
+ angle.set(this, index, endIndex);
+#if DEBUG_ANGLE
+ debugCheckPointsEqualish(index, endIndex);
+#endif
+ setToAngle(endIndex, &angle);
+}
+
+void SkOpSegment::setToAngle(int endIndex, SkOpAngle* angle) {
+ int index = 0;
+ do {
+ fTs[index].fToAngle = angle;
+ } while (++index < endIndex);
+}
+
// Defer all coincident edge processing until
// after normal intersections have been computed
@@ -408,18 +546,19 @@ void SkOpSegment::addQuad(const SkPoint pts[3], bool operand, bool evenOdd) {
// add non-coincident intersection. Resulting edges are sorted in T.
int SkOpSegment::addT(SkOpSegment* other, const SkPoint& pt, double newT) {
- if (precisely_zero(newT)) {
- newT = 0;
- } else if (precisely_equal(newT, 1)) {
- newT = 1;
- }
+ SkASSERT(this != other || fVerb == SkPath::kCubic_Verb);
+ #if 0 // this needs an even rougher association to be useful
+ SkASSERT(SkDPoint::RoughlyEqual(ptAtT(newT), pt));
+ #endif
+ const SkPoint& firstPt = fPts[0];
+ const SkPoint& lastPt = fPts[SkPathOpsVerbToPoints(fVerb)];
+ SkASSERT(newT == 0 || !precisely_zero(newT));
+ SkASSERT(newT == 1 || !precisely_equal(newT, 1));
// FIXME: in the pathological case where there is a ton of intercepts,
// binary search?
int insertedAt = -1;
- size_t tCount = fTs.count();
- const SkPoint& firstPt = fPts[0];
- const SkPoint& lastPt = fPts[SkPathOpsVerbToPoints(fVerb)];
- for (size_t index = 0; index < tCount; ++index) {
+ int tCount = fTs.count();
+ for (int index = 0; index < tCount; ++index) {
// OPTIMIZATION: if there are three or more identical Ts, then
// the fourth and following could be further insertion-sorted so
// that all the edges are clockwise or counterclockwise.
@@ -450,6 +589,7 @@ int SkOpSegment::addT(SkOpSegment* other, const SkPoint& pt, double newT) {
span = fTs.append();
}
span->fT = newT;
+ span->fOtherT = -1;
span->fOther = other;
span->fPt = pt;
#if 0
@@ -457,93 +597,71 @@ int SkOpSegment::addT(SkOpSegment* other, const SkPoint& pt, double newT) {
SkASSERT(approximately_equal(xyAtT(newT).fX, pt.fX)
&& approximately_equal(xyAtT(newT).fY, pt.fY));
#endif
+ span->fFromAngle = NULL;
+ span->fToAngle = NULL;
span->fWindSum = SK_MinS32;
span->fOppSum = SK_MinS32;
span->fWindValue = 1;
span->fOppValue = 0;
+ span->fChased = false;
+ span->fCoincident = false;
+ span->fLoop = false;
+ span->fNear = false;
+ span->fMultiple = false;
span->fSmall = false;
span->fTiny = false;
- span->fLoop = false;
if ((span->fDone = newT == 1)) {
++fDoneSpans;
}
- span->fUnsortableStart = false;
- span->fUnsortableEnd = false;
int less = -1;
- while (&span[less + 1] - fTs.begin() > 0 && AlmostEqualUlps(span[less].fPt, span->fPt)) {
- if (span[less].fDone) {
- break;
- }
- double tInterval = newT - span[less].fT;
- if (precisely_negative(tInterval)) {
- break;
- }
+// FIXME: note that this relies on spans being a continguous array
+// find range of spans with nearly the same point as this one
+ while (&span[less + 1] - fTs.begin() > 0 && AlmostEqualUlps(span[less].fPt, pt)) {
if (fVerb == SkPath::kCubic_Verb) {
+ double tInterval = newT - span[less].fT;
double tMid = newT - tInterval / 2;
SkDPoint midPt = dcubic_xy_at_t(fPts, tMid);
if (!midPt.approximatelyEqual(xyAtT(span))) {
break;
}
}
- span[less].fSmall = true;
- bool tiny = span[less].fPt == span->fPt;
- span[less].fTiny = tiny;
- span[less].fDone = true;
- if (approximately_negative(newT - span[less].fT) && tiny) {
- if (approximately_greater_than_one(newT)) {
- SkASSERT(&span[less] - fTs.begin() < fTs.count());
- span[less].fUnsortableStart = true;
- if (&span[less - 1] - fTs.begin() >= 0) {
- span[less - 1].fUnsortableEnd = true;
- }
- }
- if (approximately_less_than_zero(span[less].fT)) {
- SkASSERT(&span[less + 1] - fTs.begin() < fTs.count());
- SkASSERT(&span[less] - fTs.begin() >= 0);
- span[less + 1].fUnsortableStart = true;
- span[less].fUnsortableEnd = true;
- }
- }
- ++fDoneSpans;
--less;
}
int more = 1;
- while (fTs.end() - &span[more - 1] > 1 && AlmostEqualUlps(span[more].fPt, span->fPt)) {
- if (span[more - 1].fDone) {
- break;
- }
- double tEndInterval = span[more].fT - newT;
- if (precisely_negative(tEndInterval)) {
- if ((span->fTiny = span[more].fTiny)) {
- span->fDone = true;
- ++fDoneSpans;
- }
- break;
- }
+ while (fTs.end() - &span[more - 1] > 1 && AlmostEqualUlps(span[more].fPt, pt)) {
if (fVerb == SkPath::kCubic_Verb) {
+ double tEndInterval = span[more].fT - newT;
double tMid = newT - tEndInterval / 2;
SkDPoint midEndPt = dcubic_xy_at_t(fPts, tMid);
if (!midEndPt.approximatelyEqual(xyAtT(span))) {
break;
}
}
- span[more - 1].fSmall = true;
- bool tiny = span[more].fPt == span->fPt;
- span[more - 1].fTiny = tiny;
- span[more - 1].fDone = true;
- if (approximately_negative(span[more].fT - newT) && tiny) {
- if (approximately_greater_than_one(span[more].fT)) {
- span[more + 1].fUnsortableStart = true;
- span[more].fUnsortableEnd = true;
- }
- if (approximately_less_than_zero(newT)) {
- span[more].fUnsortableStart = true;
- span[more - 1].fUnsortableEnd = true;
- }
- }
- ++fDoneSpans;
++more;
}
+ ++less;
+ --more;
+ while (more - 1 > less && span[more].fPt == span[more - 1].fPt
+ && span[more].fT == span[more - 1].fT) {
+ --more;
+ }
+ if (less == more) {
+ return insertedAt;
+ }
+ if (precisely_negative(span[more].fT - span[less].fT)) {
+ return insertedAt;
+ }
+// if the total range of t values is big enough, mark all tiny
+ bool tiny = span[less].fPt == span[more].fPt;
+ int index = less;
+ do {
+ fSmall = span[index].fSmall = true;
+ fTiny |= span[index].fTiny = tiny;
+ if (!span[index].fDone) {
+ span[index].fDone = true;
+ ++fDoneSpans;
+ }
+ } while (++index < more);
return insertedAt;
}
@@ -572,31 +690,36 @@ void SkOpSegment::addTCancel(const SkPoint& startPt, const SkPoint& endPt, SkOpS
SkASSERT(index < fTs.count());
++index;
}
- while (index > 0 && fTs[index].fT == fTs[index - 1].fT) {
+ while (index > 0 && precisely_equal(fTs[index].fT, fTs[index - 1].fT)) {
--index;
}
+ bool oFoundEnd = false;
int oIndex = other->fTs.count();
while (startPt != other->fTs[--oIndex].fPt) { // look for startPt match
SkASSERT(oIndex > 0);
}
double oStartT = other->fTs[oIndex].fT;
// look for first point beyond match
- while (startPt == other->fTs[--oIndex].fPt || oStartT == other->fTs[oIndex].fT) {
+ while (startPt == other->fTs[--oIndex].fPt || precisely_equal(oStartT, other->fTs[oIndex].fT)) {
SkASSERT(oIndex > 0);
}
SkOpSpan* test = &fTs[index];
SkOpSpan* oTest = &other->fTs[oIndex];
SkSTArray<kOutsideTrackedTCount, SkPoint, true> outsidePts;
SkSTArray<kOutsideTrackedTCount, SkPoint, true> oOutsidePts;
+ bool decrement, track, bigger;
+ int originalWindValue;
+ const SkPoint* testPt;
+ const SkPoint* oTestPt;
do {
SkASSERT(test->fT < 1);
SkASSERT(oTest->fT < 1);
- bool decrement = test->fWindValue && oTest->fWindValue;
- bool track = test->fWindValue || oTest->fWindValue;
- bool bigger = test->fWindValue >= oTest->fWindValue;
- const SkPoint& testPt = test->fPt;
+ decrement = test->fWindValue && oTest->fWindValue;
+ track = test->fWindValue || oTest->fWindValue;
+ bigger = test->fWindValue >= oTest->fWindValue;
+ testPt = &test->fPt;
double testT = test->fT;
- const SkPoint& oTestPt = oTest->fPt;
+ oTestPt = &oTest->fPt;
double oTestT = oTest->fT;
do {
if (decrement) {
@@ -606,12 +729,12 @@ void SkOpSegment::addTCancel(const SkPoint& startPt, const SkPoint& endPt, SkOpS
decrementSpan(test);
}
} else if (track) {
- TrackOutsidePair(&outsidePts, testPt, oTestPt);
+ TrackOutsidePair(&outsidePts, *testPt, *oTestPt);
}
SkASSERT(index < fTs.count() - 1);
test = &fTs[++index];
- } while (testPt == test->fPt || testT == test->fT);
- SkDEBUGCODE(int originalWindValue = oTest->fWindValue);
+ } while (*testPt == test->fPt || precisely_equal(testT, test->fT));
+ originalWindValue = oTest->fWindValue;
do {
SkASSERT(oTest->fT < 1);
SkASSERT(originalWindValue == oTest->fWindValue);
@@ -622,15 +745,48 @@ void SkOpSegment::addTCancel(const SkPoint& startPt, const SkPoint& endPt, SkOpS
other->decrementSpan(oTest);
}
} else if (track) {
- TrackOutsidePair(&oOutsidePts, oTestPt, testPt);
+ TrackOutsidePair(&oOutsidePts, *oTestPt, *testPt);
}
if (!oIndex) {
break;
}
+ oFoundEnd |= endPt == oTest->fPt;
oTest = &other->fTs[--oIndex];
- } while (oTestPt == oTest->fPt || oTestT == oTest->fT);
+ } while (*oTestPt == oTest->fPt || precisely_equal(oTestT, oTest->fT));
} while (endPt != test->fPt && test->fT < 1);
// FIXME: determine if canceled edges need outside ts added
+ if (!oFoundEnd) {
+ for (int oIdx2 = oIndex; oIdx2 >= 0; --oIdx2) {
+ SkOpSpan* oTst2 = &other->fTs[oIdx2];
+ if (originalWindValue != oTst2->fWindValue) {
+ goto skipAdvanceOtherCancel;
+ }
+ if (!oTst2->fWindValue) {
+ goto skipAdvanceOtherCancel;
+ }
+ if (endPt == other->fTs[oIdx2].fPt) {
+ break;
+ }
+ }
+ do {
+ SkASSERT(originalWindValue == oTest->fWindValue);
+ if (decrement) {
+ if (binary && !bigger) {
+ oTest->fOppValue--;
+ } else {
+ other->decrementSpan(oTest);
+ }
+ } else if (track) {
+ TrackOutsidePair(&oOutsidePts, *oTestPt, *testPt);
+ }
+ if (!oIndex) {
+ break;
+ }
+ oTest = &other->fTs[--oIndex];
+ oFoundEnd |= endPt == oTest->fPt;
+ } while (!oFoundEnd || endPt == oTest->fPt);
+ }
+skipAdvanceOtherCancel:
int outCount = outsidePts.count();
if (!done() && outCount) {
addCancelOutsides(outsidePts[0], outsidePts[1], other);
@@ -641,16 +797,387 @@ void SkOpSegment::addTCancel(const SkPoint& startPt, const SkPoint& endPt, SkOpS
if (!other->done() && oOutsidePts.count()) {
other->addCancelOutsides(oOutsidePts[0], oOutsidePts[1], this);
}
+ setCoincidentRange(startPt, endPt, other);
+ other->setCoincidentRange(startPt, endPt, this);
}
-int SkOpSegment::addSelfT(SkOpSegment* other, const SkPoint& pt, double newT) {
+int SkOpSegment::addSelfT(const SkPoint& pt, double newT) {
// if the tail nearly intersects itself but not quite, the caller records this separately
- int result = addT(other, pt, newT);
+ int result = addT(this, pt, newT);
SkOpSpan* span = &fTs[result];
- span->fLoop = true;
+ fLoop = span->fLoop = true;
return result;
}
+// find the starting or ending span with an existing loop of angles
+// FIXME? replicate for all identical starting/ending spans?
+// OPTIMIZE? remove the spans pointing to windValue==0 here or earlier?
+// FIXME? assert that only one other span has a valid windValue or oppValue
+void SkOpSegment::addSimpleAngle(int index) {
+ SkOpSpan* span = &fTs[index];
+ if (index == 0) {
+ do {
+ if (span->fToAngle) {
+ SkASSERT(span->fToAngle->loopCount() == 2);
+ SkASSERT(!span->fFromAngle);
+ span->fFromAngle = span->fToAngle->next();
+ return;
+ }
+ span = &fTs[++index];
+ } while (span->fT == 0);
+ SkASSERT(index == 1);
+ index = 0;
+ SkASSERT(!fTs[0].fTiny && fTs[1].fT > 0);
+ addStartSpan(1);
+ } else {
+ do {
+ if (span->fFromAngle) {
+ SkASSERT(span->fFromAngle->loopCount() == 2);
+ SkASSERT(!span->fToAngle);
+ span->fToAngle = span->fFromAngle->next();
+ return;
+ }
+ span = &fTs[--index];
+ } while (span->fT == 1);
+ SkASSERT(index == count() - 2);
+ index = count() - 1;
+ SkASSERT(!fTs[index - 1].fTiny && fTs[index - 1].fT < 1);
+ addEndSpan(index);
+ }
+ span = &fTs[index];
+ SkOpSegment* other = span->fOther;
+ SkOpSpan& oSpan = other->fTs[span->fOtherIndex];
+ SkOpAngle* angle, * oAngle;
+ if (index == 0) {
+ SkASSERT(span->fOtherIndex - 1 >= 0);
+ SkASSERT(span->fOtherT == 1);
+ SkDEBUGCODE(SkOpSpan& oPrior = other->fTs[span->fOtherIndex - 1]);
+ SkASSERT(!oPrior.fTiny && oPrior.fT < 1);
+ other->addEndSpan(span->fOtherIndex);
+ angle = span->fToAngle;
+ oAngle = oSpan.fFromAngle;
+ } else {
+ SkASSERT(span->fOtherIndex + 1 < other->count());
+ SkASSERT(span->fOtherT == 0);
+ SkASSERT(!oSpan.fTiny && (other->fTs[span->fOtherIndex + 1].fT > 0
+ || (other->fTs[span->fOtherIndex + 1].fFromAngle == NULL
+ && other->fTs[span->fOtherIndex + 1].fToAngle == NULL)));
+ int oIndex = 1;
+ do {
+ const SkOpSpan& osSpan = other->span(oIndex);
+ if (osSpan.fFromAngle || osSpan.fT > 0) {
+ break;
+ }
+ ++oIndex;
+ SkASSERT(oIndex < other->count());
+ } while (true);
+ other->addStartSpan(oIndex);
+ angle = span->fFromAngle;
+ oAngle = oSpan.fToAngle;
+ }
+ angle->insert(oAngle);
+}
+
+void SkOpSegment::alignMultiples(SkTDArray<AlignedSpan>* alignedArray) {
+ debugValidate();
+ int count = this->count();
+ for (int index = 0; index < count; ++index) {
+ SkOpSpan& span = fTs[index];
+ if (!span.fMultiple) {
+ continue;
+ }
+ int end = nextExactSpan(index, 1);
+ SkASSERT(end > index + 1);
+ const SkPoint& thisPt = span.fPt;
+ while (index < end - 1) {
+ SkOpSegment* other1 = span.fOther;
+ int oCnt = other1->count();
+ for (int idx2 = index + 1; idx2 < end; ++idx2) {
+ SkOpSpan& span2 = fTs[idx2];
+ SkOpSegment* other2 = span2.fOther;
+ for (int oIdx = 0; oIdx < oCnt; ++oIdx) {
+ SkOpSpan& oSpan = other1->fTs[oIdx];
+ if (oSpan.fOther != other2) {
+ continue;
+ }
+ if (oSpan.fPt == thisPt) {
+ goto skipExactMatches;
+ }
+ }
+ for (int oIdx = 0; oIdx < oCnt; ++oIdx) {
+ SkOpSpan& oSpan = other1->fTs[oIdx];
+ if (oSpan.fOther != other2) {
+ continue;
+ }
+ if (SkDPoint::RoughlyEqual(oSpan.fPt, thisPt)) {
+ SkOpSpan& oSpan2 = other2->fTs[oSpan.fOtherIndex];
+ if (zero_or_one(span.fOtherT) || zero_or_one(oSpan.fT)
+ || zero_or_one(span2.fOtherT) || zero_or_one(oSpan2.fT)) {
+ return;
+ }
+ if (!way_roughly_equal(span.fOtherT, oSpan.fT)
+ || !way_roughly_equal(span2.fOtherT, oSpan2.fT)
+ || !way_roughly_equal(span2.fOtherT, oSpan.fOtherT)
+ || !way_roughly_equal(span.fOtherT, oSpan2.fOtherT)) {
+ return;
+ }
+ alignSpan(thisPt, span.fOtherT, other1, span2.fOtherT,
+ other2, &oSpan, alignedArray);
+ alignSpan(thisPt, span2.fOtherT, other2, span.fOtherT,
+ other1, &oSpan2, alignedArray);
+ break;
+ }
+ }
+ skipExactMatches:
+ ;
+ }
+ ++index;
+ }
+ }
+ debugValidate();
+}
+
+void SkOpSegment::alignSpan(const SkPoint& newPt, double newT, const SkOpSegment* other,
+ double otherT, const SkOpSegment* other2, SkOpSpan* oSpan,
+ SkTDArray<AlignedSpan>* alignedArray) {
+ AlignedSpan* aligned = alignedArray->append();
+ aligned->fOldPt = oSpan->fPt;
+ aligned->fPt = newPt;
+ aligned->fOldT = oSpan->fT;
+ aligned->fT = newT;
+ aligned->fSegment = this; // OPTIMIZE: may be unused, can remove
+ aligned->fOther1 = other;
+ aligned->fOther2 = other2;
+ SkASSERT(SkDPoint::RoughlyEqual(oSpan->fPt, newPt));
+ oSpan->fPt = newPt;
+// SkASSERT(way_roughly_equal(oSpan->fT, newT));
+ oSpan->fT = newT;
+// SkASSERT(way_roughly_equal(oSpan->fOtherT, otherT));
+ oSpan->fOtherT = otherT;
+}
+
+bool SkOpSegment::alignSpan(int index, double thisT, const SkPoint& thisPt) {
+ bool aligned = false;
+ SkOpSpan* span = &fTs[index];
+ SkOpSegment* other = span->fOther;
+ int oIndex = span->fOtherIndex;
+ SkOpSpan* oSpan = &other->fTs[oIndex];
+ if (span->fT != thisT) {
+ span->fT = thisT;
+ oSpan->fOtherT = thisT;
+ aligned = true;
+ }
+ if (span->fPt != thisPt) {
+ span->fPt = thisPt;
+ oSpan->fPt = thisPt;
+ aligned = true;
+ }
+ double oT = oSpan->fT;
+ if (oT == 0) {
+ return aligned;
+ }
+ int oStart = other->nextSpan(oIndex, -1) + 1;
+ oSpan = &other->fTs[oStart];
+ int otherIndex = oStart;
+ if (oT == 1) {
+ if (aligned) {
+ while (oSpan->fPt == thisPt && oSpan->fT != 1) {
+ oSpan->fTiny = true;
+ ++oSpan;
+ }
+ }
+ return aligned;
+ }
+ oT = oSpan->fT;
+ int oEnd = other->nextSpan(oIndex, 1);
+ bool oAligned = false;
+ if (oSpan->fPt != thisPt) {
+ oAligned |= other->alignSpan(oStart, oT, thisPt);
+ }
+ while (++otherIndex < oEnd) {
+ SkOpSpan* oNextSpan = &other->fTs[otherIndex];
+ if (oNextSpan->fT != oT || oNextSpan->fPt != thisPt) {
+ oAligned |= other->alignSpan(otherIndex, oT, thisPt);
+ }
+ }
+ if (oAligned) {
+ other->alignSpanState(oStart, oEnd);
+ }
+ return aligned;
+}
+
+void SkOpSegment::alignSpanState(int start, int end) {
+ SkOpSpan* lastSpan = &fTs[--end];
+ bool allSmall = lastSpan->fSmall;
+ bool allTiny = lastSpan->fTiny;
+ bool allDone = lastSpan->fDone;
+ SkDEBUGCODE(int winding = lastSpan->fWindValue);
+ SkDEBUGCODE(int oppWinding = lastSpan->fOppValue);
+ int index = start;
+ while (index < end) {
+ SkOpSpan* span = &fTs[index];
+ span->fSmall = allSmall;
+ span->fTiny = allTiny;
+ if (span->fDone != allDone) {
+ span->fDone = allDone;
+ fDoneSpans += allDone ? 1 : -1;
+ }
+ SkASSERT(span->fWindValue == winding);
+ SkASSERT(span->fOppValue == oppWinding);
+ ++index;
+ }
+}
+
+void SkOpSegment::blindCancel(const SkCoincidence& coincidence, SkOpSegment* other) {
+ bool binary = fOperand != other->fOperand;
+ int index = 0;
+ int last = this->count();
+ do {
+ SkOpSpan& span = this->fTs[--last];
+ if (span.fT != 1 && !span.fSmall) {
+ break;
+ }
+ span.fCoincident = true;
+ } while (true);
+ int oIndex = other->count();
+ do {
+ SkOpSpan& oSpan = other->fTs[--oIndex];
+ if (oSpan.fT != 1 && !oSpan.fSmall) {
+ break;
+ }
+ oSpan.fCoincident = true;
+ } while (true);
+ do {
+ SkOpSpan* test = &this->fTs[index];
+ int baseWind = test->fWindValue;
+ int baseOpp = test->fOppValue;
+ int endIndex = index;
+ while (++endIndex <= last) {
+ SkOpSpan* endSpan = &this->fTs[endIndex];
+ SkASSERT(endSpan->fT < 1);
+ if (endSpan->fWindValue != baseWind || endSpan->fOppValue != baseOpp) {
+ break;
+ }
+ endSpan->fCoincident = true;
+ }
+ SkOpSpan* oTest = &other->fTs[oIndex];
+ int oBaseWind = oTest->fWindValue;
+ int oBaseOpp = oTest->fOppValue;
+ int oStartIndex = oIndex;
+ while (--oStartIndex >= 0) {
+ SkOpSpan* oStartSpan = &other->fTs[oStartIndex];
+ if (oStartSpan->fWindValue != oBaseWind || oStartSpan->fOppValue != oBaseOpp) {
+ break;
+ }
+ oStartSpan->fCoincident = true;
+ }
+ bool decrement = baseWind && oBaseWind;
+ bool bigger = baseWind >= oBaseWind;
+ do {
+ SkASSERT(test->fT < 1);
+ if (decrement) {
+ if (binary && bigger) {
+ test->fOppValue--;
+ } else {
+ decrementSpan(test);
+ }
+ }
+ test->fCoincident = true;
+ test = &fTs[++index];
+ } while (index < endIndex);
+ do {
+ SkASSERT(oTest->fT < 1);
+ if (decrement) {
+ if (binary && !bigger) {
+ oTest->fOppValue--;
+ } else {
+ other->decrementSpan(oTest);
+ }
+ }
+ oTest->fCoincident = true;
+ oTest = &other->fTs[--oIndex];
+ } while (oIndex > oStartIndex);
+ } while (index <= last && oIndex >= 0);
+ SkASSERT(index > last);
+ SkASSERT(oIndex < 0);
+}
+
+void SkOpSegment::blindCoincident(const SkCoincidence& coincidence, SkOpSegment* other) {
+ bool binary = fOperand != other->fOperand;
+ int index = 0;
+ int last = this->count();
+ do {
+ SkOpSpan& span = this->fTs[--last];
+ if (span.fT != 1 && !span.fSmall) {
+ break;
+ }
+ span.fCoincident = true;
+ } while (true);
+ int oIndex = 0;
+ int oLast = other->count();
+ do {
+ SkOpSpan& oSpan = other->fTs[--oLast];
+ if (oSpan.fT != 1 && !oSpan.fSmall) {
+ break;
+ }
+ oSpan.fCoincident = true;
+ } while (true);
+ do {
+ SkOpSpan* test = &this->fTs[index];
+ int baseWind = test->fWindValue;
+ int baseOpp = test->fOppValue;
+ int endIndex = index;
+ SkOpSpan* endSpan;
+ while (++endIndex <= last) {
+ endSpan = &this->fTs[endIndex];
+ SkASSERT(endSpan->fT < 1);
+ if (endSpan->fWindValue != baseWind || endSpan->fOppValue != baseOpp) {
+ break;
+ }
+ endSpan->fCoincident = true;
+ }
+ SkOpSpan* oTest = &other->fTs[oIndex];
+ int oBaseWind = oTest->fWindValue;
+ int oBaseOpp = oTest->fOppValue;
+ int oEndIndex = oIndex;
+ SkOpSpan* oEndSpan;
+ while (++oEndIndex <= oLast) {
+ oEndSpan = &this->fTs[oEndIndex];
+ SkASSERT(oEndSpan->fT < 1);
+ if (oEndSpan->fWindValue != oBaseWind || oEndSpan->fOppValue != oBaseOpp) {
+ break;
+ }
+ oEndSpan->fCoincident = true;
+ }
+ // consolidate the winding count even if done
+ if ((test->fWindValue || test->fOppValue) && (oTest->fWindValue || oTest->fOppValue)) {
+ if (!binary || test->fWindValue + oTest->fOppValue >= 0) {
+ bumpCoincidentBlind(binary, index, endIndex);
+ other->bumpCoincidentOBlind(oIndex, oEndIndex);
+ } else {
+ other->bumpCoincidentBlind(binary, oIndex, oEndIndex);
+ bumpCoincidentOBlind(index, endIndex);
+ }
+ }
+ index = endIndex;
+ oIndex = oEndIndex;
+ } while (index <= last && oIndex <= oLast);
+ SkASSERT(index > last);
+ SkASSERT(oIndex > oLast);
+}
+
+void SkOpSegment::bumpCoincidentBlind(bool binary, int index, int endIndex) {
+ const SkOpSpan& oTest = fTs[index];
+ int oWindValue = oTest.fWindValue;
+ int oOppValue = oTest.fOppValue;
+ if (binary) {
+ SkTSwap<int>(oWindValue, oOppValue);
+ }
+ do {
+ (void) bumpSpan(&fTs[index], oWindValue, oOppValue);
+ } while (++index < endIndex);
+}
+
void SkOpSegment::bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* indexPtr,
SkTArray<SkPoint, true>* outsideTs) {
int index = *indexPtr;
@@ -667,10 +1194,16 @@ void SkOpSegment::bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* in
TrackOutside(outsideTs, oStartPt);
}
end = &fTs[++index];
- } while ((end->fPt == test->fPt || end->fT == test->fT) && end->fT < 1);
+ } while ((end->fPt == test->fPt || precisely_equal(end->fT, test->fT)) && end->fT < 1);
*indexPtr = index;
}
+void SkOpSegment::bumpCoincidentOBlind(int index, int endIndex) {
+ do {
+ zeroSpan(&fTs[index]);
+ } while (++index < endIndex);
+}
+
// because of the order in which coincidences are resolved, this and other
// may not have the same intermediate points. Compute the corresponding
// intermediate T values (using this as the master, other as the follower)
@@ -680,13 +1213,16 @@ void SkOpSegment::bumpCoincidentOther(const SkOpSpan& test, int* oIndexPtr,
int oIndex = *oIndexPtr;
SkOpSpan* const oTest = &fTs[oIndex];
SkOpSpan* oEnd = oTest;
- const SkPoint& startPt = test.fPt;
const SkPoint& oStartPt = oTest->fPt;
double oStartT = oTest->fT;
- if (oStartPt == oEnd->fPt || oStartT == oEnd->fT) {
+#if 0 // FIXME : figure out what disabling this breaks
+ const SkPoint& startPt = test.fPt;
+ // this is always true since oEnd == oTest && oStartPt == oTest->fPt -- find proper condition
+ if (oStartPt == oEnd->fPt || precisely_equal(oStartT, oEnd->fT)) {
TrackOutside(oOutsidePts, startPt);
}
- while (oStartPt == oEnd->fPt || oStartT == oEnd->fT) {
+#endif
+ while (oStartPt == oEnd->fPt || precisely_equal(oStartT, oEnd->fT)) {
zeroSpan(oEnd);
oEnd = &fTs[++oIndex];
}
@@ -711,7 +1247,7 @@ void SkOpSegment::addTCoincident(const SkPoint& startPt, const SkPoint& endPt, d
++index;
}
double startT = fTs[index].fT;
- while (index > 0 && fTs[index - 1].fT == startT) {
+ while (index > 0 && precisely_equal(fTs[index - 1].fT, startT)) {
--index;
}
int oIndex = 0;
@@ -720,7 +1256,7 @@ void SkOpSegment::addTCoincident(const SkPoint& startPt, const SkPoint& endPt, d
++oIndex;
}
double oStartT = other->fTs[oIndex].fT;
- while (oIndex > 0 && other->fTs[oIndex - 1].fT == oStartT) {
+ while (oIndex > 0 && precisely_equal(other->fTs[oIndex - 1].fT, oStartT)) {
--oIndex;
}
SkSTArray<kOutsideTrackedTCount, SkPoint, true> outsidePts;
@@ -734,12 +1270,10 @@ void SkOpSegment::addTCoincident(const SkPoint& startPt, const SkPoint& endPt, d
do {
SkASSERT(test->fT < 1);
SkASSERT(oTest->fT < 1);
-#if 0
- if (test->fDone || oTest->fDone) {
-#else // consolidate the winding count even if done
+
+ // consolidate the winding count even if done
if ((test->fWindValue == 0 && test->fOppValue == 0)
|| (oTest->fWindValue == 0 && oTest->fOppValue == 0)) {
-#endif
SkDEBUGCODE(int firstWind = test->fWindValue);
SkDEBUGCODE(int firstOpp = test->fOppValue);
do {
@@ -768,14 +1302,15 @@ void SkOpSegment::addTCoincident(const SkPoint& startPt, const SkPoint& endPt, d
test = &fTs[index];
testPt = &test->fPt;
testT = test->fT;
- if (endPt == *testPt || endT == testT) {
- break;
- }
oTest = &other->fTs[oIndex];
oTestPt = &oTest->fPt;
- SkASSERT(AlmostEqualUlps(*testPt, *oTestPt));
+ if (endPt == *testPt || precisely_equal(endT, testT)) {
+ break;
+ }
+// SkASSERT(AlmostEqualUlps(*testPt, *oTestPt));
} while (endPt != *oTestPt);
- if (endPt != *testPt && endT != testT) { // in rare cases, one may have ended before the other
+ // in rare cases, one may have ended before the other
+ if (endPt != *testPt && !precisely_equal(endT, testT)) {
int lastWind = test[-1].fWindValue;
int lastOpp = test[-1].fOppValue;
bool zero = lastWind == 0 && lastOpp == 0;
@@ -791,7 +1326,43 @@ void SkOpSegment::addTCoincident(const SkPoint& startPt, const SkPoint& endPt, d
test = &fTs[++index];
testPt = &test->fPt;
} while (endPt != *testPt);
- }
+ }
+ if (endPt != *oTestPt) {
+ // look ahead to see if zeroing more spans will allows us to catch up
+ int oPeekIndex = oIndex;
+ bool success = true;
+ SkOpSpan* oPeek;
+ int oCount = other->count();
+ do {
+ oPeek = &other->fTs[oPeekIndex];
+ if (++oPeekIndex == oCount) {
+ success = false;
+ break;
+ }
+ } while (endPt != oPeek->fPt);
+ if (success) {
+ // make sure the matching point completes the coincidence span
+ success = false;
+ do {
+ if (oPeek->fOther == this) {
+ success = true;
+ break;
+ }
+ oPeek = &other->fTs[++oPeekIndex];
+ } while (endPt == oPeek->fPt);
+ }
+ if (success) {
+ do {
+ if (!binary || test->fWindValue + oTest->fOppValue >= 0) {
+ other->bumpCoincidentOther(*test, &oIndex, &oOutsidePts);
+ } else {
+ other->bumpCoincidentThis(*test, binary, &oIndex, &oOutsidePts);
+ }
+ oTest = &other->fTs[oIndex];
+ oTestPt = &oTest->fPt;
+ } while (endPt != *oTestPt);
+ }
+ }
int outCount = outsidePts.count();
if (!done() && outCount) {
addCoinOutsides(outsidePts[0], endPt, other);
@@ -799,12 +1370,14 @@ void SkOpSegment::addTCoincident(const SkPoint& startPt, const SkPoint& endPt, d
if (!other->done() && oOutsidePts.count()) {
other->addCoinOutsides(oOutsidePts[0], endPt, this);
}
+ setCoincidentRange(startPt, endPt, other);
+ other->setCoincidentRange(startPt, endPt, this);
}
// FIXME: this doesn't prevent the same span from being added twice
// fix in caller, SkASSERT here?
-void SkOpSegment::addTPair(double t, SkOpSegment* other, double otherT, bool borrowWind,
- const SkPoint& pt) {
+const SkOpSpan* SkOpSegment::addTPair(double t, SkOpSegment* other, double otherT, bool borrowWind,
+ const SkPoint& pt, const SkPoint& pt2) {
int tCount = fTs.count();
for (int tIndex = 0; tIndex < tCount; ++tIndex) {
const SkOpSpan& span = fTs[tIndex];
@@ -817,7 +1390,7 @@ void SkOpSegment::addTPair(double t, SkOpSegment* other, double otherT, bool bor
SkDebugf("%s addTPair duplicate this=%d %1.9g other=%d %1.9g\n",
__FUNCTION__, fID, t, other->fID, otherT);
#endif
- return;
+ return NULL;
}
}
#if DEBUG_ADD_T_PAIR
@@ -825,26 +1398,23 @@ void SkOpSegment::addTPair(double t, SkOpSegment* other, double otherT, bool bor
__FUNCTION__, fID, t, other->fID, otherT);
#endif
int insertedAt = addT(other, pt, t);
- int otherInsertedAt = other->addT(this, pt, otherT);
+ int otherInsertedAt = other->addT(this, pt2, otherT);
addOtherT(insertedAt, otherT, otherInsertedAt);
other->addOtherT(otherInsertedAt, t, insertedAt);
matchWindingValue(insertedAt, t, borrowWind);
other->matchWindingValue(otherInsertedAt, otherT, borrowWind);
+ SkOpSpan& span = this->fTs[insertedAt];
+ if (pt != pt2) {
+ span.fNear = true;
+ SkOpSpan& oSpan = other->fTs[otherInsertedAt];
+ oSpan.fNear = true;
+ }
+ return &span;
}
-void SkOpSegment::addTwoAngles(int start, int end, SkTArray<SkOpAngle, true>* angles) const {
- // add edge leading into junction
- int min = SkMin32(end, start);
- if (fTs[min].fWindValue > 0 || fTs[min].fOppValue != 0) {
- addAngle(angles, end, start);
- }
- // add edge leading away from junction
- int step = SkSign32(end - start);
- int tIndex = nextExactSpan(end, step);
- min = SkMin32(end, tIndex);
- if (tIndex >= 0 && (fTs[min].fWindValue > 0 || fTs[min].fOppValue != 0)) {
- addAngle(angles, end, tIndex);
- }
+const SkOpSpan* SkOpSegment::addTPair(double t, SkOpSegment* other, double otherT, bool borrowWind,
+ const SkPoint& pt) {
+ return addTPair(t, other, otherT, borrowWind, pt, pt);
}
bool SkOpSegment::betweenPoints(double midT, const SkPoint& pt1, const SkPoint& pt2) const {
@@ -862,164 +1432,170 @@ bool SkOpSegment::betweenTs(int lesser, double testT, int greater) const {
return approximately_between(fTs[lesser].fT, testT, fTs[greater].fT);
}
-// note that this follows the same logic flow as active angle
-bool SkOpSegment::buildAngles(int index, SkTArray<SkOpAngle, true>* angles, bool allowOpp) const {
- double referenceT = fTs[index].fT;
- const SkPoint& referencePt = fTs[index].fPt;
- int lesser = index;
- while (--lesser >= 0 && (allowOpp || fTs[lesser].fOther->fOperand == fOperand)
- && (precisely_negative(referenceT - fTs[lesser].fT) || fTs[lesser].fTiny)) {
- buildAnglesInner(lesser, angles);
+// in extreme cases (like the buffer overflow test) return false to abort
+// for now, if one t value represents two different points, then the values are too extreme
+// to generate meaningful results
+bool SkOpSegment::calcAngles() {
+ int spanCount = fTs.count();
+ if (spanCount <= 2) {
+ return spanCount == 2;
+ }
+ int index = 1;
+ const SkOpSpan* firstSpan = &fTs[index];
+ int activePrior = checkSetAngle(0);
+ const SkOpSpan* span = &fTs[0];
+ if (firstSpan->fT == 0 || span->fTiny || span->fOtherT != 1 || span->fOther->multipleEnds()) {
+ index = findStartSpan(0); // curve start intersects
+ SkASSERT(index > 0);
+ if (activePrior >= 0) {
+ addStartSpan(index);
+ }
+ }
+ bool addEnd;
+ int endIndex = spanCount - 1;
+ span = &fTs[endIndex - 1];
+ if ((addEnd = span->fT == 1 || span->fTiny)) { // if curve end intersects
+ endIndex = findEndSpan(endIndex);
+ SkASSERT(endIndex > 0);
+ } else {
+ addEnd = fTs[endIndex].fOtherT != 0 || fTs[endIndex].fOther->multipleStarts();
+ }
+ SkASSERT(endIndex >= index);
+ int prior = 0;
+ while (index < endIndex) {
+ const SkOpSpan& fromSpan = fTs[index]; // for each intermediate intersection
+ const SkOpSpan* lastSpan;
+ span = &fromSpan;
+ int start = index;
+ do {
+ lastSpan = span;
+ span = &fTs[++index];
+ SkASSERT(index < spanCount);
+ if (!precisely_negative(span->fT - lastSpan->fT) && !lastSpan->fTiny) {
+ break;
+ }
+ if (!SkDPoint::ApproximatelyEqual(lastSpan->fPt, span->fPt)) {
+ return false;
+ }
+ } while (true);
+ SkOpAngle* angle = NULL;
+ SkOpAngle* priorAngle;
+ if (activePrior >= 0) {
+ int pActive = firstActive(prior);
+ SkASSERT(pActive < start);
+ priorAngle = &fAngles.push_back();
+ priorAngle->set(this, start, pActive);
+ }
+ int active = checkSetAngle(start);
+ if (active >= 0) {
+ SkASSERT(active < index);
+ angle = &fAngles.push_back();
+ angle->set(this, active, index);
+ }
+ #if DEBUG_ANGLE
+ debugCheckPointsEqualish(start, index);
+ #endif
+ prior = start;
+ do {
+ const SkOpSpan* startSpan = &fTs[start - 1];
+ if (!startSpan->fSmall || isCanceled(start - 1) || startSpan->fFromAngle
+ || startSpan->fToAngle) {
+ break;
+ }
+ --start;
+ } while (start > 0);
+ do {
+ if (activePrior >= 0) {
+ SkASSERT(fTs[start].fFromAngle == NULL);
+ fTs[start].fFromAngle = priorAngle;
+ }
+ if (active >= 0) {
+ SkASSERT(fTs[start].fToAngle == NULL);
+ fTs[start].fToAngle = angle;
+ }
+ } while (++start < index);
+ activePrior = active;
+ }
+ if (addEnd && activePrior >= 0) {
+ addEndSpan(endIndex);
}
- do {
- buildAnglesInner(index, angles);
- if (++index == fTs.count()) {
- break;
- }
- if (!allowOpp && fTs[index].fOther->fOperand != fOperand) {
- break;
- }
- if (fTs[index - 1].fTiny) {
- referenceT = fTs[index].fT;
- continue;
- }
- if (!precisely_negative(fTs[index].fT - referenceT) && fTs[index].fPt == referencePt) {
- // FIXME
- // testQuad8 generates the wrong output unless false is returned here. Other tests will
- // take this path although they aren't required to. This means that many go much slower
- // because of this sort fail.
- // SkDebugf("!!!\n");
- return false;
- }
- } while (precisely_negative(fTs[index].fT - referenceT));
return true;
}
-void SkOpSegment::buildAnglesInner(int index, SkTArray<SkOpAngle, true>* angles) const {
- const SkOpSpan* span = &fTs[index];
- SkOpSegment* other = span->fOther;
-// if there is only one live crossing, and no coincidence, continue
-// in the same direction
-// if there is coincidence, the only choice may be to reverse direction
- // find edge on either side of intersection
- int oIndex = span->fOtherIndex;
- // if done == -1, prior span has already been processed
- int step = 1;
- int next = other->nextExactSpan(oIndex, step);
- if (next < 0) {
- step = -step;
- next = other->nextExactSpan(oIndex, step);
+int SkOpSegment::checkSetAngle(int tIndex) const {
+ const SkOpSpan* span = &fTs[tIndex];
+ while (span->fTiny /* || span->fSmall */) {
+ span = &fTs[++tIndex];
}
- // add candidate into and away from junction
- other->addTwoAngles(next, oIndex, angles);
+ return isCanceled(tIndex) ? -1 : tIndex;
}
-int SkOpSegment::computeSum(int startIndex, int endIndex, SkOpAngle::IncludeType includeType,
- SkTArray<SkOpAngle, true>* angles, SkTArray<SkOpAngle*, true>* sorted) {
- addTwoAngles(startIndex, endIndex, angles);
- if (!buildAngles(endIndex, angles, includeType == SkOpAngle::kBinaryOpp)) {
+// at this point, the span is already ordered, or unorderable
+int SkOpSegment::computeSum(int startIndex, int endIndex, SkOpAngle::IncludeType includeType) {
+ SkASSERT(includeType != SkOpAngle::kUnaryXor);
+ SkOpAngle* firstAngle = spanToAngle(endIndex, startIndex);
+ if (NULL == firstAngle) {
return SK_NaN32;
}
- int angleCount = angles->count();
- // abort early before sorting if an unsortable (not an unorderable) angle is found
- if (includeType != SkOpAngle::kUnaryXor) {
- int firstIndex = -1;
- while (++firstIndex < angleCount) {
- const SkOpAngle& angle = (*angles)[firstIndex];
- if (angle.segment()->windSum(&angle) != SK_MinS32) {
- break;
- }
- }
- if (firstIndex == angleCount) {
- return SK_MinS32;
- }
- }
- bool sortable = SortAngles2(*angles, sorted);
-#if DEBUG_SORT_RAW
- if (sorted->count() > 0) {
- (*sorted)[0]->segment()->debugShowSort(__FUNCTION__, *sorted, 0, 0, 0, sortable);
- }
-#endif
- if (!sortable) {
- return SK_NaN32;
- }
- if (includeType == SkOpAngle::kUnaryXor) {
- return SK_MinS32;
- }
// if all angles have a computed winding,
// or if no adjacent angles are orderable,
// or if adjacent orderable angles have no computed winding,
// there's nothing to do
- // if two orderable angles are adjacent, and one has winding computed, transfer to the other
- const SkOpAngle* baseAngle = NULL;
- int last = angleCount;
- int finalInitialOrderable = -1;
+ // if two orderable angles are adjacent, and both are next to orderable angles,
+ // and one has winding computed, transfer to the other
+ SkOpAngle* baseAngle = NULL;
bool tryReverse = false;
// look for counterclockwise transfers
+ SkOpAngle* angle = firstAngle->previous();
+ SkOpAngle* next = angle->next();
+ firstAngle = next;
do {
- int index = 0;
+ SkOpAngle* prior = angle;
+ angle = next;
+ next = angle->next();
+ SkASSERT(prior->next() == angle);
+ SkASSERT(angle->next() == next);
+ if (prior->unorderable() || angle->unorderable() || next->unorderable()) {
+ baseAngle = NULL;
+ continue;
+ }
+ int testWinding = angle->segment()->windSum(angle);
+ if (SK_MinS32 != testWinding) {
+ baseAngle = angle;
+ tryReverse = true;
+ continue;
+ }
+ if (baseAngle) {
+ ComputeOneSum(baseAngle, angle, includeType);
+ baseAngle = SK_MinS32 != angle->segment()->windSum(angle) ? angle : NULL;
+ }
+ } while (next != firstAngle);
+ if (baseAngle && SK_MinS32 == firstAngle->segment()->windSum(firstAngle)) {
+ firstAngle = baseAngle;
+ tryReverse = true;
+ }
+ if (tryReverse) {
+ baseAngle = NULL;
+ SkOpAngle* prior = firstAngle;
do {
- SkOpAngle* testAngle = (*sorted)[index];
- int testWinding = testAngle->segment()->windSum(testAngle);
- if (SK_MinS32 != testWinding && !testAngle->unorderable()) {
- baseAngle = testAngle;
- continue;
- }
- if (testAngle->unorderable()) {
+ angle = prior;
+ prior = angle->previous();
+ SkASSERT(prior->next() == angle);
+ next = angle->next();
+ if (prior->unorderable() || angle->unorderable() || next->unorderable()) {
baseAngle = NULL;
- tryReverse = true;
continue;
}
- if (baseAngle) {
- ComputeOneSum(baseAngle, testAngle, includeType);
- baseAngle = SK_MinS32 != testAngle->segment()->windSum(testAngle) ? testAngle
- : NULL;
- tryReverse |= !baseAngle;
+ int testWinding = angle->segment()->windSum(angle);
+ if (SK_MinS32 != testWinding) {
+ baseAngle = angle;
continue;
}
- if (finalInitialOrderable + 1 == index) {
- finalInitialOrderable = index;
- }
- } while (++index != last);
- if (finalInitialOrderable < 0) {
- break;
- }
- last = finalInitialOrderable + 1;
- finalInitialOrderable = -2; // make this always negative the second time through
- } while (baseAngle);
- if (tryReverse) {
- baseAngle = NULL;
- last = 0;
- finalInitialOrderable = angleCount;
- do {
- int index = angleCount;
- while (--index >= last) {
- SkOpAngle* testAngle = (*sorted)[index];
- int testWinding = testAngle->segment()->windSum(testAngle);
- if (SK_MinS32 != testWinding) {
- baseAngle = testAngle;
- continue;
- }
- if (testAngle->unorderable()) {
- baseAngle = NULL;
- continue;
- }
- if (baseAngle) {
- ComputeOneSumReverse(baseAngle, testAngle, includeType);
- baseAngle = SK_MinS32 != testAngle->segment()->windSum(testAngle) ? testAngle
- : NULL;
- continue;
- }
- if (finalInitialOrderable - 1 == index) {
- finalInitialOrderable = index;
- }
- }
- if (finalInitialOrderable >= angleCount) {
- break;
+ if (baseAngle) {
+ ComputeOneSumReverse(baseAngle, angle, includeType);
+ baseAngle = SK_MinS32 != angle->segment()->windSum(angle) ? angle : NULL;
}
- last = finalInitialOrderable;
- finalInitialOrderable = angleCount + 1; // make this inactive 2nd time through
- } while (baseAngle);
+ } while (prior != firstAngle);
}
int minIndex = SkMin32(startIndex, endIndex);
return windSum(minIndex);
@@ -1083,6 +1659,44 @@ void SkOpSegment::ComputeOneSumReverse(const SkOpAngle* baseAngle, SkOpAngle* ne
nextAngle->setLastMarked(last);
}
+bool SkOpSegment::containsPt(const SkPoint& pt, int index, int endIndex) const {
+ int step = index < endIndex ? 1 : -1;
+ do {
+ const SkOpSpan& span = this->span(index);
+ if (span.fPt == pt) {
+ const SkOpSpan& endSpan = this->span(endIndex);
+ return span.fT == endSpan.fT && pt != endSpan.fPt;
+ }
+ index += step;
+ } while (index != endIndex);
+ return false;
+}
+
+bool SkOpSegment::containsT(double t, const SkOpSegment* other, double otherT) const {
+ int count = this->count();
+ for (int index = 0; index < count; ++index) {
+ const SkOpSpan& span = fTs[index];
+ if (t < span.fT) {
+ return false;
+ }
+ if (t == span.fT) {
+ if (other != span.fOther) {
+ continue;
+ }
+ if (other->fVerb != SkPath::kCubic_Verb) {
+ return true;
+ }
+ if (!other->fLoop) {
+ return true;
+ }
+ double otherMidT = (otherT + span.fOtherT) / 2;
+ SkPoint otherPt = other->ptAtT(otherMidT);
+ return SkDPoint::ApproximatelyEqual(span.fPt, otherPt);
+ }
+ }
+ return false;
+}
+
int SkOpSegment::crossedSpanY(const SkPoint& basePt, SkScalar* bestY, double* hitT,
bool* hitSomething, double mid, bool opp, bool current) const {
SkScalar bottom = fBounds.fBottom;
@@ -1206,6 +1820,223 @@ bool SkOpSegment::bumpSpan(SkOpSpan* span, int windDelta, int oppDelta) {
return false;
}
+const SkOpSpan& SkOpSegment::firstSpan(const SkOpSpan& thisSpan) const {
+ const SkOpSpan* firstSpan = &thisSpan; // rewind to the start
+ const SkOpSpan* beginSpan = fTs.begin();
+ const SkPoint& testPt = thisSpan.fPt;
+ while (firstSpan > beginSpan && firstSpan[-1].fPt == testPt) {
+ --firstSpan;
+ }
+ return *firstSpan;
+}
+
+const SkOpSpan& SkOpSegment::lastSpan(const SkOpSpan& thisSpan) const {
+ const SkOpSpan* endSpan = fTs.end() - 1; // last can't be small
+ const SkOpSpan* lastSpan = &thisSpan; // find the end
+ const SkPoint& testPt = thisSpan.fPt;
+ while (lastSpan < endSpan && lastSpan[1].fPt == testPt) {
+ ++lastSpan;
+ }
+ return *lastSpan;
+}
+
+// with a loop, the comparison is move involved
+// scan backwards and forwards to count all matching points
+// (verify that there are twp scans marked as loops)
+// compare that against 2 matching scans for loop plus other results
+bool SkOpSegment::calcLoopSpanCount(const SkOpSpan& thisSpan, int* smallCounts) {
+ const SkOpSpan& firstSpan = this->firstSpan(thisSpan); // rewind to the start
+ const SkOpSpan& lastSpan = this->lastSpan(thisSpan); // find the end
+ double firstLoopT = -1, lastLoopT = -1;
+ const SkOpSpan* testSpan = &firstSpan - 1;
+ while (++testSpan <= &lastSpan) {
+ if (testSpan->fLoop) {
+ firstLoopT = testSpan->fT;
+ break;
+ }
+ }
+ testSpan = &lastSpan + 1;
+ while (--testSpan >= &firstSpan) {
+ if (testSpan->fLoop) {
+ lastLoopT = testSpan->fT;
+ break;
+ }
+ }
+ SkASSERT((firstLoopT == -1) == (lastLoopT == -1));
+ if (firstLoopT == -1) {
+ return false;
+ }
+ SkASSERT(firstLoopT < lastLoopT);
+ testSpan = &firstSpan - 1;
+ smallCounts[0] = smallCounts[1] = 0;
+ while (++testSpan <= &lastSpan) {
+ SkASSERT(approximately_equal(testSpan->fT, firstLoopT) +
+ approximately_equal(testSpan->fT, lastLoopT) == 1);
+ smallCounts[approximately_equal(testSpan->fT, lastLoopT)]++;
+ }
+ return true;
+}
+
+double SkOpSegment::calcMissingTEnd(const SkOpSegment* ref, double loEnd, double min, double max,
+ double hiEnd, const SkOpSegment* other, int thisStart) {
+ if (max >= hiEnd) {
+ return -1;
+ }
+ int end = findOtherT(hiEnd, ref);
+ if (end < 0) {
+ return -1;
+ }
+ double tHi = span(end).fT;
+ double tLo, refLo;
+ if (thisStart >= 0) {
+ tLo = span(thisStart).fT;
+ refLo = min;
+ } else {
+ int start1 = findOtherT(loEnd, ref);
+ SkASSERT(start1 >= 0);
+ tLo = span(start1).fT;
+ refLo = loEnd;
+ }
+ double missingT = (max - refLo) / (hiEnd - refLo);
+ missingT = tLo + missingT * (tHi - tLo);
+ return missingT;
+}
+
+double SkOpSegment::calcMissingTStart(const SkOpSegment* ref, double loEnd, double min, double max,
+ double hiEnd, const SkOpSegment* other, int thisEnd) {
+ if (min <= loEnd) {
+ return -1;
+ }
+ int start = findOtherT(loEnd, ref);
+ if (start < 0) {
+ return -1;
+ }
+ double tLo = span(start).fT;
+ double tHi, refHi;
+ if (thisEnd >= 0) {
+ tHi = span(thisEnd).fT;
+ refHi = max;
+ } else {
+ int end1 = findOtherT(hiEnd, ref);
+ if (end1 < 0) {
+ return -1;
+ }
+ tHi = span(end1).fT;
+ refHi = hiEnd;
+ }
+ double missingT = (min - loEnd) / (refHi - loEnd);
+ missingT = tLo + missingT * (tHi - tLo);
+ return missingT;
+}
+
+// see if spans with two or more intersections have the same number on the other end
+void SkOpSegment::checkDuplicates() {
+ debugValidate();
+ SkSTArray<kMissingSpanCount, MissingSpan, true> missingSpans;
+ int index;
+ int endIndex = 0;
+ bool endFound;
+ do {
+ index = endIndex;
+ endIndex = nextExactSpan(index, 1);
+ if ((endFound = endIndex < 0)) {
+ endIndex = count();
+ }
+ int dupCount = endIndex - index;
+ if (dupCount < 2) {
+ continue;
+ }
+ do {
+ const SkOpSpan* thisSpan = &fTs[index];
+ if (thisSpan->fNear) {
+ continue;
+ }
+ SkOpSegment* other = thisSpan->fOther;
+ int oIndex = thisSpan->fOtherIndex;
+ int oStart = other->nextExactSpan(oIndex, -1) + 1;
+ int oEnd = other->nextExactSpan(oIndex, 1);
+ if (oEnd < 0) {
+ oEnd = other->count();
+ }
+ int oCount = oEnd - oStart;
+ // force the other to match its t and this pt if not on an end point
+ if (oCount != dupCount) {
+ MissingSpan& missing = missingSpans.push_back();
+ missing.fOther = NULL;
+ SkDEBUGCODE(sk_bzero(&missing, sizeof(missing)));
+ missing.fPt = thisSpan->fPt;
+ const SkOpSpan& oSpan = other->span(oIndex);
+ if (oCount > dupCount) {
+ missing.fSegment = this;
+ missing.fT = thisSpan->fT;
+ other->checkLinks(&oSpan, &missingSpans);
+ } else {
+ missing.fSegment = other;
+ missing.fT = oSpan.fT;
+ checkLinks(thisSpan, &missingSpans);
+ }
+ if (!missingSpans.back().fOther) {
+ missingSpans.pop_back();
+ }
+ }
+ } while (++index < endIndex);
+ } while (!endFound);
+ int missingCount = missingSpans.count();
+ if (missingCount == 0) {
+ return;
+ }
+ SkSTArray<kMissingSpanCount, MissingSpan, true> missingCoincidence;
+ for (index = 0; index < missingCount; ++index) {
+ MissingSpan& missing = missingSpans[index];
+ SkOpSegment* missingOther = missing.fOther;
+ if (missing.fSegment == missing.fOther) {
+ continue;
+ }
+#if 0 // FIXME: this eliminates spurious data from skpwww_argus_presse_fr_41 but breaks
+ // skpwww_fashionscandal_com_94 -- calcAngles complains, but I don't understand why
+ if (missing.fSegment->containsT(missing.fT, missing.fOther, missing.fOtherT)) {
+#if DEBUG_DUPLICATES
+ SkDebugf("skip 1 id=%d t=%1.9g other=%d otherT=%1.9g\n", missing.fSegment->fID,
+ missing.fT, missing.fOther->fID, missing.fOtherT);
+#endif
+ continue;
+ }
+ if (missing.fOther->containsT(missing.fOtherT, missing.fSegment, missing.fT)) {
+#if DEBUG_DUPLICATES
+ SkDebugf("skip 2 id=%d t=%1.9g other=%d otherT=%1.9g\n", missing.fOther->fID,
+ missing.fOtherT, missing.fSegment->fID, missing.fT);
+#endif
+ continue;
+ }
+#endif
+ // skip if adding would insert point into an existing coincindent span
+ if (missing.fSegment->inCoincidentSpan(missing.fT, missingOther)
+ && missingOther->inCoincidentSpan(missing.fOtherT, this)) {
+ continue;
+ }
+ // skip if the created coincident spans are small
+ if (missing.fSegment->coincidentSmall(missing.fPt, missing.fT, missingOther)
+ && missingOther->coincidentSmall(missing.fPt, missing.fOtherT, missing.fSegment)) {
+ continue;
+ }
+ const SkOpSpan* added = missing.fSegment->addTPair(missing.fT, missingOther,
+ missing.fOtherT, false, missing.fPt);
+ if (added && added->fSmall) {
+ missing.fSegment->checkSmallCoincidence(*added, &missingCoincidence);
+ }
+ }
+ for (index = 0; index < missingCount; ++index) {
+ MissingSpan& missing = missingSpans[index];
+ missing.fSegment->fixOtherTIndex();
+ missing.fOther->fixOtherTIndex();
+ }
+ for (index = 0; index < missingCoincidence.count(); ++index) {
+ MissingSpan& missing = missingCoincidence[index];
+ missing.fSegment->fixOtherTIndex();
+ }
+ debugValidate();
+}
+
// look to see if the curve end intersects an intermediary that intersects the other
void SkOpSegment::checkEnds() {
debugValidate();
@@ -1313,7 +2144,9 @@ nextPeekIndex:
int missingCount = missingSpans.count();
for (int index = 0; index < missingCount; ++index) {
MissingSpan& missing = missingSpans[index];
- addTPair(missing.fT, missing.fOther, missing.fOtherT, false, missing.fPt);
+ if (this != missing.fOther) {
+ addTPair(missing.fT, missing.fOther, missing.fOtherT, false, missing.fPt);
+ }
}
fixOtherTIndex();
// OPTIMIZATION: this may fix indices more than once. Build an array of unique segments to
@@ -1324,6 +2157,87 @@ nextPeekIndex:
debugValidate();
}
+void SkOpSegment::checkLinks(const SkOpSpan* base,
+ SkTArray<MissingSpan, true>* missingSpans) const {
+ const SkOpSpan* first = fTs.begin();
+ const SkOpSpan* last = fTs.end() - 1;
+ SkASSERT(base >= first && last >= base);
+ const SkOpSegment* other = base->fOther;
+ const SkOpSpan* oFirst = other->fTs.begin();
+ const SkOpSpan* oLast = other->fTs.end() - 1;
+ const SkOpSpan* oSpan = &other->fTs[base->fOtherIndex];
+ const SkOpSpan* test = base;
+ const SkOpSpan* missing = NULL;
+ while (test > first && (--test)->fPt == base->fPt) {
+ CheckOneLink(test, oSpan, oFirst, oLast, &missing, missingSpans);
+ }
+ test = base;
+ while (test < last && (++test)->fPt == base->fPt) {
+ CheckOneLink(test, oSpan, oFirst, oLast, &missing, missingSpans);
+ }
+}
+
+// see if spans with two or more intersections all agree on common t and point values
+void SkOpSegment::checkMultiples() {
+ debugValidate();
+ int index;
+ int end = 0;
+ while (fTs[++end].fT == 0)
+ ;
+ while (fTs[end].fT < 1) {
+ int start = index = end;
+ end = nextExactSpan(index, 1);
+ if (end <= index) {
+ return; // buffer overflow example triggers this
+ }
+ if (index + 1 == end) {
+ continue;
+ }
+ // force the duplicates to agree on t and pt if not on the end
+ SkOpSpan& span = fTs[index];
+ double thisT = span.fT;
+ const SkPoint& thisPt = span.fPt;
+ span.fMultiple = true;
+ bool aligned = false;
+ while (++index < end) {
+ aligned |= alignSpan(index, thisT, thisPt);
+ }
+ if (aligned) {
+ alignSpanState(start, end);
+ }
+ fMultiples = true;
+ }
+ debugValidate();
+}
+
+void SkOpSegment::CheckOneLink(const SkOpSpan* test, const SkOpSpan* oSpan,
+ const SkOpSpan* oFirst, const SkOpSpan* oLast, const SkOpSpan** missingPtr,
+ SkTArray<MissingSpan, true>* missingSpans) {
+ SkASSERT(oSpan->fPt == test->fPt);
+ const SkOpSpan* oTest = oSpan;
+ while (oTest > oFirst && (--oTest)->fPt == test->fPt) {
+ if (oTest->fOther == test->fOther && oTest->fOtherT == test->fOtherT) {
+ return;
+ }
+ }
+ oTest = oSpan;
+ while (oTest < oLast && (++oTest)->fPt == test->fPt) {
+ if (oTest->fOther == test->fOther && oTest->fOtherT == test->fOtherT) {
+ return;
+ }
+ }
+ if (*missingPtr) {
+ missingSpans->push_back();
+ }
+ MissingSpan& lastMissing = missingSpans->back();
+ if (*missingPtr) {
+ lastMissing = missingSpans->end()[-2];
+ }
+ *missingPtr = test;
+ lastMissing.fOther = test->fOther;
+ lastMissing.fOtherT = test->fOtherT;
+}
+
bool SkOpSegment::checkSmall(int index) const {
if (fTs[index].fSmall) {
return true;
@@ -1334,9 +2248,247 @@ bool SkOpSegment::checkSmall(int index) const {
return fTs[index].fSmall;
}
+// a pair of curves may turn into coincident lines -- small may be a hint that that happened
+// if a cubic contains a loop, the counts must be adjusted
+void SkOpSegment::checkSmall() {
+ SkSTArray<kMissingSpanCount, MissingSpan, true> missingSpans;
+ const SkOpSpan* beginSpan = fTs.begin();
+ const SkOpSpan* thisSpan = beginSpan - 1;
+ const SkOpSpan* endSpan = fTs.end() - 1; // last can't be small
+ while (++thisSpan < endSpan) {
+ if (!thisSpan->fSmall) {
+ continue;
+ }
+ if (!thisSpan->fWindValue) {
+ continue;
+ }
+ const SkOpSpan& firstSpan = this->firstSpan(*thisSpan);
+ const SkOpSpan& lastSpan = this->lastSpan(*thisSpan);
+ ptrdiff_t smallCount = &lastSpan - &firstSpan + 1;
+ SkASSERT(1 <= smallCount && smallCount < count());
+ if (smallCount <= 1) {
+ SkASSERT(1 == smallCount);
+ checkSmallCoincidence(firstSpan, NULL);
+ continue;
+ }
+ // at this point, check for missing computed intersections
+ const SkPoint& testPt = firstSpan.fPt;
+ thisSpan = &firstSpan - 1;
+ SkOpSegment* other = NULL;
+ while (++thisSpan <= &lastSpan) {
+ other = thisSpan->fOther;
+ if (other != this) {
+ break;
+ }
+ }
+ SkASSERT(other != this);
+ int oIndex = thisSpan->fOtherIndex;
+ const SkOpSpan& oSpan = other->span(oIndex);
+ const SkOpSpan& oFirstSpan = other->firstSpan(oSpan);
+ const SkOpSpan& oLastSpan = other->lastSpan(oSpan);
+ ptrdiff_t oCount = &oLastSpan - &oFirstSpan + 1;
+ if (fLoop) {
+ int smallCounts[2];
+ SkASSERT(!other->fLoop); // FIXME: we need more complicated logic for pair of loops
+ if (calcLoopSpanCount(*thisSpan, smallCounts)) {
+ if (smallCounts[0] && oCount != smallCounts[0]) {
+ SkASSERT(0); // FIXME: need a working test case to properly code & debug
+ }
+ if (smallCounts[1] && oCount != smallCounts[1]) {
+ SkASSERT(0); // FIXME: need a working test case to properly code & debug
+ }
+ goto nextSmallCheck;
+ }
+ }
+ if (other->fLoop) {
+ int otherCounts[2];
+ if (other->calcLoopSpanCount(other->span(oIndex), otherCounts)) {
+ if (otherCounts[0] && otherCounts[0] != smallCount) {
+ SkASSERT(0); // FIXME: need a working test case to properly code & debug
+ }
+ if (otherCounts[1] && otherCounts[1] != smallCount) {
+ SkASSERT(0); // FIXME: need a working test case to properly code & debug
+ }
+ goto nextSmallCheck;
+ }
+ }
+ if (oCount != smallCount) { // check if number of pts in this match other
+ MissingSpan& missing = missingSpans.push_back();
+ missing.fOther = NULL;
+ SkDEBUGCODE(sk_bzero(&missing, sizeof(missing)));
+ missing.fPt = testPt;
+ const SkOpSpan& oSpan = other->span(oIndex);
+ if (oCount > smallCount) {
+ missing.fSegment = this;
+ missing.fT = thisSpan->fT;
+ other->checkLinks(&oSpan, &missingSpans);
+ } else {
+ missing.fSegment = other;
+ missing.fT = oSpan.fT;
+ checkLinks(thisSpan, &missingSpans);
+ }
+ if (!missingSpans.back().fOther || missing.fSegment->done()) {
+ missingSpans.pop_back();
+ }
+ }
+nextSmallCheck:
+ thisSpan = &lastSpan;
+ }
+ int missingCount = missingSpans.count();
+ for (int index = 0; index < missingCount; ++index) {
+ MissingSpan& missing = missingSpans[index];
+ SkOpSegment* missingOther = missing.fOther;
+ // note that add t pair may edit span arrays, so prior pointers to spans are no longer valid
+ if (!missing.fSegment->addTPair(missing.fT, missingOther, missing.fOtherT, false,
+ missing.fPt)) {
+ continue;
+ }
+ int otherTIndex = missingOther->findT(missing.fOtherT, missing.fPt, missing.fSegment);
+ const SkOpSpan& otherSpan = missingOther->span(otherTIndex);
+ if (otherSpan.fSmall) {
+ const SkOpSpan* nextSpan = &otherSpan;
+ do {
+ ++nextSpan;
+ } while (nextSpan->fSmall);
+ missing.fSegment->addTCoincident(missing.fPt, nextSpan->fPt, nextSpan->fT,
+ missingOther);
+ } else if (otherSpan.fT > 0) {
+ const SkOpSpan* priorSpan = &otherSpan;
+ do {
+ --priorSpan;
+ } while (priorSpan->fT == otherSpan.fT);
+ if (priorSpan->fSmall) {
+ missing.fSegment->addTCancel(missing.fPt, priorSpan->fPt, missingOther);
+ }
+ }
+ }
+ // OPTIMIZATION: this may fix indices more than once. Build an array of unique segments to
+ // avoid this
+ for (int index = 0; index < missingCount; ++index) {
+ MissingSpan& missing = missingSpans[index];
+ missing.fSegment->fixOtherTIndex();
+ missing.fOther->fixOtherTIndex();
+ }
+ debugValidate();
+}
+
+void SkOpSegment::checkSmallCoincidence(const SkOpSpan& span,
+ SkTArray<MissingSpan, true>* checkMultiple) {
+ SkASSERT(span.fSmall);
+ if (0 && !span.fWindValue) {
+ return;
+ }
+ SkASSERT(&span < fTs.end() - 1);
+ const SkOpSpan* next = &span + 1;
+ SkASSERT(!next->fSmall || checkMultiple);
+ if (checkMultiple) {
+ while (next->fSmall) {
+ ++next;
+ SkASSERT(next < fTs.end());
+ }
+ }
+ SkOpSegment* other = span.fOther;
+ while (other != next->fOther) {
+ if (!checkMultiple) {
+ return;
+ }
+ const SkOpSpan* test = next + 1;
+ if (test == fTs.end()) {
+ return;
+ }
+ if (test->fPt != next->fPt || !precisely_equal(test->fT, next->fT)) {
+ return;
+ }
+ next = test;
+ }
+ SkASSERT(span.fT < next->fT);
+ int oStartIndex = other->findExactT(span.fOtherT, this);
+ int oEndIndex = other->findExactT(next->fOtherT, this);
+ // FIXME: be overly conservative by limiting this to the caller that allows multiple smalls
+ if (!checkMultiple || fVerb != SkPath::kLine_Verb || other->fVerb != SkPath::kLine_Verb) {
+ SkPoint mid = ptAtT((span.fT + next->fT) / 2);
+ const SkOpSpan& oSpanStart = other->fTs[oStartIndex];
+ const SkOpSpan& oSpanEnd = other->fTs[oEndIndex];
+ SkPoint oMid = other->ptAtT((oSpanStart.fT + oSpanEnd.fT) / 2);
+ if (!SkDPoint::ApproximatelyEqual(mid, oMid)) {
+ return;
+ }
+ }
+ // FIXME: again, be overly conservative to avoid breaking existing tests
+ const SkOpSpan& oSpan = oStartIndex < oEndIndex ? other->fTs[oStartIndex]
+ : other->fTs[oEndIndex];
+ if (checkMultiple && !oSpan.fSmall) {
+ return;
+ }
+ SkASSERT(oSpan.fSmall);
+ if (oStartIndex < oEndIndex) {
+ addTCoincident(span.fPt, next->fPt, next->fT, other);
+ } else {
+ addTCancel(span.fPt, next->fPt, other);
+ }
+ if (!checkMultiple) {
+ return;
+ }
+ // check to see if either segment is coincident with a third segment -- if it is, and if
+ // the opposite segment is not already coincident with the third, make it so
+ // OPTIMIZE: to make this check easier, add coincident and cancel could set a coincident bit
+ if (span.fWindValue != 1 || span.fOppValue != 0) {
+// start here;
+ // iterate through the spans, looking for the third coincident case
+ // if we find one, we need to return state to the caller so that the indices can be fixed
+ // this also suggests that all of this function is fragile since it relies on a valid index
+ }
+ // probably should make this a common function rather than copy/paste code
+ if (oSpan.fWindValue != 1 || oSpan.fOppValue != 0) {
+ const SkOpSpan* oTest = &oSpan;
+ while (--oTest >= other->fTs.begin()) {
+ if (oTest->fPt != oSpan.fPt || !precisely_equal(oTest->fT, oSpan.fT)) {
+ break;
+ }
+ SkOpSegment* testOther = oTest->fOther;
+ SkASSERT(testOther != this);
+ // look in both directions to see if there is a coincident span
+ const SkOpSpan* tTest = testOther->fTs.begin();
+ for (int testIndex = 0; testIndex < testOther->count(); ++testIndex) {
+ if (tTest->fPt != span.fPt) {
+ ++tTest;
+ continue;
+ }
+ if (testOther->verb() != SkPath::kLine_Verb
+ || other->verb() != SkPath::kLine_Verb) {
+ SkPoint mid = ptAtT((span.fT + next->fT) / 2);
+ SkPoint oMid = other->ptAtT((oTest->fOtherT + tTest->fT) / 2);
+ if (!SkDPoint::ApproximatelyEqual(mid, oMid)) {
+ continue;
+ }
+ }
+#if DEBUG_CONCIDENT
+ SkDebugf("%s coincident found=%d %1.9g %1.9g\n", __FUNCTION__, testOther->fID,
+ oTest->fOtherT, tTest->fT);
+#endif
+ if (tTest->fT < oTest->fOtherT) {
+ addTCoincident(span.fPt, next->fPt, next->fT, testOther);
+ } else {
+ addTCancel(span.fPt, next->fPt, testOther);
+ }
+ MissingSpan missing;
+ missing.fSegment = testOther;
+ checkMultiple->push_back(missing);
+ break;
+ }
+ }
+ oTest = &oSpan;
+ while (++oTest < other->fTs.end()) {
+ if (oTest->fPt != oSpan.fPt || !precisely_equal(oTest->fT, oSpan.fT)) {
+ break;
+ }
+
+ }
+ }
+}
+
// if pair of spans on either side of tiny have the same end point and mid point, mark
// them as parallel
-// OPTIMIZATION : mark the segment to note that some span is tiny
void SkOpSegment::checkTiny() {
SkSTArray<kMissingSpanCount, MissingSpan, true> missingSpans;
SkOpSpan* thisSpan = fTs.begin() - 1;
@@ -1401,8 +2553,12 @@ void SkOpSegment::checkTiny() {
}
for (int index = 0; index < missingCount; ++index) {
MissingSpan& missing = missingSpans[index];
- missing.fSegment->addTPair(missing.fT, missing.fOther, missing.fOtherT, false, missing.fPt);
+ if (missing.fSegment != missing.fOther) {
+ missing.fSegment->addTPair(missing.fT, missing.fOther, missing.fOtherT, false,
+ missing.fPt);
+ }
}
+ // OPTIMIZE: consolidate to avoid multiple calls to fix index
for (int index = 0; index < missingCount; ++index) {
MissingSpan& missing = missingSpans[index];
missing.fSegment->fixOtherTIndex();
@@ -1410,6 +2566,30 @@ void SkOpSegment::checkTiny() {
}
}
+bool SkOpSegment::coincidentSmall(const SkPoint& pt, double t, const SkOpSegment* other) const {
+ int count = this->count();
+ for (int index = 0; index < count; ++index) {
+ const SkOpSpan& span = this->span(index);
+ if (span.fOther != other) {
+ continue;
+ }
+ if (span.fPt == pt) {
+ continue;
+ }
+ if (!AlmostEqualUlps(span.fPt, pt)) {
+ continue;
+ }
+ if (fVerb != SkPath::kCubic_Verb) {
+ return true;
+ }
+ double tInterval = t - span.fT;
+ double tMid = t - tInterval / 2;
+ SkDPoint midPt = dcubic_xy_at_t(fPts, tMid);
+ return midPt.approximatelyEqual(xyAtT(t));
+ }
+ return false;
+}
+
bool SkOpSegment::findCoincidentMatch(const SkOpSpan* span, const SkOpSegment* other, int oStart,
int oEnd, int step, SkPoint* startPt, SkPoint* endPt, double* endT) const {
SkASSERT(span->fT == 0 || span->fT == 1);
@@ -1474,6 +2654,16 @@ bool SkOpSegment::findCoincidentMatch(const SkOpSpan* span, const SkOpSegment* o
return false;
}
+int SkOpSegment::findEndSpan(int endIndex) const {
+ const SkOpSpan* span = &fTs[--endIndex];
+ const SkPoint& lastPt = span->fPt;
+ double endT = span->fT;
+ do {
+ span = &fTs[--endIndex];
+ } while (SkDPoint::ApproximatelyEqual(span->fPt, lastPt) && (span->fT == endT || span->fTiny));
+ return endIndex + 1;
+}
+
/*
The M and S variable name parts stand for the operators.
Mi stands for Minuend (see wiki subtraction, analogous to difference)
@@ -1489,12 +2679,11 @@ SkOpSegment* SkOpSegment::findNextOp(SkTDArray<SkOpSpan*>* chase, int* nextStart
SkASSERT(startIndex != endIndex);
SkDEBUGCODE(const int count = fTs.count());
SkASSERT(startIndex < endIndex ? startIndex < count - 1 : startIndex > 0);
- const int step = SkSign32(endIndex - startIndex);
- const int end = nextExactSpan(startIndex, step);
- SkASSERT(end >= 0);
- SkOpSpan* endSpan = &fTs[end];
- SkOpSegment* other;
- if (isSimple(end)) {
+ int step = SkSign32(endIndex - startIndex);
+ *nextStart = startIndex;
+ SkOpSegment* other = isSimple(nextStart, &step);
+ if (other)
+ {
// mark the smaller of startIndex, endIndex done, and all adjacent
// spans with the same T value (but not 'other' spans)
#if DEBUG_WINDING
@@ -1505,8 +2694,6 @@ SkOpSegment* SkOpSegment::findNextOp(SkTDArray<SkOpSpan*>* chase, int* nextStart
return NULL;
}
markDoneBinary(min);
- other = endSpan->fOther;
- *nextStart = endSpan->fOtherIndex;
double startT = other->fTs[*nextStart].fT;
*nextEnd = *nextStart;
do {
@@ -1519,61 +2706,55 @@ SkOpSegment* SkOpSegment::findNextOp(SkTDArray<SkOpSpan*>* chase, int* nextStart
}
return other;
}
- // more than one viable candidate -- measure angles to find best
- SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles;
+ const int end = nextExactSpan(startIndex, step);
+ SkASSERT(end >= 0);
SkASSERT(startIndex - endIndex != 0);
SkASSERT((startIndex - endIndex < 0) ^ (step < 0));
- SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted;
- int calcWinding = computeSum(startIndex, end, SkOpAngle::kBinaryOpp, &angles, &sorted);
+ // more than one viable candidate -- measure angles to find best
+
+ int calcWinding = computeSum(startIndex, end, SkOpAngle::kBinaryOpp);
bool sortable = calcWinding != SK_NaN32;
- if (sortable && sorted.count() == 0) {
- // if no edge has a computed winding sum, we can go no further
+ if (!sortable) {
*unsortable = true;
+ markDoneBinary(SkMin32(startIndex, endIndex));
return NULL;
}
- int angleCount = angles.count();
- int firstIndex = findStartingEdge(sorted, startIndex, end);
- SkASSERT(!sortable || firstIndex >= 0);
-#if DEBUG_SORT
- debugShowSort(__FUNCTION__, sorted, firstIndex, sortable);
-#endif
- if (!sortable) {
+ SkOpAngle* angle = spanToAngle(end, startIndex);
+ if (angle->unorderable()) {
*unsortable = true;
+ markDoneBinary(SkMin32(startIndex, endIndex));
return NULL;
}
- SkASSERT(sorted[firstIndex]->segment() == this);
-#if DEBUG_WINDING
- SkDebugf("%s firstIndex=[%d] sign=%d\n", __FUNCTION__, firstIndex,
- sorted[firstIndex]->sign());
+#if DEBUG_SORT
+ SkDebugf("%s\n", __FUNCTION__);
+ angle->debugLoop();
#endif
int sumMiWinding = updateWinding(endIndex, startIndex);
+ if (sumMiWinding == SK_MinS32) {
+ *unsortable = true;
+ markDoneBinary(SkMin32(startIndex, endIndex));
+ return NULL;
+ }
int sumSuWinding = updateOppWinding(endIndex, startIndex);
if (operand()) {
SkTSwap<int>(sumMiWinding, sumSuWinding);
}
- int nextIndex = firstIndex + 1;
- int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
+ SkOpAngle* nextAngle = angle->next();
const SkOpAngle* foundAngle = NULL;
bool foundDone = false;
// iterate through the angle, and compute everyone's winding
SkOpSegment* nextSegment;
int activeCount = 0;
do {
- SkASSERT(nextIndex != firstIndex);
- if (nextIndex == angleCount) {
- nextIndex = 0;
- }
- const SkOpAngle* nextAngle = sorted[nextIndex];
nextSegment = nextAngle->segment();
- int maxWinding, sumWinding, oppMaxWinding, oppSumWinding;
bool activeAngle = nextSegment->activeOp(xorMiMask, xorSuMask, nextAngle->start(),
- nextAngle->end(), op, &sumMiWinding, &sumSuWinding,
- &maxWinding, &sumWinding, &oppMaxWinding, &oppSumWinding);
+ nextAngle->end(), op, &sumMiWinding, &sumSuWinding);
if (activeAngle) {
++activeCount;
if (!foundAngle || (foundDone && activeCount & 1)) {
if (nextSegment->isTiny(nextAngle)) {
*unsortable = true;
+ markDoneBinary(SkMin32(startIndex, endIndex));
return NULL;
}
foundAngle = nextAngle;
@@ -1587,10 +2768,11 @@ SkOpSegment* SkOpSegment::findNextOp(SkTDArray<SkOpSpan*>* chase, int* nextStart
continue;
}
if (!activeAngle) {
- nextSegment->markAndChaseDoneBinary(nextAngle->start(), nextAngle->end());
+ (void) nextSegment->markAndChaseDoneBinary(nextAngle->start(), nextAngle->end());
}
SkOpSpan* last = nextAngle->lastMarked();
if (last) {
+ SkASSERT(!SkPathOpsDebug::ChaseContains(*chase, last));
*chase->append() = last;
#if DEBUG_WINDING
SkDebugf("%s chase.append id=%d windSum=%d small=%d\n", __FUNCTION__,
@@ -1598,7 +2780,13 @@ SkOpSegment* SkOpSegment::findNextOp(SkTDArray<SkOpSpan*>* chase, int* nextStart
last->fSmall);
#endif
}
- } while (++nextIndex != lastIndex);
+ } while ((nextAngle = nextAngle->next()) != angle);
+#if DEBUG_ANGLE
+ if (foundAngle) {
+ foundAngle->debugSameAs(foundAngle);
+ }
+#endif
+
markDoneBinary(SkMin32(startIndex, endIndex));
if (!foundAngle) {
return NULL;
@@ -1620,12 +2808,11 @@ SkOpSegment* SkOpSegment::findNextWinding(SkTDArray<SkOpSpan*>* chase, int* next
SkASSERT(startIndex != endIndex);
SkDEBUGCODE(const int count = fTs.count());
SkASSERT(startIndex < endIndex ? startIndex < count - 1 : startIndex > 0);
- const int step = SkSign32(endIndex - startIndex);
- const int end = nextExactSpan(startIndex, step);
- SkASSERT(end >= 0);
- SkOpSpan* endSpan = &fTs[end];
- SkOpSegment* other;
- if (isSimple(end)) {
+ int step = SkSign32(endIndex - startIndex);
+ *nextStart = startIndex;
+ SkOpSegment* other = isSimple(nextStart, &step);
+ if (other)
+ {
// mark the smaller of startIndex, endIndex done, and all adjacent
// spans with the same T value (but not 'other' spans)
#if DEBUG_WINDING
@@ -1636,8 +2823,6 @@ SkOpSegment* SkOpSegment::findNextWinding(SkTDArray<SkOpSpan*>* chase, int* next
return NULL;
}
markDoneUnary(min);
- other = endSpan->fOther;
- *nextStart = endSpan->fOtherIndex;
double startT = other->fTs[*nextStart].fT;
*nextEnd = *nextStart;
do {
@@ -1650,51 +2835,40 @@ SkOpSegment* SkOpSegment::findNextWinding(SkTDArray<SkOpSpan*>* chase, int* next
}
return other;
}
- // more than one viable candidate -- measure angles to find best
- SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles;
+ const int end = nextExactSpan(startIndex, step);
+ SkASSERT(end >= 0);
SkASSERT(startIndex - endIndex != 0);
SkASSERT((startIndex - endIndex < 0) ^ (step < 0));
- SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted;
- int calcWinding = computeSum(startIndex, end, SkOpAngle::kUnaryWinding, &angles, &sorted);
+ // more than one viable candidate -- measure angles to find best
+
+ int calcWinding = computeSum(startIndex, end, SkOpAngle::kUnaryWinding);
bool sortable = calcWinding != SK_NaN32;
- int angleCount = angles.count();
- int firstIndex = findStartingEdge(sorted, startIndex, end);
- SkASSERT(!sortable || firstIndex >= 0);
-#if DEBUG_SORT
- debugShowSort(__FUNCTION__, sorted, firstIndex, sortable);
-#endif
if (!sortable) {
*unsortable = true;
+ markDoneUnary(SkMin32(startIndex, endIndex));
return NULL;
}
- SkASSERT(sorted[firstIndex]->segment() == this);
-#if DEBUG_WINDING
- SkDebugf("%s firstIndex=[%d] sign=%d\n", __FUNCTION__, firstIndex,
- sorted[firstIndex]->sign());
+ SkOpAngle* angle = spanToAngle(end, startIndex);
+#if DEBUG_SORT
+ SkDebugf("%s\n", __FUNCTION__);
+ angle->debugLoop();
#endif
int sumWinding = updateWinding(endIndex, startIndex);
- int nextIndex = firstIndex + 1;
- int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
+ SkOpAngle* nextAngle = angle->next();
const SkOpAngle* foundAngle = NULL;
bool foundDone = false;
- // iterate through the angle, and compute everyone's winding
SkOpSegment* nextSegment;
int activeCount = 0;
do {
- SkASSERT(nextIndex != firstIndex);
- if (nextIndex == angleCount) {
- nextIndex = 0;
- }
- const SkOpAngle* nextAngle = sorted[nextIndex];
nextSegment = nextAngle->segment();
- int maxWinding;
bool activeAngle = nextSegment->activeWinding(nextAngle->start(), nextAngle->end(),
- &maxWinding, &sumWinding);
+ &sumWinding);
if (activeAngle) {
++activeCount;
if (!foundAngle || (foundDone && activeCount & 1)) {
if (nextSegment->isTiny(nextAngle)) {
*unsortable = true;
+ markDoneUnary(SkMin32(startIndex, endIndex));
return NULL;
}
foundAngle = nextAngle;
@@ -1712,6 +2886,7 @@ SkOpSegment* SkOpSegment::findNextWinding(SkTDArray<SkOpSpan*>* chase, int* next
}
SkOpSpan* last = nextAngle->lastMarked();
if (last) {
+ SkASSERT(!SkPathOpsDebug::ChaseContains(*chase, last));
*chase->append() = last;
#if DEBUG_WINDING
SkDebugf("%s chase.append id=%d windSum=%d small=%d\n", __FUNCTION__,
@@ -1719,7 +2894,7 @@ SkOpSegment* SkOpSegment::findNextWinding(SkTDArray<SkOpSpan*>* chase, int* next
last->fSmall);
#endif
}
- } while (++nextIndex != lastIndex);
+ } while ((nextAngle = nextAngle->next()) != angle);
markDoneUnary(SkMin32(startIndex, endIndex));
if (!foundAngle) {
return NULL;
@@ -1741,11 +2916,12 @@ SkOpSegment* SkOpSegment::findNextXor(int* nextStart, int* nextEnd, bool* unsort
SkDEBUGCODE(int count = fTs.count());
SkASSERT(startIndex < endIndex ? startIndex < count - 1 : startIndex > 0);
int step = SkSign32(endIndex - startIndex);
- int end = nextExactSpan(startIndex, step);
- SkASSERT(end >= 0);
- SkOpSpan* endSpan = &fTs[end];
- SkOpSegment* other;
- if (isSimple(end)) {
+// Detect cases where all the ends canceled out (e.g.,
+// there is no angle) and therefore there's only one valid connection
+ *nextStart = startIndex;
+ SkOpSegment* other = isSimple(nextStart, &step);
+ if (other)
+ {
#if DEBUG_WINDING
SkDebugf("%s simple\n", __FUNCTION__);
#endif
@@ -1754,8 +2930,6 @@ SkOpSegment* SkOpSegment::findNextXor(int* nextStart, int* nextEnd, bool* unsort
return NULL;
}
markDone(min, 1);
- other = endSpan->fOther;
- *nextStart = endSpan->fOtherIndex;
double startT = other->fTs[*nextStart].fT;
// FIXME: I don't know why the logic here is difference from the winding case
SkDEBUGCODE(bool firstLoop = true;)
@@ -1779,39 +2953,23 @@ SkOpSegment* SkOpSegment::findNextXor(int* nextStart, int* nextEnd, bool* unsort
SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count());
return other;
}
- SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles;
SkASSERT(startIndex - endIndex != 0);
SkASSERT((startIndex - endIndex < 0) ^ (step < 0));
- SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted;
- int calcWinding = computeSum(startIndex, end, SkOpAngle::kUnaryXor, &angles, &sorted);
- bool sortable = calcWinding != SK_NaN32;
- int angleCount = angles.count();
- int firstIndex = findStartingEdge(sorted, startIndex, end);
- SkASSERT(!sortable || firstIndex >= 0);
+ // parallel block above with presorted version
+ int end = nextExactSpan(startIndex, step);
+ SkASSERT(end >= 0);
+ SkOpAngle* angle = spanToAngle(end, startIndex);
+ SkASSERT(angle);
#if DEBUG_SORT
- debugShowSort(__FUNCTION__, sorted, firstIndex, 0, 0, sortable);
+ SkDebugf("%s\n", __FUNCTION__);
+ angle->debugLoop();
#endif
- if (!sortable) {
- *unsortable = true;
- return NULL;
- }
- SkASSERT(sorted[firstIndex]->segment() == this);
-#if DEBUG_WINDING
- SkDebugf("%s firstIndex=[%d] sign=%d\n", __FUNCTION__, firstIndex,
- sorted[firstIndex]->sign());
-#endif
- int nextIndex = firstIndex + 1;
- int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
+ SkOpAngle* nextAngle = angle->next();
const SkOpAngle* foundAngle = NULL;
bool foundDone = false;
SkOpSegment* nextSegment;
int activeCount = 0;
do {
- SkASSERT(nextIndex != firstIndex);
- if (nextIndex == angleCount) {
- nextIndex = 0;
- }
- const SkOpAngle* nextAngle = sorted[nextIndex];
nextSegment = nextAngle->segment();
++activeCount;
if (!foundAngle || (foundDone && activeCount & 1)) {
@@ -1820,12 +2978,12 @@ SkOpSegment* SkOpSegment::findNextXor(int* nextStart, int* nextEnd, bool* unsort
return NULL;
}
foundAngle = nextAngle;
- foundDone = nextSegment->done(nextAngle);
- }
- if (nextSegment->done()) {
- continue;
+ if (!(foundDone = nextSegment->done(nextAngle))) {
+ break;
+ }
}
- } while (++nextIndex != lastIndex);
+ nextAngle = nextAngle->next();
+ } while (nextAngle != angle);
markDone(SkMin32(startIndex, endIndex), 1);
if (!foundAngle) {
return NULL;
@@ -1840,21 +2998,21 @@ SkOpSegment* SkOpSegment::findNextXor(int* nextStart, int* nextEnd, bool* unsort
return nextSegment;
}
-int SkOpSegment::findStartingEdge(const SkTArray<SkOpAngle*, true>& sorted, int start, int end) {
- int angleCount = sorted.count();
- int firstIndex = -1;
- for (int angleIndex = 0; angleIndex < angleCount; ++angleIndex) {
- const SkOpAngle* angle = sorted[angleIndex];
- if (angle->segment() == this && angle->start() == end &&
- angle->end() == start) {
- firstIndex = angleIndex;
- break;
- }
- }
- return firstIndex;
+int SkOpSegment::findStartSpan(int startIndex) const {
+ int index = startIndex;
+ const SkOpSpan* span = &fTs[index];
+ const SkPoint& firstPt = span->fPt;
+ double firstT = span->fT;
+ const SkOpSpan* prior;
+ do {
+ prior = span;
+ span = &fTs[++index];
+ } while (SkDPoint::ApproximatelyEqual(span->fPt, firstPt)
+ && (span->fT == firstT || prior->fTiny));
+ return index;
}
-int SkOpSegment::findT(double t, const SkOpSegment* match) const {
+int SkOpSegment::findExactT(double t, const SkOpSegment* match) const {
int count = this->count();
for (int index = 0; index < count; ++index) {
const SkOpSpan& span = fTs[index];
@@ -1866,23 +3024,47 @@ int SkOpSegment::findT(double t, const SkOpSegment* match) const {
return -1;
}
-// FIXME: either:
-// a) mark spans with either end unsortable as done, or
-// b) rewrite findTop / findTopSegment / findTopContour to iterate further
-// when encountering an unsortable span
+int SkOpSegment::findOtherT(double t, const SkOpSegment* match) const {
+ int count = this->count();
+ for (int index = 0; index < count; ++index) {
+ const SkOpSpan& span = fTs[index];
+ if (span.fOtherT == t && span.fOther == match) {
+ return index;
+ }
+ }
+ return -1;
+}
+
+int SkOpSegment::findT(double t, const SkPoint& pt, const SkOpSegment* match) const {
+ int count = this->count();
+ for (int index = 0; index < count; ++index) {
+ const SkOpSpan& span = fTs[index];
+ if (approximately_equal_orderable(span.fT, t) && span.fOther == match) {
+ return index;
+ }
+ }
+ // Usually, the pair of ts are an exact match. It's possible that the t values have
+ // been adjusted to make multiple intersections align. In this rare case, look for a
+ // matching point / match pair instead.
+ for (int index = 0; index < count; ++index) {
+ const SkOpSpan& span = fTs[index];
+ if (span.fPt == pt && span.fOther == match) {
+ return index;
+ }
+ }
+ SkASSERT(0);
+ return -1;
+}
-// OPTIMIZATION : for a pair of lines, can we compute points at T (cached)
-// and use more concise logic like the old edge walker code?
-// FIXME: this needs to deal with coincident edges
SkOpSegment* SkOpSegment::findTop(int* tIndexPtr, int* endIndexPtr, bool* unsortable,
- bool onlySortable) {
+ bool firstPass) {
// iterate through T intersections and return topmost
// topmost tangent from y-min to first pt is closer to horizontal
SkASSERT(!done());
int firstT = -1;
- /* SkPoint topPt = */ activeLeftTop(onlySortable, &firstT);
+ /* SkPoint topPt = */ activeLeftTop(&firstT);
if (firstT < 0) {
- *unsortable = true;
+ *unsortable = !firstPass;
firstT = 0;
while (fTs[firstT].fDone) {
SkASSERT(firstT < fTs.count());
@@ -1894,69 +3076,74 @@ SkOpSegment* SkOpSegment::findTop(int* tIndexPtr, int* endIndexPtr, bool* unsort
}
// sort the edges to find the leftmost
int step = 1;
- int end = nextSpan(firstT, step);
- if (end == -1) {
+ int end;
+ if (span(firstT).fDone || (end = nextSpan(firstT, step)) == -1) {
step = -1;
end = nextSpan(firstT, step);
SkASSERT(end != -1);
}
// if the topmost T is not on end, or is three-way or more, find left
// look for left-ness from tLeft to firstT (matching y of other)
- SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles;
SkASSERT(firstT - end != 0);
- addTwoAngles(end, firstT, &angles);
- if (!buildAngles(firstT, &angles, true) && onlySortable) {
-// *unsortable = true;
-// return NULL;
- }
- SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted;
- bool sortable = SortAngles(angles, &sorted, SkOpSegment::kMayBeUnordered_SortAngleKind);
- if (onlySortable && !sortable) {
- *unsortable = true;
- return NULL;
+ SkOpAngle* markAngle = spanToAngle(firstT, end);
+ if (!markAngle) {
+ markAngle = addSingletonAngles(step);
+ }
+ markAngle->markStops();
+ const SkOpAngle* baseAngle = markAngle->next() == markAngle && !isVertical() ? markAngle
+ : markAngle->findFirst();
+ if (!baseAngle) {
+ return NULL; // nothing to do
}
- int first = SK_MaxS32;
SkScalar top = SK_ScalarMax;
- int count = sorted.count();
- for (int index = 0; index < count; ++index) {
- const SkOpAngle* angle = sorted[index];
- if (onlySortable && angle->unorderable()) {
- continue;
- }
- SkOpSegment* next = angle->segment();
- SkPathOpsBounds bounds;
- next->subDivideBounds(angle->end(), angle->start(), &bounds);
- if (approximately_greater(top, bounds.fTop)) {
- top = bounds.fTop;
- first = index;
+ const SkOpAngle* firstAngle = NULL;
+ const SkOpAngle* angle = baseAngle;
+ do {
+ if (!angle->unorderable()) {
+ SkOpSegment* next = angle->segment();
+ SkPathOpsBounds bounds;
+ next->subDivideBounds(angle->end(), angle->start(), &bounds);
+ if (approximately_greater(top, bounds.fTop)) {
+ top = bounds.fTop;
+ firstAngle = angle;
+ }
}
- }
- SkASSERT(first < SK_MaxS32);
-#if DEBUG_SORT // || DEBUG_SWAP_TOP
- sorted[first]->segment()->debugShowSort(__FUNCTION__, sorted, first, 0, 0, sortable);
+ angle = angle->next();
+ } while (angle != baseAngle);
+ SkASSERT(firstAngle);
+#if DEBUG_SORT
+ SkDebugf("%s\n", __FUNCTION__);
+ firstAngle->debugLoop();
#endif
// skip edges that have already been processed
- firstT = first - 1;
- SkOpSegment* leftSegment;
+ angle = firstAngle;
+ SkOpSegment* leftSegment = NULL;
+ bool looped = false;
do {
- if (++firstT == count) {
- firstT = 0;
- }
- const SkOpAngle* angle = sorted[firstT];
- SkASSERT(!onlySortable || !angle->unsortable());
- leftSegment = angle->segment();
- *tIndexPtr = angle->end();
- *endIndexPtr = angle->start();
- } while (leftSegment->fTs[SkMin32(*tIndexPtr, *endIndexPtr)].fDone);
+ *unsortable = angle->unorderable();
+ if (firstPass || !*unsortable) {
+ leftSegment = angle->segment();
+ *tIndexPtr = angle->end();
+ *endIndexPtr = angle->start();
+ if (!leftSegment->fTs[SkMin32(*tIndexPtr, *endIndexPtr)].fDone) {
+ break;
+ }
+ }
+ angle = angle->next();
+ looped = true;
+ } while (angle != firstAngle);
+ if (angle == firstAngle && looped) {
+ return NULL;
+ }
if (leftSegment->verb() >= SkPath::kQuad_Verb) {
const int tIndex = *tIndexPtr;
const int endIndex = *endIndexPtr;
- if (!leftSegment->clockwise(tIndex, endIndex)) {
- bool swap = !leftSegment->monotonicInY(tIndex, endIndex)
- && !leftSegment->serpentine(tIndex, endIndex);
+ bool swap;
+ if (!leftSegment->clockwise(tIndex, endIndex, &swap)) {
#if DEBUG_SWAP_TOP
- SkDebugf("%s swap=%d serpentine=%d containedByEnds=%d monotonic=%d\n", __FUNCTION__,
- swap,
+ SkDebugf("%s swap=%d inflections=%d serpentine=%d controlledbyends=%d monotonic=%d\n",
+ __FUNCTION__,
+ swap, leftSegment->debugInflections(tIndex, endIndex),
leftSegment->serpentine(tIndex, endIndex),
leftSegment->controlsContainedByEnds(tIndex, endIndex),
leftSegment->monotonicInY(tIndex, endIndex));
@@ -1972,6 +3159,14 @@ SkOpSegment* SkOpSegment::findTop(int* tIndexPtr, int* endIndexPtr, bool* unsort
return leftSegment;
}
+int SkOpSegment::firstActive(int tIndex) const {
+ while (fTs[tIndex].fTiny) {
+ SkASSERT(!isCanceled(tIndex));
+ ++tIndex;
+ }
+ return tIndex;
+}
+
// FIXME: not crazy about this
// when the intersections are performed, the other index is into an
// incomplete array. As the array grows, the indices become incorrect
@@ -1999,20 +3194,40 @@ void SkOpSegment::fixOtherTIndex() {
}
}
+bool SkOpSegment::inCoincidentSpan(double t, const SkOpSegment* other) const {
+ int foundEnds = 0;
+ int count = this->count();
+ for (int index = 0; index < count; ++index) {
+ const SkOpSpan& span = this->span(index);
+ if (span.fCoincident) {
+ foundEnds |= (span.fOther == other) << ((t > span.fT) + (t >= span.fT));
+ }
+ }
+ SkASSERT(foundEnds != 7);
+ return foundEnds == 0x3 || foundEnds == 0x5 || foundEnds == 0x6; // two bits set
+}
+
void SkOpSegment::init(const SkPoint pts[], SkPath::Verb verb, bool operand, bool evenOdd) {
fDoneSpans = 0;
fOperand = operand;
fXor = evenOdd;
fPts = pts;
fVerb = verb;
+ fLoop = fMultiples = fSmall = fTiny = false;
}
-void SkOpSegment::initWinding(int start, int end) {
+void SkOpSegment::initWinding(int start, int end, SkOpAngle::IncludeType angleIncludeType) {
int local = spanSign(start, end);
- int oppLocal = oppSign(start, end);
- (void) markAndChaseWinding(start, end, local, oppLocal);
+ if (angleIncludeType == SkOpAngle::kBinarySingle) {
+ int oppLocal = oppSign(start, end);
+ (void) markAndChaseWinding(start, end, local, oppLocal);
// OPTIMIZATION: the reverse mark and chase could skip the first marking
- (void) markAndChaseWinding(end, start, local, oppLocal);
+ (void) markAndChaseWinding(end, start, local, oppLocal);
+ } else {
+ (void) markAndChaseWinding(start, end, local);
+ // OPTIMIZATION: the reverse mark and chase could skip the first marking
+ (void) markAndChaseWinding(end, start, local);
+ }
}
/*
@@ -2031,20 +3246,13 @@ void SkOpSegment::initWinding(int start, int end, double tHit, int winding, SkSc
SkASSERT(dx);
int windVal = windValue(SkMin32(start, end));
#if DEBUG_WINDING_AT_T
- SkDebugf("%s oldWinding=%d hitDx=%c dx=%c windVal=%d", __FUNCTION__, winding,
+ SkDebugf("%s id=%d oldWinding=%d hitDx=%c dx=%c windVal=%d", __FUNCTION__, debugID(), winding,
hitDx ? hitDx > 0 ? '+' : '-' : '0', dx > 0 ? '+' : '-', windVal);
#endif
- if (!winding) {
- winding = dx < 0 ? windVal : -windVal;
- } else if (winding * dx < 0) {
- int sideWind = winding + (dx < 0 ? windVal : -windVal);
- if (abs(winding) < abs(sideWind)) {
- winding = sideWind;
- }
+ int sideWind = winding + (dx < 0 ? windVal : -windVal);
+ if (abs(winding) < abs(sideWind)) {
+ winding = sideWind;
}
-#if DEBUG_WINDING_AT_T
- SkDebugf(" winding=%d\n", winding);
-#endif
SkDEBUGCODE(int oppLocal = oppSign(start, end));
SkASSERT(hitOppDx || !oppWind || !oppLocal);
int oppWindVal = oppValue(SkMin32(start, end));
@@ -2056,16 +3264,37 @@ void SkOpSegment::initWinding(int start, int end, double tHit, int winding, SkSc
oppWind = oppSideWind;
}
}
+#if DEBUG_WINDING_AT_T
+ SkDebugf(" winding=%d oppWind=%d\n", winding, oppWind);
+#endif
(void) markAndChaseWinding(start, end, winding, oppWind);
// OPTIMIZATION: the reverse mark and chase could skip the first marking
(void) markAndChaseWinding(end, start, winding, oppWind);
}
+bool SkOpSegment::inLoop(const SkOpAngle* baseAngle, int spanCount, int* indexPtr) const {
+ if (!baseAngle->inLoop()) {
+ return false;
+ }
+ int index = *indexPtr;
+ SkOpAngle* from = fTs[index].fFromAngle;
+ SkOpAngle* to = fTs[index].fToAngle;
+ while (++index < spanCount) {
+ SkOpAngle* nextFrom = fTs[index].fFromAngle;
+ SkOpAngle* nextTo = fTs[index].fToAngle;
+ if (from != nextFrom || to != nextTo) {
+ break;
+ }
+ }
+ *indexPtr = index;
+ return true;
+}
+
// OPTIMIZE: successive calls could start were the last leaves off
// or calls could specialize to walk forwards or backwards
bool SkOpSegment::isMissing(double startT, const SkPoint& pt) const {
- size_t tCount = fTs.count();
- for (size_t index = 0; index < tCount; ++index) {
+ int tCount = fTs.count();
+ for (int index = 0; index < tCount; ++index) {
const SkOpSpan& span = fTs[index];
if (approximately_zero(startT - span.fT) && pt == span.fPt) {
return false;
@@ -2074,19 +3303,9 @@ bool SkOpSegment::isMissing(double startT, const SkPoint& pt) const {
return true;
}
-bool SkOpSegment::isSimple(int end) const {
- int count = fTs.count();
- if (count == 2) {
- return true;
- }
- double t = fTs[end].fT;
- if (approximately_less_than_zero(t)) {
- return !approximately_less_than_zero(fTs[1].fT);
- }
- if (approximately_greater_than_one(t)) {
- return !approximately_greater_than_one(fTs[count - 2].fT);
- }
- return false;
+
+SkOpSegment* SkOpSegment::isSimple(int* end, int* step) {
+ return nextChase(end, step, NULL, NULL);
}
bool SkOpSegment::isTiny(const SkOpAngle* angle) const {
@@ -2103,13 +3322,13 @@ bool SkOpSegment::isTiny(int index) const {
// look pair of active edges going away from coincident edge
// one of them should be the continuation of other
// if both are active, look to see if they both the connect to another coincident pair
-// if one at least one is a line, then make the pair coincident
+// if at least one is a line, then make the pair coincident
// if neither is a line, test for coincidence
-bool SkOpSegment::joinCoincidence(SkOpSegment* other, double otherT, int step,
- bool cancel) {
- int otherTIndex = other->findT(otherT, this);
+bool SkOpSegment::joinCoincidence(SkOpSegment* other, double otherT, const SkPoint& otherPt,
+ int step, bool cancel) {
+ int otherTIndex = other->findT(otherT, otherPt, this);
int next = other->nextExactSpan(otherTIndex, step);
- int otherMin = SkTMin(otherTIndex, next);
+ int otherMin = SkMin32(otherTIndex, next);
int otherWind = other->span(otherMin).fWindValue;
if (otherWind == 0) {
return false;
@@ -2145,11 +3364,12 @@ SkOpSpan* SkOpSegment::markAndChaseDoneBinary(int index, int endIndex) {
int step = SkSign32(endIndex - index);
int min = SkMin32(index, endIndex);
markDoneBinary(min);
- SkOpSpan* last;
+ SkOpSpan* last = NULL;
SkOpSegment* other = this;
- while ((other = other->nextChase(&index, step, &min, &last))) {
+ while ((other = other->nextChase(&index, &step, &min, &last))) {
if (other->done()) {
- return NULL;
+ SkASSERT(!last);
+ break;
}
other->markDoneBinary(min);
}
@@ -2160,29 +3380,48 @@ SkOpSpan* SkOpSegment::markAndChaseDoneUnary(int index, int endIndex) {
int step = SkSign32(endIndex - index);
int min = SkMin32(index, endIndex);
markDoneUnary(min);
- SkOpSpan* last;
+ SkOpSpan* last = NULL;
SkOpSegment* other = this;
- while ((other = other->nextChase(&index, step, &min, &last))) {
+ while ((other = other->nextChase(&index, &step, &min, &last))) {
if (other->done()) {
- return NULL;
+ SkASSERT(!last);
+ break;
}
other->markDoneUnary(min);
}
return last;
}
-SkOpSpan* SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, const int winding) {
+SkOpSpan* SkOpSegment::markAndChaseWinding(const SkOpAngle* angle, int winding) {
int index = angle->start();
int endIndex = angle->end();
int step = SkSign32(endIndex - index);
int min = SkMin32(index, endIndex);
markWinding(min, winding);
- SkOpSpan* last;
+ SkOpSpan* last = NULL;
SkOpSegment* other = this;
- while ((other = other->nextChase(&index, step, &min, &last))) {
+ while ((other = other->nextChase(&index, &step, &min, &last))) {
if (other->fTs[min].fWindSum != SK_MinS32) {
SkASSERT(other->fTs[min].fWindSum == winding);
- return NULL;
+ SkASSERT(!last);
+ break;
+ }
+ other->markWinding(min, winding);
+ }
+ return last;
+}
+
+SkOpSpan* SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding) {
+ int min = SkMin32(index, endIndex);
+ int step = SkSign32(endIndex - index);
+ markWinding(min, winding);
+ SkOpSpan* last = NULL;
+ SkOpSegment* other = this;
+ while ((other = other->nextChase(&index, &step, &min, &last))) {
+ if (other->fTs[min].fWindSum != SK_MinS32) {
+ SkASSERT(other->fTs[min].fWindSum == winding || other->fTs[min].fLoop);
+ SkASSERT(!last);
+ break;
}
other->markWinding(min, winding);
}
@@ -2193,14 +3432,32 @@ SkOpSpan* SkOpSegment::markAndChaseWinding(int index, int endIndex, int winding,
int min = SkMin32(index, endIndex);
int step = SkSign32(endIndex - index);
markWinding(min, winding, oppWinding);
- SkOpSpan* last;
+ SkOpSpan* last = NULL;
SkOpSegment* other = this;
- while ((other = other->nextChase(&index, step, &min, &last))) {
+ while ((other = other->nextChase(&index, &step, &min, &last))) {
if (other->fTs[min].fWindSum != SK_MinS32) {
- SkASSERT(other->fTs[min].fWindSum == winding || other->fTs[min].fLoop);
- return NULL;
+#ifdef SK_DEBUG
+ if (!other->fTs[min].fLoop) {
+ if (fOperand == other->fOperand) {
+// FIXME: this is probably a bug -- rects4 asserts here
+// SkASSERT(other->fTs[min].fWindSum == winding);
+// FIXME: this is probably a bug -- rects3 asserts here
+// SkASSERT(other->fTs[min].fOppSum == oppWinding);
+ } else {
+ SkASSERT(other->fTs[min].fWindSum == oppWinding);
+// FIXME: this is probably a bug -- skpwww_joomla_org_23 asserts here
+// SkASSERT(other->fTs[min].fOppSum == winding);
+ }
+ }
+ SkASSERT(!last);
+#endif
+ break;
+ }
+ if (fOperand == other->fOperand) {
+ other->markWinding(min, winding, oppWinding);
+ } else {
+ other->markWinding(min, oppWinding, winding);
}
- other->markWinding(min, winding, oppWinding);
}
return last;
}
@@ -2265,6 +3522,7 @@ void SkOpSegment::markDone(int index, int winding) {
do {
markOneDone(__FUNCTION__, index, winding);
} while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT));
+ debugValidate();
}
void SkOpSegment::markDoneBinary(int index) {
@@ -2276,6 +3534,7 @@ void SkOpSegment::markDoneBinary(int index) {
do {
markOneDoneBinary(__FUNCTION__, index);
} while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT));
+ debugValidate();
}
void SkOpSegment::markDoneUnary(int index) {
@@ -2287,11 +3546,12 @@ void SkOpSegment::markDoneUnary(int index) {
do {
markOneDoneUnary(__FUNCTION__, index);
} while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT));
+ debugValidate();
}
void SkOpSegment::markOneDone(const char* funName, int tIndex, int winding) {
SkOpSpan* span = markOneWinding(funName, tIndex, winding);
- if (!span) {
+ if (!span || span->fDone) {
return;
}
span->fDone = true;
@@ -2303,6 +3563,7 @@ void SkOpSegment::markOneDoneBinary(const char* funName, int tIndex) {
if (!span) {
return;
}
+ SkASSERT(!span->fDone);
span->fDone = true;
fDoneSpans++;
}
@@ -2312,20 +3573,26 @@ void SkOpSegment::markOneDoneUnary(const char* funName, int tIndex) {
if (!span) {
return;
}
+ if (span->fWindSum == SK_MinS32) {
+ SkDebugf("%s uncomputed\n", __FUNCTION__);
+ }
+ SkASSERT(!span->fDone);
span->fDone = true;
fDoneSpans++;
}
SkOpSpan* SkOpSegment::markOneWinding(const char* funName, int tIndex, int winding) {
SkOpSpan& span = fTs[tIndex];
- if (span.fDone) {
+ if (span.fDone && !span.fSmall) {
return NULL;
}
#if DEBUG_MARK_DONE
debugShowNewWinding(funName, span, winding);
#endif
SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding);
- SkASSERT(abs(winding) <= SkPathOpsDebug::gMaxWindSum);
+#if DEBUG_LIMIT_WIND_SUM
+ SkASSERT(abs(winding) <= DEBUG_LIMIT_WIND_SUM);
+#endif
span.fWindSum = winding;
return &span;
}
@@ -2340,22 +3607,59 @@ SkOpSpan* SkOpSegment::markOneWinding(const char* funName, int tIndex, int windi
debugShowNewWinding(funName, span, winding, oppWinding);
#endif
SkASSERT(span.fWindSum == SK_MinS32 || span.fWindSum == winding);
- SkASSERT(abs(winding) <= SkPathOpsDebug::gMaxWindSum);
+#if DEBUG_LIMIT_WIND_SUM
+ SkASSERT(abs(winding) <= DEBUG_LIMIT_WIND_SUM);
+#endif
span.fWindSum = winding;
SkASSERT(span.fOppSum == SK_MinS32 || span.fOppSum == oppWinding);
- SkASSERT(abs(oppWinding) <= SkPathOpsDebug::gMaxWindSum);
+#if DEBUG_LIMIT_WIND_SUM
+ SkASSERT(abs(oppWinding) <= DEBUG_LIMIT_WIND_SUM);
+#endif
span.fOppSum = oppWinding;
+ debugValidate();
return &span;
}
// from http://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of-polygon-points-are-in-clockwise-order
-bool SkOpSegment::clockwise(int tStart, int tEnd) const {
+bool SkOpSegment::clockwise(int tStart, int tEnd, bool* swap) const {
SkASSERT(fVerb != SkPath::kLine_Verb);
SkPoint edge[4];
subDivide(tStart, tEnd, edge);
int points = SkPathOpsVerbToPoints(fVerb);
double sum = (edge[0].fX - edge[points].fX) * (edge[0].fY + edge[points].fY);
+ bool sumSet = false;
if (fVerb == SkPath::kCubic_Verb) {
+ SkDCubic cubic;
+ cubic.set(edge);
+ double inflectionTs[2];
+ int inflections = cubic.findInflections(inflectionTs);
+ // FIXME: this fixes cubicOp114 and breaks cubicOp58d
+ // the trouble is that cubics with inflections confuse whether the curve breaks towards
+ // or away, which in turn is used to determine if it is on the far right or left.
+ // Probably a totally different approach is in order. At one time I tried to project a
+ // horizontal ray to determine winding, but was confused by how to map the vertically
+ // oriented winding computation over.
+ if (0 && inflections) {
+ double tLo = this->span(tStart).fT;
+ double tHi = this->span(tEnd).fT;
+ double tLoStart = tLo;
+ for (int index = 0; index < inflections; ++index) {
+ if (between(tLo, inflectionTs[index], tHi)) {
+ tLo = inflectionTs[index];
+ }
+ }
+ if (tLo != tLoStart && tLo != tHi) {
+ SkDPoint sub[2];
+ sub[0] = cubic.ptAtT(tLo);
+ sub[1].set(edge[3]);
+ SkDPoint ctrl[2];
+ SkDCubic::SubDivide(fPts, sub[0], sub[1], tLo, tHi, ctrl);
+ edge[0] = sub[0].asSkPoint();
+ edge[1] = ctrl[0].asSkPoint();
+ edge[2] = ctrl[1].asSkPoint();
+ sum = (edge[0].fX - edge[3].fX) * (edge[0].fY + edge[3].fY);
+ }
+ }
SkScalar lesser = SkTMin<SkScalar>(edge[0].fY, edge[3].fY);
if (edge[1].fY < lesser && edge[2].fY < lesser) {
SkDLine tangent1 = {{ {edge[0].fX, edge[0].fY}, {edge[1].fX, edge[1].fY} }};
@@ -2364,20 +3668,29 @@ bool SkOpSegment::clockwise(int tStart, int tEnd) const {
SkPoint topPt = cubic_top(fPts, fTs[tStart].fT, fTs[tEnd].fT);
sum += (topPt.fX - edge[0].fX) * (topPt.fY + edge[0].fY);
sum += (edge[3].fX - topPt.fX) * (edge[3].fY + topPt.fY);
- return sum <= 0;
+ sumSet = true;
}
}
}
- for (int idx = 0; idx < points; ++idx){
- sum += (edge[idx + 1].fX - edge[idx].fX) * (edge[idx + 1].fY + edge[idx].fY);
+ if (!sumSet) {
+ for (int idx = 0; idx < points; ++idx){
+ sum += (edge[idx + 1].fX - edge[idx].fX) * (edge[idx + 1].fY + edge[idx].fY);
+ }
+ }
+ if (fVerb == SkPath::kCubic_Verb) {
+ SkDCubic cubic;
+ cubic.set(edge);
+ *swap = sum > 0 && !cubic.monotonicInY() && !cubic.serpentine();
+ } else {
+ SkDQuad quad;
+ quad.set(edge);
+ *swap = sum > 0 && !quad.monotonicInY();
}
return sum <= 0;
}
bool SkOpSegment::monotonicInY(int tStart, int tEnd) const {
- if (fVerb == SkPath::kLine_Verb) {
- return false;
- }
+ SkASSERT(fVerb != SkPath::kLine_Verb);
if (fVerb == SkPath::kQuad_Verb) {
SkDQuad dst = SkDQuad::SubDivide(fPts, fTs[tStart].fT, fTs[tEnd].fT);
return dst.monotonicInY();
@@ -2428,31 +3741,6 @@ SkOpSpan* SkOpSegment::verifyOneWindingU(const char* funName, int tIndex) {
return &span;
}
-// note that just because a span has one end that is unsortable, that's
-// not enough to mark it done. The other end may be sortable, allowing the
-// span to be added.
-// FIXME: if abs(start - end) > 1, mark intermediates as unsortable on both ends
-void SkOpSegment::markUnsortable(int start, int end) {
- SkOpSpan* span = &fTs[start];
- if (start < end) {
-#if DEBUG_UNSORTABLE
- debugShowNewWinding(__FUNCTION__, *span, 0);
-#endif
- span->fUnsortableStart = true;
- } else {
- --span;
-#if DEBUG_UNSORTABLE
- debugShowNewWinding(__FUNCTION__, *span, 0);
-#endif
- span->fUnsortableEnd = true;
- }
- if (!span->fUnsortableStart || !span->fUnsortableEnd || span->fDone) {
- return;
- }
- span->fDone = true;
- fDoneSpans++;
-}
-
void SkOpSegment::markWinding(int index, int winding) {
// SkASSERT(!done());
SkASSERT(winding);
@@ -2464,6 +3752,7 @@ void SkOpSegment::markWinding(int index, int winding) {
do {
markOneWinding(__FUNCTION__, index, winding);
} while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT));
+ debugValidate();
}
void SkOpSegment::markWinding(int index, int winding, int oppWinding) {
@@ -2477,13 +3766,29 @@ void SkOpSegment::markWinding(int index, int winding, int oppWinding) {
do {
markOneWinding(__FUNCTION__, index, winding, oppWinding);
} while (++index < fTs.count() && precisely_negative(fTs[index].fT - referenceT));
+ debugValidate();
}
void SkOpSegment::matchWindingValue(int tIndex, double t, bool borrowWind) {
int nextDoorWind = SK_MaxS32;
int nextOppWind = SK_MaxS32;
+ // prefer exact matches
if (tIndex > 0) {
const SkOpSpan& below = fTs[tIndex - 1];
+ if (below.fT == t) {
+ nextDoorWind = below.fWindValue;
+ nextOppWind = below.fOppValue;
+ }
+ }
+ if (nextDoorWind == SK_MaxS32 && tIndex + 1 < fTs.count()) {
+ const SkOpSpan& above = fTs[tIndex + 1];
+ if (above.fT == t) {
+ nextDoorWind = above.fWindValue;
+ nextOppWind = above.fOppValue;
+ }
+ }
+ if (nextDoorWind == SK_MaxS32 && tIndex > 0) {
+ const SkOpSpan& below = fTs[tIndex - 1];
if (approximately_negative(t - below.fT)) {
nextDoorWind = below.fWindValue;
nextOppWind = below.fOppValue;
@@ -2512,15 +3817,6 @@ void SkOpSegment::matchWindingValue(int tIndex, double t, bool borrowWind) {
}
}
-// return span if when chasing, two or more radiating spans are not done
-// OPTIMIZATION: ? multiple spans is detected when there is only one valid
-// candidate and the remaining spans have windValue == 0 (canceled by
-// coincidence). The coincident edges could either be removed altogether,
-// or this code could be more complicated in detecting this case. Worth it?
-bool SkOpSegment::multipleSpans(int end) const {
- return end > 0 && end < fTs.count() - 1;
-}
-
bool SkOpSegment::nextCandidate(int* start, int* end) const {
while (fTs[*end].fDone) {
if (fTs[*end].fT == 1) {
@@ -2533,27 +3829,67 @@ bool SkOpSegment::nextCandidate(int* start, int* end) const {
return true;
}
-SkOpSegment* SkOpSegment::nextChase(int* index, const int step, int* min, SkOpSpan** last) {
- int end = nextExactSpan(*index, step);
+static SkOpSegment* set_last(SkOpSpan** last, SkOpSpan* endSpan) {
+ if (last && !endSpan->fSmall) {
+ *last = endSpan;
+ }
+ return NULL;
+}
+
+SkOpSegment* SkOpSegment::nextChase(int* indexPtr, int* stepPtr, int* minPtr, SkOpSpan** last) {
+ int origIndex = *indexPtr;
+ int step = *stepPtr;
+ int end = nextExactSpan(origIndex, step);
SkASSERT(end >= 0);
- if (fTs[end].fSmall) {
- *last = NULL;
- return NULL;
+ SkOpSpan& endSpan = fTs[end];
+ SkOpAngle* angle = step > 0 ? endSpan.fFromAngle : endSpan.fToAngle;
+ int foundIndex;
+ int otherEnd;
+ SkOpSegment* other;
+ if (angle == NULL) {
+ if (endSpan.fT != 0 && endSpan.fT != 1) {
+ return NULL;
+ }
+ other = endSpan.fOther;
+ foundIndex = endSpan.fOtherIndex;
+ otherEnd = other->nextExactSpan(foundIndex, step);
+ } else {
+ int loopCount = angle->loopCount();
+ if (loopCount > 2) {
+ return set_last(last, &endSpan);
+ }
+ const SkOpAngle* next = angle->next();
+ if (angle->sign() != next->sign()) {
+#if DEBUG_WINDING
+ SkDebugf("%s mismatched signs\n", __FUNCTION__);
+#endif
+ // return set_last(last, &endSpan);
+ }
+ other = next->segment();
+ foundIndex = end = next->start();
+ otherEnd = next->end();
}
- if (multipleSpans(end)) {
- *last = &fTs[end];
- return NULL;
+ int foundStep = foundIndex < otherEnd ? 1 : -1;
+ if (*stepPtr != foundStep) {
+ return set_last(last, &endSpan);
}
- const SkOpSpan& endSpan = fTs[end];
- SkOpSegment* other = endSpan.fOther;
- *index = endSpan.fOtherIndex;
- SkASSERT(*index >= 0);
- int otherEnd = other->nextExactSpan(*index, step);
+ SkASSERT(*indexPtr >= 0);
SkASSERT(otherEnd >= 0);
- *min = SkMin32(*index, otherEnd);
- if (other->fTs[*min].fSmall) {
- *last = NULL;
- return NULL;
+#if 1
+ int origMin = origIndex + (step < 0 ? step : 0);
+ const SkOpSpan& orig = this->span(origMin);
+#endif
+ int foundMin = SkMin32(foundIndex, otherEnd);
+#if 1
+ const SkOpSpan& found = other->span(foundMin);
+ if (found.fWindValue != orig.fWindValue || found.fOppValue != orig.fOppValue) {
+ return set_last(last, &endSpan);
+ }
+#endif
+ *indexPtr = foundIndex;
+ *stepPtr = foundStep;
+ if (minPtr) {
+ *minPtr = foundMin;
}
return other;
}
@@ -2610,6 +3946,27 @@ int SkOpSegment::nextExactSpan(int from, int step) const {
return -1;
}
+void SkOpSegment::pinT(const SkPoint& pt, double* t) {
+ if (pt == fPts[0]) {
+ *t = 0;
+ }
+ int count = SkPathOpsVerbToPoints(fVerb);
+ if (pt == fPts[count]) {
+ *t = 1;
+ }
+}
+
+void SkOpSegment::setCoincidentRange(const SkPoint& startPt, const SkPoint& endPt,
+ SkOpSegment* other) {
+ int count = this->count();
+ for (int index = 0; index < count; ++index) {
+ SkOpSpan &span = fTs[index];
+ if ((startPt == span.fPt || endPt == span.fPt) && other == span.fOther) {
+ span.fCoincident = true;
+ }
+ }
+}
+
void SkOpSegment::setUpWindings(int index, int endIndex, int* sumMiWinding, int* sumSuWinding,
int* maxWinding, int* sumWinding, int* oppMaxWinding, int* oppSumWinding) {
int deltaSum = spanSign(index, endIndex);
@@ -2625,8 +3982,10 @@ void SkOpSegment::setUpWindings(int index, int endIndex, int* sumMiWinding, int*
*oppMaxWinding = *sumSuWinding;
*oppSumWinding = *sumSuWinding -= oppDeltaSum;
}
- SkASSERT(abs(*sumWinding) <= SkPathOpsDebug::gMaxWindSum);
- SkASSERT(abs(*oppSumWinding) <= SkPathOpsDebug::gMaxWindSum);
+#if DEBUG_LIMIT_WIND_SUM
+ SkASSERT(abs(*sumWinding) <= DEBUG_LIMIT_WIND_SUM);
+ SkASSERT(abs(*oppSumWinding) <= DEBUG_LIMIT_WIND_SUM);
+#endif
}
void SkOpSegment::setUpWindings(int index, int endIndex, int* sumMiWinding,
@@ -2634,73 +3993,106 @@ void SkOpSegment::setUpWindings(int index, int endIndex, int* sumMiWinding,
int deltaSum = spanSign(index, endIndex);
*maxWinding = *sumMiWinding;
*sumWinding = *sumMiWinding -= deltaSum;
- SkASSERT(abs(*sumWinding) <= SkPathOpsDebug::gMaxWindSum);
-}
-
-// This marks all spans unsortable so that this info is available for early
-// exclusion in find top and others. This could be optimized to only mark
-// adjacent spans that unsortable. However, this makes it difficult to later
-// determine starting points for edge detection in find top and the like.
-bool SkOpSegment::SortAngles(const SkTArray<SkOpAngle, true>& angles,
- SkTArray<SkOpAngle*, true>* angleList,
- SortAngleKind orderKind) {
- bool sortable = true;
- int angleCount = angles.count();
- int angleIndex;
- for (angleIndex = 0; angleIndex < angleCount; ++angleIndex) {
- const SkOpAngle& angle = angles[angleIndex];
- angleList->push_back(const_cast<SkOpAngle*>(&angle));
-#if DEBUG_ANGLE
- (*(angleList->end() - 1))->setID(angleIndex);
+#if DEBUG_LIMIT_WIND_SUM
+ SkASSERT(abs(*sumWinding) <= DEBUG_LIMIT_WIND_SUM);
#endif
- sortable &= !(angle.unsortable() || (orderKind == kMustBeOrdered_SortAngleKind
- && angle.unorderable()));
- }
- if (sortable) {
- SkTQSort<SkOpAngle>(angleList->begin(), angleList->end() - 1);
- for (angleIndex = 0; angleIndex < angleCount; ++angleIndex) {
- if (angles[angleIndex].unsortable() || (orderKind == kMustBeOrdered_SortAngleKind
- && angles[angleIndex].unorderable())) {
- sortable = false;
- break;
+}
+
+void SkOpSegment::sortAngles() {
+ int spanCount = fTs.count();
+ if (spanCount <= 2) {
+ return;
+ }
+ int index = 0;
+ do {
+ SkOpAngle* fromAngle = fTs[index].fFromAngle;
+ SkOpAngle* toAngle = fTs[index].fToAngle;
+ if (!fromAngle && !toAngle) {
+ index += 1;
+ continue;
+ }
+ SkOpAngle* baseAngle = NULL;
+ if (fromAngle) {
+ baseAngle = fromAngle;
+ if (inLoop(baseAngle, spanCount, &index)) {
+ continue;
}
}
- }
- if (!sortable) {
- for (angleIndex = 0; angleIndex < angleCount; ++angleIndex) {
- const SkOpAngle& angle = angles[angleIndex];
- angle.segment()->markUnsortable(angle.start(), angle.end());
- }
- }
- return sortable;
-}
-
-// set segments to unsortable if angle is unsortable, but do not set all angles
-// note that for a simple 4 way crossing, two of the edges may be orderable even though
-// two edges are too short to be orderable.
-// perhaps some classes of unsortable angles should make all shared angles unsortable, but
-// simple lines that have tiny crossings are always sortable on the large ends
-// OPTIMIZATION: check earlier when angles are added to input if any are unsortable
-// may make sense then to mark all segments in angle sweep as unsortableStart/unsortableEnd
-// solely for the purpose of short-circuiting future angle building around this center
-bool SkOpSegment::SortAngles2(const SkTArray<SkOpAngle, true>& angles,
- SkTArray<SkOpAngle*, true>* angleList) {
- int angleCount = angles.count();
- int angleIndex;
- for (angleIndex = 0; angleIndex < angleCount; ++angleIndex) {
- const SkOpAngle& angle = angles[angleIndex];
- if (angle.unsortable()) {
- return false;
+#if DEBUG_ANGLE
+ bool wroteAfterHeader = false;
+#endif
+ if (toAngle) {
+ if (!baseAngle) {
+ baseAngle = toAngle;
+ if (inLoop(baseAngle, spanCount, &index)) {
+ continue;
+ }
+ } else {
+ SkDEBUGCODE(int newIndex = index);
+ SkASSERT(!inLoop(baseAngle, spanCount, &newIndex) && newIndex == index);
+#if DEBUG_ANGLE
+ SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(), fTs[index].fT,
+ index);
+ wroteAfterHeader = true;
+#endif
+ baseAngle->insert(toAngle);
+ }
}
- angleList->push_back(const_cast<SkOpAngle*>(&angle));
+ SkOpAngle* nextFrom, * nextTo;
+ int firstIndex = index;
+ do {
+ SkOpSpan& span = fTs[index];
+ SkOpSegment* other = span.fOther;
+ SkOpSpan& oSpan = other->fTs[span.fOtherIndex];
+ SkOpAngle* oAngle = oSpan.fFromAngle;
+ if (oAngle) {
#if DEBUG_ANGLE
- (*(angleList->end() - 1))->setID(angleIndex);
+ if (!wroteAfterHeader) {
+ SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(), fTs[index].fT,
+ index);
+ wroteAfterHeader = true;
+ }
#endif
- }
- SkTQSort<SkOpAngle>(angleList->begin(), angleList->end() - 1);
- // at this point angles are sorted but individually may not be orderable
- // this means that only adjcent orderable segments may transfer winding
- return true;
+ if (!oAngle->loopContains(*baseAngle)) {
+ baseAngle->insert(oAngle);
+ }
+ }
+ oAngle = oSpan.fToAngle;
+ if (oAngle) {
+#if DEBUG_ANGLE
+ if (!wroteAfterHeader) {
+ SkDebugf("%s [%d] tStart=%1.9g [%d]\n", __FUNCTION__, debugID(), fTs[index].fT,
+ index);
+ wroteAfterHeader = true;
+ }
+#endif
+ if (!oAngle->loopContains(*baseAngle)) {
+ baseAngle->insert(oAngle);
+ }
+ }
+ if (++index == spanCount) {
+ break;
+ }
+ nextFrom = fTs[index].fFromAngle;
+ nextTo = fTs[index].fToAngle;
+ } while (fromAngle == nextFrom && toAngle == nextTo);
+ if (baseAngle && baseAngle->loopCount() == 1) {
+ index = firstIndex;
+ do {
+ SkOpSpan& span = fTs[index];
+ span.fFromAngle = span.fToAngle = NULL;
+ if (++index == spanCount) {
+ break;
+ }
+ nextFrom = fTs[index].fFromAngle;
+ nextTo = fTs[index].fToAngle;
+ } while (fromAngle == nextFrom && toAngle == nextTo);
+ baseAngle = NULL;
+ }
+#if DEBUG_SORT
+ SkASSERT(!baseAngle || baseAngle->loopCount() > 1);
+#endif
+ } while (index < spanCount);
}
// return true if midpoints were computed
@@ -2802,8 +4194,8 @@ void SkOpSegment::TrackOutside(SkTArray<SkPoint, true>* outsidePts, const SkPoin
}
void SkOpSegment::undoneSpan(int* start, int* end) {
- size_t tCount = fTs.count();
- size_t index;
+ int tCount = fTs.count();
+ int index;
for (index = 0; index < tCount; ++index) {
if (!fTs[index].fDone) {
break;
@@ -2844,6 +4236,9 @@ int SkOpSegment::updateOppWindingReverse(const SkOpAngle* angle) const {
int SkOpSegment::updateWinding(int index, int endIndex) const {
int lesser = SkMin32(index, endIndex);
int winding = windSum(lesser);
+ if (winding == SK_MinS32) {
+ return winding;
+ }
int spanWinding = spanSign(index, endIndex);
if (winding && UseInnerWinding(winding - spanWinding, winding)
&& winding != SK_MaxS32) {
@@ -2904,7 +4299,8 @@ int SkOpSegment::windingAtT(double tHit, int tIndex, bool crossOpp, SkScalar* dx
SkASSERT(winding != SK_MinS32);
int windVal = crossOpp ? oppValue(tIndex) : windValue(tIndex);
#if DEBUG_WINDING_AT_T
- SkDebugf("%s oldWinding=%d windValue=%d", __FUNCTION__, winding, windVal);
+ SkDebugf("%s id=%d opp=%d tHit=%1.9g t=%1.9g oldWinding=%d windValue=%d", __FUNCTION__,
+ debugID(), crossOpp, tHit, t(tIndex), winding, windVal);
#endif
// see if a + change in T results in a +/- change in X (compute x'(T))
*dx = (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, tHit).fX;
@@ -2947,382 +4343,3 @@ void SkOpSegment::zeroSpan(SkOpSpan* span) {
span->fDone = true;
++fDoneSpans;
}
-
-#if DEBUG_SWAP_TOP
-bool SkOpSegment::controlsContainedByEnds(int tStart, int tEnd) const {
- if (fVerb != SkPath::kCubic_Verb) {
- return false;
- }
- SkDCubic dst = SkDCubic::SubDivide(fPts, fTs[tStart].fT, fTs[tEnd].fT);
- return dst.controlsContainedByEnds();
-}
-#endif
-
-#if DEBUG_CONCIDENT
-// SkASSERT if pair has not already been added
-void SkOpSegment::debugAddTPair(double t, const SkOpSegment& other, double otherT) const {
- for (int i = 0; i < fTs.count(); ++i) {
- if (fTs[i].fT == t && fTs[i].fOther == &other && fTs[i].fOtherT == otherT) {
- return;
- }
- }
- SkASSERT(0);
-}
-#endif
-
-#if DEBUG_CONCIDENT
-void SkOpSegment::debugShowTs(const char* prefix) const {
- SkDebugf("%s %s id=%d", __FUNCTION__, prefix, fID);
- int lastWind = -1;
- int lastOpp = -1;
- double lastT = -1;
- int i;
- for (i = 0; i < fTs.count(); ++i) {
- bool change = lastT != fTs[i].fT || lastWind != fTs[i].fWindValue
- || lastOpp != fTs[i].fOppValue;
- if (change && lastWind >= 0) {
- SkDebugf(" t=%1.3g %1.9g,%1.9g w=%d o=%d]",
- lastT, xyAtT(i - 1).fX, xyAtT(i - 1).fY, lastWind, lastOpp);
- }
- if (change) {
- SkDebugf(" [o=%d", fTs[i].fOther->fID);
- lastWind = fTs[i].fWindValue;
- lastOpp = fTs[i].fOppValue;
- lastT = fTs[i].fT;
- } else {
- SkDebugf(",%d", fTs[i].fOther->fID);
- }
- }
- if (i <= 0) {
- return;
- }
- SkDebugf(" t=%1.3g %1.9g,%1.9g w=%d o=%d]",
- lastT, xyAtT(i - 1).fX, xyAtT(i - 1).fY, lastWind, lastOpp);
- if (fOperand) {
- SkDebugf(" operand");
- }
- if (done()) {
- SkDebugf(" done");
- }
- SkDebugf("\n");
-}
-#endif
-
-#if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY
-void SkOpSegment::debugShowActiveSpans() const {
- debugValidate();
- if (done()) {
- return;
- }
-#if DEBUG_ACTIVE_SPANS_SHORT_FORM
- int lastId = -1;
- double lastT = -1;
-#endif
- for (int i = 0; i < fTs.count(); ++i) {
- if (fTs[i].fDone) {
- continue;
- }
- SkASSERT(i < fTs.count() - 1);
-#if DEBUG_ACTIVE_SPANS_SHORT_FORM
- if (lastId == fID && lastT == fTs[i].fT) {
- continue;
- }
- lastId = fID;
- lastT = fTs[i].fT;
-#endif
- SkDebugf("%s id=%d", __FUNCTION__, fID);
- SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
- for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
- SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
- }
- const SkOpSpan* span = &fTs[i];
- SkDebugf(") t=%1.9g (%1.9g,%1.9g)", span->fT, xAtT(span), yAtT(span));
- int iEnd = i + 1;
- while (fTs[iEnd].fT < 1 && approximately_equal(fTs[i].fT, fTs[iEnd].fT)) {
- ++iEnd;
- }
- SkDebugf(" tEnd=%1.9g", fTs[iEnd].fT);
- const SkOpSegment* other = fTs[i].fOther;
- SkDebugf(" other=%d otherT=%1.9g otherIndex=%d windSum=",
- other->fID, fTs[i].fOtherT, fTs[i].fOtherIndex);
- if (fTs[i].fWindSum == SK_MinS32) {
- SkDebugf("?");
- } else {
- SkDebugf("%d", fTs[i].fWindSum);
- }
- SkDebugf(" windValue=%d oppValue=%d\n", fTs[i].fWindValue, fTs[i].fOppValue);
- }
-}
-#endif
-
-
-#if DEBUG_MARK_DONE || DEBUG_UNSORTABLE
-void SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding) {
- const SkPoint& pt = xyAtT(&span);
- SkDebugf("%s id=%d", fun, fID);
- SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
- for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
- SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
- }
- SkASSERT(&span == &span.fOther->fTs[span.fOtherIndex].fOther->
- fTs[span.fOther->fTs[span.fOtherIndex].fOtherIndex]);
- SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=%d windSum=",
- span.fT, span.fOther->fTs[span.fOtherIndex].fOtherIndex, pt.fX, pt.fY,
- (&span)[1].fT, winding);
- if (span.fWindSum == SK_MinS32) {
- SkDebugf("?");
- } else {
- SkDebugf("%d", span.fWindSum);
- }
- SkDebugf(" windValue=%d\n", span.fWindValue);
-}
-
-void SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding,
- int oppWinding) {
- const SkPoint& pt = xyAtT(&span);
- SkDebugf("%s id=%d", fun, fID);
- SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
- for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
- SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
- }
- SkASSERT(&span == &span.fOther->fTs[span.fOtherIndex].fOther->
- fTs[span.fOther->fTs[span.fOtherIndex].fOtherIndex]);
- SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=%d newOppSum=%d oppSum=",
- span.fT, span.fOther->fTs[span.fOtherIndex].fOtherIndex, pt.fX, pt.fY,
- (&span)[1].fT, winding, oppWinding);
- if (span.fOppSum == SK_MinS32) {
- SkDebugf("?");
- } else {
- SkDebugf("%d", span.fOppSum);
- }
- SkDebugf(" windSum=");
- if (span.fWindSum == SK_MinS32) {
- SkDebugf("?");
- } else {
- SkDebugf("%d", span.fWindSum);
- }
- SkDebugf(" windValue=%d\n", span.fWindValue);
-}
-#endif
-
-#if DEBUG_SORT || DEBUG_SWAP_TOP
-void SkOpSegment::debugShowSort(const char* fun, const SkTArray<SkOpAngle*, true>& angles,
- int first, const int contourWinding,
- const int oppContourWinding, bool sortable) const {
- if (--SkPathOpsDebug::gSortCount < 0) {
- return;
- }
- if (!sortable) {
- if (angles.count() == 0) {
- return;
- }
- if (first < 0) {
- first = 0;
- }
- }
- SkASSERT(angles[first]->segment() == this);
- SkASSERT(!sortable || angles.count() > 1);
- int lastSum = contourWinding;
- int oppLastSum = oppContourWinding;
- const SkOpAngle* firstAngle = angles[first];
- int windSum = lastSum - spanSign(firstAngle);
- int oppoSign = oppSign(firstAngle);
- int oppWindSum = oppLastSum - oppoSign;
- #define WIND_AS_STRING(x) char x##Str[12]; \
- if (!SkPathOpsDebug::ValidWind(x)) strcpy(x##Str, "?"); \
- else SK_SNPRINTF(x##Str, sizeof(x##Str), "%d", x)
- WIND_AS_STRING(contourWinding);
- WIND_AS_STRING(oppContourWinding);
- SkDebugf("%s %s contourWinding=%s oppContourWinding=%s sign=%d\n", fun, __FUNCTION__,
- contourWindingStr, oppContourWindingStr, spanSign(angles[first]));
- int index = first;
- bool firstTime = true;
- do {
- const SkOpAngle& angle = *angles[index];
- const SkOpSegment& segment = *angle.segment();
- int start = angle.start();
- int end = angle.end();
- const SkOpSpan& sSpan = segment.fTs[start];
- const SkOpSpan& eSpan = segment.fTs[end];
- const SkOpSpan& mSpan = segment.fTs[SkMin32(start, end)];
- bool opp = segment.fOperand ^ fOperand;
- if (!firstTime) {
- oppoSign = segment.oppSign(&angle);
- if (opp) {
- oppLastSum = oppWindSum;
- oppWindSum -= segment.spanSign(&angle);
- if (oppoSign) {
- lastSum = windSum;
- windSum -= oppoSign;
- }
- } else {
- lastSum = windSum;
- windSum -= segment.spanSign(&angle);
- if (oppoSign) {
- oppLastSum = oppWindSum;
- oppWindSum -= oppoSign;
- }
- }
- }
- SkDebugf("%s [%d] %s", __FUNCTION__, index,
- angle.unsortable() ? "*** UNSORTABLE *** " : "");
- #if DEBUG_SORT_COMPACT
- SkDebugf("id=%d %s start=%d (%1.9g,%1.9g) end=%d (%1.9g,%1.9g)",
- segment.fID, kLVerbStr[SkPathOpsVerbToPoints(segment.fVerb)],
- start, segment.xAtT(&sSpan), segment.yAtT(&sSpan), end,
- segment.xAtT(&eSpan), segment.yAtT(&eSpan));
- #else
- switch (segment.fVerb) {
- case SkPath::kLine_Verb:
- SkDebugf(LINE_DEBUG_STR, LINE_DEBUG_DATA(segment.fPts));
- break;
- case SkPath::kQuad_Verb:
- SkDebugf(QUAD_DEBUG_STR, QUAD_DEBUG_DATA(segment.fPts));
- break;
- case SkPath::kCubic_Verb:
- SkDebugf(CUBIC_DEBUG_STR, CUBIC_DEBUG_DATA(segment.fPts));
- break;
- default:
- SkASSERT(0);
- }
- SkDebugf(" tStart=%1.9g tEnd=%1.9g", sSpan.fT, eSpan.fT);
- #endif
- SkDebugf(" sign=%d windValue=%d windSum=", angle.sign(), mSpan.fWindValue);
- SkPathOpsDebug::WindingPrintf(mSpan.fWindSum);
- int last, wind;
- if (opp) {
- last = oppLastSum;
- wind = oppWindSum;
- } else {
- last = lastSum;
- wind = windSum;
- }
- bool useInner = SkPathOpsDebug::ValidWind(last) && SkPathOpsDebug::ValidWind(wind)
- && UseInnerWinding(last, wind);
- WIND_AS_STRING(last);
- WIND_AS_STRING(wind);
- WIND_AS_STRING(lastSum);
- WIND_AS_STRING(oppLastSum);
- WIND_AS_STRING(windSum);
- WIND_AS_STRING(oppWindSum);
- #undef WIND_AS_STRING
- if (!oppoSign) {
- SkDebugf(" %s->%s (max=%s)", lastStr, windStr, useInner ? windStr : lastStr);
- } else {
- SkDebugf(" %s->%s (%s->%s)", lastStr, windStr, opp ? lastSumStr : oppLastSumStr,
- opp ? windSumStr : oppWindSumStr);
- }
- SkDebugf(" done=%d unord=%d small=%d tiny=%d opp=%d\n",
- mSpan.fDone, angle.unorderable(), mSpan.fSmall, mSpan.fTiny, opp);
- ++index;
- if (index == angles.count()) {
- index = 0;
- }
- if (firstTime) {
- firstTime = false;
- }
- } while (index != first);
-}
-
-void SkOpSegment::debugShowSort(const char* fun, const SkTArray<SkOpAngle*, true>& angles,
- int first, bool sortable) {
- if (!sortable) {
- if (angles.count() == 0) {
- return;
- }
- if (first < 0) {
- first = 0;
- }
- }
- const SkOpAngle* firstAngle = angles[first];
- const SkOpSegment* segment = firstAngle->segment();
- int winding = segment->updateWinding(firstAngle);
- int oppWinding = segment->updateOppWinding(firstAngle);
- debugShowSort(fun, angles, first, winding, oppWinding, sortable);
-}
-
-#endif
-
-#if DEBUG_SHOW_WINDING
-int SkOpSegment::debugShowWindingValues(int slotCount, int ofInterest) const {
- if (!(1 << fID & ofInterest)) {
- return 0;
- }
- int sum = 0;
- SkTArray<char, true> slots(slotCount * 2);
- memset(slots.begin(), ' ', slotCount * 2);
- for (int i = 0; i < fTs.count(); ++i) {
- // if (!(1 << fTs[i].fOther->fID & ofInterest)) {
- // continue;
- // }
- sum += fTs[i].fWindValue;
- slots[fTs[i].fOther->fID - 1] = as_digit(fTs[i].fWindValue);
- sum += fTs[i].fOppValue;
- slots[slotCount + fTs[i].fOther->fID - 1] = as_digit(fTs[i].fOppValue);
- }
- SkDebugf("%s id=%2d %.*s | %.*s\n", __FUNCTION__, fID, slotCount, slots.begin(), slotCount,
- slots.begin() + slotCount);
- return sum;
-}
-#endif
-
-void SkOpSegment::debugValidate() const {
-#if DEBUG_VALIDATE
- int count = fTs.count();
- SkASSERT(count >= 2);
- SkASSERT(fTs[0].fT == 0);
- SkASSERT(fTs[count - 1].fT == 1);
- int done = 0;
- double t = -1;
- for (int i = 0; i < count; ++i) {
- const SkOpSpan& span = fTs[i];
- SkASSERT(t <= span.fT);
- t = span.fT;
- int otherIndex = span.fOtherIndex;
- const SkOpSegment* other = span.fOther;
- const SkOpSpan& otherSpan = other->fTs[otherIndex];
- SkASSERT(otherSpan.fPt == span.fPt);
- SkASSERT(otherSpan.fOtherT == t);
- SkASSERT(&fTs[i] == &otherSpan.fOther->fTs[otherSpan.fOtherIndex]);
- done += span.fDone;
- }
- SkASSERT(done == fDoneSpans);
-#endif
-}
-
-#ifdef SK_DEBUG
-void SkOpSegment::dumpPts() const {
- int last = SkPathOpsVerbToPoints(fVerb);
- SkDebugf("{{");
- int index = 0;
- do {
- SkDPoint::dump(fPts[index]);
- SkDebugf(", ");
- } while (++index < last);
- SkDPoint::dump(fPts[index]);
- SkDebugf("}}\n");
-}
-
-void SkOpSegment::dumpDPts() const {
- int count = SkPathOpsVerbToPoints(fVerb);
- SkDebugf("{{");
- int index = 0;
- do {
- SkDPoint dPt = {fPts[index].fX, fPts[index].fY};
- dPt.dump();
- if (index != count) {
- SkDebugf(", ");
- }
- } while (++index <= count);
- SkDebugf("}}\n");
-}
-
-void SkOpSegment::dumpSpans() const {
- int count = this->count();
- for (int index = 0; index < count; ++index) {
- const SkOpSpan& span = this->span(index);
- SkDebugf("[%d] ", index);
- span.dump();
- }
-}
-#endif
diff --git a/chromium/third_party/skia/src/pathops/SkOpSegment.h b/chromium/third_party/skia/src/pathops/SkOpSegment.h
index 79d83b1155f..d191e88af26 100644
--- a/chromium/third_party/skia/src/pathops/SkOpSegment.h
+++ b/chromium/third_party/skia/src/pathops/SkOpSegment.h
@@ -14,13 +14,18 @@
#include "SkTArray.h"
#include "SkTDArray.h"
+#if defined(SK_DEBUG) || !FORCE_RELEASE
+#include "SkThread.h"
+#endif
+
+struct SkCoincidence;
class SkPathWriter;
class SkOpSegment {
public:
SkOpSegment() {
-#ifdef SK_DEBUG
- fID = ++SkPathOpsDebug::gSegmentID;
+#if defined(SK_DEBUG) || !FORCE_RELEASE
+ fID = sk_atomic_inc(&SkPathOpsDebug::gSegmentID);
#endif
}
@@ -28,6 +33,16 @@ public:
return fBounds.fTop < rh.fBounds.fTop;
}
+ struct AlignedSpan {
+ double fOldT;
+ double fT;
+ SkPoint fOldPt;
+ SkPoint fPt;
+ const SkOpSegment* fSegment;
+ const SkOpSegment* fOther1;
+ const SkOpSegment* fOther2;
+ };
+
const SkPathOpsBounds& bounds() const {
return fBounds;
}
@@ -59,7 +74,6 @@ public:
return done(SkMin32(angle->start(), angle->end()));
}
- // used only by partial coincidence detection
SkDPoint dPtAtT(double mid) const {
return (*CurveDPointAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, mid);
}
@@ -72,6 +86,18 @@ public:
return dxdy(index).fY;
}
+ bool hasMultiples() const {
+ return fMultiples;
+ }
+
+ bool hasSmall() const {
+ return fSmall;
+ }
+
+ bool hasTiny() const {
+ return fTiny;
+ }
+
bool intersected() const {
return fTs.count() > 0;
}
@@ -131,11 +157,12 @@ public:
return fTs[lesser].fOppValue;
}
- const SkOpSegment* other(int index) const {
- return fTs[index].fOther;
+#if DEBUG_VALIDATE
+ bool oppXor() const {
+ return fOppXor;
}
+#endif
- // was used only by right angle winding finding
SkPoint ptAtT(double mid) const {
return (*CurvePointAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, mid);
}
@@ -160,14 +187,20 @@ public:
*sumWinding -= deltaSum;
}
- // OPTIMIZATION: mark as debugging only if used solely by tests
const SkOpSpan& span(int tIndex) const {
return fTs[tIndex];
}
- // OPTIMIZATION: mark as debugging only if used solely by tests
- const SkTDArray<SkOpSpan>& spans() const {
- return fTs;
+ const SkOpAngle* spanToAngle(int tStart, int tEnd) const {
+ SkASSERT(tStart != tEnd);
+ const SkOpSpan& span = fTs[tStart];
+ return tStart < tEnd ? span.fToAngle : span.fFromAngle;
+ }
+
+ // FIXME: create some sort of macro or template that avoids casting
+ SkOpAngle* spanToAngle(int tStart, int tEnd) {
+ const SkOpAngle* cAngle = (const_cast<const SkOpSegment*>(this))->spanToAngle(tStart, tEnd);
+ return const_cast<SkOpAngle*>(cAngle);
}
int spanSign(const SkOpAngle* angle) const {
@@ -191,10 +224,6 @@ public:
return fTs[start].fT * (1 - mid) + fTs[end].fT * mid;
}
- bool unsortable(int index) const {
- return fTs[index].fUnsortableStart || fTs[index].fUnsortableEnd;
- }
-
void updatePts(const SkPoint pts[]) {
fPts = pts;
}
@@ -217,6 +246,12 @@ public:
}
#endif
+#if DEBUG_VALIDATE
+ bool _xor() const { // FIXME: used only by SkOpAngle::debugValidateLoop()
+ return fXor;
+ }
+#endif
+
const SkPoint& xyAtT(const SkOpSpan* span) const {
return span->fPt;
}
@@ -231,46 +266,68 @@ public:
}
#endif
- bool activeAngle(int index, int* done, SkTArray<SkOpAngle, true>* angles);
- SkPoint activeLeftTop(bool onlySortable, int* firstT) const;
+ const SkOpAngle* activeAngle(int index, int* start, int* end, bool* done,
+ bool* sortable) const;
+ SkPoint activeLeftTop(int* firstT) const;
bool activeOp(int index, int endIndex, int xorMiMask, int xorSuMask, SkPathOp op);
bool activeWinding(int index, int endIndex);
void addCubic(const SkPoint pts[4], bool operand, bool evenOdd);
void addCurveTo(int start, int end, SkPathWriter* path, bool active) const;
+ void addEndSpan(int endIndex);
void addLine(const SkPoint pts[2], bool operand, bool evenOdd);
void addOtherT(int index, double otherT, int otherIndex);
void addQuad(const SkPoint pts[3], bool operand, bool evenOdd);
- int addSelfT(SkOpSegment* other, const SkPoint& pt, double newT);
+ void addSimpleAngle(int endIndex);
+ int addSelfT(const SkPoint& pt, double newT);
+ void addStartSpan(int endIndex);
int addT(SkOpSegment* other, const SkPoint& pt, double newT);
void addTCancel(const SkPoint& startPt, const SkPoint& endPt, SkOpSegment* other);
void addTCoincident(const SkPoint& startPt, const SkPoint& endPt, double endT,
- SkOpSegment* other);
- void addTPair(double t, SkOpSegment* other, double otherT, bool borrowWind, const SkPoint& pt);
+ SkOpSegment* other);
+ const SkOpSpan* addTPair(double t, SkOpSegment* other, double otherT, bool borrowWind,
+ const SkPoint& pt);
+ const SkOpSpan* addTPair(double t, SkOpSegment* other, double otherT, bool borrowWind,
+ const SkPoint& pt, const SkPoint& oPt);
+ void alignMultiples(SkTDArray<AlignedSpan>* aligned);
+ bool alignSpan(int index, double thisT, const SkPoint& thisPt);
+ void alignSpanState(int start, int end);
bool betweenTs(int lesser, double testT, int greater) const;
+ void blindCancel(const SkCoincidence& coincidence, SkOpSegment* other);
+ void blindCoincident(const SkCoincidence& coincidence, SkOpSegment* other);
+ bool calcAngles();
+ double calcMissingTEnd(const SkOpSegment* ref, double loEnd, double min, double max,
+ double hiEnd, const SkOpSegment* other, int thisEnd);
+ double calcMissingTStart(const SkOpSegment* ref, double loEnd, double min, double max,
+ double hiEnd, const SkOpSegment* other, int thisEnd);
+ void checkDuplicates();
void checkEnds();
+ void checkMultiples();
+ void checkSmall();
bool checkSmall(int index) const;
void checkTiny();
- int computeSum(int startIndex, int endIndex, SkOpAngle::IncludeType includeType,
- SkTArray<SkOpAngle, true>* angles, SkTArray<SkOpAngle*, true>* sorted);
+ int computeSum(int startIndex, int endIndex, SkOpAngle::IncludeType includeType);
+ bool containsPt(const SkPoint& , int index, int endIndex) const;
int crossedSpanY(const SkPoint& basePt, SkScalar* bestY, double* hitT, bool* hitSomething,
double mid, bool opp, bool current) const;
bool findCoincidentMatch(const SkOpSpan* span, const SkOpSegment* other, int oStart, int oEnd,
int step, SkPoint* startPt, SkPoint* endPt, double* endT) const;
SkOpSegment* findNextOp(SkTDArray<SkOpSpan*>* chase, int* nextStart, int* nextEnd,
- bool* unsortable, SkPathOp op, const int xorMiMask,
- const int xorSuMask);
+ bool* unsortable, SkPathOp op, int xorMiMask, int xorSuMask);
SkOpSegment* findNextWinding(SkTDArray<SkOpSpan*>* chase, int* nextStart, int* nextEnd,
bool* unsortable);
SkOpSegment* findNextXor(int* nextStart, int* nextEnd, bool* unsortable);
- int findT(double t, const SkOpSegment* ) const;
- SkOpSegment* findTop(int* tIndex, int* endIndex, bool* unsortable, bool onlySortable);
+ int findExactT(double t, const SkOpSegment* ) const;
+ int findOtherT(double t, const SkOpSegment* ) const;
+ int findT(double t, const SkPoint& , const SkOpSegment* ) const;
+ SkOpSegment* findTop(int* tIndex, int* endIndex, bool* unsortable, bool firstPass);
void fixOtherTIndex();
- void initWinding(int start, int end);
+ void initWinding(int start, int end, SkOpAngle::IncludeType angleIncludeType);
void initWinding(int start, int end, double tHit, int winding, SkScalar hitDx, int oppWind,
SkScalar hitOppDx);
bool isMissing(double startT, const SkPoint& pt) const;
bool isTiny(const SkOpAngle* angle) const;
- bool joinCoincidence(SkOpSegment* other, double otherT, int step, bool cancel);
+ bool joinCoincidence(SkOpSegment* other, double otherT, const SkPoint& otherPt, int step,
+ bool cancel);
SkOpSpan* markAndChaseDoneBinary(int index, int endIndex);
SkOpSpan* markAndChaseDoneUnary(int index, int endIndex);
SkOpSpan* markAndChaseWinding(const SkOpAngle* angle, int winding, int oppWinding);
@@ -281,46 +338,46 @@ public:
void markDoneUnary(int index);
bool nextCandidate(int* start, int* end) const;
int nextSpan(int from, int step) const;
+ void pinT(const SkPoint& pt, double* t);
void setUpWindings(int index, int endIndex, int* sumMiWinding, int* sumSuWinding,
int* maxWinding, int* sumWinding, int* oppMaxWinding, int* oppSumWinding);
- enum SortAngleKind {
- kMustBeOrdered_SortAngleKind, // required for winding calc
- kMayBeUnordered_SortAngleKind // ok for find top
- };
- static bool SortAngles(const SkTArray<SkOpAngle, true>& angles, // FIXME: replace with
- SkTArray<SkOpAngle*, true>* angleList, // Sort Angles 2
- SortAngleKind );
- static bool SortAngles2(const SkTArray<SkOpAngle, true>& angles,
- SkTArray<SkOpAngle*, true>* angleList);
+ void sortAngles();
bool subDivide(int start, int end, SkPoint edge[4]) const;
bool subDivide(int start, int end, SkDCubic* result) const;
void undoneSpan(int* start, int* end);
int updateOppWindingReverse(const SkOpAngle* angle) const;
int updateWindingReverse(const SkOpAngle* angle) const;
static bool UseInnerWinding(int outerWinding, int innerWinding);
+ static bool UseInnerWindingReverse(int outerWinding, int innerWinding);
int windingAtT(double tHit, int tIndex, bool crossOpp, SkScalar* dx) const;
int windSum(const SkOpAngle* angle) const;
-
-#ifdef SK_DEBUG
+// available for testing only
+#if defined(SK_DEBUG) || !FORCE_RELEASE
int debugID() const {
return fID;
}
+#else
+ int debugID() const {
+ return -1;
+ }
#endif
#if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY
void debugShowActiveSpans() const;
#endif
-#if DEBUG_SORT || DEBUG_SWAP_TOP
- void debugShowSort(const char* fun, const SkTArray<SkOpAngle*, true>& angles, int first,
- const int contourWinding, const int oppContourWinding, bool sortable) const;
- void debugShowSort(const char* fun, const SkTArray<SkOpAngle*, true>& angles, int first,
- bool sortable);
-#endif
#if DEBUG_CONCIDENT
void debugShowTs(const char* prefix) const;
#endif
#if DEBUG_SHOW_WINDING
int debugShowWindingValues(int slotCount, int ofInterest) const;
#endif
+ const SkTDArray<SkOpSpan>& debugSpans() const;
+ void debugValidate() const;
+ // available to testing only
+ const SkOpAngle* debugLastAngle() const;
+ void dumpAngles() const;
+ void dumpContour(int firstID, int lastID) const;
+ void dumpPts() const;
+ void dumpSpans() const;
private:
struct MissingSpan {
@@ -332,40 +389,66 @@ private:
SkPoint fPt;
};
- bool activeAngleOther(int index, int* done, SkTArray<SkOpAngle, true>* angles);
- bool activeAngleInner(int index, int* done, SkTArray<SkOpAngle, true>* angles);
+ const SkOpAngle* activeAngleInner(int index, int* start, int* end, bool* done,
+ bool* sortable) const;
+ const SkOpAngle* activeAngleOther(int index, int* start, int* end, bool* done,
+ bool* sortable) const;
bool activeOp(int xorMiMask, int xorSuMask, int index, int endIndex, SkPathOp op,
- int* sumMiWinding, int* sumSuWinding, int* maxWinding, int* sumWinding,
- int* oppMaxWinding, int* oppSumWinding);
- bool activeWinding(int index, int endIndex, int* maxWinding, int* sumWinding);
- void addAngle(SkTArray<SkOpAngle, true>* angles, int start, int end) const;
+ int* sumMiWinding, int* sumSuWinding);
+ bool activeWinding(int index, int endIndex, int* sumWinding);
void addCancelOutsides(const SkPoint& startPt, const SkPoint& endPt, SkOpSegment* other);
void addCoinOutsides(const SkPoint& startPt, const SkPoint& endPt, SkOpSegment* other);
- void addTPair(double t, SkOpSegment* other, double otherT, bool borrowWind, const SkPoint& pt,
- const SkPoint& oPt);
- void addTwoAngles(int start, int end, SkTArray<SkOpAngle, true>* angles) const;
+ SkOpAngle* addSingletonAngleDown(SkOpSegment** otherPtr, SkOpAngle** );
+ SkOpAngle* addSingletonAngleUp(SkOpSegment** otherPtr, SkOpAngle** );
+ SkOpAngle* addSingletonAngles(int step);
+ void alignSpan(const SkPoint& newPt, double newT, const SkOpSegment* other, double otherT,
+ const SkOpSegment* other2, SkOpSpan* oSpan, SkTDArray<AlignedSpan>* );
bool betweenPoints(double midT, const SkPoint& pt1, const SkPoint& pt2) const;
- bool buildAngles(int index, SkTArray<SkOpAngle, true>* angles, bool includeOpp) const;
- void buildAnglesInner(int index, SkTArray<SkOpAngle, true>* angles) const;
+ void bumpCoincidentBlind(bool binary, int index, int last);
void bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* index,
SkTArray<SkPoint, true>* outsideTs);
+ void bumpCoincidentOBlind(int index, int last);
void bumpCoincidentOther(const SkOpSpan& oTest, int* index,
SkTArray<SkPoint, true>* outsideTs);
bool bumpSpan(SkOpSpan* span, int windDelta, int oppDelta);
- bool clockwise(int tStart, int tEnd) const;
+ bool calcLoopSpanCount(const SkOpSpan& thisSpan, int* smallCounts);
+ bool checkForSmall(const SkOpSpan* span, const SkPoint& pt, double newT,
+ int* less, int* more) const;
+ void checkLinks(const SkOpSpan* ,
+ SkTArray<MissingSpan, true>* missingSpans) const;
+ static void CheckOneLink(const SkOpSpan* test, const SkOpSpan* oSpan,
+ const SkOpSpan* oFirst, const SkOpSpan* oLast,
+ const SkOpSpan** missingPtr,
+ SkTArray<MissingSpan, true>* missingSpans);
+ int checkSetAngle(int tIndex) const;
+ void checkSmallCoincidence(const SkOpSpan& span, SkTArray<MissingSpan, true>* );
+ bool coincidentSmall(const SkPoint& pt, double t, const SkOpSegment* other) const;
+ bool clockwise(int tStart, int tEnd, bool* swap) const;
static void ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle,
SkOpAngle::IncludeType );
static void ComputeOneSumReverse(const SkOpAngle* baseAngle, SkOpAngle* nextAngle,
SkOpAngle::IncludeType );
+ bool containsT(double t, const SkOpSegment* other, double otherT) const;
bool decrementSpan(SkOpSpan* span);
- int findStartingEdge(const SkTArray<SkOpAngle*, true>& sorted, int start, int end);
+ int findEndSpan(int endIndex) const;
+ int findStartSpan(int startIndex) const;
+ int firstActive(int tIndex) const;
+ const SkOpSpan& firstSpan(const SkOpSpan& thisSpan) const;
void init(const SkPoint pts[], SkPath::Verb verb, bool operand, bool evenOdd);
+ bool inCoincidentSpan(double t, const SkOpSegment* other) const;
+ bool inLoop(const SkOpAngle* baseAngle, int spanCount, int* indexPtr) const;
+#if OLD_CHASE
bool isSimple(int end) const;
+#else
+ SkOpSegment* isSimple(int* end, int* step);
+#endif
bool isTiny(int index) const;
+ const SkOpSpan& lastSpan(const SkOpSpan& thisSpan) const;
void matchWindingValue(int tIndex, double t, bool borrowWind);
SkOpSpan* markAndChaseDone(int index, int endIndex, int winding);
SkOpSpan* markAndChaseDoneBinary(const SkOpAngle* angle, int winding, int oppWinding);
- SkOpSpan* markAndChaseWinding(const SkOpAngle* angle, const int winding);
+ SkOpSpan* markAndChaseWinding(const SkOpAngle* angle, int winding);
+ SkOpSpan* markAndChaseWinding(int index, int endIndex, int winding);
SkOpSpan* markAndChaseWinding(int index, int endIndex, int winding, int oppWinding);
SkOpSpan* markAngle(int maxWinding, int sumWinding, const SkOpAngle* angle);
void markDoneBinary(int index, int winding, int oppWinding);
@@ -378,12 +461,17 @@ private:
SkOpSpan* markOneWinding(const char* funName, int tIndex, int winding, int oppWinding);
void markWinding(int index, int winding);
void markWinding(int index, int winding, int oppWinding);
- void markUnsortable(int start, int end);
bool monotonicInY(int tStart, int tEnd) const;
- bool multipleSpans(int end) const;
- SkOpSegment* nextChase(int* index, const int step, int* min, SkOpSpan** last);
+
+ bool multipleEnds() const { return fTs[count() - 2].fT == 1; }
+ bool multipleStarts() const { return fTs[1].fT == 0; }
+
+ SkOpSegment* nextChase(int* index, int* step, int* min, SkOpSpan** last);
int nextExactSpan(int from, int step) const;
bool serpentine(int tStart, int tEnd) const;
+ void setCoincidentRange(const SkPoint& startPt, const SkPoint& endPt, SkOpSegment* other);
+ void setFromAngle(int endIndex, SkOpAngle* );
+ void setToAngle(int endIndex, SkOpAngle* );
void setUpWindings(int index, int endIndex, int* sumMiWinding,
int* maxWinding, int* sumWinding);
void subDivideBounds(int start, int end, SkPathOpsBounds* bounds) const;
@@ -395,7 +483,6 @@ private:
int updateWinding(int index, int endIndex) const;
int updateWinding(const SkOpAngle* angle) const;
int updateWindingReverse(int index, int endIndex) const;
- static bool UseInnerWindingReverse(int outerWinding, int innerWinding);
SkOpSpan* verifyOneWinding(const char* funName, int tIndex);
SkOpSpan* verifyOneWindingU(const char* funName, int tIndex);
@@ -412,8 +499,15 @@ private:
#if DEBUG_SWAP_TOP
bool controlsContainedByEnds(int tStart, int tEnd) const;
#endif
+ void debugAddAngle(int start, int end);
#if DEBUG_CONCIDENT
- void debugAddTPair(double t, const SkOpSegment& other, double otherT) const;
+ void debugAddTPair(double t, const SkOpSegment& other, double otherT) const;
+#endif
+#if DEBUG_ANGLE
+ void debugCheckPointsEqualish(int tStart, int tEnd) const;
+#endif
+#if DEBUG_SWAP_TOP
+ int debugInflections(int index, int endIndex) const;
#endif
#if DEBUG_MARK_DONE || DEBUG_UNSORTABLE
void debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding);
@@ -424,27 +518,36 @@ private:
return value < 0 ? '?' : value <= 9 ? '0' + value : '+';
}
#endif
- void debugValidate() const;
-#ifdef SK_DEBUG
- void dumpPts() const;
+ // available to testing only
+ void debugConstruct();
+ void debugConstructCubic(SkPoint shortQuad[4]);
+ void debugConstructLine(SkPoint shortQuad[2]);
+ void debugConstructQuad(SkPoint shortQuad[3]);
+ void debugReset();
void dumpDPts() const;
- void dumpSpans() const;
-#endif
+ void dumpSpan(int index) const;
const SkPoint* fPts;
SkPathOpsBounds fBounds;
// FIXME: can't convert to SkTArray because it uses insert
- SkTDArray<SkOpSpan> fTs; // two or more (always includes t=0 t=1)
+ SkTDArray<SkOpSpan> fTs; // 2+ (always includes t=0 t=1) -- at least (number of spans) + 1
+ SkOpAngleSet fAngles; // empty or 2+ -- (number of non-zero spans) * 2
// OPTIMIZATION: could pack donespans, verb, operand, xor into 1 int-sized value
int fDoneSpans; // quick check that segment is finished
// OPTIMIZATION: force the following to be byte-sized
SkPath::Verb fVerb;
+ bool fLoop; // set if cubic intersects itself
+ bool fMultiples; // set if curve intersects multiple other curves at one interior point
bool fOperand;
bool fXor; // set if original contour had even-odd fill
bool fOppXor; // set if opposite operand had even-odd fill
-#ifdef SK_DEBUG
+ bool fSmall; // set if some span is small
+ bool fTiny; // set if some span is tiny
+#if defined(SK_DEBUG) || !FORCE_RELEASE
int fID;
#endif
+
+ friend class PathOpsSegmentTester;
};
#endif
diff --git a/chromium/third_party/skia/src/pathops/SkOpSpan.h b/chromium/third_party/skia/src/pathops/SkOpSpan.h
index 81ede1c9ab7..d9ce44eb772 100644
--- a/chromium/third_party/skia/src/pathops/SkOpSpan.h
+++ b/chromium/third_party/skia/src/pathops/SkOpSpan.h
@@ -9,28 +9,34 @@
#include "SkPoint.h"
+class SkOpAngle;
class SkOpSegment;
struct SkOpSpan {
- SkOpSegment* fOther;
SkPoint fPt; // computed when the curves are intersected
double fT;
double fOtherT; // value at fOther[fOtherIndex].fT
+ SkOpSegment* fOther;
+ SkOpAngle* fFromAngle; // (if t > 0) index into segment's angle array going negative in t
+ SkOpAngle* fToAngle; // (if t < 1) index into segment's angle array going positive in t
int fOtherIndex; // can't be used during intersection
int fWindSum; // accumulated from contours surrounding this one.
int fOppSum; // for binary operators: the opposite winding sum
int fWindValue; // 0 == canceled; 1 == normal; >1 == coincident
int fOppValue; // normally 0 -- when binary coincident edges combine, opp value goes here
+ bool fChased; // set after span has been added to chase array
+ bool fCoincident; // set if span is bumped -- if set additional points aren't inserted
bool fDone; // if set, this span to next higher T has been processed
- bool fUnsortableStart; // set when start is part of an unsortable pair
- bool fUnsortableEnd; // set when end is part of an unsortable pair
- bool fSmall; // if set, consecutive points are almost equal
- bool fTiny; // if set, span may still be considered once for edge following
bool fLoop; // set when a cubic loops back to this point
+ bool fMultiple; // set if this is one of mutiple spans with identical t and pt values
+ bool fNear; // set if opposite end point is near but not equal to this one
+ bool fSmall; // if set, consecutive points are almost equal
+ bool fTiny; // if set, consecutive points are equal but consecutive ts are not precisely equal
-#ifdef SK_DEBUG
+ // available to testing only
+ const SkOpSegment* debugToSegment(ptrdiff_t* ) const;
void dump() const;
-#endif
+ void dumpOne() const;
};
#endif
diff --git a/chromium/third_party/skia/src/pathops/SkPathOpsCommon.cpp b/chromium/third_party/skia/src/pathops/SkPathOpsCommon.cpp
index c48a7eef689..9a8a2cf4e31 100644
--- a/chromium/third_party/skia/src/pathops/SkPathOpsCommon.cpp
+++ b/chromium/third_party/skia/src/pathops/SkPathOpsCommon.cpp
@@ -10,6 +10,29 @@
#include "SkPathWriter.h"
#include "SkTSort.h"
+static void alignMultiples(SkTArray<SkOpContour*, true>* contourList,
+ SkTDArray<SkOpSegment::AlignedSpan>* aligned) {
+ int contourCount = (*contourList).count();
+ for (int cTest = 0; cTest < contourCount; ++cTest) {
+ SkOpContour* contour = (*contourList)[cTest];
+ if (contour->hasMultiples()) {
+ contour->alignMultiples(aligned);
+ }
+ }
+}
+
+static void alignCoincidence(SkTArray<SkOpContour*, true>* contourList,
+ const SkTDArray<SkOpSegment::AlignedSpan>& aligned) {
+ int contourCount = (*contourList).count();
+ for (int cTest = 0; cTest < contourCount; ++cTest) {
+ SkOpContour* contour = (*contourList)[cTest];
+ int count = aligned.count();
+ for (int index = 0; index < count; ++index) {
+ contour->alignCoincidence(aligned[index]);
+ }
+ }
+}
+
static int contourRangeCheckY(const SkTArray<SkOpContour*, true>& contourList, SkOpSegment** currentPtr,
int* indexPtr, int* endIndexPtr, double* bestHit, SkScalar* bestDx,
bool* tryAgain, double* midPtr, bool opp) {
@@ -111,75 +134,62 @@ SkOpSegment* FindUndone(SkTArray<SkOpContour*, true>& contourList, int* start, i
return NULL;
}
-SkOpSegment* FindChase(SkTDArray<SkOpSpan*>& chase, int& tIndex, int& endIndex) {
- while (chase.count()) {
+SkOpSegment* FindChase(SkTDArray<SkOpSpan*>* chase, int* tIndex, int* endIndex) {
+ while (chase->count()) {
SkOpSpan* span;
- chase.pop(&span);
+ chase->pop(&span);
const SkOpSpan& backPtr = span->fOther->span(span->fOtherIndex);
SkOpSegment* segment = backPtr.fOther;
- tIndex = backPtr.fOtherIndex;
- SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles;
- int done = 0;
- if (segment->activeAngle(tIndex, &done, &angles)) {
- SkOpAngle* last = angles.end() - 1;
- tIndex = last->start();
- endIndex = last->end();
- #if TRY_ROTATE
- *chase.insert(0) = span;
- #else
- *chase.append() = span;
- #endif
+ *tIndex = backPtr.fOtherIndex;
+ bool sortable = true;
+ bool done = true;
+ *endIndex = -1;
+ if (const SkOpAngle* last = segment->activeAngle(*tIndex, tIndex, endIndex, &done,
+ &sortable)) {
+ *tIndex = last->start();
+ *endIndex = last->end();
+ #if TRY_ROTATE
+ *chase->insert(0) = span;
+ #else
+ *chase->append() = span;
+ #endif
return last->segment();
}
- if (done == angles.count()) {
+ if (done) {
continue;
}
- SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted;
- bool sortable = SkOpSegment::SortAngles(angles, &sorted,
- SkOpSegment::kMayBeUnordered_SortAngleKind);
- int angleCount = sorted.count();
-#if DEBUG_SORT
- sorted[0]->segment()->debugShowSort(__FUNCTION__, sorted, 0, 0, 0, sortable);
-#endif
if (!sortable) {
continue;
}
// find first angle, initialize winding to computed fWindSum
- int firstIndex = -1;
- const SkOpAngle* angle;
+ const SkOpAngle* angle = segment->spanToAngle(*tIndex, *endIndex);
+ const SkOpAngle* firstAngle;
+ SkDEBUGCODE(firstAngle = angle);
+ SkDEBUGCODE(bool loop = false);
int winding;
do {
- angle = sorted[++firstIndex];
+ angle = angle->next();
+ SkASSERT(angle != firstAngle || !loop);
+ SkDEBUGCODE(loop |= angle == firstAngle);
segment = angle->segment();
winding = segment->windSum(angle);
} while (winding == SK_MinS32);
int spanWinding = segment->spanSign(angle->start(), angle->end());
#if DEBUG_WINDING
- SkDebugf("%s winding=%d spanWinding=%d\n",
- __FUNCTION__, winding, spanWinding);
+ SkDebugf("%s winding=%d spanWinding=%d\n", __FUNCTION__, winding, spanWinding);
#endif
// turn span winding into contour winding
if (spanWinding * winding < 0) {
winding += spanWinding;
}
- #if DEBUG_SORT
- segment->debugShowSort(__FUNCTION__, sorted, firstIndex, winding, 0, sortable);
- #endif
// we care about first sign and whether wind sum indicates this
// edge is inside or outside. Maybe need to pass span winding
// or first winding or something into this function?
// advance to first undone angle, then return it and winding
// (to set whether edges are active or not)
- int nextIndex = firstIndex + 1;
- int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
- angle = sorted[firstIndex];
- winding -= angle->segment()->spanSign(angle);
- do {
- SkASSERT(nextIndex != firstIndex);
- if (nextIndex == angleCount) {
- nextIndex = 0;
- }
- angle = sorted[nextIndex];
+ firstAngle = angle;
+ winding -= firstAngle->segment()->spanSign(firstAngle);
+ while ((angle = angle->next()) != firstAngle) {
segment = angle->segment();
int maxWinding = winding;
winding -= segment->spanSign(angle);
@@ -187,9 +197,9 @@ SkOpSegment* FindChase(SkTDArray<SkOpSpan*>& chase, int& tIndex, int& endIndex)
SkDebugf("%s id=%d maxWinding=%d winding=%d sign=%d\n", __FUNCTION__,
segment->debugID(), maxWinding, winding, angle->sign());
#endif
- tIndex = angle->start();
- endIndex = angle->end();
- int lesser = SkMin32(tIndex, endIndex);
+ *tIndex = angle->start();
+ *endIndex = angle->end();
+ int lesser = SkMin32(*tIndex, *endIndex);
const SkOpSpan& nextSpan = segment->span(lesser);
if (!nextSpan.fDone) {
// FIXME: this be wrong? assign startWinding if edge is in
@@ -198,11 +208,11 @@ SkOpSegment* FindChase(SkTDArray<SkOpSpan*>& chase, int& tIndex, int& endIndex)
if (SkOpSegment::UseInnerWinding(maxWinding, winding)) {
maxWinding = winding;
}
- segment->markAndChaseWinding(angle, maxWinding, 0);
+ (void) segment->markAndChaseWinding(angle, maxWinding, 0);
break;
}
- } while (++nextIndex != lastIndex);
- *chase.insert(0) = span;
+ }
+ *chase->insert(0) = span;
return segment;
}
return NULL;
@@ -217,10 +227,11 @@ void DebugShowActiveSpans(SkTArray<SkOpContour*, true>& contourList) {
}
#endif
-static SkOpSegment* findSortableTop(const SkTArray<SkOpContour*, true>& contourList,
- int* index, int* endIndex, SkPoint* topLeft, bool* unsortable,
- bool* done, bool onlySortable) {
+static SkOpSegment* findTopSegment(const SkTArray<SkOpContour*, true>& contourList, int* index,
+ int* endIndex, SkPoint* topLeft, bool* unsortable, bool* done, bool firstPass) {
SkOpSegment* result;
+ const SkOpSegment* lastTopStart = NULL;
+ int lastIndex = -1, lastEndIndex = -1;
do {
SkPoint bestXY = {SK_ScalarMax, SK_ScalarMax};
int contourCount = contourList.count();
@@ -249,28 +260,38 @@ static SkOpSegment* findSortableTop(const SkTArray<SkOpContour*, true>& contourL
return NULL;
}
*topLeft = bestXY;
- result = topStart->findTop(index, endIndex, unsortable, onlySortable);
+ result = topStart->findTop(index, endIndex, unsortable, firstPass);
+ if (!result) {
+ if (lastTopStart == topStart && lastIndex == *index && lastEndIndex == *endIndex) {
+ *done = true;
+ return NULL;
+ }
+ lastTopStart = topStart;
+ lastIndex = *index;
+ lastEndIndex = *endIndex;
+ }
} while (!result);
- if (result) {
- *unsortable = false;
- }
return result;
}
static int rightAngleWinding(const SkTArray<SkOpContour*, true>& contourList,
- SkOpSegment** current, int* index, int* endIndex, double* tHit,
- SkScalar* hitDx, bool* tryAgain, bool opp) {
+ SkOpSegment** currentPtr, int* indexPtr, int* endIndexPtr, double* tHit,
+ SkScalar* hitDx, bool* tryAgain, bool* onlyVertical, bool opp) {
double test = 0.9;
int contourWinding;
do {
- contourWinding = contourRangeCheckY(contourList, current, index, endIndex, tHit, hitDx,
- tryAgain, &test, opp);
+ contourWinding = contourRangeCheckY(contourList, currentPtr, indexPtr, endIndexPtr,
+ tHit, hitDx, tryAgain, &test, opp);
if (contourWinding != SK_MinS32 || *tryAgain) {
return contourWinding;
}
+ if (*currentPtr && (*currentPtr)->isVertical()) {
+ *onlyVertical = true;
+ return contourWinding;
+ }
test /= 2;
} while (!approximately_negative(test));
- SkASSERT(0); // should be OK to comment out, but interested when this hits
+ SkASSERT(0); // FIXME: incomplete functionality
return contourWinding;
}
@@ -285,37 +306,45 @@ static void skipVertical(const SkTArray<SkOpContour*, true>& contourList,
if (contour->done()) {
continue;
}
- *current = contour->nonVerticalSegment(index, endIndex);
- if (*current) {
+ SkOpSegment* nonVertical = contour->nonVerticalSegment(index, endIndex);
+ if (nonVertical) {
+ *current = nonVertical;
return;
}
}
+ return;
}
SkOpSegment* FindSortableTop(const SkTArray<SkOpContour*, true>& contourList,
SkOpAngle::IncludeType angleIncludeType, bool* firstContour, int* indexPtr,
- int* endIndexPtr, SkPoint* topLeft, bool* unsortable, bool* done) {
- SkOpSegment* current = findSortableTop(contourList, indexPtr, endIndexPtr, topLeft, unsortable,
- done, true);
+ int* endIndexPtr, SkPoint* topLeft, bool* unsortable, bool* done, bool* onlyVertical,
+ bool firstPass) {
+ SkOpSegment* current = findTopSegment(contourList, indexPtr, endIndexPtr, topLeft, unsortable,
+ done, firstPass);
if (!current) {
return NULL;
}
- const int index = *indexPtr;
+ const int startIndex = *indexPtr;
const int endIndex = *endIndexPtr;
if (*firstContour) {
- current->initWinding(index, endIndex);
+ current->initWinding(startIndex, endIndex, angleIncludeType);
*firstContour = false;
return current;
}
- int minIndex = SkMin32(index, endIndex);
+ int minIndex = SkMin32(startIndex, endIndex);
int sumWinding = current->windSum(minIndex);
- if (sumWinding != SK_MinS32) {
- return current;
+ if (sumWinding == SK_MinS32) {
+ int index = endIndex;
+ int oIndex = startIndex;
+ do {
+ const SkOpSpan& span = current->span(index);
+ if ((oIndex < index ? span.fFromAngle : span.fToAngle) == NULL) {
+ current->addSimpleAngle(index);
+ }
+ sumWinding = current->computeSum(oIndex, index, angleIncludeType);
+ SkTSwap(index, oIndex);
+ } while (sumWinding == SK_MinS32 && index == startIndex);
}
- SkASSERT(current->windSum(SkMin32(index, endIndex)) == SK_MinS32);
- SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles;
- SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted;
- sumWinding = current->computeSum(index, endIndex, angleIncludeType, &angles, &sorted);
if (sumWinding != SK_MinS32 && sumWinding != SK_NaN32) {
return current;
}
@@ -332,11 +361,14 @@ SkOpSegment* FindSortableTop(const SkTArray<SkOpContour*, true>& contourList,
// if only remaining candidates are vertical, then they can be marked done
SkASSERT(*indexPtr != *endIndexPtr && *indexPtr >= 0 && *endIndexPtr >= 0);
skipVertical(contourList, &current, indexPtr, endIndexPtr);
-
+ SkASSERT(current); // FIXME: if null, all remaining are vertical
SkASSERT(*indexPtr != *endIndexPtr && *indexPtr >= 0 && *endIndexPtr >= 0);
tryAgain = false;
contourWinding = rightAngleWinding(contourList, &current, indexPtr, endIndexPtr, &tHit,
- &hitDx, &tryAgain, false);
+ &hitDx, &tryAgain, onlyVertical, false);
+ if (*onlyVertical) {
+ return current;
+ }
if (tryAgain) {
continue;
}
@@ -344,13 +376,35 @@ SkOpSegment* FindSortableTop(const SkTArray<SkOpContour*, true>& contourList,
break;
}
oppContourWinding = rightAngleWinding(contourList, &current, indexPtr, endIndexPtr, &tHit,
- &hitOppDx, &tryAgain, true);
+ &hitOppDx, &tryAgain, NULL, true);
} while (tryAgain);
current->initWinding(*indexPtr, *endIndexPtr, tHit, contourWinding, hitDx, oppContourWinding,
hitOppDx);
+ if (current->done()) {
+ return NULL;
+ }
return current;
}
+static bool calcAngles(SkTArray<SkOpContour*, true>* contourList) {
+ int contourCount = (*contourList).count();
+ for (int cTest = 0; cTest < contourCount; ++cTest) {
+ SkOpContour* contour = (*contourList)[cTest];
+ if (!contour->calcAngles()) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static void checkDuplicates(SkTArray<SkOpContour*, true>* contourList) {
+ int contourCount = (*contourList).count();
+ for (int cTest = 0; cTest < contourCount; ++cTest) {
+ SkOpContour* contour = (*contourList)[cTest];
+ contour->checkDuplicates();
+ }
+}
+
static void checkEnds(SkTArray<SkOpContour*, true>* contourList) {
// it's hard to determine if the end of a cubic or conic nearly intersects another curve.
// instead, look to see if the connecting curve intersected at that same end.
@@ -361,6 +415,26 @@ static void checkEnds(SkTArray<SkOpContour*, true>* contourList) {
}
}
+static bool checkMultiples(SkTArray<SkOpContour*, true>* contourList) {
+ bool hasMultiples = false;
+ int contourCount = (*contourList).count();
+ for (int cTest = 0; cTest < contourCount; ++cTest) {
+ SkOpContour* contour = (*contourList)[cTest];
+ contour->checkMultiples();
+ hasMultiples |= contour->hasMultiples();
+ }
+ return hasMultiples;
+}
+
+// A small interval of a pair of curves may collapse to lines for each, triggering coincidence
+static void checkSmall(SkTArray<SkOpContour*, true>* contourList) {
+ int contourCount = (*contourList).count();
+ for (int cTest = 0; cTest < contourCount; ++cTest) {
+ SkOpContour* contour = (*contourList)[cTest];
+ contour->checkSmall();
+ }
+}
+
// A tiny interval may indicate an undiscovered coincidence. Find and fix.
static void checkTiny(SkTArray<SkOpContour*, true>* contourList) {
int contourCount = (*contourList).count();
@@ -386,6 +460,14 @@ static void joinCoincidence(SkTArray<SkOpContour*, true>* contourList) {
}
}
+static void sortAngles(SkTArray<SkOpContour*, true>* contourList) {
+ int contourCount = (*contourList).count();
+ for (int cTest = 0; cTest < contourCount; ++cTest) {
+ SkOpContour* contour = (*contourList)[cTest];
+ contour->sortAngles();
+ }
+}
+
static void sortSegments(SkTArray<SkOpContour*, true>* contourList) {
int contourCount = (*contourList).count();
for (int cTest = 0; cTest < contourCount; ++cTest) {
@@ -613,7 +695,7 @@ void Assemble(const SkPathWriter& path, SkPathWriter* simple) {
#endif
}
-void HandleCoincidence(SkTArray<SkOpContour*, true>* contourList, int total) {
+bool HandleCoincidence(SkTArray<SkOpContour*, true>* contourList, int total) {
#if DEBUG_SHOW_WINDING
SkOpContour::debugShowWindingValues(contourList);
#endif
@@ -622,11 +704,24 @@ void HandleCoincidence(SkTArray<SkOpContour*, true>* contourList, int total) {
SkOpContour::debugShowWindingValues(contourList);
#endif
fixOtherTIndex(contourList);
- checkEnds(contourList);
- checkTiny(contourList);
- joinCoincidence(contourList);
+ checkEnds(contourList); // check if connecting curve intersected at the same end
+ bool hasM = checkMultiples(contourList); // check if intersections agree on t and point values
+ SkTDArray<SkOpSegment::AlignedSpan> aligned;
+ if (hasM) {
+ alignMultiples(contourList, &aligned); // align pairs of identical points
+ alignCoincidence(contourList, aligned);
+ }
+ checkDuplicates(contourList); // check if spans have the same number on the other end
+ checkTiny(contourList); // if pair have the same end points, mark them as parallel
+ checkSmall(contourList); // a pair of curves with a small span may turn into coincident lines
+ joinCoincidence(contourList); // join curves that connect to a coincident pair
sortSegments(contourList);
+ if (!calcAngles(contourList)) {
+ return false;
+ }
+ sortAngles(contourList);
#if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY
DebugShowActiveSpans(*contourList);
#endif
+ return true;
}
diff --git a/chromium/third_party/skia/src/pathops/SkPathOpsCommon.h b/chromium/third_party/skia/src/pathops/SkPathOpsCommon.h
index afc751d130f..0d8cfc42f9f 100644
--- a/chromium/third_party/skia/src/pathops/SkPathOpsCommon.h
+++ b/chromium/third_party/skia/src/pathops/SkPathOpsCommon.h
@@ -15,14 +15,14 @@ class SkPathWriter;
void Assemble(const SkPathWriter& path, SkPathWriter* simple);
// FIXME: find chase uses insert, so it can't be converted to SkTArray yet
-SkOpSegment* FindChase(SkTDArray<SkOpSpan*>& chase, int& tIndex, int& endIndex);
+SkOpSegment* FindChase(SkTDArray<SkOpSpan*>* chase, int* tIndex, int* endIndex);
SkOpSegment* FindSortableTop(const SkTArray<SkOpContour*, true>& , SkOpAngle::IncludeType ,
bool* firstContour, int* index, int* endIndex, SkPoint* topLeft,
- bool* unsortable, bool* done);
+ bool* unsortable, bool* done, bool* onlyVertical, bool firstPass);
SkOpSegment* FindUndone(SkTArray<SkOpContour*, true>& contourList, int* start, int* end);
void MakeContourList(SkTArray<SkOpContour>& contours, SkTArray<SkOpContour*, true>& list,
bool evenOdd, bool oppEvenOdd);
-void HandleCoincidence(SkTArray<SkOpContour*, true>* , int );
+bool HandleCoincidence(SkTArray<SkOpContour*, true>* , int );
#if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY
void DebugShowActiveSpans(SkTArray<SkOpContour*, true>& contourList);
diff --git a/chromium/third_party/skia/src/pathops/SkPathOpsCubic.cpp b/chromium/third_party/skia/src/pathops/SkPathOpsCubic.cpp
index 8e8ec47bf97..9d70d58ec15 100644
--- a/chromium/third_party/skia/src/pathops/SkPathOpsCubic.cpp
+++ b/chromium/third_party/skia/src/pathops/SkPathOpsCubic.cpp
@@ -9,9 +9,58 @@
#include "SkPathOpsLine.h"
#include "SkPathOpsQuad.h"
#include "SkPathOpsRect.h"
+#include "SkTSort.h"
const int SkDCubic::gPrecisionUnit = 256; // FIXME: test different values in test framework
+// give up when changing t no longer moves point
+// also, copy point rather than recompute it when it does change
+double SkDCubic::binarySearch(double min, double max, double axisIntercept,
+ SearchAxis xAxis) const {
+ double t = (min + max) / 2;
+ double step = (t - min) / 2;
+ SkDPoint cubicAtT = ptAtT(t);
+ double calcPos = (&cubicAtT.fX)[xAxis];
+ double calcDist = calcPos - axisIntercept;
+ do {
+ double priorT = t - step;
+ SkASSERT(priorT >= min);
+ SkDPoint lessPt = ptAtT(priorT);
+ if (approximately_equal(lessPt.fX, cubicAtT.fX)
+ && approximately_equal(lessPt.fY, cubicAtT.fY)) {
+ return -1; // binary search found no point at this axis intercept
+ }
+ double lessDist = (&lessPt.fX)[xAxis] - axisIntercept;
+#if DEBUG_CUBIC_BINARY_SEARCH
+ SkDebugf("t=%1.9g calc=%1.9g dist=%1.9g step=%1.9g less=%1.9g\n", t, calcPos, calcDist,
+ step, lessDist);
+#endif
+ double lastStep = step;
+ step /= 2;
+ if (calcDist > 0 ? calcDist > lessDist : calcDist < lessDist) {
+ t = priorT;
+ } else {
+ double nextT = t + lastStep;
+ SkASSERT(nextT <= max);
+ SkDPoint morePt = ptAtT(nextT);
+ if (approximately_equal(morePt.fX, cubicAtT.fX)
+ && approximately_equal(morePt.fY, cubicAtT.fY)) {
+ return -1; // binary search found no point at this axis intercept
+ }
+ double moreDist = (&morePt.fX)[xAxis] - axisIntercept;
+ if (calcDist > 0 ? calcDist <= moreDist : calcDist >= moreDist) {
+ continue;
+ }
+ t = nextT;
+ }
+ SkDPoint testAtT = ptAtT(t);
+ cubicAtT = testAtT;
+ calcPos = (&cubicAtT.fX)[xAxis];
+ calcDist = calcPos - axisIntercept;
+ } while (!approximately_equal(calcPos, axisIntercept));
+ return t;
+}
+
// FIXME: cache keep the bounds and/or precision with the caller?
double SkDCubic::calcPrecision() const {
SkDRect dRect;
@@ -93,7 +142,33 @@ bool SkDCubic::monotonicInY() const {
&& between(fPts[0].fY, fPts[2].fY, fPts[3].fY);
}
+int SkDCubic::searchRoots(double extremeTs[6], int extrema, double axisIntercept,
+ SearchAxis xAxis, double* validRoots) const {
+ extrema += findInflections(&extremeTs[extrema]);
+ extremeTs[extrema++] = 0;
+ extremeTs[extrema] = 1;
+ SkTQSort(extremeTs, extremeTs + extrema);
+ int validCount = 0;
+ for (int index = 0; index < extrema; ) {
+ double min = extremeTs[index];
+ double max = extremeTs[++index];
+ if (min == max) {
+ continue;
+ }
+ double newT = binarySearch(min, max, axisIntercept, xAxis);
+ if (newT >= 0) {
+ validRoots[validCount++] = newT;
+ }
+ }
+ return validCount;
+}
+
bool SkDCubic::serpentine() const {
+#if 0 // FIXME: enabling this fixes cubicOp114 but breaks cubicOp58d and cubicOp53d
+ double tValues[2];
+ // OPTIMIZATION : another case where caching the present of cubic inflections would be useful
+ return findInflections(tValues) > 1;
+#endif
if (!controlsContainedByEnds()) {
return false;
}
@@ -205,7 +280,7 @@ int SkDCubic::RootsReal(double A, double B, double C, double D, double s[3]) {
}
r = A - adiv3;
*roots++ = r;
- if (AlmostDequalUlps(R2, Q3)) {
+ if (AlmostDequalUlps((double) R2, (double) Q3)) {
r = -A / 2 - adiv3;
if (!AlmostDequalUlps(s[0], r)) {
*roots++ = r;
@@ -455,16 +530,16 @@ void SkDCubic::subDivide(const SkDPoint& a, const SkDPoint& d,
if (t1 == 1 || t2 == 1) {
align(3, 2, t1 == 1 ? &dst[0] : &dst[1]);
}
- if (precisely_subdivide_equal(dst[0].fX, a.fX)) {
+ if (AlmostBequalUlps(dst[0].fX, a.fX)) {
dst[0].fX = a.fX;
}
- if (precisely_subdivide_equal(dst[0].fY, a.fY)) {
+ if (AlmostBequalUlps(dst[0].fY, a.fY)) {
dst[0].fY = a.fY;
}
- if (precisely_subdivide_equal(dst[1].fX, d.fX)) {
+ if (AlmostBequalUlps(dst[1].fX, d.fX)) {
dst[1].fX = d.fX;
}
- if (precisely_subdivide_equal(dst[1].fY, d.fY)) {
+ if (AlmostBequalUlps(dst[1].fY, d.fY)) {
dst[1].fY = d.fY;
}
}
@@ -508,16 +583,3 @@ SkDCubicPair SkDCubic::chopAt(double t) const {
interp_cubic_coords(&fPts[0].fY, &dst.pts[0].fY, t);
return dst;
}
-
-#ifdef SK_DEBUG
-void SkDCubic::dump() {
- SkDebugf("{{");
- int index = 0;
- do {
- fPts[index].dump();
- SkDebugf(", ");
- } while (++index < 3);
- fPts[index].dump();
- SkDebugf("}}\n");
-}
-#endif
diff --git a/chromium/third_party/skia/src/pathops/SkPathOpsCubic.h b/chromium/third_party/skia/src/pathops/SkPathOpsCubic.h
index 973b76dfb24..1037cae4f75 100644
--- a/chromium/third_party/skia/src/pathops/SkPathOpsCubic.h
+++ b/chromium/third_party/skia/src/pathops/SkPathOpsCubic.h
@@ -19,21 +19,16 @@ struct SkDCubicPair {
};
struct SkDCubic {
- SkDPoint fPts[4];
-
- void set(const SkPoint pts[4]) {
- fPts[0] = pts[0];
- fPts[1] = pts[1];
- fPts[2] = pts[2];
- fPts[3] = pts[3];
- }
-
- static const int gPrecisionUnit;
+ enum SearchAxis {
+ kXAxis,
+ kYAxis
+ };
const SkDPoint& operator[](int n) const { SkASSERT(n >= 0 && n < 4); return fPts[n]; }
SkDPoint& operator[](int n) { SkASSERT(n >= 0 && n < 4); return fPts[n]; }
void align(int endIndex, int ctrlIndex, SkDPoint* dstPt) const;
+ double binarySearch(double min, double max, double axisIntercept, SearchAxis xAxis) const;
double calcPrecision() const;
SkDCubicPair chopAt(double t) const;
bool clockwise() const;
@@ -42,9 +37,9 @@ struct SkDCubic {
SkDVector dxdyAtT(double t) const;
bool endsAreExtremaInXOrY() const;
static int FindExtrema(double a, double b, double c, double d, double tValue[2]);
- int findInflections(double tValues[]) const;
+ int findInflections(double tValues[2]) const;
- static int FindInflections(const SkPoint a[4], double tValues[]) {
+ static int FindInflections(const SkPoint a[4], double tValues[2]) {
SkDCubic cubic;
cubic.set(a);
return cubic.findInflections(tValues);
@@ -56,7 +51,18 @@ struct SkDCubic {
SkDPoint ptAtT(double t) const;
static int RootsReal(double A, double B, double C, double D, double t[3]);
static int RootsValidT(const double A, const double B, const double C, double D, double s[3]);
+
+ int searchRoots(double extremes[6], int extrema, double axisIntercept,
+ SearchAxis xAxis, double* validRoots) const;
bool serpentine() const;
+
+ void set(const SkPoint pts[4]) {
+ fPts[0] = pts[0];
+ fPts[1] = pts[1];
+ fPts[2] = pts[2];
+ fPts[3] = pts[3];
+ }
+
SkDCubic subDivide(double t1, double t2) const;
static SkDCubic SubDivide(const SkPoint a[4], double t1, double t2) {
@@ -78,9 +84,13 @@ struct SkDCubic {
void toQuadraticTs(double precision, SkTArray<double, true>* ts) const;
SkDQuad toQuad() const;
-#ifdef SK_DEBUG
- void dump();
-#endif
+ // utilities callable by the user from the debugger when the implementation code is linked in
+ void dump() const;
+ void dumpNumber() const;
+
+ static const int gPrecisionUnit;
+
+ SkDPoint fPts[4];
};
#endif
diff --git a/chromium/third_party/skia/src/pathops/SkPathOpsCurve.h b/chromium/third_party/skia/src/pathops/SkPathOpsCurve.h
index 5d12cb811ab..a7d3e816381 100644
--- a/chromium/third_party/skia/src/pathops/SkPathOpsCurve.h
+++ b/chromium/third_party/skia/src/pathops/SkPathOpsCurve.h
@@ -7,6 +7,7 @@
#ifndef SkPathOpsCurve_DEFINE
#define SkPathOpsCurve_DEFINE
+#include "SkIntersections.h"
#include "SkPathOpsCubic.h"
#include "SkPathOpsLine.h"
#include "SkPathOpsQuad.h"
@@ -149,4 +150,29 @@ static bool (* const CurveIsVertical[])(const SkPoint[], double , double) = {
cubic_is_vertical
};
+static void line_intersect_ray(const SkPoint a[2], const SkDLine& ray, SkIntersections* i) {
+ SkDLine line;
+ line.set(a);
+ i->intersectRay(line, ray);
+}
+
+static void quad_intersect_ray(const SkPoint a[3], const SkDLine& ray, SkIntersections* i) {
+ SkDQuad quad;
+ quad.set(a);
+ i->intersectRay(quad, ray);
+}
+
+static void cubic_intersect_ray(const SkPoint a[4], const SkDLine& ray, SkIntersections* i) {
+ SkDCubic cubic;
+ cubic.set(a);
+ i->intersectRay(cubic, ray);
+}
+
+static void (* const CurveIntersectRay[])(const SkPoint[] , const SkDLine& , SkIntersections* ) = {
+ NULL,
+ line_intersect_ray,
+ quad_intersect_ray,
+ cubic_intersect_ray
+};
+
#endif
diff --git a/chromium/third_party/skia/src/pathops/SkPathOpsDebug.cpp b/chromium/third_party/skia/src/pathops/SkPathOpsDebug.cpp
index b68ab2acf88..96029b340ba 100644
--- a/chromium/third_party/skia/src/pathops/SkPathOpsDebug.cpp
+++ b/chromium/third_party/skia/src/pathops/SkPathOpsDebug.cpp
@@ -10,12 +10,12 @@
#if defined SK_DEBUG || !FORCE_RELEASE
-int SkPathOpsDebug::gMaxWindSum = SK_MaxS32;
-int SkPathOpsDebug::gMaxWindValue = SK_MaxS32;
-
const char* SkPathOpsDebug::kLVerbStr[] = {"", "line", "quad", "cubic"};
-int SkPathOpsDebug::gContourID;
-int SkPathOpsDebug::gSegmentID;
+
+#if defined(SK_DEBUG) || !FORCE_RELEASE
+int SkPathOpsDebug::gContourID = 0;
+int SkPathOpsDebug::gSegmentID = 0;
+#endif
#if DEBUG_SORT || DEBUG_SWAP_TOP
int SkPathOpsDebug::gSortCountDefault = SK_MaxS32;
@@ -26,6 +26,17 @@ int SkPathOpsDebug::gSortCount;
const char* SkPathOpsDebug::kPathOpStr[] = {"diff", "sect", "union", "xor"};
#endif
+bool SkPathOpsDebug::ChaseContains(const SkTDArray<SkOpSpan *>& chaseArray,
+ const SkOpSpan* span) {
+ for (int index = 0; index < chaseArray.count(); ++index) {
+ const SkOpSpan* entry = chaseArray[index];
+ if (entry == span) {
+ return true;
+ }
+ }
+ return false;
+}
+
void SkPathOpsDebug::MathematicaIze(char* str, size_t bufferLen) {
size_t len = strlen(str);
bool num = false;
@@ -81,81 +92,474 @@ void SkPathOpsDebug::BumpTestName(char* test) {
}
#endif
+#if !DEBUG_SHOW_TEST_NAME // enable when building without extended test
+void SkPathOpsDebug::ShowPath(const SkPath& one, const SkPath& two, SkPathOp op, const char* name) {
+}
+#endif
+
+#endif // defined SK_DEBUG || !FORCE_RELEASE
+
+#include "SkOpAngle.h"
#include "SkOpSegment.h"
-void SkPathOpsDebug::DumpAngles(const SkTArray<SkOpAngle, true>& angles) {
- int count = angles.count();
- for (int index = 0; index < count; ++index) {
- angles[index].dump();
+#if DEBUG_SORT
+void SkOpAngle::debugLoop() const {
+ const SkOpAngle* first = this;
+ const SkOpAngle* next = this;
+ do {
+ next->dumpOne(true);
+ next = next->fNext;
+ } while (next && next != first);
+}
+#endif
+
+#if DEBUG_ANGLE
+void SkOpAngle::debugSameAs(const SkOpAngle* compare) const {
+ SK_ALWAYSBREAK(fSegment == compare->fSegment);
+ const SkOpSpan& startSpan = fSegment->span(fStart);
+ const SkOpSpan& oStartSpan = fSegment->span(compare->fStart);
+ SK_ALWAYSBREAK(startSpan.fToAngle == oStartSpan.fToAngle);
+ SK_ALWAYSBREAK(startSpan.fFromAngle == oStartSpan.fFromAngle);
+ const SkOpSpan& endSpan = fSegment->span(fEnd);
+ const SkOpSpan& oEndSpan = fSegment->span(compare->fEnd);
+ SK_ALWAYSBREAK(endSpan.fToAngle == oEndSpan.fToAngle);
+ SK_ALWAYSBREAK(endSpan.fFromAngle == oEndSpan.fFromAngle);
+}
+#endif
+
+#if DEBUG_VALIDATE
+void SkOpAngle::debugValidateNext() const {
+ const SkOpAngle* first = this;
+ const SkOpAngle* next = first;
+ SkTDArray<const SkOpAngle*>(angles);
+ do {
+// SK_ALWAYSBREAK(next->fSegment->debugContains(next));
+ angles.push(next);
+ next = next->next();
+ if (next == first) {
+ break;
+ }
+ SK_ALWAYSBREAK(!angles.contains(next));
+ if (!next) {
+ return;
+ }
+ } while (true);
+}
+
+void SkOpAngle::debugValidateLoop() const {
+ const SkOpAngle* first = this;
+ const SkOpAngle* next = first;
+ SK_ALWAYSBREAK(first->next() != first);
+ int signSum = 0;
+ int oppSum = 0;
+ bool firstOperand = fSegment->operand();
+ bool unorderable = false;
+ do {
+ unorderable |= next->fUnorderable;
+ const SkOpSegment* segment = next->fSegment;
+ bool operandsMatch = firstOperand == segment->operand();
+ signSum += operandsMatch ? segment->spanSign(next) : segment->oppSign(next);
+ oppSum += operandsMatch ? segment->oppSign(next) : segment->spanSign(next);
+ const SkOpSpan& span = segment->span(SkMin32(next->fStart, next->fEnd));
+ if (segment->_xor()) {
+// SK_ALWAYSBREAK(span.fWindValue == 1);
+// SK_ALWAYSBREAK(span.fWindSum == SK_MinS32 || span.fWindSum == 1);
+ }
+ if (segment->oppXor()) {
+ SK_ALWAYSBREAK(span.fOppValue == 0 || abs(span.fOppValue) == 1);
+// SK_ALWAYSBREAK(span.fOppSum == SK_MinS32 || span.fOppSum == 0 || abs(span.fOppSum) == 1);
+ }
+ next = next->next();
+ if (!next) {
+ return;
+ }
+ } while (next != first);
+ if (unorderable) {
+ return;
}
+ SK_ALWAYSBREAK(!signSum || fSegment->_xor());
+ SK_ALWAYSBREAK(!oppSum || fSegment->oppXor());
+ int lastWinding;
+ int lastOppWinding;
+ int winding;
+ int oppWinding;
+ do {
+ const SkOpSegment* segment = next->fSegment;
+ const SkOpSpan& span = segment->span(SkMin32(next->fStart, next->fEnd));
+ winding = span.fWindSum;
+ if (winding != SK_MinS32) {
+// SK_ALWAYSBREAK(winding != 0);
+ SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding));
+ lastWinding = winding;
+ int diffWinding = segment->spanSign(next);
+ if (!segment->_xor()) {
+ SK_ALWAYSBREAK(diffWinding != 0);
+ bool sameSign = (winding > 0) == (diffWinding > 0);
+ winding -= sameSign ? diffWinding : -diffWinding;
+ SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding));
+ SK_ALWAYSBREAK(abs(winding) <= abs(lastWinding));
+ if (!sameSign) {
+ SkTSwap(winding, lastWinding);
+ }
+ }
+ lastOppWinding = oppWinding = span.fOppSum;
+ if (oppWinding != SK_MinS32 && !segment->oppXor()) {
+ int oppDiffWinding = segment->oppSign(next);
+// SK_ALWAYSBREAK(abs(oppDiffWinding) <= abs(diffWinding) || segment->_xor());
+ if (oppDiffWinding) {
+ bool oppSameSign = (oppWinding > 0) == (oppDiffWinding > 0);
+ oppWinding -= oppSameSign ? oppDiffWinding : -oppDiffWinding;
+ SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(oppWinding));
+ SK_ALWAYSBREAK(abs(oppWinding) <= abs(lastOppWinding));
+ if (!oppSameSign) {
+ SkTSwap(oppWinding, lastOppWinding);
+ }
+ }
+ }
+ firstOperand = segment->operand();
+ break;
+ }
+ SK_ALWAYSBREAK(span.fOppSum == SK_MinS32);
+ next = next->next();
+ } while (next != first);
+ if (winding == SK_MinS32) {
+ return;
+ }
+ SK_ALWAYSBREAK(oppWinding == SK_MinS32 || SkPathOpsDebug::ValidWind(oppWinding));
+ first = next;
+ next = next->next();
+ do {
+ const SkOpSegment* segment = next->fSegment;
+ lastWinding = winding;
+ lastOppWinding = oppWinding;
+ bool operandsMatch = firstOperand == segment->operand();
+ if (operandsMatch) {
+ if (!segment->_xor()) {
+ winding -= segment->spanSign(next);
+ SK_ALWAYSBREAK(winding != lastWinding);
+ SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding));
+ }
+ if (!segment->oppXor()) {
+ int oppDiffWinding = segment->oppSign(next);
+ if (oppWinding != SK_MinS32) {
+ oppWinding -= oppDiffWinding;
+ SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(oppWinding));
+ } else {
+ SK_ALWAYSBREAK(oppDiffWinding == 0);
+ }
+ }
+ } else {
+ if (!segment->oppXor()) {
+ winding -= segment->oppSign(next);
+ SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding));
+ }
+ if (!segment->_xor()) {
+ oppWinding -= segment->spanSign(next);
+ SK_ALWAYSBREAK(oppWinding != lastOppWinding);
+ SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(oppWinding));
+ }
+ }
+ bool useInner = SkOpSegment::UseInnerWinding(lastWinding, winding);
+ int sumWinding = useInner ? winding : lastWinding;
+ bool oppUseInner = SkOpSegment::UseInnerWinding(lastOppWinding, oppWinding);
+ int oppSumWinding = oppUseInner ? oppWinding : lastOppWinding;
+ if (!operandsMatch) {
+ SkTSwap(useInner, oppUseInner);
+ SkTSwap(sumWinding, oppSumWinding);
+ }
+ const SkOpSpan& span = segment->span(SkMin32(next->fStart, next->fEnd));
+ if (winding == -lastWinding) {
+ if (span.fWindSum != SK_MinS32) {
+ SkDebugf("%s useInner=%d spanSign=%d lastWinding=%d winding=%d windSum=%d\n",
+ __FUNCTION__,
+ useInner, segment->spanSign(next), lastWinding, winding, span.fWindSum);
+ }
+ }
+ if (oppWinding != SK_MinS32) {
+ if (span.fOppSum != SK_MinS32) {
+ SK_ALWAYSBREAK(span.fOppSum == oppSumWinding || segment->oppXor() || segment->_xor());
+ }
+ } else {
+ SK_ALWAYSBREAK(!firstOperand);
+ SK_ALWAYSBREAK(!segment->operand());
+ SK_ALWAYSBREAK(!span.fOppValue);
+ }
+ next = next->next();
+ } while (next != first);
}
+#endif
-void SkPathOpsDebug::DumpAngles(const SkTArray<SkOpAngle* , true>& angles) {
- int count = angles.count();
- for (int index = 0; index < count; ++index) {
- angles[index]->dump();
+#if DEBUG_SWAP_TOP
+bool SkOpSegment::controlsContainedByEnds(int tStart, int tEnd) const {
+ if (fVerb != SkPath::kCubic_Verb) {
+ return false;
}
+ SkDCubic dst = SkDCubic::SubDivide(fPts, fTs[tStart].fT, fTs[tEnd].fT);
+ return dst.controlsContainedByEnds();
}
-#endif // SK_DEBUG || !FORCE_RELEASE
+#endif
-#ifdef SK_DEBUG
-void SkOpSpan::dump() const {
- SkDebugf("t=");
- DebugDumpDouble(fT);
- SkDebugf(" pt=");
- SkDPoint::dump(fPt);
- SkDebugf(" other.fID=%d", fOther->debugID());
- SkDebugf(" [%d] otherT=", fOtherIndex);
- DebugDumpDouble(fOtherT);
- SkDebugf(" windSum=");
- SkPathOpsDebug::WindingPrintf(fWindSum);
- if (SkPathOpsDebug::ValidWind(fOppSum) || fOppValue != 0) {
- SkDebugf(" oppSum=");
- SkPathOpsDebug::WindingPrintf(fOppSum);
+#if DEBUG_CONCIDENT
+// SK_ALWAYSBREAK if pair has not already been added
+void SkOpSegment::debugAddTPair(double t, const SkOpSegment& other, double otherT) const {
+ for (int i = 0; i < fTs.count(); ++i) {
+ if (fTs[i].fT == t && fTs[i].fOther == &other && fTs[i].fOtherT == otherT) {
+ return;
+ }
}
- SkDebugf(" windValue=%d", fWindValue);
- if (SkPathOpsDebug::ValidWind(fOppSum) || fOppValue != 0) {
- SkDebugf(" oppValue=%d", fOppValue);
+ SK_ALWAYSBREAK(0);
+}
+#endif
+
+#if DEBUG_ANGLE
+void SkOpSegment::debugCheckPointsEqualish(int tStart, int tEnd) const {
+ const SkPoint& basePt = fTs[tStart].fPt;
+ while (++tStart < tEnd) {
+ const SkPoint& cmpPt = fTs[tStart].fPt;
+ SK_ALWAYSBREAK(SkDPoint::ApproximatelyEqual(basePt, cmpPt));
}
- if (fDone) {
- SkDebugf(" done");
+}
+#endif
+
+#if DEBUG_SWAP_TOP
+int SkOpSegment::debugInflections(int tStart, int tEnd) const {
+ if (fVerb != SkPath::kCubic_Verb) {
+ return false;
}
- if (fUnsortableStart) {
- SkDebugf(" unsortable-start");
+ SkDCubic dst = SkDCubic::SubDivide(fPts, fTs[tStart].fT, fTs[tEnd].fT);
+ double inflections[2];
+ return dst.findInflections(inflections);
+}
+#endif
+
+const SkOpAngle* SkOpSegment::debugLastAngle() const {
+ const SkOpAngle* result = NULL;
+ for (int index = 0; index < count(); ++index) {
+ const SkOpSpan& span = this->span(index);
+ if (span.fToAngle) {
+ SkASSERT(!result);
+ result = span.fToAngle;
+ }
}
- if (fUnsortableEnd) {
- SkDebugf(" unsortable-end");
+ SkASSERT(result);
+ return result;
+}
+
+void SkOpSegment::debugReset() {
+ fTs.reset();
+ fAngles.reset();
+}
+
+#if DEBUG_CONCIDENT
+void SkOpSegment::debugShowTs(const char* prefix) const {
+ SkDebugf("%s %s id=%d", __FUNCTION__, prefix, fID);
+ int lastWind = -1;
+ int lastOpp = -1;
+ double lastT = -1;
+ int i;
+ for (i = 0; i < fTs.count(); ++i) {
+ bool change = lastT != fTs[i].fT || lastWind != fTs[i].fWindValue
+ || lastOpp != fTs[i].fOppValue;
+ if (change && lastWind >= 0) {
+ SkDebugf(" t=%1.3g %1.9g,%1.9g w=%d o=%d]",
+ lastT, xyAtT(i - 1).fX, xyAtT(i - 1).fY, lastWind, lastOpp);
+ }
+ if (change) {
+ SkDebugf(" [o=%d", fTs[i].fOther->fID);
+ lastWind = fTs[i].fWindValue;
+ lastOpp = fTs[i].fOppValue;
+ lastT = fTs[i].fT;
+ } else {
+ SkDebugf(",%d", fTs[i].fOther->fID);
+ }
}
- if (fTiny) {
- SkDebugf(" tiny");
- } else if (fSmall) {
- SkDebugf(" small");
+ if (i <= 0) {
+ return;
}
- if (fLoop) {
- SkDebugf(" loop");
+ SkDebugf(" t=%1.3g %1.9g,%1.9g w=%d o=%d]",
+ lastT, xyAtT(i - 1).fX, xyAtT(i - 1).fY, lastWind, lastOpp);
+ if (fOperand) {
+ SkDebugf(" operand");
+ }
+ if (done()) {
+ SkDebugf(" done");
}
SkDebugf("\n");
}
+#endif
-void Dump(const SkTArray<class SkOpAngle, true>& angles) {
- SkPathOpsDebug::DumpAngles(angles);
+#if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY
+void SkOpSegment::debugShowActiveSpans() const {
+ debugValidate();
+ if (done()) {
+ return;
+ }
+#if DEBUG_ACTIVE_SPANS_SHORT_FORM
+ int lastId = -1;
+ double lastT = -1;
+#endif
+ for (int i = 0; i < fTs.count(); ++i) {
+ if (fTs[i].fDone) {
+ continue;
+ }
+ SK_ALWAYSBREAK(i < fTs.count() - 1);
+#if DEBUG_ACTIVE_SPANS_SHORT_FORM
+ if (lastId == fID && lastT == fTs[i].fT) {
+ continue;
+ }
+ lastId = fID;
+ lastT = fTs[i].fT;
+#endif
+ SkDebugf("%s id=%d", __FUNCTION__, fID);
+ SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
+ for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
+ SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
+ }
+ const SkOpSpan* span = &fTs[i];
+ SkDebugf(") t=%1.9g (%1.9g,%1.9g)", span->fT, xAtT(span), yAtT(span));
+ int iEnd = i + 1;
+ while (fTs[iEnd].fT < 1 && approximately_equal(fTs[i].fT, fTs[iEnd].fT)) {
+ ++iEnd;
+ }
+ SkDebugf(" tEnd=%1.9g", fTs[iEnd].fT);
+ const SkOpSegment* other = fTs[i].fOther;
+ SkDebugf(" other=%d otherT=%1.9g otherIndex=%d windSum=",
+ other->fID, fTs[i].fOtherT, fTs[i].fOtherIndex);
+ if (fTs[i].fWindSum == SK_MinS32) {
+ SkDebugf("?");
+ } else {
+ SkDebugf("%d", fTs[i].fWindSum);
+ }
+ SkDebugf(" windValue=%d oppValue=%d\n", fTs[i].fWindValue, fTs[i].fOppValue);
+ }
}
+#endif
-void Dump(const SkTArray<class SkOpAngle* , true>& angles) {
- SkPathOpsDebug::DumpAngles(angles);
+#if DEBUG_MARK_DONE || DEBUG_UNSORTABLE
+void SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding) {
+ const SkPoint& pt = xyAtT(&span);
+ SkDebugf("%s id=%d", fun, fID);
+ SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
+ for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
+ SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
+ }
+ SK_ALWAYSBREAK(&span == &span.fOther->fTs[span.fOtherIndex].fOther->
+ fTs[span.fOther->fTs[span.fOtherIndex].fOtherIndex]);
+ SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=%d windSum=",
+ span.fT, span.fOther->fTs[span.fOtherIndex].fOtherIndex, pt.fX, pt.fY,
+ (&span)[1].fT, winding);
+ if (span.fWindSum == SK_MinS32) {
+ SkDebugf("?");
+ } else {
+ SkDebugf("%d", span.fWindSum);
+ }
+ SkDebugf(" windValue=%d\n", span.fWindValue);
}
-void Dump(const SkTArray<class SkOpAngle, true>* angles) {
- SkPathOpsDebug::DumpAngles(*angles);
+void SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding,
+ int oppWinding) {
+ const SkPoint& pt = xyAtT(&span);
+ SkDebugf("%s id=%d", fun, fID);
+ SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
+ for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
+ SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
+ }
+ SK_ALWAYSBREAK(&span == &span.fOther->fTs[span.fOtherIndex].fOther->
+ fTs[span.fOther->fTs[span.fOtherIndex].fOtherIndex]);
+ SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=%d newOppSum=%d oppSum=",
+ span.fT, span.fOther->fTs[span.fOtherIndex].fOtherIndex, pt.fX, pt.fY,
+ (&span)[1].fT, winding, oppWinding);
+ if (span.fOppSum == SK_MinS32) {
+ SkDebugf("?");
+ } else {
+ SkDebugf("%d", span.fOppSum);
+ }
+ SkDebugf(" windSum=");
+ if (span.fWindSum == SK_MinS32) {
+ SkDebugf("?");
+ } else {
+ SkDebugf("%d", span.fWindSum);
+ }
+ SkDebugf(" windValue=%d oppValue=%d\n", span.fWindValue, span.fOppValue);
}
+#endif
-void Dump(const SkTArray<class SkOpAngle* , true>* angles) {
- SkPathOpsDebug::DumpAngles(*angles);
+#if DEBUG_SHOW_WINDING
+int SkOpSegment::debugShowWindingValues(int slotCount, int ofInterest) const {
+ if (!(1 << fID & ofInterest)) {
+ return 0;
+ }
+ int sum = 0;
+ SkTArray<char, true> slots(slotCount * 2);
+ memset(slots.begin(), ' ', slotCount * 2);
+ for (int i = 0; i < fTs.count(); ++i) {
+ // if (!(1 << fTs[i].fOther->fID & ofInterest)) {
+ // continue;
+ // }
+ sum += fTs[i].fWindValue;
+ slots[fTs[i].fOther->fID - 1] = as_digit(fTs[i].fWindValue);
+ sum += fTs[i].fOppValue;
+ slots[slotCount + fTs[i].fOther->fID - 1] = as_digit(fTs[i].fOppValue);
+ }
+ SkDebugf("%s id=%2d %.*s | %.*s\n", __FUNCTION__, fID, slotCount, slots.begin(), slotCount,
+ slots.begin() + slotCount);
+ return sum;
}
-
#endif
-#if !FORCE_RELEASE && 0 // enable when building without extended test
-void SkPathOpsDebug::ShowPath(const SkPath& one, const SkPath& two, SkPathOp op, const char* name) {
-}
+void SkOpSegment::debugValidate() const {
+#if DEBUG_VALIDATE
+ int count = fTs.count();
+ SK_ALWAYSBREAK(count >= 2);
+ SK_ALWAYSBREAK(fTs[0].fT == 0);
+ SK_ALWAYSBREAK(fTs[count - 1].fT == 1);
+ int done = 0;
+ double t = -1;
+ const SkOpSpan* last = NULL;
+ bool tinyTFound = false;
+ bool hasLoop = false;
+ for (int i = 0; i < count; ++i) {
+ const SkOpSpan& span = fTs[i];
+ SK_ALWAYSBREAK(t <= span.fT);
+ t = span.fT;
+ int otherIndex = span.fOtherIndex;
+ const SkOpSegment* other = span.fOther;
+ SK_ALWAYSBREAK(other != this || fVerb == SkPath::kCubic_Verb);
+ const SkOpSpan& otherSpan = other->fTs[otherIndex];
+ SK_ALWAYSBREAK(otherSpan.fPt == span.fPt);
+ SK_ALWAYSBREAK(otherSpan.fOtherT == t);
+ SK_ALWAYSBREAK(&fTs[i] == &otherSpan.fOther->fTs[otherSpan.fOtherIndex]);
+ done += span.fDone;
+ if (last) {
+ SK_ALWAYSBREAK(last->fT != span.fT || last->fOther != span.fOther);
+ bool tsEqual = last->fT == span.fT;
+ bool tsPreciselyEqual = precisely_equal(last->fT, span.fT);
+ SK_ALWAYSBREAK(!tsEqual || tsPreciselyEqual);
+ bool pointsEqual = last->fPt == span.fPt;
+ bool pointsNearlyEqual = AlmostEqualUlps(last->fPt, span.fPt);
+#if 0 // bufferOverflow test triggers this
+ SK_ALWAYSBREAK(!tsPreciselyEqual || pointsNearlyEqual);
+#endif
+// SK_ALWAYSBREAK(!last->fTiny || !tsPreciselyEqual || span.fTiny || tinyTFound);
+ SK_ALWAYSBREAK(last->fTiny || tsPreciselyEqual || !pointsEqual || hasLoop);
+ SK_ALWAYSBREAK(!last->fTiny || pointsEqual);
+ SK_ALWAYSBREAK(!last->fTiny || last->fDone);
+ SK_ALWAYSBREAK(!last->fSmall || pointsNearlyEqual);
+ SK_ALWAYSBREAK(!last->fSmall || last->fDone);
+// SK_ALWAYSBREAK(!last->fSmall || last->fTiny);
+// SK_ALWAYSBREAK(last->fTiny || !pointsEqual || last->fDone == span.fDone);
+ if (last->fTiny) {
+ tinyTFound |= !tsPreciselyEqual;
+ } else {
+ tinyTFound = false;
+ }
+ }
+ last = &span;
+ hasLoop |= last->fLoop;
+ }
+ SK_ALWAYSBREAK(done == fDoneSpans);
+// if (fAngles.count() ) {
+// fAngles.begin()->debugValidateLoop();
+// }
#endif
+}
diff --git a/chromium/third_party/skia/src/pathops/SkPathOpsDebug.h b/chromium/third_party/skia/src/pathops/SkPathOpsDebug.h
index d2155188daf..9dc562fea1d 100644
--- a/chromium/third_party/skia/src/pathops/SkPathOpsDebug.h
+++ b/chromium/third_party/skia/src/pathops/SkPathOpsDebug.h
@@ -31,6 +31,10 @@
#define SK_SNPRINTF snprintf
#endif
+#define WIND_AS_STRING(x) char x##Str[12]; \
+ if (!SkPathOpsDebug::ValidWind(x)) strcpy(x##Str, "?"); \
+ else SK_SNPRINTF(x##Str, sizeof(x##Str), "%d", x)
+
#if FORCE_RELEASE
#define DEBUG_ACTIVE_OP 0
@@ -46,8 +50,11 @@
#define DEBUG_CHECK_TINY 0
#define DEBUG_CONCIDENT 0
#define DEBUG_CROSS 0
+#define DEBUG_CUBIC_BINARY_SEARCH 0
+#define DEBUG_DUPLICATES 0
#define DEBUG_FLAT_QUADS 0
#define DEBUG_FLOW 0
+#define DEBUG_LIMIT_WIND_SUM 0
#define DEBUG_MARK_DONE 0
#define DEBUG_PATH_CONSTRUCTION 0
#define DEBUG_SHOW_TEST_NAME 0
@@ -79,8 +86,11 @@
#define DEBUG_CHECK_TINY 1
#define DEBUG_CONCIDENT 1
#define DEBUG_CROSS 01
+#define DEBUG_CUBIC_BINARY_SEARCH 1
+#define DEBUG_DUPLICATES 1
#define DEBUG_FLAT_QUADS 0
#define DEBUG_FLOW 1
+#define DEBUG_LIMIT_WIND_SUM 4
#define DEBUG_MARK_DONE 1
#define DEBUG_PATH_CONSTRUCTION 1
#define DEBUG_SHOW_TEST_NAME 1
@@ -92,7 +102,7 @@
#define DEBUG_SORT_SINGLE 0
#define DEBUG_SWAP_TOP 1
#define DEBUG_UNSORTABLE 1
-#define DEBUG_VALIDATE 1
+#define DEBUG_VALIDATE 0
#define DEBUG_WIND_BUMP 0
#define DEBUG_WINDING 1
#define DEBUG_WINDING_AT_T 1
@@ -115,28 +125,27 @@
#define CUBIC_DEBUG_DATA(c) c[0].fX, c[0].fY, c[1].fX, c[1].fY, c[2].fX, c[2].fY, c[3].fX, c[3].fY
#define QUAD_DEBUG_DATA(q) q[0].fX, q[0].fY, q[1].fX, q[1].fY, q[2].fX, q[2].fY
#define LINE_DEBUG_DATA(l) l[0].fX, l[0].fY, l[1].fX, l[1].fY
-#define PT_DEBUG_DATA(i, n) i.pt(n).fX, i.pt(n).fY
+#define PT_DEBUG_DATA(i, n) i.pt(n).asSkPoint().fX, i.pt(n).asSkPoint().fY
#ifndef DEBUG_TEST
#define DEBUG_TEST 0
#endif
-#if defined SK_DEBUG || !FORCE_RELEASE
-
#if DEBUG_SHOW_TEST_NAME
#include "SkTLS.h"
#endif
#include "SkTArray.h"
+#include "SkTDArray.h"
class SkPathOpsDebug {
public:
- static int gMaxWindSum;
- static int gMaxWindValue;
-
static const char* kLVerbStr[];
+
+#if defined(SK_DEBUG) || !FORCE_RELEASE
static int gContourID;
static int gSegmentID;
+#endif
#if DEBUG_SORT || DEBUG_SWAP_TOP
static int gSortCountDefault;
@@ -147,6 +156,7 @@ public:
static const char* kPathOpStr[];
#endif
+ static bool ChaseContains(const SkTDArray<struct SkOpSpan *>& , const struct SkOpSpan * );
static void MathematicaIze(char* str, size_t bufferSize);
static bool ValidWind(int winding);
static void WindingPrintf(int winding);
@@ -158,18 +168,68 @@ public:
#define DEBUG_FILENAME_STRING (reinterpret_cast<char* >(SkTLS::Get(SkPathOpsDebug::CreateNameStr, \
SkPathOpsDebug::DeleteNameStr)))
static void BumpTestName(char* );
- static void ShowPath(const SkPath& one, const SkPath& two, SkPathOp op, const char* name);
#endif
- static void DumpAngles(const SkTArray<class SkOpAngle, true>& angles);
- static void DumpAngles(const SkTArray<class SkOpAngle* , true>& angles);
+ static void ShowPath(const SkPath& one, const SkPath& two, SkPathOp op, const char* name);
+ static void DumpCoincidence(const SkTArray<class SkOpContour, true>& contours);
+ static void DumpCoincidence(const SkTArray<class SkOpContour* , true>& contours);
+ static void DumpContours(const SkTArray<class SkOpContour, true>& contours);
+ static void DumpContours(const SkTArray<class SkOpContour* , true>& contours);
+ static void DumpContourAngles(const SkTArray<class SkOpContour, true>& contours);
+ static void DumpContourAngles(const SkTArray<class SkOpContour* , true>& contours);
+ static void DumpContourPt(const SkTArray<class SkOpContour, true>& contours, int id);
+ static void DumpContourPt(const SkTArray<class SkOpContour* , true>& contours, int id);
+ static void DumpContourPts(const SkTArray<class SkOpContour, true>& contours);
+ static void DumpContourPts(const SkTArray<class SkOpContour* , true>& contours);
+ static void DumpContourSpan(const SkTArray<class SkOpContour, true>& contours, int id);
+ static void DumpContourSpan(const SkTArray<class SkOpContour* , true>& contours, int id);
+ static void DumpContourSpans(const SkTArray<class SkOpContour, true>& contours);
+ static void DumpContourSpans(const SkTArray<class SkOpContour* , true>& contours);
+ static void DumpSpans(const SkTDArray<struct SkOpSpan *>& );
+ static void DumpSpans(const SkTDArray<struct SkOpSpan *>* );
};
// shorthand for calling from debugger
-void Dump(const SkTArray<class SkOpAngle, true>& angles);
-void Dump(const SkTArray<class SkOpAngle* , true>& angles);
-void Dump(const SkTArray<class SkOpAngle, true>* angles);
-void Dump(const SkTArray<class SkOpAngle* , true>* angles);
-
-#endif // SK_DEBUG || !FORCE_RELEASE
+void Dump(const SkTArray<class SkOpContour, true>& contours);
+void Dump(const SkTArray<class SkOpContour* , true>& contours);
+void Dump(const SkTArray<class SkOpContour, true>* contours);
+void Dump(const SkTArray<class SkOpContour* , true>* contours);
+
+void Dump(const SkTDArray<SkOpSpan* >& chase);
+void Dump(const SkTDArray<SkOpSpan* >* chase);
+
+void DumpAngles(const SkTArray<class SkOpContour, true>& contours);
+void DumpAngles(const SkTArray<class SkOpContour* , true>& contours);
+void DumpAngles(const SkTArray<class SkOpContour, true>* contours);
+void DumpAngles(const SkTArray<class SkOpContour* , true>* contours);
+
+void DumpCoin(const SkTArray<class SkOpContour, true>& contours);
+void DumpCoin(const SkTArray<class SkOpContour* , true>& contours);
+void DumpCoin(const SkTArray<class SkOpContour, true>* contours);
+void DumpCoin(const SkTArray<class SkOpContour* , true>* contours);
+
+void DumpPts(const SkTArray<class SkOpContour, true>& contours);
+void DumpPts(const SkTArray<class SkOpContour* , true>& contours);
+void DumpPts(const SkTArray<class SkOpContour, true>* contours);
+void DumpPts(const SkTArray<class SkOpContour* , true>* contours);
+
+void DumpPt(const SkTArray<class SkOpContour, true>& contours, int segmentID);
+void DumpPt(const SkTArray<class SkOpContour* , true>& contours, int segmentID);
+void DumpPt(const SkTArray<class SkOpContour, true>* contours, int segmentID);
+void DumpPt(const SkTArray<class SkOpContour* , true>* contours, int segmentID);
+
+void DumpSpans(const SkTArray<class SkOpContour, true>& contours);
+void DumpSpans(const SkTArray<class SkOpContour* , true>& contours);
+void DumpSpans(const SkTArray<class SkOpContour, true>* contours);
+void DumpSpans(const SkTArray<class SkOpContour* , true>* contours);
+
+void DumpSpan(const SkTArray<class SkOpContour, true>& contours, int segmentID);
+void DumpSpan(const SkTArray<class SkOpContour* , true>& contours, int segmentID);
+void DumpSpan(const SkTArray<class SkOpContour, true>* contours, int segmentID);
+void DumpSpan(const SkTArray<class SkOpContour* , true>* contours, int segmentID);
+
+// generates tools/path_sorter.htm and path_visualizer.htm compatible data
+void DumpQ(const struct SkDQuad& quad1, const struct SkDQuad& quad2, int testNo);
+
+void DumpT(const struct SkDQuad& quad, double t);
#endif
diff --git a/chromium/third_party/skia/src/pathops/SkPathOpsLine.cpp b/chromium/third_party/skia/src/pathops/SkPathOpsLine.cpp
index 1e74123abf6..622961911a4 100644
--- a/chromium/third_party/skia/src/pathops/SkPathOpsLine.cpp
+++ b/chromium/third_party/skia/src/pathops/SkPathOpsLine.cpp
@@ -63,7 +63,7 @@ double SkDLine::exactPoint(const SkDPoint& xy) const {
return -1;
}
-double SkDLine::nearPoint(const SkDPoint& xy) const {
+double SkDLine::nearPoint(const SkDPoint& xy, bool* unequal) const {
if (!AlmostBetweenUlps(fPts[0].fX, xy.fX, fPts[1].fX)
|| !AlmostBetweenUlps(fPts[0].fY, xy.fY, fPts[1].fY)) {
return -1;
@@ -86,6 +86,9 @@ double SkDLine::nearPoint(const SkDPoint& xy) const {
if (!AlmostEqualUlps(largest, largest + dist)) { // is the dist within ULPS tolerance?
return -1;
}
+ if (unequal) {
+ *unequal = (float) largest != (float) (largest + dist);
+ }
t = SkPinT(t);
SkASSERT(between(0, t, 1));
return t;
@@ -189,13 +192,3 @@ double SkDLine::NearPointV(const SkDPoint& xy, double top, double bottom, double
}
return t;
}
-
-#ifdef SK_DEBUG
-void SkDLine::dump() {
- SkDebugf("{{");
- fPts[0].dump();
- SkDebugf(", ");
- fPts[1].dump();
- SkDebugf("}}\n");
-}
-#endif
diff --git a/chromium/third_party/skia/src/pathops/SkPathOpsLine.h b/chromium/third_party/skia/src/pathops/SkPathOpsLine.h
index a3cfcf26efc..74eb6153488 100644
--- a/chromium/third_party/skia/src/pathops/SkPathOpsLine.h
+++ b/chromium/third_party/skia/src/pathops/SkPathOpsLine.h
@@ -30,7 +30,7 @@ struct SkDLine {
static double ExactPointH(const SkDPoint& xy, double left, double right, double y);
static double ExactPointV(const SkDPoint& xy, double top, double bottom, double x);
double isLeft(const SkDPoint& pt) const;
- double nearPoint(const SkDPoint& xy) const;
+ double nearPoint(const SkDPoint& xy, bool* unequal) const;
bool nearRay(const SkDPoint& xy) const;
static double NearPointH(const SkDPoint& xy, double left, double right, double y);
static double NearPointV(const SkDPoint& xy, double top, double bottom, double x);
@@ -38,9 +38,7 @@ struct SkDLine {
SkDPoint ptAtT(double t) const;
SkDLine subDivide(double t1, double t2) const;
-#ifdef SK_DEBUG
- void dump();
-#endif
+ void dump() const;
private:
SkDVector tangent() const { return fPts[0] - fPts[1]; }
};
diff --git a/chromium/third_party/skia/src/pathops/SkPathOpsOp.cpp b/chromium/third_party/skia/src/pathops/SkPathOpsOp.cpp
index 1b7b03b95ba..4c6923abb60 100644
--- a/chromium/third_party/skia/src/pathops/SkPathOpsOp.cpp
+++ b/chromium/third_party/skia/src/pathops/SkPathOpsOp.cpp
@@ -9,23 +9,23 @@
#include "SkPathOpsCommon.h"
#include "SkPathWriter.h"
-// FIXME: this and find chase should be merge together, along with
-// other code that walks winding in angles
-// OPTIMIZATION: Probably, the walked winding should be rolled into the angle structure
-// so it isn't duplicated by walkers like this one
-static SkOpSegment* findChaseOp(SkTDArray<SkOpSpan*>& chase, int& nextStart, int& nextEnd) {
+static SkOpSegment* findChaseOp(SkTDArray<SkOpSpan*>& chase, int* tIndex, int* endIndex) {
while (chase.count()) {
SkOpSpan* span;
chase.pop(&span);
const SkOpSpan& backPtr = span->fOther->span(span->fOtherIndex);
SkOpSegment* segment = backPtr.fOther;
- nextStart = backPtr.fOtherIndex;
- SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles;
- int done = 0;
- if (segment->activeAngle(nextStart, &done, &angles)) {
- SkOpAngle* last = angles.end() - 1;
- nextStart = last->start();
- nextEnd = last->end();
+ *tIndex = backPtr.fOtherIndex;
+ bool sortable = true;
+ bool done = true;
+ *endIndex = -1;
+ if (const SkOpAngle* last = segment->activeAngle(*tIndex, tIndex, endIndex, &done,
+ &sortable)) {
+ if (last->unorderable()) {
+ continue;
+ }
+ *tIndex = last->start();
+ *endIndex = last->end();
#if TRY_ROTATE
*chase.insert(0) = span;
#else
@@ -33,52 +33,34 @@ static SkOpSegment* findChaseOp(SkTDArray<SkOpSpan*>& chase, int& nextStart, int
#endif
return last->segment();
}
- if (done == angles.count()) {
+ if (done) {
continue;
}
- SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted;
- bool sortable = SkOpSegment::SortAngles(angles, &sorted,
- SkOpSegment::kMayBeUnordered_SortAngleKind);
- int angleCount = sorted.count();
-#if DEBUG_SORT
- sorted[0]->segment()->debugShowSort(__FUNCTION__, sorted, 0, sortable);
-#endif
if (!sortable) {
continue;
}
// find first angle, initialize winding to computed fWindSum
- int firstIndex = -1;
- const SkOpAngle* angle;
- bool foundAngle = true;
- do {
- ++firstIndex;
- if (firstIndex >= angleCount) {
- foundAngle = false;
- break;
- }
- angle = sorted[firstIndex];
- segment = angle->segment();
- } while (segment->windSum(angle) == SK_MinS32);
- if (!foundAngle) {
+ const SkOpAngle* angle = segment->spanToAngle(*tIndex, *endIndex);
+ if (!angle) {
continue;
}
- #if DEBUG_SORT
- segment->debugShowSort(__FUNCTION__, sorted, firstIndex, sortable);
- #endif
+ const SkOpAngle* firstAngle = angle;
+ SkDEBUGCODE(bool loop = false);
+ int winding;
+ do {
+ angle = angle->next();
+ SkASSERT(angle != firstAngle || !loop);
+ SkDEBUGCODE(loop |= angle == firstAngle);
+ segment = angle->segment();
+ winding = segment->windSum(angle);
+ } while (winding == SK_MinS32);
int sumMiWinding = segment->updateWindingReverse(angle);
int sumSuWinding = segment->updateOppWindingReverse(angle);
if (segment->operand()) {
SkTSwap<int>(sumMiWinding, sumSuWinding);
}
- int nextIndex = firstIndex + 1;
- int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
SkOpSegment* first = NULL;
- do {
- SkASSERT(nextIndex != firstIndex);
- if (nextIndex == angleCount) {
- nextIndex = 0;
- }
- angle = sorted[nextIndex];
+ while ((angle = angle->next()) != firstAngle) {
segment = angle->segment();
int start = angle->start();
int end = angle->end();
@@ -88,13 +70,14 @@ static SkOpSegment* findChaseOp(SkTDArray<SkOpSpan*>& chase, int& nextStart, int
if (!segment->done(angle)) {
if (!first) {
first = segment;
- nextStart = start;
- nextEnd = end;
+ *tIndex = start;
+ *endIndex = end;
}
+ // OPTIMIZATION: should this also add to the chase?
(void) segment->markAngle(maxWinding, sumWinding, oppMaxWinding,
oppSumWinding, angle);
}
- } while (++nextIndex != lastIndex);
+ }
if (first) {
#if TRY_ROTATE
*chase.insert(0) = span;
@@ -140,45 +123,57 @@ static bool bridgeOp(SkTArray<SkOpContour*, true>& contourList, const SkPathOp o
bool firstContour = true;
bool unsortable = false;
bool topUnsortable = false;
+ bool firstPass = true;
+ SkPoint lastTopLeft;
SkPoint topLeft = {SK_ScalarMin, SK_ScalarMin};
do {
int index, endIndex;
- bool done;
+ bool topDone;
+ bool onlyVertical = false;
+ lastTopLeft = topLeft;
SkOpSegment* current = FindSortableTop(contourList, SkOpAngle::kBinarySingle, &firstContour,
- &index, &endIndex, &topLeft, &topUnsortable, &done);
+ &index, &endIndex, &topLeft, &topUnsortable, &topDone, &onlyVertical, firstPass);
if (!current) {
- if (topUnsortable || !done) {
- topUnsortable = false;
+ if ((!topUnsortable || firstPass) && !topDone) {
SkASSERT(topLeft.fX != SK_ScalarMin && topLeft.fY != SK_ScalarMin);
+ if (lastTopLeft.fX == SK_ScalarMin && lastTopLeft.fY == SK_ScalarMin) {
+ if (firstPass) {
+ firstPass = false;
+ } else {
+ break;
+ }
+ }
topLeft.fX = topLeft.fY = SK_ScalarMin;
continue;
}
break;
+ } else if (onlyVertical) {
+ break;
}
- SkTDArray<SkOpSpan*> chaseArray;
+ firstPass = !topUnsortable || lastTopLeft != topLeft;
+ SkTDArray<SkOpSpan*> chase;
do {
if (current->activeOp(index, endIndex, xorMask, xorOpMask, op)) {
do {
if (!unsortable && current->done()) {
- #if DEBUG_ACTIVE_SPANS
- DebugShowActiveSpans(contourList);
- #endif
- if (simple->isEmpty()) {
- simple->init();
- }
break;
}
SkASSERT(unsortable || !current->done());
int nextStart = index;
int nextEnd = endIndex;
- SkOpSegment* next = current->findNextOp(&chaseArray, &nextStart, &nextEnd,
+ SkOpSegment* next = current->findNextOp(&chase, &nextStart, &nextEnd,
&unsortable, op, xorMask, xorOpMask);
if (!next) {
if (!unsortable && simple->hasMove()
&& current->verb() != SkPath::kLine_Verb
&& !simple->isClosed()) {
current->addCurveTo(index, endIndex, simple, true);
- SkASSERT(simple->isClosed());
+ #if DEBUG_ACTIVE_SPANS
+ if (!simple->isClosed()) {
+ DebugShowActiveSpans(contourList);
+ }
+ #endif
+// SkASSERT(simple->isClosed());
}
break;
}
@@ -199,7 +194,6 @@ static bool bridgeOp(SkTArray<SkOpContour*, true>& contourList, const SkPathOp o
if (!unsortable && !simple->isEmpty()) {
unsortable = current->checkSmall(min);
}
- SkASSERT(unsortable || simple->isEmpty());
if (!current->done(min)) {
current->addCurveTo(index, endIndex, simple, true);
current->markDoneBinary(min);
@@ -208,11 +202,18 @@ static bool bridgeOp(SkTArray<SkOpContour*, true>& contourList, const SkPathOp o
simple->close();
} else {
SkOpSpan* last = current->markAndChaseDoneBinary(index, endIndex);
- if (last && !last->fLoop) {
- *chaseArray.append() = last;
+ if (last && !last->fChased && !last->fLoop) {
+ last->fChased = true;
+ SkASSERT(!SkPathOpsDebug::ChaseContains(chase, last));
+ *chase.append() = last;
+#if DEBUG_WINDING
+ SkDebugf("%s chase.append id=%d windSum=%d small=%d\n", __FUNCTION__,
+ last->fOther->span(last->fOtherIndex).fOther->debugID(), last->fWindSum,
+ last->fSmall);
+#endif
}
}
- current = findChaseOp(chaseArray, index, endIndex);
+ current = findChaseOp(chase, &index, &endIndex);
#if DEBUG_ACTIVE_SPANS
DebugShowActiveSpans(contourList);
#endif
@@ -304,7 +305,9 @@ bool Op(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result) {
for (index = 0; index < contourList.count(); ++index) {
total += contourList[index]->segments().count();
}
- HandleCoincidence(&contourList, total);
+ if (!HandleCoincidence(&contourList, total)) {
+ return false;
+ }
// construct closed contours
SkPathWriter wrapper(*result);
bridgeOp(contourList, op, xorMask, xorOpMask, &wrapper);
diff --git a/chromium/third_party/skia/src/pathops/SkPathOpsPoint.h b/chromium/third_party/skia/src/pathops/SkPathOpsPoint.h
index c3e0b40ab9f..5c2e3a50ddd 100644
--- a/chromium/third_party/skia/src/pathops/SkPathOpsPoint.h
+++ b/chromium/third_party/skia/src/pathops/SkPathOpsPoint.h
@@ -15,7 +15,13 @@ inline bool AlmostEqualUlps(const SkPoint& pt1, const SkPoint& pt2) {
}
struct SkDVector {
- double fX, fY;
+ double fX;
+ double fY;
+
+ void set(const SkVector& pt) {
+ fX = pt.fX;
+ fY = pt.fY;
+ }
friend SkDPoint operator+(const SkDPoint& a, const SkDVector& b);
@@ -48,6 +54,13 @@ struct SkDVector {
return fX * a.fY - fY * a.fX;
}
+ // similar to cross, this bastardization considers nearly coincident to be zero
+ double crossCheck(const SkDVector& a) const {
+ double xy = fX * a.fY;
+ double yx = fY * a.fX;
+ return AlmostEqualUlps(xy, yx) ? 0 : xy - yx;
+ }
+
double dot(const SkDVector& a) const {
return fX * a.fX + fY * a.fY;
}
@@ -85,7 +98,6 @@ struct SkDPoint {
fY = pt.fY;
}
-
void operator+=(const SkDVector& v) {
fX += v.fX;
fY += v.fY;
@@ -136,6 +148,13 @@ struct SkDPoint {
return AlmostBequalUlps((double) largest, largest + dist); // is dist within ULPS tolerance?
}
+ static bool RoughlyEqual(const SkPoint& a, const SkPoint& b) {
+ if (approximately_equal(a.fX, b.fX) && approximately_equal(a.fY, b.fY)) {
+ return true;
+ }
+ return RoughlyEqualUlps(a.fX, b.fX) && RoughlyEqualUlps(a.fY, b.fY);
+ }
+
bool approximatelyPEqual(const SkDPoint& a) const {
if (approximately_equal(fX, a.fX) && approximately_equal(fY, a.fY)) {
return true;
@@ -150,6 +169,20 @@ struct SkDPoint {
return AlmostPequalUlps(largest, largest + dist); // is the dist within ULPS tolerance?
}
+ bool approximatelyDEqual(const SkDPoint& a) const {
+ if (approximately_equal(fX, a.fX) && approximately_equal(fY, a.fY)) {
+ return true;
+ }
+ if (!RoughlyEqualUlps(fX, a.fX) || !RoughlyEqualUlps(fY, a.fY)) {
+ return false;
+ }
+ double dist = distance(a); // OPTIMIZATION: can we compare against distSq instead ?
+ double tiniest = SkTMin(SkTMin(SkTMin(fX, a.fX), fY), a.fY);
+ double largest = SkTMax(SkTMax(SkTMax(fX, a.fX), fY), a.fY);
+ largest = SkTMax(largest, -tiniest);
+ return AlmostDequalUlps(largest, largest + dist); // is the dist within ULPS tolerance?
+ }
+
bool approximatelyZero() const {
return approximately_zero(fX) && approximately_zero(fY);
}
@@ -191,23 +224,9 @@ struct SkDPoint {
return roughly_equal(a.fY, fY) && roughly_equal(a.fX, fX);
}
- #ifdef SK_DEBUG
- void dump() {
- SkDebugf("{");
- DebugDumpDouble(fX);
- SkDebugf(", ");
- DebugDumpDouble(fY);
- SkDebugf("}");
- }
-
- static void dump(const SkPoint& pt) {
- SkDebugf("{");
- DebugDumpFloat(pt.fX);
- SkDebugf(", ");
- DebugDumpFloat(pt.fY);
- SkDebugf("}");
- }
- #endif
+ // utilities callable by the user from the debugger when the implementation code is linked in
+ void dump() const;
+ static void Dump(const SkPoint& pt);
};
#endif
diff --git a/chromium/third_party/skia/src/pathops/SkPathOpsQuad.cpp b/chromium/third_party/skia/src/pathops/SkPathOpsQuad.cpp
index 63e20388dd8..c1d068af345 100644
--- a/chromium/third_party/skia/src/pathops/SkPathOpsQuad.cpp
+++ b/chromium/third_party/skia/src/pathops/SkPathOpsQuad.cpp
@@ -252,10 +252,10 @@ SkDPoint SkDQuad::subDivide(const SkDPoint& a, const SkDPoint& c, double t1, dou
SkDLine b1 = {{c, sub[1] + (c - sub[2])}};
SkIntersections i;
i.intersectRay(b0, b1);
- if (i.used() == 1) {
+ if (i.used() == 1 && i[0][0] >= 0 && i[1][0] >= 0) {
b = i.pt(0);
} else {
- SkASSERT(i.used() == 2 || i.used() == 0);
+ SkASSERT(i.used() <= 2);
b = SkDPoint::Mid(b0[1], b1[1]);
}
#endif
@@ -265,14 +265,14 @@ SkDPoint SkDQuad::subDivide(const SkDPoint& a, const SkDPoint& c, double t1, dou
if (t1 == 1 || t2 == 1) {
align(2, &b);
}
- if (precisely_subdivide_equal(b.fX, a.fX)) {
+ if (AlmostBequalUlps(b.fX, a.fX)) {
b.fX = a.fX;
- } else if (precisely_subdivide_equal(b.fX, c.fX)) {
+ } else if (AlmostBequalUlps(b.fX, c.fX)) {
b.fX = c.fX;
}
- if (precisely_subdivide_equal(b.fY, a.fY)) {
+ if (AlmostBequalUlps(b.fY, a.fY)) {
b.fY = a.fY;
- } else if (precisely_subdivide_equal(b.fY, c.fY)) {
+ } else if (AlmostBequalUlps(b.fY, c.fY)) {
b.fY = c.fY;
}
return b;
@@ -340,16 +340,3 @@ void SkDQuad::SetABC(const double* quad, double* a, double* b, double* c) {
*a -= *b; // a = A - 2*B + C
*b -= *c; // b = 2*B - 2*C
}
-
-#ifdef SK_DEBUG
-void SkDQuad::dump() {
- SkDebugf("{{");
- int index = 0;
- do {
- fPts[index].dump();
- SkDebugf(", ");
- } while (++index < 2);
- fPts[index].dump();
- SkDebugf("}}\n");
-}
-#endif
diff --git a/chromium/third_party/skia/src/pathops/SkPathOpsQuad.h b/chromium/third_party/skia/src/pathops/SkPathOpsQuad.h
index 69d5a6dd904..932c5fbe75d 100644
--- a/chromium/third_party/skia/src/pathops/SkPathOpsQuad.h
+++ b/chromium/third_party/skia/src/pathops/SkPathOpsQuad.h
@@ -62,9 +62,10 @@ struct SkDQuad {
SkDCubic toCubic() const;
SkDPoint top(double startT, double endT) const;
-#ifdef SK_DEBUG
- void dump();
-#endif
+ // utilities callable by the user from the debugger when the implementation code is linked in
+ void dump() const;
+ void dumpComma(const char*) const;
+
private:
// static double Tangent(const double* quadratic, double t); // uncalled
};
diff --git a/chromium/third_party/skia/src/pathops/SkPathOpsSimplify.cpp b/chromium/third_party/skia/src/pathops/SkPathOpsSimplify.cpp
index 548f83e6605..57090ac4238 100644
--- a/chromium/third_party/skia/src/pathops/SkPathOpsSimplify.cpp
+++ b/chromium/third_party/skia/src/pathops/SkPathOpsSimplify.cpp
@@ -13,38 +13,38 @@ static bool bridgeWinding(SkTArray<SkOpContour*, true>& contourList, SkPathWrite
bool firstContour = true;
bool unsortable = false;
bool topUnsortable = false;
+ bool firstPass = true;
+ SkPoint lastTopLeft;
SkPoint topLeft = {SK_ScalarMin, SK_ScalarMin};
do {
int index, endIndex;
bool topDone;
+ bool onlyVertical = false;
+ lastTopLeft = topLeft;
SkOpSegment* current = FindSortableTop(contourList, SkOpAngle::kUnaryWinding, &firstContour,
- &index, &endIndex, &topLeft, &topUnsortable, &topDone);
+ &index, &endIndex, &topLeft, &topUnsortable, &topDone, &onlyVertical, firstPass);
if (!current) {
- if (topUnsortable || !topDone) {
- topUnsortable = false;
+ if ((!topUnsortable || firstPass) && !topDone) {
SkASSERT(topLeft.fX != SK_ScalarMin && topLeft.fY != SK_ScalarMin);
topLeft.fX = topLeft.fY = SK_ScalarMin;
continue;
}
break;
+ } else if (onlyVertical) {
+ break;
}
- SkTDArray<SkOpSpan*> chaseArray;
+ firstPass = !topUnsortable || lastTopLeft != topLeft;
+ SkTDArray<SkOpSpan*> chase;
do {
if (current->activeWinding(index, endIndex)) {
do {
if (!unsortable && current->done()) {
- #if DEBUG_ACTIVE_SPANS
- DebugShowActiveSpans(contourList);
- #endif
- if (simple->isEmpty()) {
- simple->init();
- break;
- }
+ break;
}
SkASSERT(unsortable || !current->done());
int nextStart = index;
int nextEnd = endIndex;
- SkOpSegment* next = current->findNextWinding(&chaseArray, &nextStart, &nextEnd,
+ SkOpSegment* next = current->findNextWinding(&chase, &nextStart, &nextEnd,
&unsortable);
if (!next) {
if (!unsortable && simple->hasMove()
@@ -67,7 +67,7 @@ static bool bridgeWinding(SkTArray<SkOpContour*, true>& contourList, SkPathWrite
} while (!simple->isClosed() && (!unsortable
|| !current->done(SkMin32(index, endIndex))));
if (current->activeWinding(index, endIndex) && !simple->isClosed()) {
- SkASSERT(unsortable || simple->isEmpty());
+// SkASSERT(unsortable || simple->isEmpty());
int min = SkMin32(index, endIndex);
if (!current->done(min)) {
current->addCurveTo(index, endIndex, simple, true);
@@ -77,11 +77,19 @@ static bool bridgeWinding(SkTArray<SkOpContour*, true>& contourList, SkPathWrite
simple->close();
} else {
SkOpSpan* last = current->markAndChaseDoneUnary(index, endIndex);
- if (last && !last->fLoop) {
- *chaseArray.append() = last;
+ if (last && !last->fChased && !last->fLoop) {
+ last->fChased = true;
+ SkASSERT(!SkPathOpsDebug::ChaseContains(chase, last));
+ // assert that last isn't already in array
+ *chase.append() = last;
+#if DEBUG_WINDING
+ SkDebugf("%s chase.append id=%d windSum=%d small=%d\n", __FUNCTION__,
+ last->fOther->span(last->fOtherIndex).fOther->debugID(), last->fWindSum,
+ last->fSmall);
+#endif
}
}
- current = FindChase(chaseArray, index, endIndex);
+ current = FindChase(&chase, &index, &endIndex);
#if DEBUG_ACTIVE_SPANS
DebugShowActiveSpans(contourList);
#endif
@@ -182,7 +190,9 @@ bool Simplify(const SkPath& path, SkPath* result) {
next = *nextPtr++;
} while (AddIntersectTs(current, next) && nextPtr != listEnd);
} while (currentPtr != listEnd);
- HandleCoincidence(&contourList, 0);
+ if (!HandleCoincidence(&contourList, 0)) {
+ return false;
+ }
// construct closed contours
SkPathWriter simple(*result);
if (builder.xorMask() == kWinding_PathOpsMask ? bridgeWinding(contourList, &simple)
diff --git a/chromium/third_party/skia/src/pathops/SkPathOpsTriangle.cpp b/chromium/third_party/skia/src/pathops/SkPathOpsTriangle.cpp
index 7db4831a069..77845e06730 100644
--- a/chromium/third_party/skia/src/pathops/SkPathOpsTriangle.cpp
+++ b/chromium/third_party/skia/src/pathops/SkPathOpsTriangle.cpp
@@ -23,7 +23,7 @@ bool SkDTriangle::contains(const SkDPoint& pt) const {
double dot12 = v1.dot(v2);
// original code doesn't handle degenerate input; isn't symmetric with inclusion of corner pts;
-// introduces necessary error with divide; doesn't short circuit on early answer
+// introduces error with divide; doesn't short circuit on early answer
#if 0
// Compute barycentric coordinates
double invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
diff --git a/chromium/third_party/skia/src/pathops/SkPathOpsTypes.cpp b/chromium/third_party/skia/src/pathops/SkPathOpsTypes.cpp
index dbed086fbd9..2c8d778c695 100644
--- a/chromium/third_party/skia/src/pathops/SkPathOpsTypes.cpp
+++ b/chromium/third_party/skia/src/pathops/SkPathOpsTypes.cpp
@@ -102,6 +102,13 @@ bool AlmostDequalUlps(float a, float b) {
return d_equal_ulps(a, b, UlpsEpsilon);
}
+bool AlmostDequalUlps(double a, double b) {
+ if (SkScalarIsFinite(a) || SkScalarIsFinite(b)) {
+ return AlmostDequalUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
+ }
+ return fabs(a - b) / SkTMax(fabs(a), fabs(b)) < FLT_EPSILON * 16;
+}
+
bool AlmostEqualUlps(float a, float b) {
const int UlpsEpsilon = 16;
return equal_ulps(a, b, UlpsEpsilon, UlpsEpsilon);
diff --git a/chromium/third_party/skia/src/pathops/SkPathOpsTypes.h b/chromium/third_party/skia/src/pathops/SkPathOpsTypes.h
index 4fa86abd91b..96627842b37 100644
--- a/chromium/third_party/skia/src/pathops/SkPathOpsTypes.h
+++ b/chromium/third_party/skia/src/pathops/SkPathOpsTypes.h
@@ -30,9 +30,7 @@ inline bool AlmostEqualUlps(double a, double b) {
// Use Almost Dequal when comparing should not special case denormalized values.
bool AlmostDequalUlps(float a, float b);
-inline bool AlmostDequalUlps(double a, double b) {
- return AlmostDequalUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
-}
+bool AlmostDequalUlps(double a, double b);
bool NotAlmostEqualUlps(float a, float b);
inline bool NotAlmostEqualUlps(double a, double b) {
@@ -85,6 +83,7 @@ inline int UlpsDistance(double a, double b) {
const double FLT_EPSILON_CUBED = FLT_EPSILON * FLT_EPSILON * FLT_EPSILON;
const double FLT_EPSILON_HALF = FLT_EPSILON / 2;
const double FLT_EPSILON_DOUBLE = FLT_EPSILON * 2;
+const double FLT_EPSILON_ORDERABLE_ERR = FLT_EPSILON * 16;
const double FLT_EPSILON_SQUARED = FLT_EPSILON * FLT_EPSILON;
const double FLT_EPSILON_SQRT = sqrt(FLT_EPSILON);
const double FLT_EPSILON_INVERSE = 1 / FLT_EPSILON;
@@ -92,6 +91,11 @@ const double DBL_EPSILON_ERR = DBL_EPSILON * 4; // FIXME: tune -- allow a few b
const double DBL_EPSILON_SUBDIVIDE_ERR = DBL_EPSILON * 16;
const double ROUGH_EPSILON = FLT_EPSILON * 64;
const double MORE_ROUGH_EPSILON = FLT_EPSILON * 256;
+const double WAY_ROUGH_EPSILON = FLT_EPSILON * 2048;
+
+inline bool zero_or_one(double x) {
+ return x == 0 || x == 1;
+}
inline bool approximately_zero(double x) {
return fabs(x) < FLT_EPSILON;
@@ -121,6 +125,10 @@ inline bool approximately_zero_double(double x) {
return fabs(x) < FLT_EPSILON_DOUBLE;
}
+inline bool approximately_zero_orderable(double x) {
+ return fabs(x) < FLT_EPSILON_ORDERABLE_ERR;
+}
+
inline bool approximately_zero_squared(double x) {
return fabs(x) < FLT_EPSILON_SQUARED;
}
@@ -139,7 +147,7 @@ inline bool approximately_zero_inverse(double x) {
// OPTIMIZATION: if called multiple times with the same denom, we want to pass 1/y instead
inline bool approximately_zero_when_compared_to(double x, double y) {
- return x == 0 || fabs(x / y) < FLT_EPSILON;
+ return x == 0 || fabs(x) < fabs(y * FLT_EPSILON);
}
// Use this for comparing Ts in the range of 0 to 1. For general numbers (larger and smaller) use
@@ -164,6 +172,10 @@ inline bool approximately_equal_double(double x, double y) {
return approximately_zero_double(x - y);
}
+inline bool approximately_equal_orderable(double x, double y) {
+ return approximately_zero_orderable(x - y);
+}
+
inline bool approximately_equal_squared(double x, double y) {
return approximately_equal(x, y);
}
@@ -172,18 +184,50 @@ inline bool approximately_greater(double x, double y) {
return x - FLT_EPSILON >= y;
}
+inline bool approximately_greater_double(double x, double y) {
+ return x - FLT_EPSILON_DOUBLE >= y;
+}
+
+inline bool approximately_greater_orderable(double x, double y) {
+ return x - FLT_EPSILON_ORDERABLE_ERR >= y;
+}
+
inline bool approximately_greater_or_equal(double x, double y) {
return x + FLT_EPSILON > y;
}
+inline bool approximately_greater_or_equal_double(double x, double y) {
+ return x + FLT_EPSILON_DOUBLE > y;
+}
+
+inline bool approximately_greater_or_equal_orderable(double x, double y) {
+ return x + FLT_EPSILON_ORDERABLE_ERR > y;
+}
+
inline bool approximately_lesser(double x, double y) {
return x + FLT_EPSILON <= y;
}
+inline bool approximately_lesser_double(double x, double y) {
+ return x + FLT_EPSILON_DOUBLE <= y;
+}
+
+inline bool approximately_lesser_orderable(double x, double y) {
+ return x + FLT_EPSILON_ORDERABLE_ERR <= y;
+}
+
inline bool approximately_lesser_or_equal(double x, double y) {
return x - FLT_EPSILON < y;
}
+inline bool approximately_lesser_or_equal_double(double x, double y) {
+ return x - FLT_EPSILON_DOUBLE < y;
+}
+
+inline bool approximately_lesser_or_equal_orderable(double x, double y) {
+ return x - FLT_EPSILON_ORDERABLE_ERR < y;
+}
+
inline bool approximately_greater_than_one(double x) {
return x > 1 - FLT_EPSILON;
}
@@ -204,6 +248,10 @@ inline bool approximately_negative(double x) {
return x < FLT_EPSILON;
}
+inline bool approximately_negative_orderable(double x) {
+ return x < FLT_EPSILON_ORDERABLE_ERR;
+}
+
inline bool precisely_negative(double x) {
return x < DBL_EPSILON_ERR;
}
@@ -212,6 +260,10 @@ inline bool approximately_one_or_less(double x) {
return x < 1 + FLT_EPSILON;
}
+inline bool approximately_one_or_less_double(double x) {
+ return x < 1 + FLT_EPSILON_DOUBLE;
+}
+
inline bool approximately_positive(double x) {
return x > -FLT_EPSILON;
}
@@ -224,6 +276,16 @@ inline bool approximately_zero_or_more(double x) {
return x > -FLT_EPSILON;
}
+inline bool approximately_zero_or_more_double(double x) {
+ return x > -FLT_EPSILON_DOUBLE;
+}
+
+inline bool approximately_between_orderable(double a, double b, double c) {
+ return a <= c
+ ? approximately_negative_orderable(a - b) && approximately_negative_orderable(b - c)
+ : approximately_negative_orderable(b - a) && approximately_negative_orderable(c - b);
+}
+
inline bool approximately_between(double a, double b, double c) {
return a <= c ? approximately_negative(a - b) && approximately_negative(b - c)
: approximately_negative(b - a) && approximately_negative(c - b);
@@ -240,12 +302,16 @@ inline bool between(double a, double b, double c) {
return (a - b) * (c - b) <= 0;
}
+inline bool roughly_equal(double x, double y) {
+ return fabs(x - y) < ROUGH_EPSILON;
+}
+
inline bool more_roughly_equal(double x, double y) {
return fabs(x - y) < MORE_ROUGH_EPSILON;
}
-inline bool roughly_equal(double x, double y) {
- return fabs(x - y) < ROUGH_EPSILON;
+inline bool way_roughly_equal(double x, double y) {
+ return fabs(x - y) < WAY_ROUGH_EPSILON;
}
struct SkDPoint;
@@ -311,22 +377,4 @@ inline double SkPinT(double t) {
return precisely_less_than_zero(t) ? 0 : precisely_greater_than_one(t) ? 1 : t;
}
-#ifdef SK_DEBUG
-inline void DebugDumpDouble(double x) {
- if (x == floor(x)) {
- SkDebugf("%.0f", x);
- } else {
- SkDebugf("%1.17g", x);
- }
-}
-
-inline void DebugDumpFloat(float x) {
- if (x == floorf(x)) {
- SkDebugf("%.0f", x);
- } else {
- SkDebugf("%1.9gf", x);
- }
-}
-#endif
-
#endif
diff --git a/chromium/third_party/skia/src/pathops/SkPathWriter.h b/chromium/third_party/skia/src/pathops/SkPathWriter.h
index 574708231b3..f32074d3cde 100644
--- a/chromium/third_party/skia/src/pathops/SkPathWriter.h
+++ b/chromium/third_party/skia/src/pathops/SkPathWriter.h
@@ -41,5 +41,4 @@ private:
bool fMoved;
};
-
#endif /* defined(__PathOps__SkPathWriter__) */
diff --git a/chromium/third_party/skia/src/pathops/SkQuarticRoot.cpp b/chromium/third_party/skia/src/pathops/SkQuarticRoot.cpp
index e5b486c76c0..f9a7bf51799 100644
--- a/chromium/third_party/skia/src/pathops/SkQuarticRoot.cpp
+++ b/chromium/third_party/skia/src/pathops/SkQuarticRoot.cpp
@@ -71,7 +71,9 @@ int SkReducedQuarticRoots(const double t4, const double t3, const double t2, con
return num;
}
if (oneHint) {
- SkASSERT(approximately_zero_double(t4 + t3 + t2 + t1 + t0)); // 1 is one root
+ SkASSERT(approximately_zero_double(t4 + t3 + t2 + t1 + t0) ||
+ approximately_zero_when_compared_to(t4 + t3 + t2 + t1 + t0, // 1 is one root
+ SkTMax(fabs(t4), SkTMax(fabs(t3), SkTMax(fabs(t2), SkTMax(fabs(t1), fabs(t0)))))));
// note that -C == A + B + D + E
int num = SkDCubic::RootsReal(t4, t4 + t3, -(t1 + t0), -t0, roots);
for (int i = 0; i < num; ++i) {
@@ -101,7 +103,8 @@ int SkQuarticRootsReal(int firstCubicRoot, const double A, const double B, const
const double q = a2 * a / 8 - a * b / 2 + c;
const double r = -3 * a2 * a2 / 256 + a2 * b / 16 - a * c / 4 + d;
int num;
- if (approximately_zero(r)) {
+ double largest = SkTMax(fabs(p), fabs(q));
+ if (approximately_zero_when_compared_to(r, largest)) {
/* no absolute term: y(y^3 + py + q) = 0 */
num = SkDCubic::RootsReal(1, 0, p, q, s);
s[num++] = 0;
diff --git a/chromium/third_party/skia/src/pathops/SkReduceOrder.cpp b/chromium/third_party/skia/src/pathops/SkReduceOrder.cpp
index ada52761b5c..bb2038b45f2 100644
--- a/chromium/third_party/skia/src/pathops/SkReduceOrder.cpp
+++ b/chromium/third_party/skia/src/pathops/SkReduceOrder.cpp
@@ -161,8 +161,8 @@ static int check_linear(const SkDCubic& cubic,
while (cubic[startIndex].approximatelyEqual(cubic[endIndex])) {
--endIndex;
if (endIndex == 0) {
- SkDebugf("%s shouldn't get here if all four points are about equal\n", __FUNCTION__);
- SkASSERT(0);
+ endIndex = 3;
+ break;
}
}
if (!cubic.isLinear(startIndex, endIndex)) {
diff --git a/chromium/third_party/skia/src/pathops/main.cpp b/chromium/third_party/skia/src/pathops/main.cpp
deleted file mode 100644
index 65479c25282..00000000000
--- a/chromium/third_party/skia/src/pathops/main.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "Test.h"
-
-using namespace skiatest;
-
-int main(int /*argc*/, char** /*argv*/) {
- Test tester;
- tester.run();
- return 0;
-}
diff --git a/chromium/third_party/skia/src/pdf/SkPDFDevice.cpp b/chromium/third_party/skia/src/pdf/SkPDFDevice.cpp
index 6625a8e701c..ab4d71d37f8 100644
--- a/chromium/third_party/skia/src/pdf/SkPDFDevice.cpp
+++ b/chromium/third_party/skia/src/pdf/SkPDFDevice.cpp
@@ -131,12 +131,12 @@ static int max_glyphid_for_typeface(SkTypeface* typeface) {
typedef SkAutoSTMalloc<128, uint16_t> SkGlyphStorage;
-static size_t force_glyph_encoding(const SkPaint& paint, const void* text,
- size_t len, SkGlyphStorage* storage,
- uint16_t** glyphIDs) {
+static int force_glyph_encoding(const SkPaint& paint, const void* text,
+ size_t len, SkGlyphStorage* storage,
+ uint16_t** glyphIDs) {
// Make sure we have a glyph id encoding.
if (paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding) {
- size_t numGlyphs = paint.textToGlyphs(text, len, NULL);
+ int numGlyphs = paint.textToGlyphs(text, len, NULL);
storage->reset(numGlyphs);
paint.textToGlyphs(text, len, storage->get());
*glyphIDs = storage->get();
@@ -145,12 +145,12 @@ static size_t force_glyph_encoding(const SkPaint& paint, const void* text,
// For user supplied glyph ids we need to validate them.
SkASSERT((len & 1) == 0);
- size_t numGlyphs = len / 2;
+ int numGlyphs = SkToInt(len / 2);
const uint16_t* input =
reinterpret_cast<uint16_t*>(const_cast<void*>((text)));
int maxGlyphID = max_glyphid_for_typeface(paint.getTypeface());
- size_t validated;
+ int validated;
for (validated = 0; validated < numGlyphs; ++validated) {
if (input[validated] > maxGlyphID) {
break;
@@ -167,7 +167,7 @@ static size_t force_glyph_encoding(const SkPaint& paint, const void* text,
memcpy(storage->get(), input, validated * sizeof(uint16_t));
}
- for (size_t i = validated; i < numGlyphs; ++i) {
+ for (int i = validated; i < numGlyphs; ++i) {
storage->get()[i] = input[i];
if (input[i] > maxGlyphID) {
storage->get()[i] = 0;
@@ -232,15 +232,14 @@ GraphicStateEntry::GraphicStateEntry() : fColor(SK_ColorBLACK),
fMatrix.reset();
}
-bool GraphicStateEntry::compareInitialState(const GraphicStateEntry& b) {
- return fColor == b.fColor &&
- fShaderIndex == b.fShaderIndex &&
- fGraphicStateIndex == b.fGraphicStateIndex &&
- fMatrix == b.fMatrix &&
- fClipStack == b.fClipStack &&
- (fTextScaleX == 0 ||
- b.fTextScaleX == 0 ||
- (fTextScaleX == b.fTextScaleX && fTextFill == b.fTextFill));
+bool GraphicStateEntry::compareInitialState(const GraphicStateEntry& cur) {
+ return fColor == cur.fColor &&
+ fShaderIndex == cur.fShaderIndex &&
+ fGraphicStateIndex == cur.fGraphicStateIndex &&
+ fMatrix == cur.fMatrix &&
+ fClipStack == cur.fClipStack &&
+ (fTextScaleX == 0 ||
+ (fTextScaleX == cur.fTextScaleX && fTextFill == cur.fTextFill));
}
class GraphicStackState {
@@ -405,10 +404,8 @@ static bool get_clip_stack_path(const SkMatrix& transform,
outClipPath->reset();
outClipPath->setFillType(SkPath::kInverseWinding_FillType);
continue;
- } else if (SkClipStack::Element::kRect_Type == clipEntry->getType()) {
- entryPath.addRect(clipEntry->getRect());
- } else if (SkClipStack::Element::kPath_Type == clipEntry->getType()) {
- entryPath = clipEntry->getPath();
+ } else {
+ clipEntry->asPath(&entryPath);
}
entryPath.transform(transform);
@@ -506,14 +503,13 @@ void GraphicStackState::updateClip(const SkClipStack& clipStack,
emit_clip(NULL, &translatedClip, fContentStream);
break;
}
- case SkClipStack::Element::kPath_Type: {
+ default: {
SkPath translatedPath;
- clipEntry->getPath().transform(transform, &translatedPath);
+ clipEntry->asPath(&translatedPath);
+ translatedPath.transform(transform, &translatedPath);
emit_clip(&translatedPath, NULL, fContentStream);
break;
}
- default:
- SkASSERT(false);
}
}
}
@@ -586,13 +582,10 @@ void GraphicStackState::updateDrawingState(const GraphicStateEntry& state) {
}
}
-SkBaseDevice* SkPDFDevice::onCreateCompatibleDevice(SkBitmap::Config config,
- int width, int height,
- bool isOpaque,
- Usage usage) {
+SkBaseDevice* SkPDFDevice::onCreateDevice(const SkImageInfo& info, Usage usage) {
SkMatrix initialTransform;
initialTransform.reset();
- SkISize size = SkISize::Make(width, height);
+ SkISize size = SkISize::Make(info.width(), info.height());
return SkNEW_ARGS(SkPDFDevice, (size, size, initialTransform));
}
@@ -711,7 +704,7 @@ private:
static inline SkBitmap makeContentBitmap(const SkISize& contentSize,
const SkMatrix* initialTransform) {
- SkBitmap bitmap;
+ SkImageInfo info;
if (initialTransform) {
// Compute the size of the drawing area.
SkVector drawingSize;
@@ -725,17 +718,19 @@ static inline SkBitmap makeContentBitmap(const SkISize& contentSize,
}
inverse.mapVectors(&drawingSize, 1);
SkISize size = SkSize::Make(drawingSize.fX, drawingSize.fY).toRound();
- bitmap.setConfig(SkBitmap::kNo_Config, abs(size.fWidth),
- abs(size.fHeight));
+ info = SkImageInfo::MakeUnknown(abs(size.fWidth), abs(size.fHeight));
} else {
- bitmap.setConfig(SkBitmap::kNo_Config, abs(contentSize.fWidth),
- abs(contentSize.fHeight));
+ info = SkImageInfo::MakeUnknown(abs(contentSize.fWidth),
+ abs(contentSize.fHeight));
}
+ SkBitmap bitmap;
+ bitmap.setInfo(info);
return bitmap;
}
// TODO(vandebo) change pageSize to SkSize.
+// TODO: inherit from SkBaseDevice instead of SkBitmapDevice
SkPDFDevice::SkPDFDevice(const SkISize& pageSize, const SkISize& contentSize,
const SkMatrix& initialTransform)
: SkBitmapDevice(makeContentBitmap(contentSize, &initialTransform)),
@@ -812,10 +807,6 @@ void SkPDFDevice::cleanUp(bool clearFontUsage) {
}
}
-uint32_t SkPDFDevice::getDeviceCapabilities() {
- return kVector_Capability;
-}
-
void SkPDFDevice::clear(SkColor color) {
this->cleanUp(true);
this->init();
@@ -992,10 +983,7 @@ void SkPDFDevice::drawPath(const SkDraw& d, const SkPath& origPath,
}
origPath.transform(*prePathMatrix, pathPtr);
} else {
- if (!matrix.preConcat(*prePathMatrix)) {
- // TODO(edisonn): report somehow why we failed?
- return;
- }
+ matrix.preConcat(*prePathMatrix);
}
}
@@ -1138,8 +1126,7 @@ void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len,
SkGlyphStorage storage(0);
uint16_t* glyphIDs = NULL;
- size_t numGlyphs = force_glyph_encoding(paint, text, len, &storage,
- &glyphIDs);
+ int numGlyphs = force_glyph_encoding(paint, text, len, &storage, &glyphIDs);
textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc();
@@ -1147,11 +1134,11 @@ void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len,
content.entry()->fContent.writeText("BT\n");
set_text_transform(x, y, textPaint.getTextSkewX(),
&content.entry()->fContent);
- size_t consumedGlyphCount = 0;
+ int consumedGlyphCount = 0;
while (numGlyphs > consumedGlyphCount) {
updateFont(textPaint, glyphIDs[consumedGlyphCount], content.entry());
SkPDFFont* font = content.entry()->fState.fFont;
- size_t availableGlyphs =
+ int availableGlyphs =
font->glyphsToPDFFontEncoding(glyphIDs + consumedGlyphCount,
numGlyphs - consumedGlyphCount);
fFontGlyphUsage->noteGlyphUsage(font, glyphIDs + consumedGlyphCount,
@@ -1341,18 +1328,12 @@ void SkPDFDevice::drawVertices(const SkDraw& d, SkCanvas::VertexMode,
if (d.fClip->isEmpty()) {
return;
}
- NOT_IMPLEMENTED("drawVerticies", true);
+ // TODO: implement drawVertices
}
void SkPDFDevice::drawDevice(const SkDraw& d, SkBaseDevice* device,
int x, int y, const SkPaint& paint) {
- if ((device->getDeviceCapabilities() & kVector_Capability) == 0) {
- // If we somehow get a raster device, do what our parent would do.
- INHERITED::drawDevice(d, device, x, y, paint);
- return;
- }
-
- // Assume that a vector capable device means that it's a PDF Device.
+ // our onCreateDevice() always creates SkPDFDevice subclasses.
SkPDFDevice* pdfDevice = static_cast<SkPDFDevice*>(device);
if (pdfDevice->isContentEmpty()) {
return;
@@ -2047,8 +2028,7 @@ void SkPDFDevice::populateGraphicStateEntryFromPaint(
const SkPaint& paint,
bool hasText,
GraphicStateEntry* entry) {
- SkASSERT(paint.getPathEffect() == NULL);
-
+ NOT_IMPLEMENTED(paint.getPathEffect() != NULL, false);
NOT_IMPLEMENTED(paint.getMaskFilter() != NULL, false);
NOT_IMPLEMENTED(paint.getColorFilter() != NULL, false);
@@ -2250,13 +2230,11 @@ void SkPDFDevice::internalDrawBitmap(const SkMatrix& origMatrix,
// the image. Avoiding alpha will reduce the pdf size and generation
// CPU time some.
- perspectiveBitmap.setConfig(
- SkBitmap::kARGB_8888_Config,
- SkScalarCeilToInt(
- physicalPerspectiveOutline.getBounds().width()),
- SkScalarCeilToInt(
- physicalPerspectiveOutline.getBounds().height()));
- perspectiveBitmap.allocPixels();
+ const int w = SkScalarCeilToInt(physicalPerspectiveOutline.getBounds().width());
+ const int h = SkScalarCeilToInt(physicalPerspectiveOutline.getBounds().height());
+ if (!perspectiveBitmap.allocPixels(SkImageInfo::MakeN32Premul(w, h))) {
+ return;
+ }
perspectiveBitmap.eraseColor(SK_ColorTRANSPARENT);
SkBitmapDevice device(perspectiveBitmap);
@@ -2327,11 +2305,6 @@ void SkPDFDevice::internalDrawBitmap(const SkMatrix& origMatrix,
&content.entry()->fContent);
}
-bool SkPDFDevice::onReadPixels(const SkBitmap& bitmap, int x, int y,
- SkCanvas::Config8888) {
- return false;
-}
-
-bool SkPDFDevice::allowImageFilter(SkImageFilter*) {
+bool SkPDFDevice::allowImageFilter(const SkImageFilter*) {
return false;
}
diff --git a/chromium/third_party/skia/src/pdf/SkPDFDeviceFlattener.cpp b/chromium/third_party/skia/src/pdf/SkPDFDeviceFlattener.cpp
index 91c9803c320..aea87f6546a 100644
--- a/chromium/third_party/skia/src/pdf/SkPDFDeviceFlattener.cpp
+++ b/chromium/third_party/skia/src/pdf/SkPDFDeviceFlattener.cpp
@@ -6,7 +6,6 @@
*/
#include "SkPDFDeviceFlattener.h"
-
#include "SkDraw.h"
static SkISize SkSizeToISize(const SkSize& size) {
@@ -25,9 +24,9 @@ SkPDFDeviceFlattener::~SkPDFDeviceFlattener() {
static void flattenPaint(const SkDraw& d, SkPaint* paint) {
if (paint->getShader()) {
- SkMatrix local = paint->getShader()->getLocalMatrix();
- local.preConcat(*d.fMatrix);
- paint->getShader()->setLocalMatrix(local);
+ SkAutoTUnref<SkShader> lms(SkShader::CreateLocalMatrixShader(paint->getShader(),
+ *d.fMatrix));
+ paint->setShader(lms);
}
}
diff --git a/chromium/third_party/skia/src/pdf/SkPDFDocument.cpp b/chromium/third_party/skia/src/pdf/SkPDFDocument.cpp
index 0633d308285..79699a0292f 100644
--- a/chromium/third_party/skia/src/pdf/SkPDFDocument.cpp
+++ b/chromium/third_party/skia/src/pdf/SkPDFDocument.cpp
@@ -258,11 +258,13 @@ bool SkPDFDocument::appendPage(SkPDFDevice* pdfDevice) {
return true;
}
+// Deprecated.
void SkPDFDocument::getCountOfFontTypes(
- int counts[SkAdvancedTypefaceMetrics::kNotEmbeddable_Font + 1]) const {
+ int counts[SkAdvancedTypefaceMetrics::kOther_Font + 2]) const {
sk_bzero(counts, sizeof(int) *
- (SkAdvancedTypefaceMetrics::kNotEmbeddable_Font + 1));
+ (SkAdvancedTypefaceMetrics::kOther_Font + 2));
SkTDArray<SkFontID> seenFonts;
+ int notEmbeddable = 0;
for (int pageNumber = 0; pageNumber < fPages.count(); pageNumber++) {
const SkTDArray<SkPDFFont*>& fontResources =
@@ -272,9 +274,49 @@ void SkPDFDocument::getCountOfFontTypes(
if (seenFonts.find(fontID) == -1) {
counts[fontResources[font]->getType()]++;
seenFonts.push(fontID);
+ if (!fontResources[font]->canEmbed()) {
+ notEmbeddable++;
+ }
}
}
}
+ counts[SkAdvancedTypefaceMetrics::kOther_Font + 1] = notEmbeddable;
+}
+
+void SkPDFDocument::getCountOfFontTypes(
+ int counts[SkAdvancedTypefaceMetrics::kOther_Font + 1],
+ int* notSubsettableCount,
+ int* notEmbeddableCount) const {
+ sk_bzero(counts, sizeof(int) *
+ (SkAdvancedTypefaceMetrics::kOther_Font + 1));
+ SkTDArray<SkFontID> seenFonts;
+ int notSubsettable = 0;
+ int notEmbeddable = 0;
+
+ for (int pageNumber = 0; pageNumber < fPages.count(); pageNumber++) {
+ const SkTDArray<SkPDFFont*>& fontResources =
+ fPages[pageNumber]->getFontResources();
+ for (int font = 0; font < fontResources.count(); font++) {
+ SkFontID fontID = fontResources[font]->typeface()->uniqueID();
+ if (seenFonts.find(fontID) == -1) {
+ counts[fontResources[font]->getType()]++;
+ seenFonts.push(fontID);
+ if (!fontResources[font]->canSubset()) {
+ notSubsettable++;
+ }
+ if (!fontResources[font]->canEmbed()) {
+ notEmbeddable++;
+ }
+ }
+ }
+ }
+ if (notSubsettableCount) {
+ *notSubsettableCount = notSubsettable;
+
+ }
+ if (notEmbeddableCount) {
+ *notEmbeddableCount = notEmbeddable;
+ }
}
void SkPDFDocument::emitHeader(SkWStream* stream) {
diff --git a/chromium/third_party/skia/src/pdf/SkPDFFont.cpp b/chromium/third_party/skia/src/pdf/SkPDFFont.cpp
index 07ecbba37e2..49d383b204e 100644
--- a/chromium/third_party/skia/src/pdf/SkPDFFont.cpp
+++ b/chromium/third_party/skia/src/pdf/SkPDFFont.cpp
@@ -568,21 +568,21 @@ static void sk_delete_array(const void* ptr, size_t, void*) {
}
#endif
-static int get_subset_font_stream(const char* fontName,
- const SkTypeface* typeface,
- const SkTDArray<uint32_t>& subset,
- SkPDFStream** fontStream) {
+static size_t get_subset_font_stream(const char* fontName,
+ const SkTypeface* typeface,
+ const SkTDArray<uint32_t>& subset,
+ SkPDFStream** fontStream) {
int ttcIndex;
SkAutoTUnref<SkStream> fontData(typeface->openStream(&ttcIndex));
- int fontSize = fontData->getLength();
+ size_t fontSize = fontData->getLength();
#if defined (SK_SFNTLY_SUBSETTER)
// Read font into buffer.
SkPDFStream* subsetFontStream = NULL;
SkTDArray<unsigned char> originalFont;
- originalFont.setCount(fontSize);
- if (fontData->read(originalFont.begin(), fontSize) == (size_t)fontSize) {
+ originalFont.setCount(SkToInt(fontSize));
+ if (fontData->read(originalFont.begin(), fontSize) == fontSize) {
unsigned char* subsetFont = NULL;
// sfntly requires unsigned int* to be passed in, as far as we know,
// unsigned int is equivalent to uint32_t on all platforms.
@@ -761,18 +761,35 @@ SkAdvancedTypefaceMetrics::FontType SkPDFFont::getType() {
return fFontType;
}
+bool SkPDFFont::canEmbed() const {
+ if (!fFontInfo.get()) {
+ SkASSERT(fFontType == SkAdvancedTypefaceMetrics::kOther_Font);
+ return true;
+ }
+ return (fFontInfo->fFlags &
+ SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag) == 0;
+}
+
+bool SkPDFFont::canSubset() const {
+ if (!fFontInfo.get()) {
+ SkASSERT(fFontType == SkAdvancedTypefaceMetrics::kOther_Font);
+ return true;
+ }
+ return (fFontInfo->fFlags &
+ SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag) == 0;
+}
+
bool SkPDFFont::hasGlyph(uint16_t id) {
return (id >= fFirstGlyphID && id <= fLastGlyphID) || id == 0;
}
-size_t SkPDFFont::glyphsToPDFFontEncoding(uint16_t* glyphIDs,
- size_t numGlyphs) {
+int SkPDFFont::glyphsToPDFFontEncoding(uint16_t* glyphIDs, int numGlyphs) {
// A font with multibyte glyphs will support all glyph IDs in a single font.
if (this->multiByteGlyphs()) {
return numGlyphs;
}
- for (size_t i = 0; i < numGlyphs; i++) {
+ for (int i = 0; i < numGlyphs; i++) {
if (glyphIDs[i] == 0) {
continue;
}
@@ -809,7 +826,7 @@ SkPDFFont* SkPDFFont::GetFontResource(SkTypeface* typeface, uint16_t glyphID) {
// This only is to catch callers who pass invalid glyph ids.
// If glyph id is invalid, then we will create duplicate entries
- // for True Type fonts.
+ // for TrueType fonts.
SkAdvancedTypefaceMetrics::FontType fontType =
fontMetrics.get() ? fontMetrics.get()->fType :
SkAdvancedTypefaceMetrics::kOther_Font;
@@ -889,9 +906,8 @@ SkPDFFont::SkPDFFont(SkAdvancedTypefaceMetrics* info, SkTypeface* typeface,
fLastGlyphID(info ? info->fLastGlyphID : 0),
fFontInfo(SkSafeRef(info)),
fDescriptor(SkSafeRef(relatedFontDescriptor)) {
- if (info == NULL) {
- fFontType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
- } else if (info->fMultiMaster) {
+ if (info == NULL ||
+ info->fFlags & SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag) {
fFontType = SkAdvancedTypefaceMetrics::kOther_Font;
} else {
fFontType = info->fType;
@@ -903,9 +919,10 @@ SkPDFFont* SkPDFFont::Create(SkAdvancedTypefaceMetrics* info,
SkTypeface* typeface, uint16_t glyphID,
SkPDFDict* relatedFontDescriptor) {
SkAdvancedTypefaceMetrics::FontType type =
- info ? info->fType : SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
+ info ? info->fType : SkAdvancedTypefaceMetrics::kOther_Font;
- if (info && info->fMultiMaster) {
+ if (info &&
+ (info->fFlags & SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag)) {
NOT_IMPLEMENTED(true, true);
return new SkPDFType3Font(info,
typeface,
@@ -924,8 +941,7 @@ SkPDFFont* SkPDFFont::Create(SkAdvancedTypefaceMetrics* info,
}
SkASSERT(type == SkAdvancedTypefaceMetrics::kCFF_Font ||
- type == SkAdvancedTypefaceMetrics::kOther_Font ||
- type == SkAdvancedTypefaceMetrics::kNotEmbeddable_Font);
+ type == SkAdvancedTypefaceMetrics::kOther_Font);
return new SkPDFType3Font(info, typeface, glyphID);
}
@@ -1053,11 +1069,17 @@ SkPDFType0Font::SkPDFType0Font(SkAdvancedTypefaceMetrics* info,
SkTypeface* typeface)
: SkPDFFont(info, typeface, NULL) {
SkDEBUGCODE(fPopulated = false);
+ if (!canSubset()) {
+ populate(NULL);
+ }
}
SkPDFType0Font::~SkPDFType0Font() {}
SkPDFFont* SkPDFType0Font::getFontSubset(const SkPDFGlyphSet* subset) {
+ if (!canSubset()) {
+ return NULL;
+ }
SkPDFType0Font* newSubset = new SkPDFType0Font(fontInfo(), typeface());
newSubset->populate(subset);
return newSubset;
@@ -1106,19 +1128,34 @@ bool SkPDFCIDFont::addFontDescriptor(int16_t defaultWidth,
SkAutoTUnref<SkPDFDict> descriptor(new SkPDFDict("FontDescriptor"));
setFontDescriptor(descriptor.get());
addResource(descriptor.get());
+ insert("FontDescriptor", new SkPDFObjRef(descriptor.get()))->unref();
+ if (!addCommonFontDescriptorEntries(defaultWidth)) {
+ return false;
+ }
+ if (!canEmbed()) {
+ return true;
+ }
switch (getType()) {
case SkAdvancedTypefaceMetrics::kTrueType_Font: {
- SkASSERT(subset);
- // Font subsetting
- SkPDFStream* rawStream = NULL;
- int fontSize = get_subset_font_stream(fontInfo()->fFontName.c_str(),
+ SkAutoTUnref<SkPDFStream> fontStream;
+ size_t fontSize = 0;
+ if (canSubset()) {
+ SkPDFStream* rawStream = NULL;
+ fontSize = get_subset_font_stream(fontInfo()->fFontName.c_str(),
typeface(),
*subset,
&rawStream);
+ fontStream.reset(rawStream);
+ } else {
+ int ttcIndex;
+ SkAutoTUnref<SkStream> fontData(
+ typeface()->openStream(&ttcIndex));
+ fontStream.reset(new SkPDFStream(fontData.get()));
+ fontSize = fontData->getLength();
+ }
SkASSERT(fontSize);
- SkASSERT(rawStream);
- SkAutoTUnref<SkPDFStream> fontStream(rawStream);
+ SkASSERT(fontStream.get());
addResource(fontStream.get());
fontStream->insertInt("Length1", fontSize);
@@ -1146,9 +1183,7 @@ bool SkPDFCIDFont::addFontDescriptor(int16_t defaultWidth,
default:
SkASSERT(false);
}
-
- insert("FontDescriptor", new SkPDFObjRef(descriptor.get()))->unref();
- return addCommonFontDescriptorEntries(defaultWidth);
+ return true;
}
bool SkPDFCIDFont::populate(const SkPDFGlyphSet* subset) {
@@ -1267,12 +1302,15 @@ bool SkPDFType1Font::addFontDescriptor(int16_t defaultWidth) {
if (fontData == NULL) {
return false;
}
- SkAutoTUnref<SkPDFStream> fontStream(new SkPDFStream(fontData));
- addResource(fontStream.get());
- fontStream->insertInt("Length1", header);
- fontStream->insertInt("Length2", data);
- fontStream->insertInt("Length3", trailer);
- descriptor->insert("FontFile", new SkPDFObjRef(fontStream.get()))->unref();
+ if (canEmbed()) {
+ SkAutoTUnref<SkPDFStream> fontStream(new SkPDFStream(fontData));
+ addResource(fontStream.get());
+ fontStream->insertInt("Length1", header);
+ fontStream->insertInt("Length2", data);
+ fontStream->insertInt("Length3", trailer);
+ descriptor->insert("FontFile",
+ new SkPDFObjRef(fontStream.get()))->unref();
+ }
addResource(descriptor.get());
insert("FontDescriptor", new SkPDFObjRef(descriptor.get()))->unref();
diff --git a/chromium/third_party/skia/src/pdf/SkPDFFont.h b/chromium/third_party/skia/src/pdf/SkPDFFont.h
index 694c69ac398..058a0422f5f 100644
--- a/chromium/third_party/skia/src/pdf/SkPDFFont.h
+++ b/chromium/third_party/skia/src/pdf/SkPDFFont.h
@@ -21,7 +21,7 @@ class SkPaint;
class SkPDFCatalog;
class SkPDFFont;
-class SkPDFGlyphSet : public SkNoncopyable {
+class SkPDFGlyphSet : SkNoncopyable {
public:
SkPDFGlyphSet();
@@ -34,7 +34,7 @@ private:
SkBitSet fBitSet;
};
-class SkPDFGlyphSetMap : public SkNoncopyable {
+class SkPDFGlyphSetMap : SkNoncopyable {
public:
struct FontGlyphSetPair {
FontGlyphSetPair(SkPDFFont* font, SkPDFGlyphSet* glyphSet);
@@ -99,6 +99,14 @@ public:
*/
virtual bool multiByteGlyphs() const = 0;
+ /** Returns true if the machine readable licensing bits allow embedding.
+ */
+ bool canEmbed() const;
+
+ /** Returns true if the machine readable licensing bits allow subsetting.
+ */
+ bool canSubset() const;
+
/** Return true if this font has an encoding for the passed glyph id.
*/
bool hasGlyph(uint16_t glyphID);
@@ -111,7 +119,7 @@ public:
* @param numGlyphs The number of input glyphs.
* @return Returns the number of glyphs consumed.
*/
- size_t glyphsToPDFFontEncoding(uint16_t* glyphIDs, size_t numGlyphs);
+ int glyphsToPDFFontEncoding(uint16_t* glyphIDs, int numGlyphs);
/** Get the font resource for the passed typeface and glyphID. The
* reference count of the object is incremented and it is the caller's
@@ -121,8 +129,7 @@ public:
* @param typeface The typeface to find.
* @param glyphID Specify which section of a large font is of interest.
*/
- static SkPDFFont* GetFontResource(SkTypeface* typeface,
- uint16_t glyphID);
+ static SkPDFFont* GetFontResource(SkTypeface* typeface, uint16_t glyphID);
/** Subset the font based on usage set. Returns a SkPDFFont instance with
* subset.
@@ -188,8 +195,6 @@ private:
// this will be a subset if the font has more than 255 glyphs.
uint16_t fFirstGlyphID;
uint16_t fLastGlyphID;
- // The font info is only kept around after construction for large
- // Type1 (non CID) fonts that need multiple "fonts" to access all glyphs.
SkAutoTUnref<SkAdvancedTypefaceMetrics> fFontInfo;
SkTDArray<SkPDFObject*> fResources;
SkAutoTUnref<SkPDFDict> fDescriptor;
diff --git a/chromium/third_party/skia/src/pdf/SkPDFFontImpl.h b/chromium/third_party/skia/src/pdf/SkPDFFontImpl.h
index 4b49683a5ab..4b49683a5ab 100755..100644
--- a/chromium/third_party/skia/src/pdf/SkPDFFontImpl.h
+++ b/chromium/third_party/skia/src/pdf/SkPDFFontImpl.h
diff --git a/chromium/third_party/skia/src/pdf/SkPDFGraphicState.cpp b/chromium/third_party/skia/src/pdf/SkPDFGraphicState.cpp
index 9f8edfd2061..1b495341b91 100644
--- a/chromium/third_party/skia/src/pdf/SkPDFGraphicState.cpp
+++ b/chromium/third_party/skia/src/pdf/SkPDFGraphicState.cpp
@@ -82,24 +82,20 @@ size_t SkPDFGraphicState::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
}
// static
-SkTDArray<SkPDFGraphicState::GSCanonicalEntry>&
-SkPDFGraphicState::CanonicalPaints() {
- // This initialization is only thread safe with gcc.
+SkTDArray<SkPDFGraphicState::GSCanonicalEntry>& SkPDFGraphicState::CanonicalPaints() {
+ CanonicalPaintsMutex().assertHeld();
static SkTDArray<SkPDFGraphicState::GSCanonicalEntry> gCanonicalPaints;
return gCanonicalPaints;
}
// static
SkBaseMutex& SkPDFGraphicState::CanonicalPaintsMutex() {
- // This initialization is only thread safe with gcc or when
- // POD-style mutex initialization is used.
SK_DECLARE_STATIC_MUTEX(gCanonicalPaintsMutex);
return gCanonicalPaintsMutex;
}
// static
-SkPDFGraphicState* SkPDFGraphicState::GetGraphicStateForPaint(
- const SkPaint& paint) {
+SkPDFGraphicState* SkPDFGraphicState::GetGraphicStateForPaint(const SkPaint& paint) {
SkAutoMutexAcquire lock(CanonicalPaintsMutex());
int index = Find(paint);
if (index >= 0) {
@@ -114,6 +110,7 @@ SkPDFGraphicState* SkPDFGraphicState::GetGraphicStateForPaint(
// static
SkPDFObject* SkPDFGraphicState::GetInvertFunction() {
// This assumes that canonicalPaintsMutex is held.
+ CanonicalPaintsMutex().assertHeld();
static SkPDFStream* invertFunction = NULL;
if (!invertFunction) {
// Acrobat crashes if we use a type 0 function, kpdf crashes if we use
@@ -185,6 +182,7 @@ SkPDFGraphicState* SkPDFGraphicState::GetNoSMaskGraphicState() {
// static
int SkPDFGraphicState::Find(const SkPaint& paint) {
+ CanonicalPaintsMutex().assertHeld();
GSCanonicalEntry search(&paint);
return CanonicalPaints().find(search);
}
diff --git a/chromium/third_party/skia/src/pdf/SkPDFImage.cpp b/chromium/third_party/skia/src/pdf/SkPDFImage.cpp
index 81adcc20d6b..77fd84eff94 100644
--- a/chromium/third_party/skia/src/pdf/SkPDFImage.cpp
+++ b/chromium/third_party/skia/src/pdf/SkPDFImage.cpp
@@ -27,16 +27,17 @@ static bool skip_compression(SkPDFCatalog* catalog) {
static size_t get_uncompressed_size(const SkBitmap& bitmap,
const SkIRect& srcRect) {
- switch (bitmap.config()) {
- case SkBitmap::kIndex8_Config:
+ switch (bitmap.colorType()) {
+ case kIndex_8_SkColorType:
return srcRect.width() * srcRect.height();
- case SkBitmap::kARGB_4444_Config:
+ case kARGB_4444_SkColorType:
return ((srcRect.width() * 3 + 1) / 2) * srcRect.height();
- case SkBitmap::kRGB_565_Config:
+ case kRGB_565_SkColorType:
return srcRect.width() * 3 * srcRect.height();
- case SkBitmap::kARGB_8888_Config:
+ case kRGBA_8888_SkColorType:
+ case kBGRA_8888_SkColorType:
return srcRect.width() * 3 * srcRect.height();
- case SkBitmap::kA8_Config:
+ case kAlpha_8_SkColorType:
return 1;
default:
SkASSERT(false);
@@ -208,9 +209,9 @@ static SkStream* create_black_image() {
static SkStream* extract_image_data(const SkBitmap& bitmap,
const SkIRect& srcRect,
bool extractAlpha, bool* isTransparent) {
- SkBitmap::Config config = bitmap.config();
- if (extractAlpha && (config == SkBitmap::kIndex8_Config ||
- config == SkBitmap::kRGB_565_Config)) {
+ SkColorType colorType = bitmap.colorType();
+ if (extractAlpha && (kIndex_8_SkColorType == colorType ||
+ kRGB_565_SkColorType == colorType)) {
if (isTransparent != NULL) {
*isTransparent = false;
}
@@ -221,26 +222,26 @@ static SkStream* extract_image_data(const SkBitmap& bitmap,
SkStream* stream = NULL;
bitmap.lockPixels();
- switch (config) {
- case SkBitmap::kIndex8_Config:
+ switch (colorType) {
+ case kIndex_8_SkColorType:
if (!extractAlpha) {
stream = extract_index8_image(bitmap, srcRect);
}
break;
- case SkBitmap::kARGB_4444_Config:
+ case kARGB_4444_SkColorType:
stream = extract_argb4444_data(bitmap, srcRect, extractAlpha,
&isOpaque, &transparent);
break;
- case SkBitmap::kRGB_565_Config:
+ case kRGB_565_SkColorType:
if (!extractAlpha) {
stream = extract_rgb565_image(bitmap, srcRect);
}
break;
- case SkBitmap::kARGB_8888_Config:
+ case kN32_SkColorType:
stream = extract_argb8888_data(bitmap, srcRect, extractAlpha,
&isOpaque, &transparent);
break;
- case SkBitmap::kA8_Config:
+ case kAlpha_8_SkColorType:
if (!extractAlpha) {
stream = create_black_image();
} else {
@@ -373,14 +374,13 @@ static uint16_t get_argb4444_neighbor_avg_color(const SkBitmap& bitmap,
static SkBitmap unpremultiply_bitmap(const SkBitmap& bitmap,
const SkIRect& srcRect) {
SkBitmap outBitmap;
- outBitmap.setConfig(bitmap.config(), srcRect.width(), srcRect.height());
- outBitmap.allocPixels();
+ outBitmap.allocPixels(bitmap.info().makeWH(srcRect.width(), srcRect.height()));
int dstRow = 0;
outBitmap.lockPixels();
bitmap.lockPixels();
- switch (bitmap.config()) {
- case SkBitmap::kARGB_4444_Config: {
+ switch (bitmap.colorType()) {
+ case kARGB_4444_SkColorType: {
for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
uint16_t* dst = outBitmap.getAddr16(0, dstRow);
uint16_t* src = bitmap.getAddr16(0, y);
@@ -408,7 +408,7 @@ static SkBitmap unpremultiply_bitmap(const SkBitmap& bitmap,
}
break;
}
- case SkBitmap::kARGB_8888_Config: {
+ case kN32_SkColorType: {
for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
uint32_t* dst = outBitmap.getAddr32(0, dstRow);
uint32_t* src = bitmap.getAddr32(0, y);
@@ -440,7 +440,7 @@ static SkBitmap unpremultiply_bitmap(const SkBitmap& bitmap,
SkPDFImage* SkPDFImage::CreateImage(const SkBitmap& bitmap,
const SkIRect& srcRect,
SkPicture::EncodeBitmap encoder) {
- if (bitmap.config() == SkBitmap::kNo_Config) {
+ if (bitmap.colorType() == kUnknown_SkColorType) {
return NULL;
}
@@ -459,9 +459,9 @@ SkPDFImage* SkPDFImage::CreateImage(const SkBitmap& bitmap,
}
SkPDFImage* image;
- SkBitmap::Config config = bitmap.config();
- if (alphaData.get() != NULL && (config == SkBitmap::kARGB_8888_Config ||
- config == SkBitmap::kARGB_4444_Config)) {
+ SkColorType colorType = bitmap.colorType();
+ if (alphaData.get() != NULL && (kN32_SkColorType == colorType ||
+ kARGB_4444_SkColorType == colorType)) {
SkBitmap unpremulBitmap = unpremultiply_bitmap(bitmap, srcRect);
image = SkNEW_ARGS(SkPDFImage, (NULL, unpremulBitmap, false,
SkIRect::MakeWH(srcRect.width(), srcRect.height()),
@@ -507,7 +507,7 @@ SkPDFImage::SkPDFImage(SkStream* stream,
if (bitmap.isImmutable()) {
fBitmap = bitmap;
} else {
- bitmap.deepCopyTo(&fBitmap, bitmap.config());
+ bitmap.deepCopyTo(&fBitmap);
fBitmap.setImmutable();
}
@@ -518,12 +518,12 @@ SkPDFImage::SkPDFImage(SkStream* stream,
fStreamValid = false;
}
- SkBitmap::Config config = fBitmap.config();
+ SkColorType colorType = fBitmap.colorType();
insertName("Type", "XObject");
insertName("Subtype", "Image");
- bool alphaOnly = (config == SkBitmap::kA8_Config);
+ bool alphaOnly = (kAlpha_8_SkColorType == colorType);
if (!isAlpha && alphaOnly) {
// For alpha only images, we stretch a single pixel of black for
@@ -538,7 +538,7 @@ SkPDFImage::SkPDFImage(SkStream* stream,
if (isAlpha || alphaOnly) {
insertName("ColorSpace", "DeviceGray");
- } else if (config == SkBitmap::kIndex8_Config) {
+ } else if (kIndex_8_SkColorType == colorType) {
SkAutoLockPixels alp(fBitmap);
insert("ColorSpace",
make_indexed_color_space(fBitmap.getColorTable()))->unref();
@@ -547,12 +547,12 @@ SkPDFImage::SkPDFImage(SkStream* stream,
}
int bitsPerComp = 8;
- if (config == SkBitmap::kARGB_4444_Config) {
+ if (kARGB_4444_SkColorType == colorType) {
bitsPerComp = 4;
}
insertInt("BitsPerComponent", bitsPerComp);
- if (config == SkBitmap::kRGB_565_Config) {
+ if (kRGB_565_SkColorType == colorType) {
SkASSERT(!isAlpha);
SkAutoTUnref<SkPDFInt> zeroVal(new SkPDFInt(0));
SkAutoTUnref<SkPDFScalar> scale5Val(
@@ -592,8 +592,6 @@ bool SkPDFImage::populate(SkPDFCatalog* catalog) {
SkBitmap subset;
// Extract subset
if (!fBitmap.extractSubset(&subset, fSrcRect)) {
- // TODO(edisonn) It fails only for kA1_Config, if that is a
- // major concern we will fix it later, so far it is NYI.
return false;
}
size_t pixelRefOffset = 0;
diff --git a/chromium/third_party/skia/src/pdf/SkPDFShader.cpp b/chromium/third_party/skia/src/pdf/SkPDFShader.cpp
index 94bdf2d78d9..62adf5811db 100644
--- a/chromium/third_party/skia/src/pdf/SkPDFShader.cpp
+++ b/chromium/third_party/skia/src/pdf/SkPDFShader.cpp
@@ -988,8 +988,8 @@ SkPDFImageShader::SkPDFImageShader(SkPDFShader::State* state) : fState(state) {
SkMatrix unflip;
unflip.setTranslate(0, SkScalarRoundToScalar(deviceBounds.height()));
unflip.preScale(SK_Scalar1, -SK_Scalar1);
- SkISize size = SkISize::Make(SkScalarRound(deviceBounds.width()),
- SkScalarRound(deviceBounds.height()));
+ SkISize size = SkISize::Make(SkScalarRoundToInt(deviceBounds.width()),
+ SkScalarRoundToInt(deviceBounds.height()));
// TODO(edisonn): should we pass here the DCT encoder of the destination device?
// TODO(edisonn): NYI Perspective, use SkPDFDeviceFlattener.
SkPDFDevice pattern(size, size, unflip);
diff --git a/chromium/third_party/skia/src/pdf/SkPDFTypes.cpp b/chromium/third_party/skia/src/pdf/SkPDFTypes.cpp
index 55871c507d2..e3cc90c1de2 100644
--- a/chromium/third_party/skia/src/pdf/SkPDFTypes.cpp
+++ b/chromium/third_party/skia/src/pdf/SkPDFTypes.cpp
@@ -140,15 +140,9 @@ void SkPDFScalar::Append(SkScalar value, SkWStream* stream) {
// When using floats that are outside the whole value range, we can use
// integers instead.
-
-#if defined(SK_SCALAR_IS_FIXED)
- stream->writeScalarAsText(value);
- return;
-#endif // SK_SCALAR_IS_FIXED
-
#if !defined(SK_ALLOW_LARGE_PDF_SCALARS)
if (value > 32767 || value < -32767) {
- stream->writeDecAsText(SkScalarRound(value));
+ stream->writeDecAsText(SkScalarRoundToInt(value));
return;
}
@@ -158,7 +152,7 @@ void SkPDFScalar::Append(SkScalar value, SkWStream* stream) {
return;
#endif // !SK_ALLOW_LARGE_PDF_SCALARS
-#if defined(SK_SCALAR_IS_FLOAT) && defined(SK_ALLOW_LARGE_PDF_SCALARS)
+#if defined(SK_ALLOW_LARGE_PDF_SCALARS)
// Floats have 24bits of significance, so anything outside that range is
// no more precise than an int. (Plus PDF doesn't support scientific
// notation, so this clamps to SK_Max/MinS32).
@@ -185,7 +179,7 @@ void SkPDFScalar::Append(SkScalar value, SkWStream* stream) {
}
stream->writeText(buffer);
return;
-#endif // SK_SCALAR_IS_FLOAT && SK_ALLOW_LARGE_PDF_SCALARS
+#endif // SK_ALLOW_LARGE_PDF_SCALARS
}
SkPDFString::SkPDFString(const char value[])
diff --git a/chromium/third_party/skia/src/pdf/SkPDFTypes.h b/chromium/third_party/skia/src/pdf/SkPDFTypes.h
index 5ed6386bddc..1f06c4c5fe6 100644
--- a/chromium/third_party/skia/src/pdf/SkPDFTypes.h
+++ b/chromium/third_party/skia/src/pdf/SkPDFTypes.h
@@ -392,6 +392,14 @@ public:
*/
void insertInt(const char key[], int32_t value);
+ /**
+ * Calls insertInt() but asserts in debug builds that the value can be represented
+ * by an int32_t.
+ */
+ void insertInt(const char key[], size_t value) {
+ this->insertInt(key, SkToS32(value));
+ }
+
/** Add the scalar to the dictionary with the given key.
* @param key The text of the key for this dictionary entry.
* @param value The scalar value for this dictionary entry.
diff --git a/chromium/third_party/skia/src/pipe/SkGPipePriv.h b/chromium/third_party/skia/src/pipe/SkGPipePriv.h
index 66b43666552..58cafe80b13 100644
--- a/chromium/third_party/skia/src/pipe/SkGPipePriv.h
+++ b/chromium/third_party/skia/src/pipe/SkGPipePriv.h
@@ -45,6 +45,7 @@ enum DrawOps {
kDrawBitmapRectToRect_DrawOp,
kDrawClear_DrawOp,
kDrawData_DrawOp,
+ kDrawDRRect_DrawOp,
kDrawOval_DrawOp,
kDrawPaint_DrawOp,
kDrawPath_DrawOp,
@@ -142,6 +143,7 @@ enum {
kDrawVertices_HasTexs_DrawOpFlag = 1 << 0,
kDrawVertices_HasColors_DrawOpFlag = 1 << 1,
kDrawVertices_HasIndices_DrawOpFlag = 1 << 2,
+ kDrawVertices_HasXfermode_DrawOpFlag = 1 << 3,
};
enum {
kDrawBitmap_HasPaint_DrawOpFlag = 1 << 0,
@@ -222,6 +224,7 @@ enum PaintOps {
kFlags_PaintOp, // arg inline
kColor_PaintOp, // arg 32
+ kFilterLevel_PaintOp, // arg inline
kStyle_PaintOp, // arg inline
kJoin_PaintOp, // arg inline
kCap_PaintOp, // arg inline
diff --git a/chromium/third_party/skia/src/pipe/SkGPipeRead.cpp b/chromium/third_party/skia/src/pipe/SkGPipeRead.cpp
index 877d380d614..41c417f92ec 100644
--- a/chromium/third_party/skia/src/pipe/SkGPipeRead.cpp
+++ b/chromium/third_party/skia/src/pipe/SkGPipeRead.cpp
@@ -20,7 +20,7 @@
#include "SkDrawLooper.h"
#include "SkImageFilter.h"
#include "SkMaskFilter.h"
-#include "SkOrderedReadBuffer.h"
+#include "SkReadBuffer.h"
#include "SkPathEffect.h"
#include "SkRasterizer.h"
#include "SkRRect.h"
@@ -105,7 +105,7 @@ public:
return fFlags;
}
- void setReader(SkOrderedReadBuffer* reader) {
+ void setReader(SkReadBuffer* reader) {
fReader = reader;
this->updateReader();
}
@@ -156,7 +156,7 @@ public:
}
/**
- * Override of SkBitmapHeapReader, so that SkOrderedReadBuffer can use
+ * Override of SkBitmapHeapReader, so that SkReadBuffer can use
* these SkBitmaps for bitmap shaders. Used only in cross process mode
* without a shared heap.
*/
@@ -203,7 +203,7 @@ private:
}
bool crossProcess = SkToBool(fFlags & SkGPipeWriter::kCrossProcess_Flag);
fReader->setFlags(SkSetClearMask(fReader->getFlags(), crossProcess,
- SkFlattenableReadBuffer::kCrossProcess_Flag));
+ SkReadBuffer::kCrossProcess_Flag));
if (crossProcess) {
fReader->setFactoryArray(&fFactoryArray);
} else {
@@ -216,7 +216,7 @@ private:
fReader->setBitmapStorage(fSharedHeap);
}
}
- SkOrderedReadBuffer* fReader;
+ SkReadBuffer* fReader;
SkPaint fPaint;
SkTDArray<SkFlattenable*> fFlatArray;
SkTDArray<SkTypeface*> fTypefaces;
@@ -230,15 +230,13 @@ private:
///////////////////////////////////////////////////////////////////////////////
-template <typename T> const T* skip(SkReader32* reader, int count = 1) {
- SkASSERT(count >= 0);
+template <typename T> const T* skip(SkReader32* reader, size_t count = 1) {
size_t size = sizeof(T) * count;
SkASSERT(SkAlign4(size) == size);
return reinterpret_cast<const T*>(reader->skip(size));
}
-template <typename T> const T* skipAlign(SkReader32* reader, int count = 1) {
- SkASSERT(count >= 0);
+template <typename T> const T* skipAlign(SkReader32* reader, size_t count = 1) {
size_t size = SkAlign4(sizeof(T) * count);
return reinterpret_cast<const T*>(reader->skip(size));
}
@@ -396,6 +394,16 @@ static void drawRRect_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
}
}
+static void drawDRRect_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
+ SkGPipeState* state) {
+ SkRRect outer, inner;
+ reader->readRRect(&outer);
+ reader->readRRect(&inner);
+ if (state->shouldDraw()) {
+ canvas->drawDRRect(outer, inner, state->paint());
+ }
+}
+
static void drawPath_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
SkPath path;
@@ -409,7 +417,7 @@ static void drawVertices_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
unsigned flags = DrawOp_unpackFlags(op32);
- SkCanvas::VertexMode mode = (SkCanvas::VertexMode)reader->readU32();
+ SkCanvas::VertexMode vmode = (SkCanvas::VertexMode)reader->readU32();
int vertexCount = reader->readU32();
const SkPoint* verts = skip<SkPoint>(reader, vertexCount);
@@ -423,8 +431,11 @@ static void drawVertices_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
colors = skip<SkColor>(reader, vertexCount);
}
- // TODO: flatten/unflatten xfermodes
- SkXfermode* xfer = NULL;
+ SkAutoTUnref<SkXfermode> xfer;
+ if (flags & kDrawVertices_HasXfermode_DrawOpFlag) {
+ SkXfermode::Mode mode = (SkXfermode::Mode)reader->readU32();
+ xfer.reset(SkXfermode::Create(mode));
+ }
int indexCount = 0;
const uint16_t* indices = NULL;
@@ -433,7 +444,7 @@ static void drawVertices_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
indices = skipAlign<uint16_t>(reader, indexCount);
}
if (state->shouldDraw()) {
- canvas->drawVertices(mode, vertexCount, verts, texs, colors, xfer,
+ canvas->drawVertices(vmode, vertexCount, verts, texs, colors, xfer,
indices, indexCount, state->paint());
}
}
@@ -649,6 +660,7 @@ static void paintOp_rp(SkCanvas*, SkReader32* reader, uint32_t op32,
case kReset_PaintOp: p->reset(); break;
case kFlags_PaintOp: p->setFlags(data); break;
case kColor_PaintOp: p->setColor(reader->readU32()); break;
+ case kFilterLevel_PaintOp: p->setFilterLevel((SkPaint::FilterLevel)data); break;
case kStyle_PaintOp: p->setStyle((SkPaint::Style)data); break;
case kJoin_PaintOp: p->setStrokeJoin((SkPaint::Join)data); break;
case kCap_PaintOp: p->setStrokeCap((SkPaint::Cap)data); break;
@@ -693,8 +705,8 @@ static void annotation_rp(SkCanvas*, SkReader32* reader, uint32_t op32,
const size_t size = DrawOp_unpackData(op32);
if (size > 0) {
- SkOrderedReadBuffer buffer(reader->skip(size), size);
- p->setAnnotation(SkNEW_ARGS(SkAnnotation, (buffer)))->unref();
+ SkReadBuffer buffer(reader->skip(size), size);
+ p->setAnnotation(SkAnnotation::Create(buffer))->unref();
SkASSERT(buffer.offset() == size);
} else {
p->setAnnotation(NULL);
@@ -760,6 +772,7 @@ static const ReadProc gReadTable[] = {
drawBitmapRect_rp,
drawClear_rp,
drawData_rp,
+ drawDRRect_rp,
drawOval_rp,
drawPaint_rp,
drawPath_rp,
@@ -854,7 +867,7 @@ SkGPipeReader::Status SkGPipeReader::playback(const void* data, size_t length,
SkASSERT(SK_ARRAY_COUNT(gReadTable) == (kDone_DrawOp + 1));
const ReadProc* table = gReadTable;
- SkOrderedReadBuffer reader(data, length);
+ SkReadBuffer reader(data, length);
reader.setBitmapDecoder(fProc);
SkCanvas* canvas = fCanvas;
Status status = kEOF_Status;
diff --git a/chromium/third_party/skia/src/pipe/SkGPipeWrite.cpp b/chromium/third_party/skia/src/pipe/SkGPipeWrite.cpp
index 43240803256..a3c38646bb5 100644
--- a/chromium/third_party/skia/src/pipe/SkGPipeWrite.cpp
+++ b/chromium/third_party/skia/src/pipe/SkGPipeWrite.cpp
@@ -17,7 +17,7 @@
#include "SkGPipePriv.h"
#include "SkImageFilter.h"
#include "SkMaskFilter.h"
-#include "SkOrderedWriteBuffer.h"
+#include "SkWriteBuffer.h"
#include "SkPaint.h"
#include "SkPathEffect.h"
#include "SkPictureFlat.h"
@@ -59,7 +59,7 @@ static size_t writeTypeface(SkWriter32* writer, SkTypeface* typeface) {
typeface->serialize(&stream);
size_t size = stream.getOffset();
if (writer) {
- writer->write32(size);
+ writer->write32(SkToU32(size));
SkAutoDataUnref data(stream.copyToData());
writer->writePad(data->data(), size);
}
@@ -71,11 +71,11 @@ static size_t writeTypeface(SkWriter32* writer, SkTypeface* typeface) {
class FlattenableHeap : public SkFlatController {
public:
FlattenableHeap(int numFlatsToKeep, SkNamedFactorySet* fset, bool isCrossProcess)
- : fNumFlatsToKeep(numFlatsToKeep) {
+ : INHERITED(isCrossProcess ? SkWriteBuffer::kCrossProcess_Flag : 0)
+ , fNumFlatsToKeep(numFlatsToKeep) {
SkASSERT((isCrossProcess && fset != NULL) || (!isCrossProcess && NULL == fset));
if (isCrossProcess) {
this->setNamedFactorySet(fset);
- this->setWriteBufferFlags(SkFlattenableWriteBuffer::kCrossProcess_Flag);
}
}
@@ -109,6 +109,8 @@ private:
SkTDArray<int> fFlatsThatMustBeKept;
SkTDArray<void*> fPointers;
const int fNumFlatsToKeep;
+
+ typedef SkFlatController INHERITED;
};
void FlattenableHeap::unalloc(void* ptr) {
@@ -150,20 +152,13 @@ const SkFlatData* FlattenableHeap::flatToReplace() const {
///////////////////////////////////////////////////////////////////////////////
-class FlatDictionary : public SkFlatDictionary<SkFlattenable> {
-public:
- FlatDictionary(FlattenableHeap* heap)
- : SkFlatDictionary<SkFlattenable>(heap) {
- fFlattenProc = &flattenFlattenableProc;
- // No need to define fUnflattenProc since the writer will never
- // unflatten the data.
+struct SkFlattenableTraits {
+ static void Flatten(SkWriteBuffer& buffer, const SkFlattenable& flattenable) {
+ buffer.writeFlattenable(&flattenable);
}
- static void flattenFlattenableProc(SkOrderedWriteBuffer& buffer,
- const void* obj) {
- buffer.writeFlattenable((SkFlattenable*)obj);
- }
-
+ // No need to define unflatten if we never call it.
};
+typedef SkFlatDictionary<SkFlattenable, SkFlattenableTraits> FlatDictionary;
///////////////////////////////////////////////////////////////////////////////
@@ -234,22 +229,7 @@ public:
}
// overrides from SkCanvas
- virtual int save(SaveFlags) SK_OVERRIDE;
- virtual int saveLayer(const SkRect* bounds, const SkPaint*,
- SaveFlags) SK_OVERRIDE;
- virtual void restore() SK_OVERRIDE;
virtual bool isDrawingToLayer() const SK_OVERRIDE;
- virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE;
- virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE;
- virtual bool rotate(SkScalar degrees) SK_OVERRIDE;
- virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE;
- virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE;
- virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE;
- virtual bool clipRect(const SkRect&, SkRegion::Op op, bool doAntiAlias = false) SK_OVERRIDE;
- virtual bool clipRRect(const SkRRect&, SkRegion::Op op, bool doAntiAlias = false) SK_OVERRIDE;
- virtual bool clipPath(const SkPath& path, SkRegion::Op op,
- bool doAntiAlias = false) SK_OVERRIDE;
- virtual bool clipRegion(const SkRegion& region, SkRegion::Op op) SK_OVERRIDE;
virtual void clear(SkColor) SK_OVERRIDE;
virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
virtual void drawPoints(PointMode, size_t count, const SkPoint pts[],
@@ -269,17 +249,6 @@ public:
const SkRect& dst, const SkPaint* paint = NULL) SK_OVERRIDE;
virtual void drawSprite(const SkBitmap&, int left, int top,
const SkPaint*) SK_OVERRIDE;
- virtual void drawText(const void* text, size_t byteLength, SkScalar x,
- SkScalar y, const SkPaint&) SK_OVERRIDE;
- virtual void drawPosText(const void* text, size_t byteLength,
- const SkPoint pos[], const SkPaint&) SK_OVERRIDE;
- virtual void drawPosTextH(const void* text, size_t byteLength,
- const SkScalar xpos[], SkScalar constY,
- const SkPaint&) SK_OVERRIDE;
- virtual void drawTextOnPath(const void* text, size_t byteLength,
- const SkPath& path, const SkMatrix* matrix,
- const SkPaint&) SK_OVERRIDE;
- virtual void drawPicture(SkPicture& picture) SK_OVERRIDE;
virtual void drawVertices(VertexMode, int vertexCount,
const SkPoint vertices[], const SkPoint texs[],
const SkColor colors[], SkXfermode*,
@@ -295,7 +264,37 @@ public:
* according to slot.
*/
bool shuttleBitmap(const SkBitmap&, int32_t slot);
+
+protected:
+ virtual void willSave(SaveFlags) SK_OVERRIDE;
+ virtual SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SaveFlags) SK_OVERRIDE;
+ virtual void willRestore() SK_OVERRIDE;
+
+ virtual void didConcat(const SkMatrix&) SK_OVERRIDE;
+ virtual void didSetMatrix(const SkMatrix&) SK_OVERRIDE;
+
+ virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) SK_OVERRIDE;
+ virtual void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
+ const SkPaint&) SK_OVERRIDE;
+ virtual void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
+ const SkPaint&) SK_OVERRIDE;
+ virtual void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
+ SkScalar constY, const SkPaint&) SK_OVERRIDE;
+ virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
+ const SkMatrix* matrix, const SkPaint&) SK_OVERRIDE;
+
+ virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
+ virtual void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
+ virtual void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
+ virtual void onClipRegion(const SkRegion&, SkRegion::Op) SK_OVERRIDE;
+
+ virtual void onDrawPicture(const SkPicture* picture) SK_OVERRIDE;
+
private:
+ void recordTranslate(const SkMatrix&);
+ void recordScale(const SkMatrix&);
+ void recordConcat(const SkMatrix&);
+
enum {
kNoSaveLayer = -1,
};
@@ -368,7 +367,7 @@ void SkGPipeCanvas::flattenFactoryNames() {
const char* name;
while ((name = fFactorySet->getNextAddedFactoryName()) != NULL) {
size_t len = strlen(name);
- if (this->needOpBytes(len)) {
+ if (this->needOpBytes(SkWriter32::WriteStringSize(name, len))) {
this->writeOp(kDef_Factory_DrawOp);
fWriter.writeString(name, len);
}
@@ -377,11 +376,11 @@ void SkGPipeCanvas::flattenFactoryNames() {
bool SkGPipeCanvas::shuttleBitmap(const SkBitmap& bm, int32_t slot) {
SkASSERT(shouldFlattenBitmaps(fFlags));
- SkOrderedWriteBuffer buffer(1024);
+ SkWriteBuffer buffer;
buffer.setNamedFactoryRecorder(fFactorySet);
buffer.writeBitmap(bm);
this->flattenFactoryNames();
- uint32_t size = buffer.size();
+ size_t size = buffer.bytesWritten();
if (this->needOpBytes(size)) {
this->writeOp(kDef_Bitmap_DrawOp, 0, slot);
void* dst = static_cast<void*>(fWriter.reserve(size));
@@ -430,11 +429,13 @@ int SkGPipeCanvas::flattenToIndex(SkFlattenable* obj, PaintFlats paintflat) {
SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller,
SkWriter32* writer, uint32_t flags,
uint32_t width, uint32_t height)
-: fFactorySet(isCrossProcess(flags) ? SkNEW(SkNamedFactorySet) : NULL)
-, fWriter(*writer)
-, fFlags(flags)
-, fFlattenableHeap(FLATTENABLES_TO_KEEP, fFactorySet, isCrossProcess(flags))
-, fFlatDictionary(&fFlattenableHeap) {
+ : SkCanvas(width, height)
+ , fFactorySet(isCrossProcess(flags) ? SkNEW(SkNamedFactorySet) : NULL)
+ , fWriter(*writer)
+ , fFlags(flags)
+ , fFlattenableHeap(FLATTENABLES_TO_KEEP, fFactorySet, isCrossProcess(flags))
+ , fFlatDictionary(&fFlattenableHeap)
+{
fController = controller;
fDone = false;
fBlockSize = 0; // need first block from controller
@@ -442,13 +443,6 @@ SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller,
fFirstSaveLayerStackLevel = kNoSaveLayer;
sk_bzero(fCurrFlatIndex, sizeof(fCurrFlatIndex));
- // we need a device to limit our clip
- // We don't allocate pixels for the bitmap
- SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
- SkBaseDevice* device = SkNEW_ARGS(SkBitmapDevice, (bitmap));
- this->setDevice(device)->unref();
-
// Tell the reader the appropriate flags to use.
if (this->needOpBytes()) {
this->writeOp(kReportFlags_DrawOp, fFlags, 0);
@@ -481,12 +475,13 @@ bool SkGPipeCanvas::needOpBytes(size_t needed) {
}
needed += 4; // size of DrawOp atom
+ needed = SkTMax<size_t>(MIN_BLOCK_SIZE, needed);
+ needed = SkAlign4(needed);
if (fWriter.bytesWritten() + needed > fBlockSize) {
// Before we wipe out any data that has already been written, read it
// out.
this->doNotify();
- size_t blockSize = SkMax32(MIN_BLOCK_SIZE, needed);
- void* block = fController->requestBlock(blockSize, &fBlockSize);
+ void* block = fController->requestBlock(needed, &fBlockSize);
if (NULL == block) {
// Do not notify the readers, which would call this function again.
this->finish(false);
@@ -520,16 +515,17 @@ uint32_t SkGPipeCanvas::getTypefaceID(SkTypeface* face) {
#define NOTIFY_SETUP(canvas) \
AutoPipeNotify apn(canvas)
-int SkGPipeCanvas::save(SaveFlags flags) {
+void SkGPipeCanvas::willSave(SaveFlags flags) {
NOTIFY_SETUP(this);
if (this->needOpBytes()) {
this->writeOp(kSave_DrawOp, 0, flags);
}
- return this->INHERITED::save(flags);
+
+ this->INHERITED::willSave(flags);
}
-int SkGPipeCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
- SaveFlags saveFlags) {
+SkCanvas::SaveLayerStrategy SkGPipeCanvas::willSaveLayer(const SkRect* bounds, const SkPaint* paint,
+ SaveFlags saveFlags) {
NOTIFY_SETUP(this);
size_t size = 0;
unsigned opFlags = 0;
@@ -553,135 +549,130 @@ int SkGPipeCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
if (kNoSaveLayer == fFirstSaveLayerStackLevel){
fFirstSaveLayerStackLevel = this->getSaveCount();
}
- // we just pass on the save, so we don't create a layer
- return this->INHERITED::save(saveFlags);
+
+ this->INHERITED::willSaveLayer(bounds, paint, saveFlags);
+ // we don't create a layer
+ return kNoLayer_SaveLayerStrategy;
}
-void SkGPipeCanvas::restore() {
+void SkGPipeCanvas::willRestore() {
NOTIFY_SETUP(this);
if (this->needOpBytes()) {
this->writeOp(kRestore_DrawOp);
}
- this->INHERITED::restore();
-
- if (this->getSaveCount() == fFirstSaveLayerStackLevel){
+ if (this->getSaveCount() - 1 == fFirstSaveLayerStackLevel){
fFirstSaveLayerStackLevel = kNoSaveLayer;
}
+
+ this->INHERITED::willRestore();
}
bool SkGPipeCanvas::isDrawingToLayer() const {
return kNoSaveLayer != fFirstSaveLayerStackLevel;
}
-bool SkGPipeCanvas::translate(SkScalar dx, SkScalar dy) {
- if (dx || dy) {
- NOTIFY_SETUP(this);
- if (this->needOpBytes(2 * sizeof(SkScalar))) {
- this->writeOp(kTranslate_DrawOp);
- fWriter.writeScalar(dx);
- fWriter.writeScalar(dy);
- }
- }
- return this->INHERITED::translate(dx, dy);
-}
-
-bool SkGPipeCanvas::scale(SkScalar sx, SkScalar sy) {
- if (sx || sy) {
- NOTIFY_SETUP(this);
- if (this->needOpBytes(2 * sizeof(SkScalar))) {
- this->writeOp(kScale_DrawOp);
- fWriter.writeScalar(sx);
- fWriter.writeScalar(sy);
- }
+void SkGPipeCanvas::recordTranslate(const SkMatrix& m) {
+ if (this->needOpBytes(2 * sizeof(SkScalar))) {
+ this->writeOp(kTranslate_DrawOp);
+ fWriter.writeScalar(m.getTranslateX());
+ fWriter.writeScalar(m.getTranslateY());
}
- return this->INHERITED::scale(sx, sy);
}
-bool SkGPipeCanvas::rotate(SkScalar degrees) {
- if (degrees) {
- NOTIFY_SETUP(this);
- if (this->needOpBytes(sizeof(SkScalar))) {
- this->writeOp(kRotate_DrawOp);
- fWriter.writeScalar(degrees);
- }
+void SkGPipeCanvas::recordScale(const SkMatrix& m) {
+ if (this->needOpBytes(2 * sizeof(SkScalar))) {
+ this->writeOp(kScale_DrawOp);
+ fWriter.writeScalar(m.getScaleX());
+ fWriter.writeScalar(m.getScaleY());
}
- return this->INHERITED::rotate(degrees);
}
-bool SkGPipeCanvas::skew(SkScalar sx, SkScalar sy) {
- if (sx || sy) {
- NOTIFY_SETUP(this);
- if (this->needOpBytes(2 * sizeof(SkScalar))) {
- this->writeOp(kSkew_DrawOp);
- fWriter.writeScalar(sx);
- fWriter.writeScalar(sy);
- }
+void SkGPipeCanvas::recordConcat(const SkMatrix& m) {
+ if (this->needOpBytes(m.writeToMemory(NULL))) {
+ this->writeOp(kConcat_DrawOp);
+ fWriter.writeMatrix(m);
}
- return this->INHERITED::skew(sx, sy);
}
-bool SkGPipeCanvas::concat(const SkMatrix& matrix) {
+void SkGPipeCanvas::didConcat(const SkMatrix& matrix) {
if (!matrix.isIdentity()) {
NOTIFY_SETUP(this);
- if (this->needOpBytes(matrix.writeToMemory(NULL))) {
- this->writeOp(kConcat_DrawOp);
- fWriter.writeMatrix(matrix);
+ switch (matrix.getType()) {
+ case SkMatrix::kTranslate_Mask:
+ this->recordTranslate(matrix);
+ break;
+ case SkMatrix::kScale_Mask:
+ this->recordScale(matrix);
+ break;
+ default:
+ this->recordConcat(matrix);
+ break;
}
}
- return this->INHERITED::concat(matrix);
+
+ this->INHERITED::didConcat(matrix);
}
-void SkGPipeCanvas::setMatrix(const SkMatrix& matrix) {
+void SkGPipeCanvas::didSetMatrix(const SkMatrix& matrix) {
NOTIFY_SETUP(this);
if (this->needOpBytes(matrix.writeToMemory(NULL))) {
this->writeOp(kSetMatrix_DrawOp);
fWriter.writeMatrix(matrix);
}
- this->INHERITED::setMatrix(matrix);
+ this->INHERITED::didSetMatrix(matrix);
}
-bool SkGPipeCanvas::clipRect(const SkRect& rect, SkRegion::Op rgnOp,
- bool doAntiAlias) {
+void SkGPipeCanvas::onClipRect(const SkRect& rect, SkRegion::Op rgnOp,
+ ClipEdgeStyle edgeStyle) {
NOTIFY_SETUP(this);
if (this->needOpBytes(sizeof(SkRect))) {
- unsigned flags = doAntiAlias & kClip_HasAntiAlias_DrawOpFlag;
+ unsigned flags = 0;
+ if (kSoft_ClipEdgeStyle == edgeStyle) {
+ flags = kClip_HasAntiAlias_DrawOpFlag;
+ }
this->writeOp(kClipRect_DrawOp, flags, rgnOp);
fWriter.writeRect(rect);
}
- return this->INHERITED::clipRect(rect, rgnOp, doAntiAlias);
+ this->INHERITED::onClipRect(rect, rgnOp, edgeStyle);
}
-bool SkGPipeCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op rgnOp,
- bool doAntiAlias) {
+void SkGPipeCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op rgnOp,
+ ClipEdgeStyle edgeStyle) {
NOTIFY_SETUP(this);
if (this->needOpBytes(kSizeOfFlatRRect)) {
- unsigned flags = doAntiAlias & kClip_HasAntiAlias_DrawOpFlag;
+ unsigned flags = 0;
+ if (kSoft_ClipEdgeStyle == edgeStyle) {
+ flags = kClip_HasAntiAlias_DrawOpFlag;
+ }
this->writeOp(kClipRRect_DrawOp, flags, rgnOp);
fWriter.writeRRect(rrect);
}
- return this->INHERITED::clipRRect(rrect, rgnOp, doAntiAlias);
+ this->INHERITED::onClipRRect(rrect, rgnOp, edgeStyle);
}
-bool SkGPipeCanvas::clipPath(const SkPath& path, SkRegion::Op rgnOp,
- bool doAntiAlias) {
+void SkGPipeCanvas::onClipPath(const SkPath& path, SkRegion::Op rgnOp,
+ ClipEdgeStyle edgeStyle) {
NOTIFY_SETUP(this);
if (this->needOpBytes(path.writeToMemory(NULL))) {
- unsigned flags = doAntiAlias & kClip_HasAntiAlias_DrawOpFlag;
+ unsigned flags = 0;
+ if (kSoft_ClipEdgeStyle == edgeStyle) {
+ flags = kClip_HasAntiAlias_DrawOpFlag;
+ }
this->writeOp(kClipPath_DrawOp, flags, rgnOp);
fWriter.writePath(path);
}
// we just pass on the bounds of the path
- return this->INHERITED::clipRect(path.getBounds(), rgnOp, doAntiAlias);
+ this->INHERITED::onClipRect(path.getBounds(), rgnOp, edgeStyle);
}
-bool SkGPipeCanvas::clipRegion(const SkRegion& region, SkRegion::Op rgnOp) {
+void SkGPipeCanvas::onClipRegion(const SkRegion& region, SkRegion::Op rgnOp) {
NOTIFY_SETUP(this);
if (this->needOpBytes(region.writeToMemory(NULL))) {
this->writeOp(kClipRegion_DrawOp, 0, rgnOp);
fWriter.writeRegion(region);
}
- return this->INHERITED::clipRegion(region, rgnOp);
+ this->INHERITED::onClipRegion(region, rgnOp);
}
///////////////////////////////////////////////////////////////////////////////
@@ -715,7 +706,7 @@ void SkGPipeCanvas::drawPoints(PointMode mode, size_t count,
this->writePaint(paint);
if (this->needOpBytes(4 + count * sizeof(SkPoint))) {
this->writeOp(kDrawPoints_DrawOp, mode, 0);
- fWriter.write32(count);
+ fWriter.write32(SkToU32(count));
fWriter.write(pts, count * sizeof(SkPoint));
}
}
@@ -748,6 +739,17 @@ void SkGPipeCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
}
}
+void SkGPipeCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
+ const SkPaint& paint) {
+ NOTIFY_SETUP(this);
+ this->writePaint(paint);
+ if (this->needOpBytes(kSizeOfFlatRRect * 2)) {
+ this->writeOp(kDrawDRRect_DrawOp);
+ fWriter.writeRRect(outer);
+ fWriter.writeRRect(inner);
+ }
+}
+
void SkGPipeCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
NOTIFY_SETUP(this);
this->writePaint(paint);
@@ -761,16 +763,23 @@ bool SkGPipeCanvas::commonDrawBitmap(const SkBitmap& bm, DrawOps op,
unsigned flags,
size_t opBytesNeeded,
const SkPaint* paint) {
+ if (fDone) {
+ return false;
+ }
+
if (paint != NULL) {
flags |= kDrawBitmap_HasPaint_DrawOpFlag;
this->writePaint(*paint);
}
+ // This needs to run first so its calls to needOpBytes() and its writes
+ // don't interlace with the needOpBytes() and write below.
+ SkASSERT(fBitmapHeap != NULL);
+ int32_t bitmapIndex = fBitmapHeap->insert(bm);
+ if (SkBitmapHeap::INVALID_SLOT == bitmapIndex) {
+ return false;
+ }
+
if (this->needOpBytes(opBytesNeeded)) {
- SkASSERT(fBitmapHeap != NULL);
- int32_t bitmapIndex = fBitmapHeap->insert(bm);
- if (SkBitmapHeap::INVALID_SLOT == bitmapIndex) {
- return false;
- }
this->writeOp(op, flags, bitmapIndex);
return true;
}
@@ -848,14 +857,14 @@ void SkGPipeCanvas::drawSprite(const SkBitmap& bm, int left, int top,
}
}
-void SkGPipeCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
- SkScalar y, const SkPaint& paint) {
+void SkGPipeCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
+ const SkPaint& paint) {
if (byteLength) {
NOTIFY_SETUP(this);
this->writePaint(paint);
if (this->needOpBytes(4 + SkAlign4(byteLength) + 2 * sizeof(SkScalar))) {
this->writeOp(kDrawText_DrawOp);
- fWriter.write32(byteLength);
+ fWriter.write32(SkToU32(byteLength));
fWriter.writePad(text, byteLength);
fWriter.writeScalar(x);
fWriter.writeScalar(y);
@@ -863,15 +872,15 @@ void SkGPipeCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
}
}
-void SkGPipeCanvas::drawPosText(const void* text, size_t byteLength,
- const SkPoint pos[], const SkPaint& paint) {
+void SkGPipeCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
+ const SkPaint& paint) {
if (byteLength) {
NOTIFY_SETUP(this);
this->writePaint(paint);
int count = paint.textToGlyphs(text, byteLength, NULL);
if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkPoint))) {
this->writeOp(kDrawPosText_DrawOp);
- fWriter.write32(byteLength);
+ fWriter.write32(SkToU32(byteLength));
fWriter.writePad(text, byteLength);
fWriter.write32(count);
fWriter.write(pos, count * sizeof(SkPoint));
@@ -879,16 +888,15 @@ void SkGPipeCanvas::drawPosText(const void* text, size_t byteLength,
}
}
-void SkGPipeCanvas::drawPosTextH(const void* text, size_t byteLength,
- const SkScalar xpos[], SkScalar constY,
- const SkPaint& paint) {
+void SkGPipeCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
+ SkScalar constY, const SkPaint& paint) {
if (byteLength) {
NOTIFY_SETUP(this);
this->writePaint(paint);
int count = paint.textToGlyphs(text, byteLength, NULL);
if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkScalar) + 4)) {
this->writeOp(kDrawPosTextH_DrawOp);
- fWriter.write32(byteLength);
+ fWriter.write32(SkToU32(byteLength));
fWriter.writePad(text, byteLength);
fWriter.write32(count);
fWriter.write(xpos, count * sizeof(SkScalar));
@@ -897,9 +905,8 @@ void SkGPipeCanvas::drawPosTextH(const void* text, size_t byteLength,
}
}
-void SkGPipeCanvas::drawTextOnPath(const void* text, size_t byteLength,
- const SkPath& path, const SkMatrix* matrix,
- const SkPaint& paint) {
+void SkGPipeCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
+ const SkMatrix* matrix, const SkPaint& paint) {
if (byteLength) {
NOTIFY_SETUP(this);
unsigned flags = 0;
@@ -912,7 +919,7 @@ void SkGPipeCanvas::drawTextOnPath(const void* text, size_t byteLength,
if (this->needOpBytes(size)) {
this->writeOp(kDrawTextOnPath_DrawOp, flags, 0);
- fWriter.write32(byteLength);
+ fWriter.write32(SkToU32(byteLength));
fWriter.writePad(text, byteLength);
fWriter.writePath(path);
@@ -923,14 +930,14 @@ void SkGPipeCanvas::drawTextOnPath(const void* text, size_t byteLength,
}
}
-void SkGPipeCanvas::drawPicture(SkPicture& picture) {
+void SkGPipeCanvas::onDrawPicture(const SkPicture* picture) {
// we want to playback the picture into individual draw calls
- this->INHERITED::drawPicture(picture);
+ this->INHERITED::onDrawPicture(picture);
}
-void SkGPipeCanvas::drawVertices(VertexMode mode, int vertexCount,
+void SkGPipeCanvas::drawVertices(VertexMode vmode, int vertexCount,
const SkPoint vertices[], const SkPoint texs[],
- const SkColor colors[], SkXfermode*,
+ const SkColor colors[], SkXfermode* xfer,
const uint16_t indices[], int indexCount,
const SkPaint& paint) {
if (0 == vertexCount) {
@@ -938,9 +945,15 @@ void SkGPipeCanvas::drawVertices(VertexMode mode, int vertexCount,
}
NOTIFY_SETUP(this);
- size_t size = 4 + vertexCount * sizeof(SkPoint);
this->writePaint(paint);
- unsigned flags = 0;
+
+ unsigned flags = 0; // packs with the op, so needs no extra space
+
+ size_t size = 0;
+ size += 4; // vmode
+ size += 4; // vertex count
+ size += vertexCount * sizeof(SkPoint); // vertices
+
if (texs) {
flags |= kDrawVertices_HasTexs_DrawOpFlag;
size += vertexCount * sizeof(SkPoint);
@@ -949,26 +962,33 @@ void SkGPipeCanvas::drawVertices(VertexMode mode, int vertexCount,
flags |= kDrawVertices_HasColors_DrawOpFlag;
size += vertexCount * sizeof(SkColor);
}
+ if (xfer && !SkXfermode::IsMode(xfer, SkXfermode::kModulate_Mode)) {
+ flags |= kDrawVertices_HasXfermode_DrawOpFlag;
+ size += sizeof(int32_t); // SkXfermode::Mode
+ }
if (indices && indexCount > 0) {
flags |= kDrawVertices_HasIndices_DrawOpFlag;
- size += 4 + SkAlign4(indexCount * sizeof(uint16_t));
+ size += 4; // index count
+ size += SkAlign4(indexCount * sizeof(uint16_t)); // indices
}
if (this->needOpBytes(size)) {
this->writeOp(kDrawVertices_DrawOp, flags, 0);
- fWriter.write32(mode);
+ fWriter.write32(vmode);
fWriter.write32(vertexCount);
fWriter.write(vertices, vertexCount * sizeof(SkPoint));
- if (texs) {
+ if (flags & kDrawVertices_HasTexs_DrawOpFlag) {
fWriter.write(texs, vertexCount * sizeof(SkPoint));
}
- if (colors) {
+ if (flags & kDrawVertices_HasColors_DrawOpFlag) {
fWriter.write(colors, vertexCount * sizeof(SkColor));
}
-
- // TODO: flatten xfermode
-
- if (indices && indexCount > 0) {
+ if (flags & kDrawVertices_HasXfermode_DrawOpFlag) {
+ SkXfermode::Mode mode = SkXfermode::kModulate_Mode;
+ SkAssertResult(xfer->asMode(&mode));
+ fWriter.write32(mode);
+ }
+ if (flags & kDrawVertices_HasIndices_DrawOpFlag) {
fWriter.write32(indexCount);
fWriter.writePad(indices, indexCount * sizeof(uint16_t));
}
@@ -985,7 +1005,7 @@ void SkGPipeCanvas::drawData(const void* ptr, size_t size) {
if (this->needOpBytes(4 + SkAlign4(size))) {
this->writeOp(kDrawData_DrawOp, 0, data);
if (0 == data) {
- fWriter.write32(size);
+ fWriter.write32(SkToU32(size));
}
fWriter.writePad(ptr, size);
}
@@ -1005,7 +1025,7 @@ void SkGPipeCanvas::endCommentGroup() {
}
void SkGPipeCanvas::flushRecording(bool detachCurrentBlock) {
- doNotify();
+ this->doNotify();
if (detachCurrentBlock) {
// force a new block to be requested for the next recorded command
fBlockSize = 0;
@@ -1044,6 +1064,10 @@ void SkGPipeCanvas::writePaint(const SkPaint& paint) {
*ptr++ = paint.getColor();
base.setColor(paint.getColor());
}
+ if (base.getFilterLevel() != paint.getFilterLevel()) {
+ *ptr++ = PaintOp_packOpData(kFilterLevel_PaintOp, paint.getFilterLevel());
+ base.setFilterLevel(paint.getFilterLevel());
+ }
if (base.getStyle() != paint.getStyle()) {
*ptr++ = PaintOp_packOpData(kStyle_PaintOp, paint.getStyle());
base.setStyle(paint.getStyle());
@@ -1131,7 +1155,7 @@ void SkGPipeCanvas::writePaint(const SkPaint& paint) {
size_t size = (char*)ptr - (char*)storage;
if (size && this->needOpBytes(size)) {
- this->writeOp(kPaintOp_DrawOp, 0, size);
+ this->writeOp(kPaintOp_DrawOp, 0, SkToU32(size));
fWriter.write(storage, size);
for (size_t i = 0; i < size/4; i++) {
// SkDebugf("[%d] %08X\n", i, storage[i]);
@@ -1147,11 +1171,11 @@ void SkGPipeCanvas::writePaint(const SkPaint& paint) {
this->writeOp(kSetAnnotation_DrawOp, 0, 0);
}
} else {
- SkOrderedWriteBuffer buffer(1024);
+ SkWriteBuffer buffer;
paint.getAnnotation()->writeToBuffer(buffer);
const size_t size = buffer.bytesWritten();
if (this->needOpBytes(size)) {
- this->writeOp(kSetAnnotation_DrawOp, 0, size);
+ this->writeOp(kSetAnnotation_DrawOp, 0, SkToU32(size));
buffer.writeToMemory(fWriter.reserve(size));
}
}
diff --git a/chromium/third_party/skia/src/pipe/utils/SamplePipeControllers.cpp b/chromium/third_party/skia/src/pipe/utils/SamplePipeControllers.cpp
index 1e25cb61c40..ea2c39cff0c 100644
--- a/chromium/third_party/skia/src/pipe/utils/SamplePipeControllers.cpp
+++ b/chromium/third_party/skia/src/pipe/utils/SamplePipeControllers.cpp
@@ -25,7 +25,7 @@ PipeController::~PipeController() {
void* PipeController::requestBlock(size_t minRequest, size_t *actual) {
sk_free(fBlock);
- fBlockSize = minRequest * 4;
+ fBlockSize = minRequest;
fBlock = sk_malloc_throw(fBlockSize);
fBytesWritten = 0;
*actual = fBlockSize;
diff --git a/chromium/third_party/skia/src/ports/SkAtomics_sync.h b/chromium/third_party/skia/src/ports/SkAtomics_sync.h
new file mode 100644
index 00000000000..b0d17527f07
--- /dev/null
+++ b/chromium/third_party/skia/src/ports/SkAtomics_sync.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkAtomics_sync_DEFINED
+#define SkAtomics_sync_DEFINED
+
+/** GCC/Clang __sync based atomics. */
+
+#include <stdint.h>
+
+static inline __attribute__((always_inline)) int32_t sk_atomic_inc(int32_t* addr) {
+ return __sync_fetch_and_add(addr, 1);
+}
+
+static inline __attribute__((always_inline)) int32_t sk_atomic_add(int32_t* addr, int32_t inc) {
+ return __sync_fetch_and_add(addr, inc);
+}
+
+static inline __attribute__((always_inline)) int32_t sk_atomic_dec(int32_t* addr) {
+ return __sync_fetch_and_add(addr, -1);
+}
+
+static inline __attribute__((always_inline)) void sk_membar_acquire__after_atomic_dec() { }
+
+static inline __attribute__((always_inline)) bool sk_atomic_cas(int32_t* addr,
+ int32_t before,
+ int32_t after) {
+ return __sync_bool_compare_and_swap(addr, before, after);
+}
+
+static inline __attribute__((always_inline)) void* sk_atomic_cas(void** addr,
+ void* before,
+ void* after) {
+ return __sync_val_compare_and_swap(addr, before, after);
+}
+
+static inline __attribute__((always_inline)) void sk_membar_acquire__after_atomic_conditional_inc() { }
+
+#endif
diff --git a/chromium/third_party/skia/src/ports/SkAtomics_win.h b/chromium/third_party/skia/src/ports/SkAtomics_win.h
new file mode 100644
index 00000000000..16923947ef0
--- /dev/null
+++ b/chromium/third_party/skia/src/ports/SkAtomics_win.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkAtomics_win_DEFINED
+#define SkAtomics_win_DEFINED
+
+/** Windows Interlocked atomics. */
+
+#include <intrin.h>
+#include <stdint.h>
+
+//MSDN says in order to declare an interlocked function for use as an
+//intrinsic, include intrin.h and put the function in a #pragma intrinsic
+//directive.
+//The pragma appears to be unnecessary, but doesn't hurt.
+#pragma intrinsic(_InterlockedIncrement, _InterlockedExchangeAdd, _InterlockedDecrement)
+#pragma intrinsic(_InterlockedCompareExchange)
+
+static inline int32_t sk_atomic_inc(int32_t* addr) {
+ // InterlockedIncrement returns the new value, we want to return the old.
+ return _InterlockedIncrement(reinterpret_cast<long*>(addr)) - 1;
+}
+
+static inline int32_t sk_atomic_add(int32_t* addr, int32_t inc) {
+ return _InterlockedExchangeAdd(reinterpret_cast<long*>(addr), static_cast<long>(inc));
+}
+
+static inline int32_t sk_atomic_dec(int32_t* addr) {
+ // InterlockedDecrement returns the new value, we want to return the old.
+ return _InterlockedDecrement(reinterpret_cast<long*>(addr)) + 1;
+}
+
+static inline void sk_membar_acquire__after_atomic_dec() { }
+
+static inline bool sk_atomic_cas(int32_t* addr, int32_t before, int32_t after) {
+ return _InterlockedCompareExchange(reinterpret_cast<long*>(addr), after, before) == before;
+}
+
+static inline void* sk_atomic_cas(void** addr, void* before, void* after) {
+ return InterlockedCompareExchangePointer(addr, after, before);
+}
+
+static inline void sk_membar_acquire__after_atomic_conditional_inc() { }
+
+#endif
diff --git a/chromium/third_party/skia/src/ports/SkBarriers_arm.h b/chromium/third_party/skia/src/ports/SkBarriers_arm.h
new file mode 100644
index 00000000000..9161cddebcf
--- /dev/null
+++ b/chromium/third_party/skia/src/ports/SkBarriers_arm.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkBarriers_arm_DEFINED
+#define SkBarriers_arm_DEFINED
+
+static inline void sk_compiler_barrier() { asm volatile("" : : : "memory"); }
+
+template <typename T>
+T sk_acquire_load(T* ptr) {
+ T val = *ptr;
+ __sync_synchronize(); // Issue a full barrier, which is an overkill acquire barrier.
+ return val;
+}
+
+template <typename T>
+void sk_release_store(T* ptr, T val) {
+ __sync_synchronize(); // Issue a full barrier, which is an overkill release barrier.
+ *ptr = val;
+}
+
+#endif//SkBarriers_x86_DEFINED
diff --git a/chromium/third_party/skia/src/ports/SkBarriers_tsan.h b/chromium/third_party/skia/src/ports/SkBarriers_tsan.h
new file mode 100644
index 00000000000..6f273907aba
--- /dev/null
+++ b/chromium/third_party/skia/src/ports/SkBarriers_tsan.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkBarriers_tsan_DEFINED
+#define SkBarriers_tsan_DEFINED
+
+static inline void sk_compiler_barrier() { asm volatile("" : : : "memory"); }
+
+template <typename T>
+T sk_acquire_load(T* ptr) {
+ SkASSERT(__atomic_always_lock_free(sizeof(T), ptr));
+ return __atomic_load_n(ptr, __ATOMIC_ACQUIRE);
+}
+
+template <typename T>
+void sk_release_store(T* ptr, T val) {
+ SkASSERT(__atomic_always_lock_free(sizeof(T), ptr));
+ return __atomic_store_n(ptr, val, __ATOMIC_RELEASE);
+}
+
+#endif//SkBarriers_tsan_DEFINED
diff --git a/chromium/third_party/skia/src/ports/SkBarriers_x86.h b/chromium/third_party/skia/src/ports/SkBarriers_x86.h
new file mode 100644
index 00000000000..fc57615e048
--- /dev/null
+++ b/chromium/third_party/skia/src/ports/SkBarriers_x86.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkBarriers_x86_DEFINED
+#define SkBarriers_x86_DEFINED
+
+#ifdef SK_BUILD_FOR_WIN
+# include <intrin.h>
+static inline void sk_compiler_barrier() { _ReadWriteBarrier(); }
+#else
+static inline void sk_compiler_barrier() { asm volatile("" : : : "memory"); }
+#endif
+
+template <typename T>
+T sk_acquire_load(T* ptr) {
+ T val = *ptr;
+ // On x86, all loads are acquire loads, so we only need a compiler barrier.
+ sk_compiler_barrier();
+ return val;
+}
+
+template <typename T>
+void sk_release_store(T* ptr, T val) {
+ // On x86, all stores are release stores, so we only need a compiler barrier.
+ sk_compiler_barrier();
+ *ptr = val;
+}
+
+#endif//SkBarriers_x86_DEFINED
diff --git a/chromium/third_party/skia/src/ports/SkDiscardableMemory_ashmem.cpp b/chromium/third_party/skia/src/ports/SkDiscardableMemory_ashmem.cpp
deleted file mode 100644
index e5e5f539693..00000000000
--- a/chromium/third_party/skia/src/ports/SkDiscardableMemory_ashmem.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright 2013 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include <unistd.h>
-#include <sys/mman.h>
-#include "SkDiscardableMemory.h"
-#include "SkTypes.h"
-#include "android/ashmem.h"
-
-////////////////////////////////////////////////////////////////////////////////
-namespace {
-/**
- * DiscardableMemory implementation that uses the Android kernel's
- * ashmem (Android shared memory).
- */
-class SkAshmemDiscardableMemory : public SkDiscardableMemory {
-public:
- SkAshmemDiscardableMemory(int fd, void* address, size_t size);
- virtual ~SkAshmemDiscardableMemory();
- virtual bool lock() SK_OVERRIDE;
- virtual void* data() SK_OVERRIDE;
- virtual void unlock() SK_OVERRIDE;
-private:
- bool fLocked;
- int fFd;
- void* fMemory;
- const size_t fSize;
-};
-
-SkAshmemDiscardableMemory::SkAshmemDiscardableMemory(int fd,
- void* address,
- size_t size)
- : fLocked(true) // Ashmem pages are pinned by default.
- , fFd(fd)
- , fMemory(address)
- , fSize(size) {
- SkASSERT(fFd >= 0);
- SkASSERT(fMemory != NULL);
- SkASSERT(fSize > 0);
-}
-
-SkAshmemDiscardableMemory::~SkAshmemDiscardableMemory() {
- SkASSERT(!fLocked);
- if (NULL != fMemory) {
- munmap(fMemory, fSize);
- }
- if (fFd != -1) {
- close(fFd);
- }
-}
-
-bool SkAshmemDiscardableMemory::lock() {
- SkASSERT(!fLocked);
- if (-1 == fFd) {
- fLocked = false;
- return false;
- }
- SkASSERT(fMemory != NULL);
- if (fLocked || (ASHMEM_NOT_PURGED == ashmem_pin_region(fFd, 0, 0))) {
- fLocked = true;
- return true;
- } else {
- munmap(fMemory, fSize);
- fMemory = NULL;
-
- close(fFd);
- fFd = -1;
- fLocked = false;
- return false;
- }
-}
-
-void* SkAshmemDiscardableMemory::data() {
- SkASSERT(fLocked);
- return fLocked ? fMemory : NULL;
-}
-
-void SkAshmemDiscardableMemory::unlock() {
- SkASSERT(fLocked);
- if (fLocked && (fFd != -1)) {
- ashmem_unpin_region(fFd, 0, 0);
- }
- fLocked = false;
-}
-} // namespace
-////////////////////////////////////////////////////////////////////////////////
-
-SkDiscardableMemory* SkDiscardableMemory::Create(size_t bytes) {
- // ashmem likes lengths on page boundaries.
- const size_t mask = getpagesize() - 1;
- size_t size = (bytes + mask) & ~mask;
-
- static const char name[] = "Skia_Ashmem_Discardable_Memory";
- int fd = ashmem_create_region(name, size);
- if (fd < 0) {
- return NULL;
- }
- if (0 != ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE)) {
- close(fd);
- return NULL;
- }
- void* addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
- if ((MAP_FAILED == addr) || (NULL == addr)) {
- close(fd);
- return NULL;
- }
-
- return SkNEW_ARGS(SkAshmemDiscardableMemory, (fd, addr, size));
-}
diff --git a/chromium/third_party/skia/src/ports/SkFontConfigInterface_android.cpp b/chromium/third_party/skia/src/ports/SkFontConfigInterface_android.cpp
index 6f9ed3a93b4..20e6c5eb84b 100644
--- a/chromium/third_party/skia/src/ports/SkFontConfigInterface_android.cpp
+++ b/chromium/third_party/skia/src/ports/SkFontConfigInterface_android.cpp
@@ -174,7 +174,7 @@ static bool has_font(const SkTArray<FontRec>& array, const SkString& filename) {
#define SK_FONT_FILE_PREFIX "/fonts/"
#endif
-static void get_path_for_sys_fonts(SkString* full, const char name[]) {
+static void get_path_for_sys_fonts(SkString* full, const SkString& name) {
if (gTestFontFilePrefix) {
full->set(gTestFontFilePrefix);
} else {
@@ -220,7 +220,7 @@ SkFontConfigInterfaceAndroid::SkFontConfigInterfaceAndroid(SkTDArray<FontFamily*
for (int j = 0; j < family->fFontFiles.count(); ++j) {
SkString filename;
- get_path_for_sys_fonts(&filename, family->fFontFiles[j]->fFileName);
+ get_path_for_sys_fonts(&filename, family->fFontFiles[j].fFileName);
if (has_font(fFonts, filename)) {
SkDebugf("---- system font and fallback font files specify a duplicate "
@@ -265,9 +265,9 @@ SkFontConfigInterfaceAndroid::SkFontConfigInterfaceAndroid(SkTDArray<FontFamily*
fontRec.fFamilyRecID = familyRecID;
familyRec->fIsFallbackFont = family->fIsFallbackFont;
- familyRec->fPaintOptions = family->fFontFiles[j]->fPaintOptions;
+ familyRec->fPaintOptions = family->fFontFiles[j].fPaintOptions;
- } else if (familyRec->fPaintOptions != family->fFontFiles[j]->fPaintOptions) {
+ } else if (familyRec->fPaintOptions != family->fFontFiles[j].fPaintOptions) {
SkDebugf("Every font file within a family must have identical"
"language and variant attributes");
sk_throw();
@@ -289,14 +289,14 @@ SkFontConfigInterfaceAndroid::SkFontConfigInterfaceAndroid(SkTDArray<FontFamily*
addFallbackFamily(familyRecID);
} else {
// add the names that map to this family to the dictionary for easy lookup
- const SkTDArray<const char*>& names = family->fNames;
- if (names.isEmpty()) {
+ const SkTArray<SkString>& names = family->fNames;
+ if (names.empty()) {
SkDEBUGFAIL("ERROR: non-fallback font with no name");
continue;
}
for (int i = 0; i < names.count(); i++) {
- insert_into_name_dict(fFamilyNameDict, names[i], familyRecID);
+ insert_into_name_dict(fFamilyNameDict, names[i].c_str(), familyRecID);
}
}
}
@@ -633,7 +633,7 @@ SkTypeface* SkFontConfigInterfaceAndroid::nextLogicalTypeface(SkFontID currFontI
const SkTypeface* currTypeface = SkTypefaceCache::FindByID(currFontID);
// non-system fonts are not in the font cache so if we are asked to fallback
// for a non-system font we will start at the front of the chain.
- if (NULL != currTypeface && currFontID != origFontID) {
+ if (NULL != currTypeface) {
currFontRecID = ((FontConfigTypeface*)currTypeface)->getIdentity().fID;
SkASSERT(INVALID_FONT_REC_ID != currFontRecID);
}
@@ -781,8 +781,6 @@ SkTypeface* SkGetTypefaceForGlyphID(uint16_t glyphID, const SkTypeface* origType
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
struct HB_UnicodeMapping {
- // TODO: when the WebView no longer needs harfbuzz_old, remove
- HB_Script script_old;
hb_script_t script;
const SkUnichar unicode;
};
@@ -803,50 +801,38 @@ struct HB_UnicodeMapping {
#define HB_Script_Unknown HB_ScriptCount
static HB_UnicodeMapping HB_UnicodeMappingArray[] = {
- {HB_Script_Armenian, HB_SCRIPT_ARMENIAN, 0x0531},
- {HB_Script_Hebrew, HB_SCRIPT_HEBREW, 0x0591},
- {HB_Script_Arabic, HB_SCRIPT_ARABIC, 0x0600},
- {HB_Script_Syriac, HB_SCRIPT_SYRIAC, 0x0710},
- {HB_Script_Thaana, HB_SCRIPT_THAANA, 0x0780},
- {HB_Script_Nko, HB_SCRIPT_NKO, 0x07C0},
- {HB_Script_Devanagari, HB_SCRIPT_DEVANAGARI, 0x0901},
- {HB_Script_Bengali, HB_SCRIPT_BENGALI, 0x0981},
- {HB_Script_Gurmukhi, HB_SCRIPT_GURMUKHI, 0x0A10},
- {HB_Script_Gujarati, HB_SCRIPT_GUJARATI, 0x0A90},
- {HB_Script_Oriya, HB_SCRIPT_ORIYA, 0x0B10},
- {HB_Script_Tamil, HB_SCRIPT_TAMIL, 0x0B82},
- {HB_Script_Telugu, HB_SCRIPT_TELUGU, 0x0C10},
- {HB_Script_Kannada, HB_SCRIPT_KANNADA, 0x0C90},
- {HB_Script_Malayalam, HB_SCRIPT_MALAYALAM, 0x0D10},
- {HB_Script_Sinhala, HB_SCRIPT_SINHALA, 0x0D90},
- {HB_Script_Thai, HB_SCRIPT_THAI, 0x0E01},
- {HB_Script_Lao, HB_SCRIPT_LAO, 0x0E81},
- {HB_Script_Tibetan, HB_SCRIPT_TIBETAN, 0x0F00},
- {HB_Script_Myanmar, HB_SCRIPT_MYANMAR, 0x1000},
- {HB_Script_Georgian, HB_SCRIPT_GEORGIAN, 0x10A0},
- {HB_Script_Unknown, HB_SCRIPT_ETHIOPIC, 0x1200},
- {HB_Script_Unknown, HB_SCRIPT_CHEROKEE, 0x13A0},
- {HB_Script_Ogham, HB_SCRIPT_OGHAM, 0x1680},
- {HB_Script_Runic, HB_SCRIPT_RUNIC, 0x16A0},
- {HB_Script_Khmer, HB_SCRIPT_KHMER, 0x1780},
- {HB_Script_Unknown, HB_SCRIPT_TAI_LE, 0x1950},
- {HB_Script_Unknown, HB_SCRIPT_NEW_TAI_LUE, 0x1980},
- {HB_Script_Unknown, HB_SCRIPT_TAI_THAM, 0x1A20},
- {HB_Script_Unknown, HB_SCRIPT_CHAM, 0xAA00},
+ {HB_SCRIPT_ARMENIAN, 0x0531},
+ {HB_SCRIPT_HEBREW, 0x0591},
+ {HB_SCRIPT_ARABIC, 0x0600},
+ {HB_SCRIPT_SYRIAC, 0x0710},
+ {HB_SCRIPT_THAANA, 0x0780},
+ {HB_SCRIPT_NKO, 0x07C0},
+ {HB_SCRIPT_DEVANAGARI, 0x0901},
+ {HB_SCRIPT_BENGALI, 0x0981},
+ {HB_SCRIPT_GURMUKHI, 0x0A10},
+ {HB_SCRIPT_GUJARATI, 0x0A90},
+ {HB_SCRIPT_ORIYA, 0x0B10},
+ {HB_SCRIPT_TAMIL, 0x0B82},
+ {HB_SCRIPT_TELUGU, 0x0C10},
+ {HB_SCRIPT_KANNADA, 0x0C90},
+ {HB_SCRIPT_MALAYALAM, 0x0D10},
+ {HB_SCRIPT_SINHALA, 0x0D90},
+ {HB_SCRIPT_THAI, 0x0E01},
+ {HB_SCRIPT_LAO, 0x0E81},
+ {HB_SCRIPT_TIBETAN, 0x0F00},
+ {HB_SCRIPT_MYANMAR, 0x1000},
+ {HB_SCRIPT_GEORGIAN, 0x10A0},
+ {HB_SCRIPT_ETHIOPIC, 0x1200},
+ {HB_SCRIPT_CHEROKEE, 0x13A0},
+ {HB_SCRIPT_OGHAM, 0x1680},
+ {HB_SCRIPT_RUNIC, 0x16A0},
+ {HB_SCRIPT_KHMER, 0x1780},
+ {HB_SCRIPT_TAI_LE, 0x1950},
+ {HB_SCRIPT_NEW_TAI_LUE, 0x1980},
+ {HB_SCRIPT_TAI_THAM, 0x1A20},
+ {HB_SCRIPT_CHAM, 0xAA00},
};
-static hb_script_t getHBScriptFromHBScriptOld(HB_Script script_old) {
- hb_script_t script = HB_SCRIPT_INVALID;
- int numSupportedFonts = sizeof(HB_UnicodeMappingArray) / sizeof(HB_UnicodeMapping);
- for (int i = 0; i < numSupportedFonts; i++) {
- if (script_old == HB_UnicodeMappingArray[i].script_old) {
- script = HB_UnicodeMappingArray[i].script;
- break;
- }
- }
- return script;
-}
-
// returns 0 for "Not Found"
static SkUnichar getUnicodeFromHBScript(hb_script_t script) {
SkUnichar unichar = 0;
@@ -884,8 +870,8 @@ static int typefaceLookupCompare(const TypefaceLookupStruct& first,
return 0;
}
-SkTypeface* SkCreateTypefaceForScriptNG(hb_script_t script, SkTypeface::Style style,
- SkPaintOptionsAndroid::FontVariant fontVariant) {
+SkTypeface* SkCreateTypefaceForScript(hb_script_t script, SkTypeface::Style style,
+ SkPaintOptionsAndroid::FontVariant fontVariant) {
SkAutoMutexAcquire ac(gTypefaceTableMutex);
TypefaceLookupStruct key;
@@ -920,11 +906,6 @@ SkTypeface* SkCreateTypefaceForScriptNG(hb_script_t script, SkTypeface::Style st
return SkSafeRef(retTypeface);
}
-SkTypeface* SkCreateTypefaceForScript(HB_Script script, SkTypeface::Style style,
- SkPaintOptionsAndroid::FontVariant fontVariant) {
- return SkCreateTypefaceForScriptNG(getHBScriptFromHBScriptOld(script), style, fontVariant);
-}
-
#endif
///////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/third_party/skia/src/ports/SkFontConfigInterface_direct.cpp b/chromium/third_party/skia/src/ports/SkFontConfigInterface_direct.cpp
index 13993f10c0d..dc9afbae1f4 100644
--- a/chromium/third_party/skia/src/ports/SkFontConfigInterface_direct.cpp
+++ b/chromium/third_party/skia/src/ports/SkFontConfigInterface_direct.cpp
@@ -15,6 +15,7 @@
#include "SkBuffer.h"
#include "SkFontConfigInterface.h"
+#include "SkLazyPtr.h"
#include "SkStream.h"
size_t SkFontConfigInterface::FontIdentity::writeToMemory(void* addr) const {
@@ -124,16 +125,8 @@ private:
};
SkFontConfigInterface* SkFontConfigInterface::GetSingletonDirectInterface() {
- static SkFontConfigInterface* gDirect;
- if (NULL == gDirect) {
- static SkMutex gMutex;
- SkAutoMutexAcquire ac(gMutex);
-
- if (NULL == gDirect) {
- gDirect = new SkFontConfigInterfaceDirect;
- }
- }
- return gDirect;
+ SK_DECLARE_STATIC_LAZY_PTR(SkFontConfigInterfaceDirect, direct);
+ return direct.get();
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/third_party/skia/src/ports/SkFontConfigParser_android.cpp b/chromium/third_party/skia/src/ports/SkFontConfigParser_android.cpp
index 73de73bb54e..38a6ee65206 100644
--- a/chromium/third_party/skia/src/ports/SkFontConfigParser_android.cpp
+++ b/chromium/third_party/skia/src/ports/SkFontConfigParser_android.cpp
@@ -52,18 +52,13 @@ static void textHandler(void *data, const char *s, int len) {
// Make sure we're in the right state to store this name information
if (familyData->currentFamily &&
(familyData->currentTag == NAMESET_TAG || familyData->currentTag == FILESET_TAG)) {
- // Malloc new buffer to store the string
- char *buff;
- buff = (char*) malloc((len + 1) * sizeof(char));
- strncpy(buff, s, len);
- buff[len] = '\0';
switch (familyData->currentTag) {
case NAMESET_TAG:
- *(familyData->currentFamily->fNames.append()) = buff;
+ familyData->currentFamily->fNames.push_back().set(s, len);
break;
case FILESET_TAG:
if (familyData->currentFontInfo) {
- familyData->currentFontInfo->fFileName = buff;
+ familyData->currentFontInfo->fFileName.set(s, len);
}
break;
default:
@@ -78,7 +73,8 @@ static void textHandler(void *data, const char *s, int len) {
* variants then lets textHandler handle the actual file name
*/
static void fontFileElementHandler(FamilyData *familyData, const char **attributes) {
- FontFileInfo* newFileInfo = new FontFileInfo();
+
+ FontFileInfo& newFileInfo = familyData->currentFamily->fFontFiles.push_back();
if (attributes) {
int currentAttributeIndex = 0;
while (attributes[currentAttributeIndex]) {
@@ -88,19 +84,18 @@ static void fontFileElementHandler(FamilyData *familyData, const char **attribut
int valueLength = strlen(attributeValue);
if (strncmp(attributeName, "variant", nameLength) == 0) {
if (strncmp(attributeValue, "elegant", valueLength) == 0) {
- newFileInfo->fPaintOptions.setFontVariant(SkPaintOptionsAndroid::kElegant_Variant);
+ newFileInfo.fPaintOptions.setFontVariant(SkPaintOptionsAndroid::kElegant_Variant);
} else if (strncmp(attributeValue, "compact", valueLength) == 0) {
- newFileInfo->fPaintOptions.setFontVariant(SkPaintOptionsAndroid::kCompact_Variant);
+ newFileInfo.fPaintOptions.setFontVariant(SkPaintOptionsAndroid::kCompact_Variant);
}
} else if (strncmp(attributeName, "lang", nameLength) == 0) {
- newFileInfo->fPaintOptions.setLanguage(attributeValue);
+ newFileInfo.fPaintOptions.setLanguage(attributeValue);
}
//each element is a pair of attributeName/attributeValue string pairs
currentAttributeIndex += 2;
}
}
- *(familyData->currentFamily->fFontFiles.append()) = newFileInfo;
- familyData->currentFontInfo = newFileInfo;
+ familyData->currentFontInfo = &newFileInfo;
XML_SetCharacterDataHandler(*familyData->parser, textHandler);
}
diff --git a/chromium/third_party/skia/src/ports/SkFontConfigParser_android.h b/chromium/third_party/skia/src/ports/SkFontConfigParser_android.h
index fd64496f774..e2247efb0ab 100644
--- a/chromium/third_party/skia/src/ports/SkFontConfigParser_android.h
+++ b/chromium/third_party/skia/src/ports/SkFontConfigParser_android.h
@@ -15,9 +15,7 @@
#include "SkTDArray.h"
struct FontFileInfo {
- FontFileInfo() : fFileName(NULL) {}
-
- const char* fFileName;
+ SkString fFileName;
SkPaintOptionsAndroid fPaintOptions;
};
@@ -32,8 +30,8 @@ struct FontFileInfo {
struct FontFamily {
FontFamily() : fIsFallbackFont(false), order(-1) {}
- SkTDArray<const char*> fNames;
- SkTDArray<FontFileInfo*> fFontFiles;
+ SkTArray<SkString> fNames;
+ SkTArray<FontFileInfo> fFontFiles;
bool fIsFallbackFont;
int order; // only used internally by SkFontConfigParser
};
diff --git a/chromium/third_party/skia/src/ports/SkFontConfigTypeface.h b/chromium/third_party/skia/src/ports/SkFontConfigTypeface.h
index dc92f1dffb6..b6f8797eb7c 100644
--- a/chromium/third_party/skia/src/ports/SkFontConfigTypeface.h
+++ b/chromium/third_party/skia/src/ports/SkFontConfigTypeface.h
@@ -18,19 +18,14 @@ class FontConfigTypeface : public SkTypeface_FreeType {
SkStream* fLocalStream;
public:
- FontConfigTypeface(Style style,
- const SkFontConfigInterface::FontIdentity& fi,
- const SkString& familyName)
- : INHERITED(style, SkTypefaceCache::NewFontID(), false)
- , fIdentity(fi)
- , fFamilyName(familyName)
- , fLocalStream(NULL) {}
+ static FontConfigTypeface* Create(Style style,
+ const SkFontConfigInterface::FontIdentity& fi,
+ const SkString& familyName) {
+ return SkNEW_ARGS(FontConfigTypeface, (style, fi, familyName));
+ }
- FontConfigTypeface(Style style, bool fixedWidth, SkStream* localStream)
- : INHERITED(style, SkTypefaceCache::NewFontID(), fixedWidth) {
- // we default to empty fFamilyName and fIdentity
- fLocalStream = localStream;
- SkSafeRef(localStream);
+ static FontConfigTypeface* Create(Style style, bool fixedWidth, SkStream* localStream) {
+ return SkNEW_ARGS(FontConfigTypeface, (style, fixedWidth, localStream));
}
virtual ~FontConfigTypeface() {
@@ -55,6 +50,21 @@ public:
protected:
friend class SkFontHost; // hack until we can make public versions
+ FontConfigTypeface(Style style,
+ const SkFontConfigInterface::FontIdentity& fi,
+ const SkString& familyName)
+ : INHERITED(style, SkTypefaceCache::NewFontID(), false)
+ , fIdentity(fi)
+ , fFamilyName(familyName)
+ , fLocalStream(NULL) {}
+
+ FontConfigTypeface(Style style, bool fixedWidth, SkStream* localStream)
+ : INHERITED(style, SkTypefaceCache::NewFontID(), fixedWidth) {
+ // we default to empty fFamilyName and fIdentity
+ fLocalStream = localStream;
+ SkSafeRef(localStream);
+ }
+
virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE;
virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE;
diff --git a/chromium/third_party/skia/src/ports/SkFontHost_FreeType.cpp b/chromium/third_party/skia/src/ports/SkFontHost_FreeType.cpp
index 745a58a9963..12edc49d9e8 100644
--- a/chromium/third_party/skia/src/ports/SkFontHost_FreeType.cpp
+++ b/chromium/third_party/skia/src/ports/SkFontHost_FreeType.cpp
@@ -6,6 +6,7 @@
* found in the LICENSE file.
*/
+#include "SkAdvancedTypefaceMetrics.h"
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkColorPriv.h"
@@ -17,8 +18,9 @@
#include "SkGlyph.h"
#include "SkMask.h"
#include "SkMaskGamma.h"
+#include "SkMatrix22.h"
#include "SkOTUtils.h"
-#include "SkAdvancedTypefaceMetrics.h"
+#include "SkOnce.h"
#include "SkScalerContext.h"
#include "SkStream.h"
#include "SkString.h"
@@ -42,6 +44,8 @@
#include FT_LCD_FILTER_H
#endif
+// Defined in FreeType 2.3.8 and later.
+// This is a silly build time check, we would need a runtime check if we really cared.
#ifdef FT_ADVANCES_H
#include FT_ADVANCES_H
#endif
@@ -160,17 +164,22 @@ static bool InitFreetype() {
return true;
}
-// Lazy, once, wrapper to ask the FreeType Library if it can support LCD text
-static bool is_lcd_supported() {
+// Called while holding gFTMutex.
+static void determine_lcd_support(bool* lcdSupported) {
if (!gLCDSupportValid) {
- SkAutoMutexAcquire ac(gFTMutex);
-
- if (!gLCDSupportValid) {
- InitFreetype();
- FT_Done_FreeType(gFTLibrary);
- }
+ // This will determine LCD support as a side effect.
+ InitFreetype();
+ FT_Done_FreeType(gFTLibrary);
}
- return gLCDSupport;
+ SkASSERT(gLCDSupportValid);
+ *lcdSupported = gLCDSupport;
+}
+
+// Lazy, once, wrapper to ask the FreeType Library if it can support LCD text
+static bool is_lcd_supported() {
+ static bool lcdSupported = false;
+ SkOnce(&gLCDSupportValid, &gFTMutex, determine_lcd_support, &lcdSupported);
+ return lcdSupported;
}
class SkScalerContext_FreeType : public SkScalerContext_FreeType_Base {
@@ -213,8 +222,12 @@ private:
FT_Error setupSize();
void getBBoxForCurrentGlyph(SkGlyph* glyph, FT_BBox* bbox,
bool snapToPixelBoundary = false);
+ bool getCBoxForLetter(char letter, FT_BBox* bbox);
// Caller must lock gFTMutex before calling this function.
void updateGlyphIfLCD(SkGlyph* glyph);
+ // Caller must lock gFTMutex before calling this function.
+ // update FreeType2 glyph slot with glyph emboldened
+ void emboldenIfNeeded(FT_Face face, FT_GlyphSlot glyph);
};
///////////////////////////////////////////////////////////////////////////
@@ -427,11 +440,26 @@ static bool canEmbed(FT_Face face) {
#endif
}
+static bool canSubset(FT_Face face) {
+#ifdef FT_FSTYPE_NO_SUBSETTING
+ FT_UShort fsType = FT_Get_FSType_Flags(face);
+ return (fsType & FT_FSTYPE_NO_SUBSETTING) == 0;
+#else
+ // No subset is 0x100.
+ TT_OS2* os2_table;
+ if ((os2_table = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != NULL) {
+ return (os2_table->fsType & 0x100) == 0;
+ }
+ return false; // We tried, fail safe.
+#endif
+}
+
static bool GetLetterCBox(FT_Face face, char letter, FT_BBox* bbox) {
const FT_UInt glyph_id = FT_Get_Char_Index(face, letter);
if (!glyph_id)
return false;
- FT_Load_Glyph(face, glyph_id, FT_LOAD_NO_SCALE);
+ if (FT_Load_Glyph(face, glyph_id, FT_LOAD_NO_SCALE) != 0)
+ return false;
FT_Outline_Get_CBox(&face->glyph->outline, bbox);
return true;
}
@@ -511,7 +539,21 @@ SkAdvancedTypefaceMetrics* SkTypeface_FreeType::onGetAdvancedTypefaceMetrics(
SkAdvancedTypefaceMetrics* info = new SkAdvancedTypefaceMetrics;
info->fFontName.set(FT_Get_Postscript_Name(face));
- info->fMultiMaster = FT_HAS_MULTIPLE_MASTERS(face);
+ info->fFlags = SkAdvancedTypefaceMetrics::kEmpty_FontFlag;
+ if (FT_HAS_MULTIPLE_MASTERS(face)) {
+ info->fFlags = SkTBitOr<SkAdvancedTypefaceMetrics::FontFlags>(
+ info->fFlags, SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag);
+ }
+ if (!canEmbed(face)) {
+ info->fFlags = SkTBitOr<SkAdvancedTypefaceMetrics::FontFlags>(
+ info->fFlags,
+ SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag);
+ }
+ if (!canSubset(face)) {
+ info->fFlags = SkTBitOr<SkAdvancedTypefaceMetrics::FontFlags>(
+ info->fFlags,
+ SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag);
+ }
info->fLastGlyphID = face->num_glyphs - 1;
info->fEmSize = 1000;
@@ -582,8 +624,10 @@ SkAdvancedTypefaceMetrics* SkTypeface_FreeType::onGetAdvancedTypefaceMetrics(
info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
else if (serif_style >= 9 && serif_style <= 12)
info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
- } else if ((os2_table =
- (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != NULL) {
+ } else if (((os2_table = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != NULL) &&
+ // sCapHeight is available only when version 2 or later.
+ os2_table->version != 0xFFFF &&
+ os2_table->version >= 2) {
info->fCapHeight = os2_table->sCapHeight;
} else {
// Figure out a good guess for CapHeight: average the height of M and X.
@@ -598,14 +642,16 @@ SkAdvancedTypefaceMetrics* SkTypeface_FreeType::onGetAdvancedTypefaceMetrics(
info->fCapHeight = m_bbox.yMax - m_bbox.yMin;
} else if (!got_m && got_x) {
info->fCapHeight = x_bbox.yMax - x_bbox.yMin;
+ } else {
+ // Last resort, use the ascent.
+ info->fCapHeight = info->fAscent;
}
}
info->fBBox = SkIRect::MakeLTRB(face->bbox.xMin, face->bbox.yMax,
face->bbox.xMax, face->bbox.yMin);
- if (!canEmbed(face) || !FT_IS_SCALABLE(face) ||
- info->fType == SkAdvancedTypefaceMetrics::kOther_Font) {
+ if (!FT_IS_SCALABLE(face)) {
perGlyphInfo = SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo;
}
@@ -668,18 +714,12 @@ SkAdvancedTypefaceMetrics* SkTypeface_FreeType::onGetAdvancedTypefaceMetrics(
populate_glyph_to_unicode(face, &(info->fGlyphToUnicode));
}
- if (!canEmbed(face))
- info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
-
return info;
#endif
}
///////////////////////////////////////////////////////////////////////////
-#define BLACK_LUMINANCE_LIMIT 0x40
-#define WHITE_LUMINANCE_LIMIT 0xA0
-
static bool bothZero(SkScalar a, SkScalar b) {
return 0 == a && 0 == b;
}
@@ -833,53 +873,60 @@ SkScalerContext_FreeType::SkScalerContext_FreeType(SkTypeface* typeface,
}
fFace = fFaceRec->fFace;
- // compute our factors from the record
-
- SkMatrix m;
-
- fRec.getSingleMatrix(&m);
-
-#ifdef DUMP_STRIKE_CREATION
- SkString keyString;
- SkFontHost::GetDescriptorKeyString(desc, &keyString);
- printf("========== strike [%g %g %g] [%g %g %g %g] hints %d format %d %s\n", SkScalarToFloat(fRec.fTextSize),
- SkScalarToFloat(fRec.fPreScaleX), SkScalarToFloat(fRec.fPreSkewX),
- SkScalarToFloat(fRec.fPost2x2[0][0]), SkScalarToFloat(fRec.fPost2x2[0][1]),
- SkScalarToFloat(fRec.fPost2x2[1][0]), SkScalarToFloat(fRec.fPost2x2[1][1]),
- fRec.getHinting(), fRec.fMaskFormat, keyString.c_str());
-#endif
-
- // now compute our scale factors
- SkScalar sx = m.getScaleX();
- SkScalar sy = m.getScaleY();
+ // A is the total matrix.
+ SkMatrix A;
+ fRec.getSingleMatrix(&A);
+ SkScalar sx = A.getScaleX();
+ SkScalar sy = A.getScaleY();
fMatrix22Scalar.reset();
- if (m.getSkewX() || m.getSkewY() || sx < 0 || sy < 0) {
- // sort of give up on hinting
- sx = SkMaxScalar(SkScalarAbs(sx), SkScalarAbs(m.getSkewX()));
- sy = SkMaxScalar(SkScalarAbs(m.getSkewY()), SkScalarAbs(sy));
- sx = sy = SkScalarAve(sx, sy);
-
- SkScalar inv = SkScalarInvert(sx);
-
- // flip the skew elements to go from our Y-down system to FreeType's
- fMatrix22.xx = SkScalarToFixed(SkScalarMul(m.getScaleX(), inv));
- fMatrix22.xy = -SkScalarToFixed(SkScalarMul(m.getSkewX(), inv));
- fMatrix22.yx = -SkScalarToFixed(SkScalarMul(m.getSkewY(), inv));
- fMatrix22.yy = SkScalarToFixed(SkScalarMul(m.getScaleY(), inv));
-
- fMatrix22Scalar.setScaleX(SkScalarMul(m.getScaleX(), inv));
- fMatrix22Scalar.setSkewX(-SkScalarMul(m.getSkewX(), inv));
- fMatrix22Scalar.setSkewY(-SkScalarMul(m.getSkewY(), inv));
- fMatrix22Scalar.setScaleY(SkScalarMul(m.getScaleY(), inv));
- } else {
- fMatrix22.xx = fMatrix22.yy = SK_Fixed1;
- fMatrix22.xy = fMatrix22.yx = 0;
+ // In GDI, the hinter is aware of the current transformation
+ // (the transform is in some sense applied before/with the hinting).
+ // The bytecode can then test if it is rotated or stretched and decide
+ // to apply instructions or not.
+ //
+ // FreeType, however, always does the transformation strictly after hinting.
+ // It just sets 'rotated' and 'stretched' to false and only applies the
+ // size before hinting.
+ //
+ // Also, FreeType respects the head::flags::IntegerScaling flag,
+ // (although this is patched out on most major distros)
+ // so it is critical to get the size correct on the request.
+ //
+ // This also gets us the actual closest size on bitmap fonts as well.
+ if (A.getSkewX() || A.getSkewY() || sx < 0 || sy < 0) {
+ // h is where A maps the horizontal baseline.
+ SkPoint h = SkPoint::Make(SK_Scalar1, 0);
+ A.mapPoints(&h, 1);
+
+ // G is the Givens Matrix for A (rotational matrix where GA[0][1] == 0).
+ SkMatrix G;
+ SkComputeGivensRotation(h, &G);
+
+ // GA is the matrix A with rotation removed.
+ SkMatrix GA(G);
+ GA.preConcat(A);
+
+ sx = SkScalarAbs(GA.get(SkMatrix::kMScaleX));
+ sy = SkScalarAbs(GA.get(SkMatrix::kMScaleY));
+
+ // sA is the total matrix A without the text scale.
+ SkMatrix sA(A);
+ sA.preScale(SkScalarInvert(sx), SkScalarInvert(sy)); //remove text size
+
+ fMatrix22Scalar.setScaleX(sA.getScaleX());
+ fMatrix22Scalar.setSkewX(-sA.getSkewX());
+ fMatrix22Scalar.setSkewY(-sA.getSkewY());
+ fMatrix22Scalar.setScaleY(sA.getScaleY());
}
fScale.set(sx, sy);
fScaleX = SkScalarToFixed(sx);
fScaleY = SkScalarToFixed(sy);
+ fMatrix22.xx = SkScalarToFixed(fMatrix22Scalar.getScaleX());
+ fMatrix22.xy = SkScalarToFixed(fMatrix22Scalar.getSkewX());
+ fMatrix22.yx = SkScalarToFixed(fMatrix22Scalar.getSkewY());
+ fMatrix22.yy = SkScalarToFixed(fMatrix22Scalar.getScaleY());
fLCDIsVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag);
@@ -905,13 +952,12 @@ SkScalerContext_FreeType::SkScalerContext_FreeType(SkTypeface* typeface,
loadFlags = FT_LOAD_TARGET_LIGHT; // This implies FORCE_AUTOHINT
break;
case SkPaint::kNormal_Hinting:
- if (fRec.fFlags & SkScalerContext::kAutohinting_Flag)
+ if (fRec.fFlags & SkScalerContext::kForceAutohinting_Flag) {
loadFlags = FT_LOAD_FORCE_AUTOHINT;
- else
- loadFlags = FT_LOAD_NO_AUTOHINT;
+ }
break;
case SkPaint::kFull_Hinting:
- if (fRec.fFlags & SkScalerContext::kAutohinting_Flag) {
+ if (fRec.fFlags & SkScalerContext::kForceAutohinting_Flag) {
loadFlags = FT_LOAD_FORCE_AUTOHINT;
break;
}
@@ -1126,6 +1172,17 @@ void SkScalerContext_FreeType::getBBoxForCurrentGlyph(SkGlyph* glyph,
}
}
+bool SkScalerContext_FreeType::getCBoxForLetter(char letter, FT_BBox* bbox) {
+ const FT_UInt glyph_id = FT_Get_Char_Index(fFace, letter);
+ if (!glyph_id)
+ return false;
+ if (FT_Load_Glyph(fFace, glyph_id, fLoadGlyphFlags) != 0)
+ return false;
+ emboldenIfNeeded(fFace, fFace->glyph);
+ FT_Outline_Get_CBox(&fFace->glyph->outline, bbox);
+ return true;
+}
+
void SkScalerContext_FreeType::updateGlyphIfLCD(SkGlyph* glyph) {
if (isLCD(fRec)) {
if (fLCDIsVert) {
@@ -1171,6 +1228,7 @@ void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) {
glyph->zeroMetrics();
return;
}
+ emboldenIfNeeded(fFace, fFace->glyph);
switch ( fFace->glyph->format ) {
case FT_GLYPH_FORMAT_OUTLINE:
@@ -1180,10 +1238,6 @@ void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) {
glyph->fTop = 0;
glyph->fLeft = 0;
} else {
- if (fRec.fFlags & kEmbolden_Flag && !(fFace->style_flags & FT_STYLE_FLAG_BOLD)) {
- emboldenOutline(fFace, &fFace->glyph->outline);
- }
-
FT_BBox bbox;
getBBoxForCurrentGlyph(glyph, &bbox, true);
@@ -1197,11 +1251,6 @@ void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) {
break;
case FT_GLYPH_FORMAT_BITMAP:
- if (fRec.fFlags & kEmbolden_Flag) {
- FT_GlyphSlot_Own_Bitmap(fFace->glyph);
- FT_Bitmap_Embolden(gFTLibrary, &fFace->glyph->bitmap, kBitmapEmboldenStrength, 0);
- }
-
if (fRec.fFlags & SkScalerContext::kVertical_Flag) {
FT_Vector vector;
vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX;
@@ -1280,6 +1329,7 @@ void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) {
return;
}
+ emboldenIfNeeded(fFace, fFace->glyph);
generateGlyphImage(fFace, glyph);
}
@@ -1307,6 +1357,7 @@ void SkScalerContext_FreeType::generatePath(const SkGlyph& glyph,
path->reset();
return;
}
+ emboldenIfNeeded(fFace, fFace->glyph);
generateGlyphPath(fFace, path);
@@ -1358,14 +1409,19 @@ void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* mx,
// use the os/2 table as a source of reasonable defaults.
SkScalar x_height = 0.0f;
SkScalar avgCharWidth = 0.0f;
+ SkScalar cap_height = 0.0f;
TT_OS2* os2 = (TT_OS2*) FT_Get_Sfnt_Table(face, ft_sfnt_os2);
if (os2) {
x_height = scaleX * SkIntToScalar(os2->sxHeight) / upem;
avgCharWidth = SkIntToScalar(os2->xAvgCharWidth) / upem;
+ if (os2->version != 0xFFFF && os2->version >= 2) {
+ cap_height = scaleX * SkIntToScalar(os2->sCapHeight) / upem;
+ }
}
// pull from format-specific metrics as needed
SkScalar ascent, descent, leading, xmin, xmax, ymin, ymax;
+ SkScalar underlineThickness, underlinePosition;
if (face->face_flags & FT_FACE_FLAG_SCALABLE) { // scalable outline font
ascent = -SkIntToScalar(face->ascender) / upem;
descent = -SkIntToScalar(face->descender) / upem;
@@ -1374,19 +1430,31 @@ void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* mx,
xmax = SkIntToScalar(face->bbox.xMax) / upem;
ymin = -SkIntToScalar(face->bbox.yMin) / upem;
ymax = -SkIntToScalar(face->bbox.yMax) / upem;
- // we may be able to synthesize x_height from outline
+ underlineThickness = SkIntToScalar(face->underline_thickness) / upem;
+ underlinePosition = -SkIntToScalar(face->underline_position +
+ face->underline_thickness / 2) / upem;
+
+ if(mx) {
+ mx->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
+ mx->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
+ }
+ if(my){
+ my->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
+ my->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
+ }
+ // we may be able to synthesize x_height and cap_height from outline
if (!x_height) {
- const FT_UInt x_glyph = FT_Get_Char_Index(fFace, 'x');
- if (x_glyph) {
- FT_BBox bbox;
- FT_Load_Glyph(fFace, x_glyph, fLoadGlyphFlags);
- if ((fRec.fFlags & kEmbolden_Flag) && !(fFace->style_flags & FT_STYLE_FLAG_BOLD)) {
- emboldenOutline(fFace, &fFace->glyph->outline);
- }
- FT_Outline_Get_CBox(&fFace->glyph->outline, &bbox);
+ FT_BBox bbox;
+ if (getCBoxForLetter('x', &bbox)) {
x_height = SkIntToScalar(bbox.yMax) / 64.0f;
}
}
+ if (!cap_height) {
+ FT_BBox bbox;
+ if (getCBoxForLetter('H', &bbox)) {
+ cap_height = SkIntToScalar(bbox.yMax) / 64.0f;
+ }
+ }
} else if (fStrikeIndex != -1) { // bitmap strike metrics
SkScalar xppem = SkIntToScalar(face->size->metrics.x_ppem);
SkScalar yppem = SkIntToScalar(face->size->metrics.y_ppem);
@@ -1398,11 +1466,16 @@ void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* mx,
xmax = SkIntToScalar(face->available_sizes[fStrikeIndex].width) / xppem;
ymin = descent + leading;
ymax = ascent - descent;
- if (!x_height) {
- x_height = -ascent;
+ underlineThickness = 0;
+ underlinePosition = 0;
+
+ if(mx) {
+ mx->fFlags &= ~SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
+ mx->fFlags &= ~SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
}
- if (!avgCharWidth) {
- avgCharWidth = xmax - xmin;
+ if(my){
+ my->fFlags &= ~SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
+ my->fFlags &= ~SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
}
} else {
goto ERROR;
@@ -1415,6 +1488,9 @@ void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* mx,
if (!avgCharWidth) {
avgCharWidth = xmax - xmin;
}
+ if (!cap_height) {
+ cap_height = -ascent;
+ }
// disallow negative linespacing
if (leading < 0.0f) {
@@ -1431,6 +1507,9 @@ void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* mx,
mx->fXMin = xmin;
mx->fXMax = xmax;
mx->fXHeight = x_height;
+ mx->fCapHeight = cap_height;
+ mx->fUnderlineThickness = underlineThickness * mxy;
+ mx->fUnderlinePosition = underlinePosition * mxy;
}
if (my) {
my->fTop = ymax * myy;
@@ -1442,6 +1521,38 @@ void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* mx,
my->fXMin = xmin;
my->fXMax = xmax;
my->fXHeight = x_height;
+ my->fCapHeight = cap_height;
+ my->fUnderlineThickness = underlineThickness * myy;
+ my->fUnderlinePosition = underlinePosition * myy;
+ }
+}
+
+void SkScalerContext_FreeType::emboldenIfNeeded(FT_Face face, FT_GlyphSlot glyph)
+{
+ // check to see if the embolden bit is set
+ if (0 == (fRec.fFlags & SkScalerContext::kEmbolden_Flag)) {
+ return;
+ }
+
+#if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK)
+ // Android doesn't want to embolden a font that is already bold.
+ if ((fFace->style_flags & FT_STYLE_FLAG_BOLD)) {
+ return;
+ }
+#endif
+
+ switch (glyph->format) {
+ case FT_GLYPH_FORMAT_OUTLINE:
+ FT_Pos strength;
+ strength = FT_MulFix(face->units_per_EM, face->size->metrics.y_scale) / 24;
+ FT_Outline_Embolden(&glyph->outline, strength);
+ break;
+ case FT_GLYPH_FORMAT_BITMAP:
+ FT_GlyphSlot_Own_Bitmap(glyph);
+ FT_Bitmap_Embolden(glyph->library, &glyph->bitmap, kBitmapEmboldenStrength, 0);
+ break;
+ default:
+ SkDEBUGFAIL("unknown glyph format");
}
}
diff --git a/chromium/third_party/skia/src/ports/SkFontHost_FreeType_common.cpp b/chromium/third_party/skia/src/ports/SkFontHost_FreeType_common.cpp
index 065a83a41c2..b27ae96fff2 100644
--- a/chromium/third_party/skia/src/ports/SkFontHost_FreeType_common.cpp
+++ b/chromium/third_party/skia/src/ports/SkFontHost_FreeType_common.cpp
@@ -295,11 +295,11 @@ static void packA8ToA1(const SkMask& mask, const uint8_t* src, size_t srcRB) {
}
}
-inline SkMask::Format SkMaskFormat_for_SkBitmapConfig(SkBitmap::Config config) {
- switch (config) {
- case SkBitmap::kA8_Config:
+inline SkMask::Format SkMaskFormat_for_SkColorType(SkColorType colorType) {
+ switch (colorType) {
+ case kAlpha_8_SkColorType:
return SkMask::kA8_Format;
- case SkBitmap::kARGB_8888_Config:
+ case kN32_SkColorType:
return SkMask::kARGB32_Format;
default:
SkDEBUGFAIL("unsupported SkBitmap::Config");
@@ -307,30 +307,30 @@ inline SkMask::Format SkMaskFormat_for_SkBitmapConfig(SkBitmap::Config config) {
}
}
-inline SkBitmap::Config SkBitmapConfig_for_FTPixelMode(FT_Pixel_Mode pixel_mode) {
+inline SkColorType SkColorType_for_FTPixelMode(FT_Pixel_Mode pixel_mode) {
switch (pixel_mode) {
case FT_PIXEL_MODE_MONO:
case FT_PIXEL_MODE_GRAY:
- return SkBitmap::kA8_Config;
+ return kAlpha_8_SkColorType;
case FT_PIXEL_MODE_BGRA:
- return SkBitmap::kARGB_8888_Config;
+ return kN32_SkColorType;
default:
SkDEBUGFAIL("unsupported FT_PIXEL_MODE");
- return SkBitmap::kA8_Config;
+ return kAlpha_8_SkColorType;
}
}
-inline SkBitmap::Config SkBitmapConfig_for_SkMaskFormat(SkMask::Format format) {
+inline SkColorType SkColorType_for_SkMaskFormat(SkMask::Format format) {
switch (format) {
case SkMask::kBW_Format:
case SkMask::kA8_Format:
case SkMask::kLCD16_Format:
- return SkBitmap::kA8_Config;
+ return kAlpha_8_SkColorType;
case SkMask::kARGB32_Format:
- return SkBitmap::kARGB_8888_Config;
+ return kN32_SkColorType;
default:
SkDEBUGFAIL("unsupported destination SkBitmap::Config");
- return SkBitmap::kA8_Config;
+ return kAlpha_8_SkColorType;
}
}
@@ -344,11 +344,6 @@ void SkScalerContext_FreeType_Base::generateGlyphImage(FT_Face face, const SkGly
FT_BBox bbox;
FT_Bitmap target;
- if (fRec.fFlags & SkScalerContext::kEmbolden_Flag &&
- !(face->style_flags & FT_STYLE_FLAG_BOLD)) {
- emboldenOutline(face, outline);
- }
-
int dx = 0, dy = 0;
if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) {
dx = SkFixedToFDot6(glyph.getSubXFixed());
@@ -431,15 +426,16 @@ void SkScalerContext_FreeType_Base::generateGlyphImage(FT_Face face, const SkGly
// Copy the FT_Bitmap into an SkBitmap (either A8 or ARGB)
SkBitmap unscaledBitmap;
- unscaledBitmap.setConfig(SkBitmapConfig_for_FTPixelMode(pixel_mode),
- face->glyph->bitmap.width, face->glyph->bitmap.rows);
- unscaledBitmap.allocPixels();
+ unscaledBitmap.allocPixels(SkImageInfo::Make(face->glyph->bitmap.width,
+ face->glyph->bitmap.rows,
+ SkColorType_for_FTPixelMode(pixel_mode),
+ kPremul_SkAlphaType));
SkMask unscaledBitmapAlias;
unscaledBitmapAlias.fImage = reinterpret_cast<uint8_t*>(unscaledBitmap.getPixels());
unscaledBitmapAlias.fBounds.set(0, 0, unscaledBitmap.width(), unscaledBitmap.height());
unscaledBitmapAlias.fRowBytes = unscaledBitmap.rowBytes();
- unscaledBitmapAlias.fFormat = SkMaskFormat_for_SkBitmapConfig(unscaledBitmap.config());
+ unscaledBitmapAlias.fFormat = SkMaskFormat_for_SkColorType(unscaledBitmap.colorType());
copyFTBitmap(face->glyph->bitmap, unscaledBitmapAlias);
// Wrap the glyph's mask in a bitmap, unless the glyph's mask is BW or LCD.
@@ -451,8 +447,10 @@ void SkScalerContext_FreeType_Base::generateGlyphImage(FT_Face face, const SkGly
bitmapRowBytes = glyph.rowBytes();
}
SkBitmap dstBitmap;
- dstBitmap.setConfig(SkBitmapConfig_for_SkMaskFormat(maskFormat),
- glyph.fWidth, glyph.fHeight, bitmapRowBytes);
+ dstBitmap.setInfo(SkImageInfo::Make(glyph.fWidth, glyph.fHeight,
+ SkColorType_for_SkMaskFormat(maskFormat),
+ kPremul_SkAlphaType),
+ bitmapRowBytes);
if (SkMask::kBW_Format == maskFormat || SkMask::kLCD16_Format == maskFormat) {
dstBitmap.allocPixels();
} else {
@@ -547,10 +545,6 @@ static int cubic_proc(const FT_Vector* pt0, const FT_Vector* pt1,
void SkScalerContext_FreeType_Base::generateGlyphPath(FT_Face face,
SkPath* path)
{
- if (fRec.fFlags & SkScalerContext::kEmbolden_Flag) {
- emboldenOutline(face, &face->glyph->outline);
- }
-
FT_Outline_Funcs funcs;
funcs.move_to = move_proc;
@@ -569,11 +563,3 @@ void SkScalerContext_FreeType_Base::generateGlyphPath(FT_Face face,
path->close();
}
-
-void SkScalerContext_FreeType_Base::emboldenOutline(FT_Face face, FT_Outline* outline)
-{
- FT_Pos strength;
- strength = FT_MulFix(face->units_per_EM, face->size->metrics.y_scale)
- / 24;
- FT_Outline_Embolden(outline, strength);
-}
diff --git a/chromium/third_party/skia/src/ports/SkFontHost_FreeType_common.h b/chromium/third_party/skia/src/ports/SkFontHost_FreeType_common.h
index 0021dfdd802..aef4d82044b 100644
--- a/chromium/third_party/skia/src/ports/SkFontHost_FreeType_common.h
+++ b/chromium/third_party/skia/src/ports/SkFontHost_FreeType_common.h
@@ -39,7 +39,6 @@ protected:
void generateGlyphImage(FT_Face face, const SkGlyph& glyph);
void generateGlyphPath(FT_Face face, SkPath* path);
- void emboldenOutline(FT_Face face, FT_Outline* outline);
private:
typedef SkScalerContext INHERITED;
diff --git a/chromium/third_party/skia/src/ports/SkFontHost_fontconfig.cpp b/chromium/third_party/skia/src/ports/SkFontHost_fontconfig.cpp
index 3700ed1e97d..07bfbd044cb 100644
--- a/chromium/third_party/skia/src/ports/SkFontHost_fontconfig.cpp
+++ b/chromium/third_party/skia/src/ports/SkFontHost_fontconfig.cpp
@@ -118,7 +118,7 @@ SkTypeface* FontConfigTypeface::LegacyCreateTypeface(
return face;
}
- face = SkNEW_ARGS(FontConfigTypeface, (outStyle, indentity, outFamilyName));
+ face = FontConfigTypeface::Create(outStyle, indentity, outFamilyName);
SkTypefaceCache::Add(face, style);
// SkDebugf("add face <%s> <%s> %p [%d]\n", familyName, outFamilyName.c_str(), face, face->getRefCnt());
return face;
diff --git a/chromium/third_party/skia/src/ports/SkFontHost_linux.cpp b/chromium/third_party/skia/src/ports/SkFontHost_linux.cpp
index 9eabac31c6a..d6a020067be 100644
--- a/chromium/third_party/skia/src/ports/SkFontHost_linux.cpp
+++ b/chromium/third_party/skia/src/ports/SkFontHost_linux.cpp
@@ -24,9 +24,6 @@
#ifndef SK_FONT_FILE_PREFIX
# define SK_FONT_FILE_PREFIX "/usr/share/fonts/truetype/"
#endif
-#ifndef SK_FONT_FILE_DIR_SEPERATOR
-# define SK_FONT_FILE_DIR_SEPERATOR "/"
-#endif
bool find_name_and_attributes(SkStream* stream, SkString* name,
SkTypeface::Style* style, bool* isFixedPitch);
@@ -89,7 +86,7 @@ public:
protected:
virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
*ttcIndex = 0;
- return SkRef(fStream.get());
+ return fStream->duplicate();
}
private:
@@ -215,21 +212,21 @@ public:
}
protected:
- virtual int onCountFamilies() SK_OVERRIDE {
+ virtual int onCountFamilies() const SK_OVERRIDE {
return fFamilies.count();
}
- virtual void onGetFamilyName(int index, SkString* familyName) SK_OVERRIDE {
+ virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE {
SkASSERT(index < fFamilies.count());
familyName->set(fFamilies[index]->fFamilyName);
}
- virtual SkFontStyleSet_Custom* onCreateStyleSet(int index) SK_OVERRIDE {
+ virtual SkFontStyleSet_Custom* onCreateStyleSet(int index) const SK_OVERRIDE {
SkASSERT(index < fFamilies.count());
return SkRef(fFamilies[index].get());
}
- virtual SkFontStyleSet_Custom* onMatchFamily(const char familyName[]) SK_OVERRIDE {
+ virtual SkFontStyleSet_Custom* onMatchFamily(const char familyName[]) const SK_OVERRIDE {
for (int i = 0; i < fFamilies.count(); ++i) {
if (fFamilies[i]->fFamilyName.equals(familyName)) {
return SkRef(fFamilies[i].get());
@@ -239,14 +236,14 @@ protected:
}
virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
- const SkFontStyle& fontStyle) SK_OVERRIDE
+ const SkFontStyle& fontStyle) const SK_OVERRIDE
{
SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
return sset->matchStyle(fontStyle);
}
virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
- const SkFontStyle& fontStyle) SK_OVERRIDE
+ const SkFontStyle& fontStyle) const SK_OVERRIDE
{
for (int i = 0; i < fFamilies.count(); ++i) {
for (int j = 0; j < fFamilies[i]->fStyles.count(); ++j) {
@@ -258,12 +255,12 @@ protected:
return NULL;
}
- virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) SK_OVERRIDE {
+ virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE {
SkAutoTUnref<SkStream> stream(new SkMemoryStream(data));
return this->createFromStream(stream, ttcIndex);
}
- virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) SK_OVERRIDE {
+ virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE {
if (NULL == stream || stream->getLength() <= 0) {
SkDELETE(stream);
return NULL;
@@ -279,13 +276,13 @@ protected:
}
}
- virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) SK_OVERRIDE {
+ virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE {
SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL;
}
virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
- unsigned styleBits) SK_OVERRIDE
+ unsigned styleBits) const SK_OVERRIDE
{
SkTypeface::Style oldStyle = (SkTypeface::Style)styleBits;
SkFontStyle style = SkFontStyle(oldStyle & SkTypeface::kBold
@@ -326,8 +323,8 @@ private:
SkString name;
while (iter.next(&name, false)) {
- SkString filename(directory);
- filename.append(name);
+ SkString filename(
+ SkOSPath::SkPathJoin(directory.c_str(), name.c_str()));
bool isFixedPitch;
SkString realname;
@@ -358,9 +355,8 @@ private:
if (name.startsWith(".")) {
continue;
}
- SkString dirname(directory);
- dirname.append(name);
- dirname.append(SK_FONT_FILE_DIR_SEPERATOR);
+ SkString dirname(
+ SkOSPath::SkPathJoin(directory.c_str(), name.c_str()));
load_directory_fonts(dirname);
}
}
@@ -377,7 +373,7 @@ private:
// Try to pick a default font.
static const char* gDefaultNames[] = {
- "Arial", "Verdana", "Times New Roman", NULL
+ "Arial", "Verdana", "Times New Roman", "Droid Sans", NULL
};
for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) {
SkFontStyleSet_Custom* set = this->onMatchFamily(gDefaultNames[i]);
diff --git a/chromium/third_party/skia/src/ports/SkFontHost_mac.cpp b/chromium/third_party/skia/src/ports/SkFontHost_mac.cpp
index fe3fd069817..e00b87b59b4 100755
--- a/chromium/third_party/skia/src/ports/SkFontHost_mac.cpp
+++ b/chromium/third_party/skia/src/ports/SkFontHost_mac.cpp
@@ -149,7 +149,7 @@ static CGFloat CGRectGetWidth_inline(const CGRect& rect) {
///////////////////////////////////////////////////////////////////////////////
static void sk_memset_rect32(uint32_t* ptr, uint32_t value,
- size_t width, size_t height, size_t rowBytes) {
+ int width, int height, size_t rowBytes) {
SkASSERT(width);
SkASSERT(width * sizeof(uint32_t) <= rowBytes);
@@ -1379,6 +1379,11 @@ void SkScalerContext_Mac::generateFontMetrics(SkPaint::FontMetrics* mx,
theMetrics.fXMin = CGToScalar( CGRectGetMinX_inline(theBounds));
theMetrics.fXMax = CGToScalar( CGRectGetMaxX_inline(theBounds));
theMetrics.fXHeight = CGToScalar( CTFontGetXHeight(fCTFont));
+ theMetrics.fUnderlineThickness = CGToScalar( CTFontGetUnderlineThickness(fCTFont));
+ theMetrics.fUnderlinePosition = -CGToScalar( CTFontGetUnderlinePosition(fCTFont));
+
+ theMetrics.fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
+ theMetrics.fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
if (mx != NULL) {
*mx = theMetrics;
@@ -1441,7 +1446,7 @@ static SkTypeface* create_from_dataProvider(CGDataProviderRef provider) {
// so the performance impact isn't too bad.
static void populate_glyph_to_unicode_slow(CTFontRef ctFont, CFIndex glyphCount,
SkTDArray<SkUnichar>* glyphToUnicode) {
- glyphToUnicode->setCount(glyphCount);
+ glyphToUnicode->setCount(SkToInt(glyphCount));
SkUnichar* out = glyphToUnicode->begin();
sk_bzero(out, glyphCount * sizeof(SkUnichar));
UniChar unichar = 0;
@@ -1485,7 +1490,7 @@ static void populate_glyph_to_unicode(CTFontRef ctFont, CFIndex glyphCount,
length = 8192;
}
const UInt8* bits = CFDataGetBytePtr(bitmap);
- glyphToUnicode->setCount(glyphCount);
+ glyphToUnicode->setCount(SkToInt(glyphCount));
SkUnichar* out = glyphToUnicode->begin();
sk_bzero(out, glyphCount * sizeof(SkUnichar));
for (int i = 0; i < length; i++) {
@@ -1539,17 +1544,16 @@ SkAdvancedTypefaceMetrics* SkTypeface_Mac::onGetAdvancedTypefaceMetrics(
CFStringToSkString(fontName, &info->fFontName);
}
- info->fMultiMaster = false;
CFIndex glyphCount = CTFontGetGlyphCount(ctFont);
info->fLastGlyphID = SkToU16(glyphCount - 1);
info->fEmSize = CTFontGetUnitsPerEm(ctFont);
+ info->fFlags = SkAdvancedTypefaceMetrics::kEmpty_FontFlag;
+ info->fStyle = 0;
if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) {
populate_glyph_to_unicode(ctFont, glyphCount, &info->fGlyphToUnicode);
}
- info->fStyle = 0;
-
// If it's not a truetype font, mark it as 'other'. Assume that TrueType
// fonts always have both glyf and loca tables. At the least, this is what
// sfntly needs to subset the font. CTFontCopyAttribute() does not always
@@ -1613,10 +1617,7 @@ SkAdvancedTypefaceMetrics* SkTypeface_Mac::onGetAdvancedTypefaceMetrics(
}
}
- if (false) { // TODO: haven't figured out how to know if font is embeddable
- // (information is in the OS/2 table)
- info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
- } else if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) {
+ if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) {
if (info->fStyle & SkAdvancedTypefaceMetrics::kFixedPitch_Style) {
skia_advanced_typeface_metrics_utils::appendRange(&info->fGlyphWidths, 0);
info->fGlyphWidths->fAdvance.append(1, &min_width);
@@ -1625,7 +1626,7 @@ SkAdvancedTypefaceMetrics* SkTypeface_Mac::onGetAdvancedTypefaceMetrics(
} else {
info->fGlyphWidths.reset(
skia_advanced_typeface_metrics_utils::getAdvanceData(ctFont.get(),
- glyphCount,
+ SkToInt(glyphCount),
glyphIDs,
glyphIDsCount,
&getWidthAdvance));
@@ -1724,8 +1725,8 @@ SkStream* SkTypeface_Mac::onOpenStream(int* ttcIndex) const {
entry->tag = SkEndian_SwapBE32(tableTags[tableIndex]);
entry->checksum = SkEndian_SwapBE32(SkOTUtils::CalcTableChecksum((SK_OT_ULONG*)dataPtr,
tableSize));
- entry->offset = SkEndian_SwapBE32(dataPtr - dataStart);
- entry->logicalLength = SkEndian_SwapBE32(tableSize);
+ entry->offset = SkEndian_SwapBE32(SkToU32(dataPtr - dataStart));
+ entry->logicalLength = SkEndian_SwapBE32(SkToU32(tableSize));
dataPtr += (tableSize + 3) & ~3;
++entry;
@@ -1785,7 +1786,7 @@ int SkTypeface_Mac::onGetTableTags(SkFontTableTag tags[]) const {
if (NULL == cfArray) {
return 0;
}
- int count = CFArrayGetCount(cfArray);
+ int count = SkToInt(CFArrayGetCount(cfArray));
if (tags) {
for (int i = 0; i < count; ++i) {
uintptr_t fontTag = reinterpret_cast<uintptr_t>(CFArrayGetValueAtIndex(cfArray, i));
@@ -1832,7 +1833,7 @@ void SkTypeface_Mac::onFilterRec(SkScalerContextRec* rec) const {
}
unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag |
- SkScalerContext::kAutohinting_Flag |
+ SkScalerContext::kForceAutohinting_Flag |
SkScalerContext::kLCD_BGROrder_Flag |
SkScalerContext::kLCD_Vertical_Flag;
@@ -1930,7 +1931,7 @@ int SkTypeface_Mac::onCharsToGlyphs(const void* chars, Encoding encoding,
SkUnichar uni = SkUTF8_NextUnichar(&utf8);
utf16 += SkUTF16_FromUnichar(uni, utf16);
}
- srcCount = utf16 - src;
+ srcCount = SkToInt(utf16 - src);
break;
}
case kUTF16_Encoding: {
@@ -1951,7 +1952,7 @@ int SkTypeface_Mac::onCharsToGlyphs(const void* chars, Encoding encoding,
for (int i = 0; i < glyphCount; ++i) {
utf16 += SkUTF16_FromUnichar(utf32[i], utf16);
}
- srcCount = utf16 - src;
+ srcCount = SkToInt(utf16 - src);
break;
}
}
@@ -1999,7 +2000,7 @@ int SkTypeface_Mac::onCharsToGlyphs(const void* chars, Encoding encoding,
}
int SkTypeface_Mac::onCountGlyphs() const {
- return CTFontGetGlyphCount(fFontRef);
+ return SkToInt(CTFontGetGlyphCount(fFontRef));
}
///////////////////////////////////////////////////////////////////////////////
@@ -2142,7 +2143,7 @@ public:
if (NULL == fArray) {
fArray = CFArrayCreate(NULL, NULL, 0, NULL);
}
- fCount = CFArrayGetCount(fArray);
+ fCount = SkToInt(CFArrayGetCount(fArray));
}
virtual ~SkFontStyleSet_Mac() {
@@ -2208,21 +2209,14 @@ private:
};
class SkFontMgr_Mac : public SkFontMgr {
- int fCount;
CFArrayRef fNames;
+ int fCount;
CFStringRef stringAt(int index) const {
SkASSERT((unsigned)index < (unsigned)fCount);
return (CFStringRef)CFArrayGetValueAtIndex(fNames, index);
}
- void lazyInit() {
- if (NULL == fNames) {
- fNames = SkCTFontManagerCopyAvailableFontFamilyNames();
- fCount = fNames ? CFArrayGetCount(fNames) : 0;
- }
- }
-
static SkFontStyleSet* CreateSet(CFStringRef cfFamilyName) {
AutoCFRelease<CFMutableDictionaryRef> cfAttr(
CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
@@ -2237,20 +2231,20 @@ class SkFontMgr_Mac : public SkFontMgr {
}
public:
- SkFontMgr_Mac() : fCount(0), fNames(NULL) {}
+ SkFontMgr_Mac()
+ : fNames(SkCTFontManagerCopyAvailableFontFamilyNames())
+ , fCount(fNames ? SkToInt(CFArrayGetCount(fNames)) : 0) {}
virtual ~SkFontMgr_Mac() {
CFSafeRelease(fNames);
}
protected:
- virtual int onCountFamilies() SK_OVERRIDE {
- this->lazyInit();
+ virtual int onCountFamilies() const SK_OVERRIDE {
return fCount;
}
- virtual void onGetFamilyName(int index, SkString* familyName) SK_OVERRIDE {
- this->lazyInit();
+ virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE {
if ((unsigned)index < (unsigned)fCount) {
CFStringToSkString(this->stringAt(index), familyName);
} else {
@@ -2258,31 +2252,30 @@ protected:
}
}
- virtual SkFontStyleSet* onCreateStyleSet(int index) SK_OVERRIDE {
- this->lazyInit();
+ virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE {
if ((unsigned)index >= (unsigned)fCount) {
return NULL;
}
return CreateSet(this->stringAt(index));
}
- virtual SkFontStyleSet* onMatchFamily(const char familyName[]) SK_OVERRIDE {
+ virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE {
AutoCFRelease<CFStringRef> cfName(make_CFString(familyName));
return CreateSet(cfName);
}
virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
- const SkFontStyle&) SK_OVERRIDE {
+ const SkFontStyle&) const SK_OVERRIDE {
return NULL;
}
virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
- const SkFontStyle&) SK_OVERRIDE {
+ const SkFontStyle&) const SK_OVERRIDE {
return NULL;
}
virtual SkTypeface* onCreateFromData(SkData* data,
- int ttcIndex) SK_OVERRIDE {
+ int ttcIndex) const SK_OVERRIDE {
AutoCFRelease<CGDataProviderRef> pr(SkCreateDataProviderFromData(data));
if (NULL == pr) {
return NULL;
@@ -2291,7 +2284,7 @@ protected:
}
virtual SkTypeface* onCreateFromStream(SkStream* stream,
- int ttcIndex) SK_OVERRIDE {
+ int ttcIndex) const SK_OVERRIDE {
AutoCFRelease<CGDataProviderRef> pr(SkCreateDataProviderFromStream(stream));
if (NULL == pr) {
return NULL;
@@ -2300,7 +2293,7 @@ protected:
}
virtual SkTypeface* onCreateFromFile(const char path[],
- int ttcIndex) SK_OVERRIDE {
+ int ttcIndex) const SK_OVERRIDE {
AutoCFRelease<CGDataProviderRef> pr(CGDataProviderCreateWithFilename(path));
if (NULL == pr) {
return NULL;
@@ -2309,7 +2302,7 @@ protected:
}
virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
- unsigned styleBits) SK_OVERRIDE {
+ unsigned styleBits) const SK_OVERRIDE {
return create_typeface(NULL, familyName, (SkTypeface::Style)styleBits);
}
};
diff --git a/chromium/third_party/skia/src/ports/SkFontHost_sandbox_none.cpp b/chromium/third_party/skia/src/ports/SkFontHost_sandbox_none.cpp
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/chromium/third_party/skia/src/ports/SkFontHost_sandbox_none.cpp
+++ /dev/null
diff --git a/chromium/third_party/skia/src/ports/SkFontHost_win.cpp b/chromium/third_party/skia/src/ports/SkFontHost_win.cpp
index aee2b863e64..5a902148bd5 100755
--- a/chromium/third_party/skia/src/ports/SkFontHost_win.cpp
+++ b/chromium/third_party/skia/src/ports/SkFontHost_win.cpp
@@ -16,6 +16,7 @@
#include "SkGlyph.h"
#include "SkHRESULT.h"
#include "SkMaskGamma.h"
+#include "SkMatrix22.h"
#include "SkOTTable_maxp.h"
#include "SkOTTable_name.h"
#include "SkOTUtils.h"
@@ -152,6 +153,10 @@ static inline FIXED SkScalarToFIXED(SkScalar x) {
return SkFixedToFIXED(SkScalarToFixed(x));
}
+static inline SkScalar SkFIXEDToScalar(FIXED x) {
+ return SkFixedToScalar(SkFIXEDToFixed(x));
+}
+
static unsigned calculateGlyphCount(HDC hdc, const LOGFONT& lf) {
TEXTMETRIC textMetric;
if (0 == GetTextMetrics(hdc, &textMetric)) {
@@ -280,15 +285,6 @@ protected:
class FontMemResourceTypeface : public LogFontTypeface {
public:
/**
- * Takes ownership of fontMemResource.
- */
- FontMemResourceTypeface(SkTypeface::Style style, SkFontID fontID, const LOGFONT& lf, HANDLE fontMemResource) :
- LogFontTypeface(style, fontID, lf, true), fFontMemResource(fontMemResource) {
- }
-
- HANDLE fFontMemResource;
-
- /**
* The created FontMemResourceTypeface takes ownership of fontMemResource.
*/
static FontMemResourceTypeface* Create(const LOGFONT& lf, HANDLE fontMemResource) {
@@ -305,6 +301,15 @@ protected:
}
private:
+ /**
+ * Takes ownership of fontMemResource.
+ */
+ FontMemResourceTypeface(SkTypeface::Style style, SkFontID fontID, const LOGFONT& lf, HANDLE fontMemResource) :
+ LogFontTypeface(style, fontID, lf, true), fFontMemResource(fontMemResource) {
+ }
+
+ HANDLE fFontMemResource;
+
typedef LogFontTypeface INHERITED;
};
@@ -583,7 +588,7 @@ private:
*/
SkMatrix fG_inv;
enum Type {
- kTrueType_Type, kBitmap_Type,
+ kTrueType_Type, kBitmap_Type, kLine_Type
} fType;
TEXTMETRIC fTM;
};
@@ -632,41 +637,16 @@ SkScalerContext_GDI::SkScalerContext_GDI(SkTypeface* rawTypeface,
fRec.getSingleMatrix(&A);
A.mapPoints(&h, 1);
- // Find the Given's matrix [[c, -s],[s, c]] which rotates the baseline vector h
- // (where the baseline is mapped to) to the positive horizontal axis.
- const SkScalar& a = h.fX;
- const SkScalar& b = h.fY;
- SkScalar c, s;
- if (0 == b) {
- c = SkDoubleToScalar(_copysign(SK_Scalar1, a));
- s = 0;
- } else if (0 == a) {
- c = 0;
- s = SkDoubleToScalar(-_copysign(SK_Scalar1, b));
- } else if (SkScalarAbs(b) > SkScalarAbs(a)) {
- SkScalar t = a / b;
- SkScalar u = SkDoubleToScalar(_copysign(SkScalarSqrt(SK_Scalar1 + t*t), b));
- s = -1 / u;
- c = -s * t;
- } else {
- SkScalar t = b / a;
- SkScalar u = SkDoubleToScalar(_copysign(SkScalarSqrt(SK_Scalar1 + t*t), a));
- c = 1 / u;
- s = -c * t;
- }
-
- // G is the Given's Matrix for A (rotational matrix such that GA[0][1] == 0).
+ // G is the Givens Matrix for A (rotational matrix where GA[0][1] == 0).
SkMatrix G;
- G.setAll(c, -s, 0,
- s, c, 0,
- 0, 0, SkScalarToPersp(SK_Scalar1));
+ SkComputeGivensRotation(h, &G);
// GA is the matrix A with rotation removed.
SkMatrix GA(G);
GA.preConcat(A);
// realTextSize is the actual device size we want (as opposed to the size the user requested).
- // gdiTextSide is the size we request from GDI.
+ // gdiTextSize is the size we request from GDI.
// If the scale is negative, this means the matrix will do the flip anyway.
SkScalar realTextSize = SkScalarAbs(GA.get(SkMatrix::kMScaleY));
SkScalar gdiTextSize = SkScalarRoundToScalar(realTextSize);
@@ -717,21 +697,24 @@ SkScalerContext_GDI::SkScalerContext_GDI(SkTypeface* rawTypeface,
fTM.tmPitchAndFamily = TMPF_TRUETYPE;
}
}
- // Used a logfont on a memory context, should never get a device font.
- // Therefore all TMPF_DEVICE will be PostScript fonts.
-
- // If TMPF_VECTOR is set, one of TMPF_TRUETYPE or TMPF_DEVICE must be set,
- // otherwise we have a vector FON, which we don't support.
- // This was determined by testing with Type1 PFM/PFB and OpenTypeCFF OTF,
- // as well as looking at Wine bugs and sources.
- SkASSERT(!(fTM.tmPitchAndFamily & TMPF_VECTOR) ||
- (fTM.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_DEVICE)));
XFORM xform;
if (fTM.tmPitchAndFamily & TMPF_VECTOR) {
- // Truetype or PostScript.
- // Stroked FON also gets here (TMPF_VECTOR), but we don't handle it.
- fType = SkScalerContext_GDI::kTrueType_Type;
+ // Used a logfont on a memory context, should never get a device font.
+ // Therefore all TMPF_DEVICE will be PostScript fonts.
+
+ // If TMPF_VECTOR is set, one of TMPF_TRUETYPE or TMPF_DEVICE means that
+ // we have an outline font. Otherwise we have a vector FON, which is
+ // scalable, but not an outline font.
+ // This was determined by testing with Type1 PFM/PFB and
+ // OpenTypeCFF OTF, as well as looking at Wine bugs and sources.
+ if (fTM.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_DEVICE)) {
+ // Truetype or PostScript.
+ fType = SkScalerContext_GDI::kTrueType_Type;
+ } else {
+ // Stroked FON.
+ fType = SkScalerContext_GDI::kLine_Type;
+ }
// fPost2x2 is column-major, left handed (y down).
// XFORM 2x2 is row-major, left handed (y down).
@@ -833,8 +816,8 @@ uint16_t SkScalerContext_GDI::generateCharToGlyph(SkUnichar utf32) {
*
* When GGI_MARK_NONEXISTING_GLYPHS is not specified and a character does not map to a
* glyph, then the 'default character's glyph is returned instead. The 'default character'
- * is available in fTM.tmDefaultChar. FON fonts have adefault character, and there exists a
- * usDefaultChar in the 'OS/2' table, version 2 and later. If there is no
+ * is available in fTM.tmDefaultChar. FON fonts have a default character, and there exists
+ * a usDefaultChar in the 'OS/2' table, version 2 and later. If there is no
* 'default character' specified by the font, then often the first character found is used.
*
* When GGI_MARK_NONEXISTING_GLYPHS is specified and a character does not map to a glyph,
@@ -845,7 +828,11 @@ uint16_t SkScalerContext_GDI::generateCharToGlyph(SkUnichar utf32) {
DWORD result = GetGlyphIndicesW(fDDC, utf16, 1, &index, GGI_MARK_NONEXISTING_GLYPHS);
if (result == GDI_ERROR
|| 0xFFFF == index
- || (0x1F == index && fType == SkScalerContext_GDI::kBitmap_Type /*&& winVer < Vista */))
+ || (0x1F == index &&
+ (fType == SkScalerContext_GDI::kBitmap_Type ||
+ fType == SkScalerContext_GDI::kLine_Type)
+ /*&& winVer < Vista */)
+ )
{
index = 0;
}
@@ -885,7 +872,7 @@ void SkScalerContext_GDI::generateAdvance(SkGlyph* glyph) {
void SkScalerContext_GDI::generateMetrics(SkGlyph* glyph) {
SkASSERT(fDDC);
- if (fType == SkScalerContext_GDI::kBitmap_Type) {
+ if (fType == SkScalerContext_GDI::kBitmap_Type || fType == SkScalerContext_GDI::kLine_Type) {
SIZE size;
WORD glyphs = glyph->getGlyphID(0);
if (0 == GetTextExtentPointI(fDDC, &glyphs, 1, &size)) {
@@ -896,12 +883,30 @@ void SkScalerContext_GDI::generateMetrics(SkGlyph* glyph) {
glyph->fHeight = SkToS16(size.cy);
glyph->fTop = SkToS16(-fTM.tmAscent);
+ // Bitmap FON cannot underhang, but vector FON may.
+ // There appears no means of determining underhang of vector FON.
glyph->fLeft = SkToS16(0);
glyph->fAdvanceX = SkIntToFixed(glyph->fWidth);
glyph->fAdvanceY = 0;
+ // Vector FON will transform nicely, but bitmap FON do not.
+ if (fType == SkScalerContext_GDI::kLine_Type) {
+ SkRect bounds = SkRect::MakeXYWH(glyph->fLeft, glyph->fTop,
+ glyph->fWidth, glyph->fHeight);
+ SkMatrix m;
+ m.setAll(SkFIXEDToScalar(fMat22.eM11), -SkFIXEDToScalar(fMat22.eM21), 0,
+ -SkFIXEDToScalar(fMat22.eM12), SkFIXEDToScalar(fMat22.eM22), 0,
+ 0, 0, SkScalarToPersp(SK_Scalar1));
+ m.mapRect(&bounds);
+ bounds.roundOut();
+ glyph->fLeft = SkScalarTruncToInt(bounds.fLeft);
+ glyph->fTop = SkScalarTruncToInt(bounds.fTop);
+ glyph->fWidth = SkScalarTruncToInt(bounds.width());
+ glyph->fHeight = SkScalarTruncToInt(bounds.height());
+ }
+
// Apply matrix to advance.
- glyph->fAdvanceY = SkFixedMul(SkFIXEDToFixed(fMat22.eM21), glyph->fAdvanceX);
+ glyph->fAdvanceY = SkFixedMul(-SkFIXEDToFixed(fMat22.eM12), glyph->fAdvanceX);
glyph->fAdvanceX = SkFixedMul(SkFIXEDToFixed(fMat22.eM11), glyph->fAdvanceX);
return;
@@ -988,7 +993,7 @@ void SkScalerContext_GDI::generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint:
SkASSERT(fDDC);
#ifndef SK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS
- if (fType == SkScalerContext_GDI::kBitmap_Type) {
+ if (fType == SkScalerContext_GDI::kBitmap_Type || fType == SkScalerContext_GDI::kLine_Type) {
#endif
if (mx) {
mx->fTop = SkIntToScalar(-fTM.tmAscent);
@@ -1032,6 +1037,11 @@ void SkScalerContext_GDI::generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint:
mx->fDescent = SkIntToScalar(-otm.otmDescent);
mx->fBottom = SkIntToScalar(otm.otmrcFontBox.right);
mx->fLeading = SkIntToScalar(otm.otmLineGap);
+ mx->fUnderlineThickness = SkIntToScalar(otm.otmsUnderscoreSize);
+ mx->fUnderlinePosition = -SkIntToScalar(otm.otmsUnderscorePosition);
+
+ mx->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
+ mx->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
}
if (my) {
@@ -1046,6 +1056,12 @@ void SkScalerContext_GDI::generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint:
my->fXMin = SkIntToScalar(otm.otmrcFontBox.left);
my->fXMax = SkIntToScalar(otm.otmrcFontBox.right);
#endif
+ my->fUnderlineThickness = SkIntToScalar(otm.otmsUnderscoreSize);
+ my->fUnderlinePosition = -SkIntToScalar(otm.otmsUnderscorePosition);
+
+ my->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
+ my->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
+
my->fXHeight = SkIntToScalar(otm.otmsXHeight);
GLYPHMETRICS gm;
@@ -1065,7 +1081,7 @@ static void build_power_table(uint8_t table[], float ee) {
for (int i = 0; i < 256; i++) {
float x = i / 255.f;
x = sk_float_pow(x, ee);
- int xx = SkScalarRound(x * 255);
+ int xx = SkScalarRoundToInt(x * 255);
table[i] = SkToU8(xx);
}
}
@@ -1851,10 +1867,18 @@ SkAdvancedTypefaceMetrics* LogFontTypeface::onGetAdvancedTypefaceMetrics(
info = new SkAdvancedTypefaceMetrics;
info->fEmSize = otm.otmEMSquare;
- info->fMultiMaster = false;
info->fLastGlyphID = SkToU16(glyphCount - 1);
info->fStyle = 0;
tchar_to_skstring(lf.lfFaceName, &info->fFontName);
+ info->fFlags = SkAdvancedTypefaceMetrics::kEmpty_FontFlag;
+ // If bit 1 is set, the font may not be embedded in a document.
+ // If bit 1 is clear, the font can be embedded.
+ // If bit 2 is set, the embedding is read-only.
+ if (otm.otmfsType & 0x1) {
+ info->fFlags = SkTBitOr<SkAdvancedTypefaceMetrics::FontFlags>(
+ info->fFlags,
+ SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag);
+ }
if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) {
populate_glyph_to_unicode(hdc, glyphCount, &(info->fGlyphToUnicode));
@@ -1915,13 +1939,7 @@ SkAdvancedTypefaceMetrics* LogFontTypeface::onGetAdvancedTypefaceMetrics(
}
}
- // If bit 1 is set, the font may not be embedded in a document.
- // If bit 1 is clear, the font can be embedded.
- // If bit 2 is set, the embedding is read-only.
- if (otm.otmfsType & 0x1) {
- info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
- } else if (perGlyphInfo &
- SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) {
+ if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) {
if (info->fStyle & SkAdvancedTypefaceMetrics::kFixedPitch_Style) {
appendRange(&info->fGlyphWidths, 0);
info->fGlyphWidths->fAdvance.append(1, &min_width);
@@ -2391,7 +2409,7 @@ void LogFontTypeface::onFilterRec(SkScalerContextRec* rec) const {
}
unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag |
- SkScalerContext::kAutohinting_Flag |
+ SkScalerContext::kForceAutohinting_Flag |
SkScalerContext::kEmbeddedBitmapText_Flag |
SkScalerContext::kEmbolden_Flag |
SkScalerContext::kLCD_BGROrder_Flag |
@@ -2532,21 +2550,21 @@ public:
}
protected:
- virtual int onCountFamilies() SK_OVERRIDE {
+ virtual int onCountFamilies() const SK_OVERRIDE {
return fLogFontArray.count();
}
- virtual void onGetFamilyName(int index, SkString* familyName) SK_OVERRIDE {
+ virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE {
SkASSERT((unsigned)index < (unsigned)fLogFontArray.count());
tchar_to_skstring(fLogFontArray[index].elfLogFont.lfFaceName, familyName);
}
- virtual SkFontStyleSet* onCreateStyleSet(int index) SK_OVERRIDE {
+ virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE {
SkASSERT((unsigned)index < (unsigned)fLogFontArray.count());
return SkNEW_ARGS(SkFontStyleSetGDI, (fLogFontArray[index].elfLogFont.lfFaceName));
}
- virtual SkFontStyleSet* onMatchFamily(const char familyName[]) SK_OVERRIDE {
+ virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE {
if (NULL == familyName) {
familyName = ""; // do we need this check???
}
@@ -2556,38 +2574,38 @@ protected:
}
virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
- const SkFontStyle& fontstyle) SK_OVERRIDE {
+ const SkFontStyle& fontstyle) const SK_OVERRIDE {
// could be in base impl
SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
return sset->matchStyle(fontstyle);
}
virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
- const SkFontStyle& fontstyle) SK_OVERRIDE {
+ const SkFontStyle& fontstyle) const SK_OVERRIDE {
// could be in base impl
SkString familyName;
((LogFontTypeface*)familyMember)->getFamilyName(&familyName);
return this->matchFamilyStyle(familyName.c_str(), fontstyle);
}
- virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) SK_OVERRIDE {
+ virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE {
return create_from_stream(stream);
}
- virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) SK_OVERRIDE {
+ virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE {
// could be in base impl
SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream, (data)));
return this->createFromStream(stream);
}
- virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) SK_OVERRIDE {
+ virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE {
// could be in base impl
SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
return this->createFromStream(stream);
}
virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
- unsigned styleBits) SK_OVERRIDE {
+ unsigned styleBits) const SK_OVERRIDE {
LOGFONT lf;
if (NULL == familyName) {
lf = get_default_font();
diff --git a/chromium/third_party/skia/src/ports/SkFontHost_win_dw.cpp b/chromium/third_party/skia/src/ports/SkFontHost_win_dw.cpp
deleted file mode 100644
index 00623623b07..00000000000
--- a/chromium/third_party/skia/src/ports/SkFontHost_win_dw.cpp
+++ /dev/null
@@ -1,1912 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkTypes.h"
-#undef GetGlyphIndices
-
-#include "SkAdvancedTypefaceMetrics.h"
-#include "SkColorFilter.h"
-#include "SkDWriteFontFileStream.h"
-#include "SkDWriteGeometrySink.h"
-#include "SkDescriptor.h"
-#include "SkEndian.h"
-#include "SkFontDescriptor.h"
-#include "SkFontHost.h"
-#include "SkFontMgr.h"
-#include "SkFontStream.h"
-#include "SkGlyph.h"
-#include "SkHRESULT.h"
-#include "SkMaskGamma.h"
-#include "SkOnce.h"
-#include "SkOTTable_head.h"
-#include "SkOTTable_hhea.h"
-#include "SkOTTable_OS_2.h"
-#include "SkOTTable_post.h"
-#include "SkPath.h"
-#include "SkStream.h"
-#include "SkString.h"
-#include "SkTScopedComPtr.h"
-#include "SkThread.h"
-#include "SkTypeface_win.h"
-#include "SkTypefaceCache.h"
-#include "SkUtils.h"
-
-#include <dwrite.h>
-
-static bool isLCD(const SkScalerContext::Rec& rec) {
- return SkMask::kLCD16_Format == rec.fMaskFormat ||
- SkMask::kLCD32_Format == rec.fMaskFormat;
-}
-
-/** Prefer to use this type to prevent template proliferation. */
-typedef SkAutoSTMalloc<16, WCHAR> SkSMallocWCHAR;
-
-/** Converts a utf8 string to a WCHAR string. */
-static HRESULT cstring_to_wchar(const char* skname, SkSMallocWCHAR* name) {
- int wlen = MultiByteToWideChar(CP_UTF8, 0, skname, -1, NULL, 0);
- if (0 == wlen) {
- HRM(HRESULT_FROM_WIN32(GetLastError()),
- "Could not get length for wchar to utf-8 conversion.");
- }
- name->reset(wlen);
- wlen = MultiByteToWideChar(CP_UTF8, 0, skname, -1, name->get(), wlen);
- if (0 == wlen) {
- HRM(HRESULT_FROM_WIN32(GetLastError()), "Could not convert wchar to utf-8.");
- }
- return S_OK;
-}
-
-/** Converts a WCHAR string to a utf8 string. */
-static HRESULT wchar_to_skstring(WCHAR* name, SkString* skname) {
- int len = WideCharToMultiByte(CP_UTF8, 0, name, -1, NULL, 0, NULL, NULL);
- if (0 == len) {
- HRM(HRESULT_FROM_WIN32(GetLastError()),
- "Could not get length for utf-8 to wchar conversion.");
- }
- skname->resize(len - 1);
- len = WideCharToMultiByte(CP_UTF8, 0, name, -1, skname->writable_str(), len, NULL, NULL);
- if (0 == len) {
- HRM(HRESULT_FROM_WIN32(GetLastError()), "Could not convert utf-8 to wchar.");
- }
- return S_OK;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-static void create_dwrite_factory(IDWriteFactory** factory) {
- typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc;
- DWriteCreateFactoryProc dWriteCreateFactoryProc = reinterpret_cast<DWriteCreateFactoryProc>(
- GetProcAddress(LoadLibraryW(L"dwrite.dll"), "DWriteCreateFactory"));
-
- if (!dWriteCreateFactoryProc) {
- HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
- if (!IS_ERROR(hr)) {
- hr = ERROR_PROC_NOT_FOUND;
- }
- HRVM(hr, "Could not get DWriteCreateFactory proc.");
- }
-
- HRVM(dWriteCreateFactoryProc(DWRITE_FACTORY_TYPE_SHARED,
- __uuidof(IDWriteFactory),
- reinterpret_cast<IUnknown**>(factory)),
- "Could not create DirectWrite factory.");
-}
-
-static IDWriteFactory* get_dwrite_factory() {
- static IDWriteFactory* gDWriteFactory = NULL;
- SK_DECLARE_STATIC_ONCE(once);
- SkOnce(&once, create_dwrite_factory, &gDWriteFactory);
-
- return gDWriteFactory;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-class StreamFontFileLoader;
-
-class SkFontMgr_DirectWrite : public SkFontMgr {
-public:
- /** localeNameLength must include the null terminator. */
- SkFontMgr_DirectWrite(IDWriteFontCollection* fontCollection,
- WCHAR* localeName, int localeNameLength)
- : fFontCollection(SkRefComPtr(fontCollection))
- , fLocaleName(localeNameLength)
- {
- memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR));
- }
-
- SkTypefaceCache* getTypefaceCache() { return &fTFCache; }
-
- SkTypeface* createTypefaceFromDWriteFont(IDWriteFontFace* fontFace,
- IDWriteFont* font,
- IDWriteFontFamily* fontFamily,
- StreamFontFileLoader* = NULL,
- IDWriteFontCollectionLoader* = NULL);
-
-protected:
- virtual int onCountFamilies() SK_OVERRIDE;
- virtual void onGetFamilyName(int index, SkString* familyName) SK_OVERRIDE;
- virtual SkFontStyleSet* onCreateStyleSet(int index) SK_OVERRIDE;
- virtual SkFontStyleSet* onMatchFamily(const char familyName[]) SK_OVERRIDE;
- virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
- const SkFontStyle& fontstyle) SK_OVERRIDE;
- virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
- const SkFontStyle& fontstyle) SK_OVERRIDE;
- virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) SK_OVERRIDE;
- virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) SK_OVERRIDE;
- virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) SK_OVERRIDE;
- virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
- unsigned styleBits) SK_OVERRIDE;
-
-private:
- HRESULT getByFamilyName(const WCHAR familyName[], IDWriteFontFamily** fontFamily);
- HRESULT getDefaultFontFamily(IDWriteFontFamily** fontFamily);
-
- SkMutex fTFCacheMutex;
- void Add(SkTypeface* face, SkTypeface::Style requestedStyle, bool strong) {
- SkAutoMutexAcquire ama(fTFCacheMutex);
- fTFCache.add(face, requestedStyle, strong);
- }
-
- SkTypeface* FindByProcAndRef(SkTypefaceCache::FindProc proc, void* ctx) {
- SkAutoMutexAcquire ama(fTFCacheMutex);
- SkTypeface* typeface = fTFCache.findByProcAndRef(proc, ctx);
- return typeface;
- }
-
- friend class SkFontStyleSet_DirectWrite;
- SkTScopedComPtr<IDWriteFontCollection> fFontCollection;
- SkSMallocWCHAR fLocaleName;
- SkTypefaceCache fTFCache;
-};
-
-class SkFontStyleSet_DirectWrite : public SkFontStyleSet {
-public:
- SkFontStyleSet_DirectWrite(SkFontMgr_DirectWrite* fontMgr, IDWriteFontFamily* fontFamily)
- : fFontMgr(SkRef(fontMgr))
- , fFontFamily(SkRefComPtr(fontFamily))
- { }
-
- virtual int count() SK_OVERRIDE;
- virtual void getStyle(int index, SkFontStyle* fs, SkString* styleName) SK_OVERRIDE;
- virtual SkTypeface* createTypeface(int index) SK_OVERRIDE;
- virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE;
-
-private:
- SkAutoTUnref<SkFontMgr_DirectWrite> fFontMgr;
- SkTScopedComPtr<IDWriteFontFamily> fFontFamily;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-class DWriteOffscreen {
-public:
- DWriteOffscreen() : fWidth(0), fHeight(0) {
- }
-
- void init(IDWriteFontFace* fontFace, const DWRITE_MATRIX& xform, FLOAT fontSize) {
- fFontFace = fontFace;
- fFontSize = fontSize;
- fXform = xform;
- }
-
- const void* draw(const SkGlyph&, bool isBW);
-
-private:
- uint16_t fWidth;
- uint16_t fHeight;
- IDWriteFontFace* fFontFace;
- FLOAT fFontSize;
- DWRITE_MATRIX fXform;
- SkTDArray<uint8_t> fBits;
-};
-
-const void* DWriteOffscreen::draw(const SkGlyph& glyph, bool isBW) {
- IDWriteFactory* factory = get_dwrite_factory();
- SkASSERT(factory != NULL);
-
- if (fWidth < glyph.fWidth || fHeight < glyph.fHeight) {
- fWidth = SkMax32(fWidth, glyph.fWidth);
- fHeight = SkMax32(fHeight, glyph.fHeight);
-
- if (isBW) {
- fBits.setCount(fWidth * fHeight);
- } else {
- fBits.setCount(fWidth * fHeight * 3);
- }
- }
-
- // erase
- memset(fBits.begin(), 0, fBits.count());
-
- fXform.dx = SkFixedToFloat(glyph.getSubXFixed());
- fXform.dy = SkFixedToFloat(glyph.getSubYFixed());
-
- FLOAT advance = 0.0f;
-
- UINT16 index = glyph.getGlyphID();
-
- DWRITE_GLYPH_OFFSET offset;
- offset.advanceOffset = 0.0f;
- offset.ascenderOffset = 0.0f;
-
- DWRITE_GLYPH_RUN run;
- run.glyphCount = 1;
- run.glyphAdvances = &advance;
- run.fontFace = fFontFace;
- run.fontEmSize = fFontSize;
- run.bidiLevel = 0;
- run.glyphIndices = &index;
- run.isSideways = FALSE;
- run.glyphOffsets = &offset;
-
- DWRITE_RENDERING_MODE renderingMode;
- DWRITE_TEXTURE_TYPE textureType;
- if (isBW) {
- renderingMode = DWRITE_RENDERING_MODE_ALIASED;
- textureType = DWRITE_TEXTURE_ALIASED_1x1;
- } else {
- renderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
- textureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
- }
- SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
- HRNM(factory->CreateGlyphRunAnalysis(&run,
- 1.0f, // pixelsPerDip,
- &fXform,
- renderingMode,
- DWRITE_MEASURING_MODE_NATURAL,
- 0.0f, // baselineOriginX,
- 0.0f, // baselineOriginY,
- &glyphRunAnalysis),
- "Could not create glyph run analysis.");
-
- //NOTE: this assumes that the glyph has already been measured
- //with an exact same glyph run analysis.
- RECT bbox;
- bbox.left = glyph.fLeft;
- bbox.top = glyph.fTop;
- bbox.right = glyph.fLeft + glyph.fWidth;
- bbox.bottom = glyph.fTop + glyph.fHeight;
- HRNM(glyphRunAnalysis->CreateAlphaTexture(textureType,
- &bbox,
- fBits.begin(),
- fBits.count()),
- "Could not draw mask.");
- return fBits.begin();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-class StreamFontFileLoader : public IDWriteFontFileLoader {
-public:
- // IUnknown methods
- virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
- virtual ULONG STDMETHODCALLTYPE AddRef();
- virtual ULONG STDMETHODCALLTYPE Release();
-
- // IDWriteFontFileLoader methods
- virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey(
- void const* fontFileReferenceKey,
- UINT32 fontFileReferenceKeySize,
- IDWriteFontFileStream** fontFileStream);
-
- static HRESULT Create(SkStream* stream, StreamFontFileLoader** streamFontFileLoader) {
- *streamFontFileLoader = new StreamFontFileLoader(stream);
- if (NULL == streamFontFileLoader) {
- return E_OUTOFMEMORY;
- }
- return S_OK;
- }
-
- SkAutoTUnref<SkStream> fStream;
-
-private:
- StreamFontFileLoader(SkStream* stream) : fRefCount(1), fStream(SkRef(stream)) { }
-
- ULONG fRefCount;
-};
-
-HRESULT StreamFontFileLoader::QueryInterface(REFIID iid, void** ppvObject) {
- if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) {
- *ppvObject = this;
- AddRef();
- return S_OK;
- } else {
- *ppvObject = NULL;
- return E_NOINTERFACE;
- }
-}
-
-ULONG StreamFontFileLoader::AddRef() {
- return InterlockedIncrement(&fRefCount);
-}
-
-ULONG StreamFontFileLoader::Release() {
- ULONG newCount = InterlockedDecrement(&fRefCount);
- if (0 == newCount) {
- delete this;
- }
- return newCount;
-}
-
-HRESULT StreamFontFileLoader::CreateStreamFromKey(
- void const* fontFileReferenceKey,
- UINT32 fontFileReferenceKeySize,
- IDWriteFontFileStream** fontFileStream)
-{
- SkTScopedComPtr<SkDWriteFontFileStreamWrapper> stream;
- HR(SkDWriteFontFileStreamWrapper::Create(fStream, &stream));
- *fontFileStream = stream.release();
- return S_OK;
-}
-
-class StreamFontFileEnumerator : public IDWriteFontFileEnumerator {
-public:
- // IUnknown methods
- virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
- virtual ULONG STDMETHODCALLTYPE AddRef();
- virtual ULONG STDMETHODCALLTYPE Release();
-
- // IDWriteFontFileEnumerator methods
- virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile);
- virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** fontFile);
-
- static HRESULT Create(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader,
- StreamFontFileEnumerator** streamFontFileEnumerator) {
- *streamFontFileEnumerator = new StreamFontFileEnumerator(factory, fontFileLoader);
- if (NULL == streamFontFileEnumerator) {
- return E_OUTOFMEMORY;
- }
- return S_OK;
- }
-private:
- StreamFontFileEnumerator(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader);
- ULONG fRefCount;
-
- SkTScopedComPtr<IDWriteFactory> fFactory;
- SkTScopedComPtr<IDWriteFontFile> fCurrentFile;
- SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
- bool fHasNext;
-};
-
-StreamFontFileEnumerator::StreamFontFileEnumerator(IDWriteFactory* factory,
- IDWriteFontFileLoader* fontFileLoader)
- : fRefCount(1)
- , fFactory(SkRefComPtr(factory))
- , fCurrentFile()
- , fFontFileLoader(SkRefComPtr(fontFileLoader))
- , fHasNext(true)
-{ }
-
-HRESULT StreamFontFileEnumerator::QueryInterface(REFIID iid, void** ppvObject) {
- if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) {
- *ppvObject = this;
- AddRef();
- return S_OK;
- } else {
- *ppvObject = NULL;
- return E_NOINTERFACE;
- }
-}
-
-ULONG StreamFontFileEnumerator::AddRef() {
- return InterlockedIncrement(&fRefCount);
-}
-
-ULONG StreamFontFileEnumerator::Release() {
- ULONG newCount = InterlockedDecrement(&fRefCount);
- if (0 == newCount) {
- delete this;
- }
- return newCount;
-}
-
-HRESULT StreamFontFileEnumerator::MoveNext(BOOL* hasCurrentFile) {
- *hasCurrentFile = FALSE;
-
- if (!fHasNext) {
- return S_OK;
- }
- fHasNext = false;
-
- UINT32 dummy = 0;
- HR(fFactory->CreateCustomFontFileReference(
- &dummy, //cannot be NULL
- sizeof(dummy), //even if this is 0
- fFontFileLoader.get(),
- &fCurrentFile));
-
- *hasCurrentFile = TRUE;
- return S_OK;
-}
-
-HRESULT StreamFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile) {
- if (fCurrentFile.get() == NULL) {
- *fontFile = NULL;
- return E_FAIL;
- }
-
- *fontFile = SkRefComPtr(fCurrentFile.get());
- return S_OK;
-}
-
-class StreamFontCollectionLoader : public IDWriteFontCollectionLoader {
-public:
- // IUnknown methods
- virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
- virtual ULONG STDMETHODCALLTYPE AddRef();
- virtual ULONG STDMETHODCALLTYPE Release();
-
- // IDWriteFontCollectionLoader methods
- virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey(
- IDWriteFactory* factory,
- void const* collectionKey,
- UINT32 collectionKeySize,
- IDWriteFontFileEnumerator** fontFileEnumerator);
-
- static HRESULT Create(IDWriteFontFileLoader* fontFileLoader,
- StreamFontCollectionLoader** streamFontCollectionLoader) {
- *streamFontCollectionLoader = new StreamFontCollectionLoader(fontFileLoader);
- if (NULL == streamFontCollectionLoader) {
- return E_OUTOFMEMORY;
- }
- return S_OK;
- }
-private:
- StreamFontCollectionLoader(IDWriteFontFileLoader* fontFileLoader)
- : fRefCount(1)
- , fFontFileLoader(SkRefComPtr(fontFileLoader))
- { }
-
- ULONG fRefCount;
- SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
-};
-
-HRESULT StreamFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject) {
- if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) {
- *ppvObject = this;
- AddRef();
- return S_OK;
- } else {
- *ppvObject = NULL;
- return E_NOINTERFACE;
- }
-}
-
-ULONG StreamFontCollectionLoader::AddRef() {
- return InterlockedIncrement(&fRefCount);
-}
-
-ULONG StreamFontCollectionLoader::Release() {
- ULONG newCount = InterlockedDecrement(&fRefCount);
- if (0 == newCount) {
- delete this;
- }
- return newCount;
-}
-
-HRESULT StreamFontCollectionLoader::CreateEnumeratorFromKey(
- IDWriteFactory* factory,
- void const* collectionKey,
- UINT32 collectionKeySize,
- IDWriteFontFileEnumerator** fontFileEnumerator)
-{
- SkTScopedComPtr<StreamFontFileEnumerator> enumerator;
- HR(StreamFontFileEnumerator::Create(factory, fFontFileLoader.get(), &enumerator));
- *fontFileEnumerator = enumerator.release();
- return S_OK;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-static SkTypeface::Style get_style(IDWriteFont* font) {
- int style = SkTypeface::kNormal;
- DWRITE_FONT_WEIGHT weight = font->GetWeight();
- if (DWRITE_FONT_WEIGHT_DEMI_BOLD <= weight) {
- style |= SkTypeface::kBold;
- }
- DWRITE_FONT_STYLE angle = font->GetStyle();
- if (DWRITE_FONT_STYLE_OBLIQUE == angle || DWRITE_FONT_STYLE_ITALIC == angle) {
- style |= SkTypeface::kItalic;
- }
- return static_cast<SkTypeface::Style>(style);
-}
-
-class DWriteFontTypeface : public SkTypeface {
-private:
- DWriteFontTypeface(SkTypeface::Style style, SkFontID fontID,
- IDWriteFontFace* fontFace,
- IDWriteFont* font,
- IDWriteFontFamily* fontFamily,
- StreamFontFileLoader* fontFileLoader = NULL,
- IDWriteFontCollectionLoader* fontCollectionLoader = NULL)
- : SkTypeface(style, fontID, false)
- , fDWriteFontCollectionLoader(SkSafeRefComPtr(fontCollectionLoader))
- , fDWriteFontFileLoader(SkSafeRefComPtr(fontFileLoader))
- , fDWriteFontFamily(SkRefComPtr(fontFamily))
- , fDWriteFont(SkRefComPtr(font))
- , fDWriteFontFace(SkRefComPtr(fontFace))
- { }
-
-public:
- SkTScopedComPtr<IDWriteFontCollectionLoader> fDWriteFontCollectionLoader;
- SkTScopedComPtr<StreamFontFileLoader> fDWriteFontFileLoader;
- SkTScopedComPtr<IDWriteFontFamily> fDWriteFontFamily;
- SkTScopedComPtr<IDWriteFont> fDWriteFont;
- SkTScopedComPtr<IDWriteFontFace> fDWriteFontFace;
-
- static DWriteFontTypeface* Create(IDWriteFontFace* fontFace,
- IDWriteFont* font,
- IDWriteFontFamily* fontFamily,
- StreamFontFileLoader* fontFileLoader = NULL,
- IDWriteFontCollectionLoader* fontCollectionLoader = NULL) {
- SkTypeface::Style style = get_style(font);
- SkFontID fontID = SkTypefaceCache::NewFontID();
- return SkNEW_ARGS(DWriteFontTypeface, (style, fontID,
- fontFace, font, fontFamily,
- fontFileLoader, fontCollectionLoader));
- }
-
- ~DWriteFontTypeface() {
- if (fDWriteFontCollectionLoader.get() == NULL) return;
-
- IDWriteFactory* factory = get_dwrite_factory();
- SkASSERT(factory != NULL);
- HRV(factory->UnregisterFontCollectionLoader(fDWriteFontCollectionLoader.get()));
- HRV(factory->UnregisterFontFileLoader(fDWriteFontFileLoader.get()));
- }
-
-protected:
- virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE;
- virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK_OVERRIDE;
- virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE;
- virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics(
- SkAdvancedTypefaceMetrics::PerGlyphInfo,
- const uint32_t*, uint32_t) const SK_OVERRIDE;
- virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE;
- virtual int onCharsToGlyphs(const void* chars, Encoding encoding,
- uint16_t glyphs[], int glyphCount) const SK_OVERRIDE;
- virtual int onCountGlyphs() const SK_OVERRIDE;
- virtual int onGetUPEM() const SK_OVERRIDE;
- virtual SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const SK_OVERRIDE;
- virtual int onGetTableTags(SkFontTableTag tags[]) const SK_OVERRIDE;
- virtual size_t onGetTableData(SkFontTableTag, size_t offset,
- size_t length, void* data) const SK_OVERRIDE;
-};
-
-class SkScalerContext_DW : public SkScalerContext {
-public:
- SkScalerContext_DW(DWriteFontTypeface*, const SkDescriptor* desc);
- virtual ~SkScalerContext_DW();
-
-protected:
- virtual unsigned generateGlyphCount() SK_OVERRIDE;
- virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE;
- virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE;
- virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE;
- virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE;
- virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE;
- virtual void generateFontMetrics(SkPaint::FontMetrics* mX,
- SkPaint::FontMetrics* mY) SK_OVERRIDE;
-
-private:
- DWriteOffscreen fOffscreen;
- DWRITE_MATRIX fXform;
- SkAutoTUnref<DWriteFontTypeface> fTypeface;
- int fGlyphCount;
-};
-
-static bool are_same(IUnknown* a, IUnknown* b) {
- SkTScopedComPtr<IUnknown> iunkA;
- if (FAILED(a->QueryInterface(&iunkA))) {
- return false;
- }
-
- SkTScopedComPtr<IUnknown> iunkB;
- if (FAILED(b->QueryInterface(&iunkB))) {
- return false;
- }
-
- return iunkA.get() == iunkB.get();
-}
-static bool FindByDWriteFont(SkTypeface* face, SkTypeface::Style requestedStyle, void* ctx) {
- //Check to see if the two fonts are identical.
- DWriteFontTypeface* dwFace = reinterpret_cast<DWriteFontTypeface*>(face);
- IDWriteFont* dwFont = reinterpret_cast<IDWriteFont*>(ctx);
- if (are_same(dwFace->fDWriteFont.get(), dwFont)) {
- return true;
- }
-
- //Check if the two fonts share the same loader and have the same key.
- SkTScopedComPtr<IDWriteFontFace> dwFaceFontFace;
- SkTScopedComPtr<IDWriteFontFace> dwFontFace;
- HRB(dwFace->fDWriteFont->CreateFontFace(&dwFaceFontFace));
- HRB(dwFont->CreateFontFace(&dwFontFace));
- if (are_same(dwFaceFontFace.get(), dwFontFace.get())) {
- return true;
- }
-
- UINT32 dwFaceNumFiles;
- UINT32 dwNumFiles;
- HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, NULL));
- HRB(dwFontFace->GetFiles(&dwNumFiles, NULL));
- if (dwFaceNumFiles != dwNumFiles) {
- return false;
- }
-
- SkTScopedComPtr<IDWriteFontFile> dwFaceFontFile;
- SkTScopedComPtr<IDWriteFontFile> dwFontFile;
- HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, &dwFaceFontFile));
- HRB(dwFontFace->GetFiles(&dwNumFiles, &dwFontFile));
-
- //for (each file) { //we currently only admit fonts from one file.
- SkTScopedComPtr<IDWriteFontFileLoader> dwFaceFontFileLoader;
- SkTScopedComPtr<IDWriteFontFileLoader> dwFontFileLoader;
- HRB(dwFaceFontFile->GetLoader(&dwFaceFontFileLoader));
- HRB(dwFontFile->GetLoader(&dwFontFileLoader));
- if (!are_same(dwFaceFontFileLoader.get(), dwFontFileLoader.get())) {
- return false;
- }
- //}
-
- const void* dwFaceFontRefKey;
- UINT32 dwFaceFontRefKeySize;
- const void* dwFontRefKey;
- UINT32 dwFontRefKeySize;
- HRB(dwFaceFontFile->GetReferenceKey(&dwFaceFontRefKey, &dwFaceFontRefKeySize));
- HRB(dwFontFile->GetReferenceKey(&dwFontRefKey, &dwFontRefKeySize));
- if (dwFaceFontRefKeySize != dwFontRefKeySize) {
- return false;
- }
- if (0 != memcmp(dwFaceFontRefKey, dwFontRefKey, dwFontRefKeySize)) {
- return false;
- }
-
- //TODO: better means than comparing name strings?
- //NOTE: .tfc and fake bold/italic will end up here.
- SkTScopedComPtr<IDWriteFontFamily> dwFaceFontFamily;
- SkTScopedComPtr<IDWriteFontFamily> dwFontFamily;
- HRB(dwFace->fDWriteFont->GetFontFamily(&dwFaceFontFamily));
- HRB(dwFont->GetFontFamily(&dwFontFamily));
-
- SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontFamilyNames;
- SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontNames;
- HRB(dwFaceFontFamily->GetFamilyNames(&dwFaceFontFamilyNames));
- HRB(dwFace->fDWriteFont->GetFaceNames(&dwFaceFontNames));
-
- SkTScopedComPtr<IDWriteLocalizedStrings> dwFontFamilyNames;
- SkTScopedComPtr<IDWriteLocalizedStrings> dwFontNames;
- HRB(dwFontFamily->GetFamilyNames(&dwFontFamilyNames));
- HRB(dwFont->GetFaceNames(&dwFontNames));
-
- UINT32 dwFaceFontFamilyNameLength;
- UINT32 dwFaceFontNameLength;
- HRB(dwFaceFontFamilyNames->GetStringLength(0, &dwFaceFontFamilyNameLength));
- HRB(dwFaceFontNames->GetStringLength(0, &dwFaceFontNameLength));
-
- UINT32 dwFontFamilyNameLength;
- UINT32 dwFontNameLength;
- HRB(dwFontFamilyNames->GetStringLength(0, &dwFontFamilyNameLength));
- HRB(dwFontNames->GetStringLength(0, &dwFontNameLength));
-
- if (dwFaceFontFamilyNameLength != dwFontFamilyNameLength ||
- dwFaceFontNameLength != dwFontNameLength)
- {
- return false;
- }
-
- SkSMallocWCHAR dwFaceFontFamilyNameChar(dwFaceFontFamilyNameLength+1);
- SkSMallocWCHAR dwFaceFontNameChar(dwFaceFontNameLength+1);
- HRB(dwFaceFontFamilyNames->GetString(0, dwFaceFontFamilyNameChar.get(), dwFaceFontFamilyNameLength+1));
- HRB(dwFaceFontNames->GetString(0, dwFaceFontNameChar.get(), dwFaceFontNameLength+1));
-
- SkSMallocWCHAR dwFontFamilyNameChar(dwFontFamilyNameLength+1);
- SkSMallocWCHAR dwFontNameChar(dwFontNameLength+1);
- HRB(dwFontFamilyNames->GetString(0, dwFontFamilyNameChar.get(), dwFontFamilyNameLength+1));
- HRB(dwFontNames->GetString(0, dwFontNameChar.get(), dwFontNameLength+1));
-
- return wcscmp(dwFaceFontFamilyNameChar.get(), dwFontFamilyNameChar.get()) == 0 &&
- wcscmp(dwFaceFontNameChar.get(), dwFontNameChar.get()) == 0;
-}
-
-SkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface,
- const SkDescriptor* desc)
- : SkScalerContext(typeface, desc)
- , fTypeface(SkRef(typeface))
- , fGlyphCount(-1) {
-
- fXform.m11 = SkScalarToFloat(fRec.fPost2x2[0][0]);
- fXform.m12 = SkScalarToFloat(fRec.fPost2x2[1][0]);
- fXform.m21 = SkScalarToFloat(fRec.fPost2x2[0][1]);
- fXform.m22 = SkScalarToFloat(fRec.fPost2x2[1][1]);
- fXform.dx = 0;
- fXform.dy = 0;
-
- fOffscreen.init(fTypeface->fDWriteFontFace.get(), fXform, SkScalarToFloat(fRec.fTextSize));
-}
-
-SkScalerContext_DW::~SkScalerContext_DW() {
-}
-
-unsigned SkScalerContext_DW::generateGlyphCount() {
- if (fGlyphCount < 0) {
- fGlyphCount = fTypeface->fDWriteFontFace->GetGlyphCount();
- }
- return fGlyphCount;
-}
-
-uint16_t SkScalerContext_DW::generateCharToGlyph(SkUnichar uni) {
- uint16_t index = 0;
- fTypeface->fDWriteFontFace->GetGlyphIndices(reinterpret_cast<UINT32*>(&uni), 1, &index);
- return index;
-}
-
-void SkScalerContext_DW::generateAdvance(SkGlyph* glyph) {
- //Delta is the difference between the right/left side bearing metric
- //and where the right/left side bearing ends up after hinting.
- //DirectWrite does not provide this information.
- glyph->fRsbDelta = 0;
- glyph->fLsbDelta = 0;
-
- glyph->fAdvanceX = 0;
- glyph->fAdvanceY = 0;
-
- uint16_t glyphId = glyph->getGlyphID();
- DWRITE_GLYPH_METRICS gm;
- HRVM(fTypeface->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm),
- "Could not get design metrics.");
-
- DWRITE_FONT_METRICS dwfm;
- fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
-
- SkScalar advanceX = SkScalarMulDiv(fRec.fTextSize,
- SkIntToScalar(gm.advanceWidth),
- SkIntToScalar(dwfm.designUnitsPerEm));
-
- if (!(fRec.fFlags & kSubpixelPositioning_Flag)) {
- advanceX = SkScalarRoundToScalar(advanceX);
- }
-
- SkVector vecs[1] = { { advanceX, 0 } };
- SkMatrix mat;
- fRec.getMatrixFrom2x2(&mat);
- mat.mapVectors(vecs, SK_ARRAY_COUNT(vecs));
-
- glyph->fAdvanceX = SkScalarToFixed(vecs[0].fX);
- glyph->fAdvanceY = SkScalarToFixed(vecs[0].fY);
-}
-
-void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) {
- glyph->fWidth = 0;
-
- this->generateAdvance(glyph);
-
- //Measure raster size.
- fXform.dx = SkFixedToFloat(glyph->getSubXFixed());
- fXform.dy = SkFixedToFloat(glyph->getSubYFixed());
-
- FLOAT advance = 0;
-
- UINT16 glyphId = glyph->getGlyphID();
-
- DWRITE_GLYPH_OFFSET offset;
- offset.advanceOffset = 0.0f;
- offset.ascenderOffset = 0.0f;
-
- DWRITE_GLYPH_RUN run;
- run.glyphCount = 1;
- run.glyphAdvances = &advance;
- run.fontFace = fTypeface->fDWriteFontFace.get();
- run.fontEmSize = SkScalarToFloat(fRec.fTextSize);
- run.bidiLevel = 0;
- run.glyphIndices = &glyphId;
- run.isSideways = FALSE;
- run.glyphOffsets = &offset;
-
- IDWriteFactory* factory = get_dwrite_factory();
- SkASSERT(factory != NULL);
-
- const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
- DWRITE_RENDERING_MODE renderingMode;
- DWRITE_TEXTURE_TYPE textureType;
- if (isBW) {
- renderingMode = DWRITE_RENDERING_MODE_ALIASED;
- textureType = DWRITE_TEXTURE_ALIASED_1x1;
- } else {
- renderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
- textureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
- }
-
- SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
- HRVM(factory->CreateGlyphRunAnalysis(&run,
- 1.0f, // pixelsPerDip,
- &fXform,
- renderingMode,
- DWRITE_MEASURING_MODE_NATURAL,
- 0.0f, // baselineOriginX,
- 0.0f, // baselineOriginY,
- &glyphRunAnalysis),
- "Could not create glyph run analysis.");
-
- RECT bbox;
- HRVM(glyphRunAnalysis->GetAlphaTextureBounds(textureType, &bbox),
- "Could not get texture bounds.");
-
- glyph->fWidth = SkToU16(bbox.right - bbox.left);
- glyph->fHeight = SkToU16(bbox.bottom - bbox.top);
- glyph->fLeft = SkToS16(bbox.left);
- glyph->fTop = SkToS16(bbox.top);
-}
-
-void SkScalerContext_DW::generateFontMetrics(SkPaint::FontMetrics* mx,
- SkPaint::FontMetrics* my) {
- if (!(mx || my))
- return;
-
- if (mx) {
- sk_bzero(mx, sizeof(*mx));
- }
- if (my) {
- sk_bzero(my, sizeof(*my));
- }
-
- DWRITE_FONT_METRICS dwfm;
- fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
-
- SkScalar upem = SkIntToScalar(dwfm.designUnitsPerEm);
- if (mx) {
- mx->fTop = -fRec.fTextSize * SkIntToScalar(dwfm.ascent) / upem;
- mx->fAscent = mx->fTop;
- mx->fDescent = fRec.fTextSize * SkIntToScalar(dwfm.descent) / upem;
- mx->fBottom = mx->fDescent;
- mx->fLeading = fRec.fTextSize * SkIntToScalar(dwfm.lineGap) / upem;
- mx->fXHeight = fRec.fTextSize * SkIntToScalar(dwfm.xHeight) / upem;
- }
-
- if (my) {
- my->fTop = -fRec.fTextSize * SkIntToScalar(dwfm.ascent) / upem;
- my->fAscent = my->fTop;
- my->fDescent = fRec.fTextSize * SkIntToScalar(dwfm.descent) / upem;
- my->fBottom = my->fDescent;
- my->fLeading = fRec.fTextSize * SkIntToScalar(dwfm.lineGap) / upem;
- my->fXHeight = fRec.fTextSize * SkIntToScalar(dwfm.xHeight) / upem;
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-#include "SkColorPriv.h"
-
-static void bilevel_to_bw(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph) {
- const int width = glyph.fWidth;
- const size_t dstRB = (width + 7) >> 3;
- uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
-
- int byteCount = width >> 3;
- int bitCount = width & 7;
-
- for (int y = 0; y < glyph.fHeight; ++y) {
- if (byteCount > 0) {
- for (int i = 0; i < byteCount; ++i) {
- unsigned byte = 0;
- byte |= src[0] & (1 << 7);
- byte |= src[1] & (1 << 6);
- byte |= src[2] & (1 << 5);
- byte |= src[3] & (1 << 4);
- byte |= src[4] & (1 << 3);
- byte |= src[5] & (1 << 2);
- byte |= src[6] & (1 << 1);
- byte |= src[7] & (1 << 0);
- dst[i] = byte;
- src += 8;
- }
- }
- if (bitCount > 0) {
- unsigned byte = 0;
- unsigned mask = 0x80;
- for (int i = 0; i < bitCount; i++) {
- byte |= (src[i]) & mask;
- mask >>= 1;
- }
- dst[byteCount] = byte;
- }
- src += bitCount;
- dst += dstRB;
- }
-}
-
-template<bool APPLY_PREBLEND>
-static void rgb_to_a8(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, const uint8_t* table8) {
- const size_t dstRB = glyph.rowBytes();
- const U16CPU width = glyph.fWidth;
- uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
-
- for (U16CPU y = 0; y < glyph.fHeight; y++) {
- for (U16CPU i = 0; i < width; i++) {
- U8CPU r = *(src++);
- U8CPU g = *(src++);
- U8CPU b = *(src++);
- dst[i] = sk_apply_lut_if<APPLY_PREBLEND>((r + g + b) / 3, table8);
- }
- dst = (uint8_t*)((char*)dst + dstRB);
- }
-}
-
-template<bool APPLY_PREBLEND>
-static void rgb_to_lcd16(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
- const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
- const size_t dstRB = glyph.rowBytes();
- const U16CPU width = glyph.fWidth;
- uint16_t* SK_RESTRICT dst = static_cast<uint16_t*>(glyph.fImage);
-
- for (U16CPU y = 0; y < glyph.fHeight; y++) {
- for (U16CPU i = 0; i < width; i++) {
- U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
- U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
- U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
- dst[i] = SkPack888ToRGB16(r, g, b);
- }
- dst = (uint16_t*)((char*)dst + dstRB);
- }
-}
-
-template<bool APPLY_PREBLEND>
-static void rgb_to_lcd32(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
- const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
- const size_t dstRB = glyph.rowBytes();
- const U16CPU width = glyph.fWidth;
- SkPMColor* SK_RESTRICT dst = static_cast<SkPMColor*>(glyph.fImage);
-
- for (U16CPU y = 0; y < glyph.fHeight; y++) {
- for (U16CPU i = 0; i < width; i++) {
- U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
- U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
- U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
- dst[i] = SkPackARGB32(0xFF, r, g, b);
- }
- dst = (SkPMColor*)((char*)dst + dstRB);
- }
-}
-
-void SkScalerContext_DW::generateImage(const SkGlyph& glyph) {
- const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
- const bool isAA = !isLCD(fRec);
-
- //Create the mask.
- const void* bits = fOffscreen.draw(glyph, isBW);
- if (!bits) {
- sk_bzero(glyph.fImage, glyph.computeImageSize());
- return;
- }
-
- //Copy the mask into the glyph.
- const uint8_t* src = (const uint8_t*)bits;
- if (isBW) {
- bilevel_to_bw(src, glyph);
- } else if (isAA) {
- if (fPreBlend.isApplicable()) {
- rgb_to_a8<true>(src, glyph, fPreBlend.fG);
- } else {
- rgb_to_a8<false>(src, glyph, fPreBlend.fG);
- }
- } else if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
- if (fPreBlend.isApplicable()) {
- rgb_to_lcd16<true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
- } else {
- rgb_to_lcd16<false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
- }
- } else {
- SkASSERT(SkMask::kLCD32_Format == glyph.fMaskFormat);
- if (fPreBlend.isApplicable()) {
- rgb_to_lcd32<true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
- } else {
- rgb_to_lcd32<false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
- }
- }
-}
-
-void SkScalerContext_DW::generatePath(const SkGlyph& glyph, SkPath* path) {
- SkASSERT(&glyph && path);
-
- path->reset();
-
- SkTScopedComPtr<IDWriteGeometrySink> geometryToPath;
- HRVM(SkDWriteGeometrySink::Create(path, &geometryToPath),
- "Could not create geometry to path converter.");
- uint16_t glyphId = glyph.getGlyphID();
- //TODO: convert to<->from DIUs? This would make a difference if hinting.
- //It may not be needed, it appears that DirectWrite only hints at em size.
- HRVM(fTypeface->fDWriteFontFace->GetGlyphRunOutline(SkScalarToFloat(fRec.fTextSize),
- &glyphId,
- NULL, //advances
- NULL, //offsets
- 1, //num glyphs
- FALSE, //sideways
- FALSE, //rtl
- geometryToPath.get()),
- "Could not create glyph outline.");
-
- SkMatrix mat;
- fRec.getMatrixFrom2x2(&mat);
- path->transform(mat);
-}
-
-void DWriteFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
- bool* isLocalStream) const {
- // Get the family name.
- SkTScopedComPtr<IDWriteLocalizedStrings> dwFamilyNames;
- HRV(fDWriteFontFamily->GetFamilyNames(&dwFamilyNames));
-
- UINT32 dwFamilyNamesLength;
- HRV(dwFamilyNames->GetStringLength(0, &dwFamilyNamesLength));
-
- SkSMallocWCHAR dwFamilyNameChar(dwFamilyNamesLength+1);
- HRV(dwFamilyNames->GetString(0, dwFamilyNameChar.get(), dwFamilyNamesLength+1));
-
- SkString utf8FamilyName;
- HRV(wchar_to_skstring(dwFamilyNameChar.get(), &utf8FamilyName));
-
- desc->setFamilyName(utf8FamilyName.c_str());
- *isLocalStream = SkToBool(fDWriteFontFileLoader.get());
-}
-
-static SkUnichar next_utf8(const void** chars) {
- return SkUTF8_NextUnichar((const char**)chars);
-}
-
-static SkUnichar next_utf16(const void** chars) {
- return SkUTF16_NextUnichar((const uint16_t**)chars);
-}
-
-static SkUnichar next_utf32(const void** chars) {
- const SkUnichar** uniChars = (const SkUnichar**)chars;
- SkUnichar uni = **uniChars;
- *uniChars += 1;
- return uni;
-}
-
-typedef SkUnichar (*EncodingProc)(const void**);
-
-static EncodingProc find_encoding_proc(SkTypeface::Encoding enc) {
- static const EncodingProc gProcs[] = {
- next_utf8, next_utf16, next_utf32
- };
- SkASSERT((size_t)enc < SK_ARRAY_COUNT(gProcs));
- return gProcs[enc];
-}
-
-int DWriteFontTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
- uint16_t glyphs[], int glyphCount) const
-{
- if (NULL == glyphs) {
- EncodingProc next_ucs4_proc = find_encoding_proc(encoding);
- for (int i = 0; i < glyphCount; ++i) {
- const SkUnichar c = next_ucs4_proc(&chars);
- BOOL exists;
- fDWriteFont->HasCharacter(c, &exists);
- if (!exists) {
- return i;
- }
- }
- return glyphCount;
- }
-
- switch (encoding) {
- case SkTypeface::kUTF8_Encoding:
- case SkTypeface::kUTF16_Encoding: {
- static const int scratchCount = 256;
- UINT32 scratch[scratchCount];
- EncodingProc next_ucs4_proc = find_encoding_proc(encoding);
- for (int baseGlyph = 0; baseGlyph < glyphCount; baseGlyph += scratchCount) {
- int glyphsLeft = glyphCount - baseGlyph;
- int limit = SkTMin(glyphsLeft, scratchCount);
- for (int i = 0; i < limit; ++i) {
- scratch[i] = next_ucs4_proc(&chars);
- }
- fDWriteFontFace->GetGlyphIndices(scratch, limit, &glyphs[baseGlyph]);
- }
- break;
- }
- case SkTypeface::kUTF32_Encoding: {
- const UINT32* utf32 = reinterpret_cast<const UINT32*>(chars);
- fDWriteFontFace->GetGlyphIndices(utf32, glyphCount, glyphs);
- break;
- }
- default:
- SK_CRASH();
- }
-
- for (int i = 0; i < glyphCount; ++i) {
- if (0 == glyphs[i]) {
- return i;
- }
- }
- return glyphCount;
-}
-
-int DWriteFontTypeface::onCountGlyphs() const {
- return fDWriteFontFace->GetGlyphCount();
-}
-
-int DWriteFontTypeface::onGetUPEM() const {
- DWRITE_FONT_METRICS metrics;
- fDWriteFontFace->GetMetrics(&metrics);
- return metrics.designUnitsPerEm;
-}
-
-class LocalizedStrings_IDWriteLocalizedStrings : public SkTypeface::LocalizedStrings {
-public:
- /** Takes ownership of the IDWriteLocalizedStrings. */
- explicit LocalizedStrings_IDWriteLocalizedStrings(IDWriteLocalizedStrings* strings)
- : fIndex(0), fStrings(strings)
- { }
-
- virtual bool next(SkTypeface::LocalizedString* localizedString) SK_OVERRIDE {
- if (fIndex >= fStrings->GetCount()) {
- return false;
- }
-
- // String
- UINT32 stringLength;
- HRBM(fStrings->GetStringLength(fIndex, &stringLength), "Could not get string length.");
- stringLength += 1;
-
- SkSMallocWCHAR wString(stringLength);
- HRBM(fStrings->GetString(fIndex, wString.get(), stringLength), "Could not get string.");
-
- HRB(wchar_to_skstring(wString.get(), &localizedString->fString));
-
- // Locale
- UINT32 localeLength;
- HRBM(fStrings->GetLocaleNameLength(fIndex, &localeLength), "Could not get locale length.");
- localeLength += 1;
-
- SkSMallocWCHAR wLocale(localeLength);
- HRBM(fStrings->GetLocaleName(fIndex, wLocale.get(), localeLength), "Could not get locale.");
-
- HRB(wchar_to_skstring(wLocale.get(), &localizedString->fLanguage));
-
- ++fIndex;
- return true;
- }
-
-private:
- UINT32 fIndex;
- SkTScopedComPtr<IDWriteLocalizedStrings> fStrings;
-};
-
-SkTypeface::LocalizedStrings* DWriteFontTypeface::onCreateFamilyNameIterator() const {
- SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
- HRNM(fDWriteFontFamily->GetFamilyNames(&familyNames), "Could not obtain family names.");
-
- return new LocalizedStrings_IDWriteLocalizedStrings(familyNames.release());
-}
-
-int DWriteFontTypeface::onGetTableTags(SkFontTableTag tags[]) const {
- DWRITE_FONT_FACE_TYPE type = fDWriteFontFace->GetType();
- if (type != DWRITE_FONT_FACE_TYPE_CFF &&
- type != DWRITE_FONT_FACE_TYPE_TRUETYPE &&
- type != DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION)
- {
- return 0;
- }
-
- int ttcIndex;
- SkAutoTUnref<SkStream> stream(this->openStream(&ttcIndex));
- return stream.get() ? SkFontStream::GetTableTags(stream, ttcIndex, tags) : 0;
-}
-
-class AutoDWriteTable {
-public:
- AutoDWriteTable(IDWriteFontFace* fontFace, UINT32 beTag) : fFontFace(fontFace), fExists(FALSE) {
- // Any errors are ignored, user must check fExists anyway.
- fontFace->TryGetFontTable(beTag,
- reinterpret_cast<const void **>(&fData), &fSize, &fLock, &fExists);
- }
- ~AutoDWriteTable() {
- if (fExists) {
- fFontFace->ReleaseFontTable(fLock);
- }
- }
-
- const uint8_t* fData;
- UINT32 fSize;
- BOOL fExists;
-private:
- // Borrowed reference, the user must ensure the fontFace stays alive.
- IDWriteFontFace* fFontFace;
- void* fLock;
-};
-
-size_t DWriteFontTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
- size_t length, void* data) const
-{
- AutoDWriteTable table(fDWriteFontFace.get(), SkEndian_SwapBE32(tag));
- if (!table.fExists) {
- return 0;
- }
-
- if (offset > table.fSize) {
- return 0;
- }
- size_t size = SkTMin(length, table.fSize - offset);
- if (NULL != data) {
- memcpy(data, table.fData + offset, size);
- }
-
- return size;
-}
-
-template <typename T> class SkAutoIDWriteUnregister {
-public:
- SkAutoIDWriteUnregister(IDWriteFactory* factory, T* unregister)
- : fFactory(factory), fUnregister(unregister)
- { }
-
- ~SkAutoIDWriteUnregister() {
- if (fUnregister) {
- unregister(fFactory, fUnregister);
- }
- }
-
- T* detatch() {
- T* old = fUnregister;
- fUnregister = NULL;
- return old;
- }
-
-private:
- HRESULT unregister(IDWriteFactory* factory, IDWriteFontFileLoader* unregister) {
- return factory->UnregisterFontFileLoader(unregister);
- }
-
- HRESULT unregister(IDWriteFactory* factory, IDWriteFontCollectionLoader* unregister) {
- return factory->UnregisterFontCollectionLoader(unregister);
- }
-
- IDWriteFactory* fFactory;
- T* fUnregister;
-};
-
-static SkTypeface* create_from_stream(SkStream* stream, int ttcIndex) {
- IDWriteFactory* factory = get_dwrite_factory();
- if (NULL == factory) {
- return NULL;
- }
-
- SkTScopedComPtr<StreamFontFileLoader> fontFileLoader;
- HRN(StreamFontFileLoader::Create(stream, &fontFileLoader));
- HRN(factory->RegisterFontFileLoader(fontFileLoader.get()));
- SkAutoIDWriteUnregister<StreamFontFileLoader> autoUnregisterFontFileLoader(
- factory, fontFileLoader.get());
-
- SkTScopedComPtr<StreamFontCollectionLoader> fontCollectionLoader;
- HRN(StreamFontCollectionLoader::Create(fontFileLoader.get(), &fontCollectionLoader));
- HRN(factory->RegisterFontCollectionLoader(fontCollectionLoader.get()));
- SkAutoIDWriteUnregister<StreamFontCollectionLoader> autoUnregisterFontCollectionLoader(
- factory, fontCollectionLoader.get());
-
- SkTScopedComPtr<IDWriteFontCollection> fontCollection;
- HRN(factory->CreateCustomFontCollection(fontCollectionLoader.get(), NULL, 0, &fontCollection));
-
- // Find the first non-simulated font which has the given ttc index.
- UINT32 familyCount = fontCollection->GetFontFamilyCount();
- for (UINT32 familyIndex = 0; familyIndex < familyCount; ++familyIndex) {
- SkTScopedComPtr<IDWriteFontFamily> fontFamily;
- HRN(fontCollection->GetFontFamily(familyIndex, &fontFamily));
-
- UINT32 fontCount = fontFamily->GetFontCount();
- for (UINT32 fontIndex = 0; fontIndex < fontCount; ++fontIndex) {
- SkTScopedComPtr<IDWriteFont> font;
- HRN(fontFamily->GetFont(fontIndex, &font));
- if (font->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) {
- continue;
- }
-
- SkTScopedComPtr<IDWriteFontFace> fontFace;
- HRN(font->CreateFontFace(&fontFace));
-
- UINT32 faceIndex = fontFace->GetIndex();
- if (faceIndex == ttcIndex) {
- return DWriteFontTypeface::Create(fontFace.get(), font.get(), fontFamily.get(),
- autoUnregisterFontFileLoader.detatch(),
- autoUnregisterFontCollectionLoader.detatch());
- }
- }
- }
-
- return NULL;
-}
-
-SkStream* DWriteFontTypeface::onOpenStream(int* ttcIndex) const {
- *ttcIndex = fDWriteFontFace->GetIndex();
-
- UINT32 numFiles;
- HRNM(fDWriteFontFace->GetFiles(&numFiles, NULL),
- "Could not get number of font files.");
- if (numFiles != 1) {
- return NULL;
- }
-
- SkTScopedComPtr<IDWriteFontFile> fontFile;
- HRNM(fDWriteFontFace->GetFiles(&numFiles, &fontFile), "Could not get font files.");
-
- const void* fontFileKey;
- UINT32 fontFileKeySize;
- HRNM(fontFile->GetReferenceKey(&fontFileKey, &fontFileKeySize),
- "Could not get font file reference key.");
-
- SkTScopedComPtr<IDWriteFontFileLoader> fontFileLoader;
- HRNM(fontFile->GetLoader(&fontFileLoader), "Could not get font file loader.");
-
- SkTScopedComPtr<IDWriteFontFileStream> fontFileStream;
- HRNM(fontFileLoader->CreateStreamFromKey(fontFileKey, fontFileKeySize,
- &fontFileStream),
- "Could not create font file stream.");
-
- return SkNEW_ARGS(SkDWriteFontFileStream, (fontFileStream.get()));
-}
-
-SkScalerContext* DWriteFontTypeface::onCreateScalerContext(const SkDescriptor* desc) const {
- return SkNEW_ARGS(SkScalerContext_DW, (const_cast<DWriteFontTypeface*>(this), desc));
-}
-
-void DWriteFontTypeface::onFilterRec(SkScalerContext::Rec* rec) const {
- if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag ||
- rec->fFlags & SkScalerContext::kLCD_Vertical_Flag)
- {
- rec->fMaskFormat = SkMask::kA8_Format;
- }
-
- unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag |
- SkScalerContext::kAutohinting_Flag |
- SkScalerContext::kEmbeddedBitmapText_Flag |
- SkScalerContext::kEmbolden_Flag |
- SkScalerContext::kLCD_BGROrder_Flag |
- SkScalerContext::kLCD_Vertical_Flag;
- rec->fFlags &= ~flagsWeDontSupport;
-
- SkPaint::Hinting h = rec->getHinting();
- // DirectWrite does not provide for hinting hints.
- h = SkPaint::kSlight_Hinting;
- rec->setHinting(h);
-
-#if SK_FONT_HOST_USE_SYSTEM_SETTINGS
- IDWriteFactory* factory = get_dwrite_factory();
- if (factory != NULL) {
- SkTScopedComPtr<IDWriteRenderingParams> defaultRenderingParams;
- if (SUCCEEDED(factory->CreateRenderingParams(&defaultRenderingParams))) {
- float gamma = defaultRenderingParams->GetGamma();
- rec->setDeviceGamma(gamma);
- rec->setPaintGamma(gamma);
-
- rec->setContrast(defaultRenderingParams->GetEnhancedContrast());
- }
- }
-#endif
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//PDF Support
-
-using namespace skia_advanced_typeface_metrics_utils;
-
-// Construct Glyph to Unicode table.
-// Unicode code points that require conjugate pairs in utf16 are not
-// supported.
-// TODO(arthurhsu): Add support for conjugate pairs. It looks like that may
-// require parsing the TTF cmap table (platform 4, encoding 12) directly instead
-// of calling GetFontUnicodeRange().
-// TODO(bungeman): This never does what anyone wants.
-// What is really wanted is the text to glyphs mapping
-static void populate_glyph_to_unicode(IDWriteFontFace* fontFace,
- const unsigned glyphCount,
- SkTDArray<SkUnichar>* glyphToUnicode) {
- HRESULT hr = S_OK;
-
- //Do this like free type instead
- UINT32 count = 0;
- for (UINT32 c = 0; c < 0x10FFFF; ++c) {
- UINT16 glyph;
- hr = fontFace->GetGlyphIndices(&c, 1, &glyph);
- if (glyph > 0) {
- ++count;
- }
- }
-
- SkAutoTArray<UINT32> chars(count);
- count = 0;
- for (UINT32 c = 0; c < 0x10FFFF; ++c) {
- UINT16 glyph;
- hr = fontFace->GetGlyphIndices(&c, 1, &glyph);
- if (glyph > 0) {
- chars[count] = c;
- ++count;
- }
- }
-
- SkAutoTArray<UINT16> glyph(count);
- fontFace->GetGlyphIndices(chars.get(), count, glyph.get());
-
- USHORT maxGlyph = 0;
- for (USHORT j = 0; j < count; ++j) {
- if (glyph[j] > maxGlyph) maxGlyph = glyph[j];
- }
-
- glyphToUnicode->setCount(maxGlyph+1);
- for (USHORT j = 0; j < maxGlyph+1u; ++j) {
- (*glyphToUnicode)[j] = 0;
- }
-
- //'invert'
- for (USHORT j = 0; j < count; ++j) {
- if (glyph[j] < glyphCount && (*glyphToUnicode)[glyph[j]] == 0) {
- (*glyphToUnicode)[glyph[j]] = chars[j];
- }
- }
-}
-
-static bool getWidthAdvance(IDWriteFontFace* fontFace, int gId, int16_t* advance) {
- SkASSERT(advance);
-
- UINT16 glyphId = gId;
- DWRITE_GLYPH_METRICS gm;
- HRESULT hr = fontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm);
-
- if (FAILED(hr)) {
- *advance = 0;
- return false;
- }
-
- *advance = gm.advanceWidth;
- return true;
-}
-
-template<typename T> class AutoTDWriteTable : public AutoDWriteTable {
-public:
- static const UINT32 tag = DWRITE_MAKE_OPENTYPE_TAG(T::TAG0, T::TAG1, T::TAG2, T::TAG3);
- AutoTDWriteTable(IDWriteFontFace* fontFace) : AutoDWriteTable(fontFace, tag) { }
-
- const T* operator->() const { return reinterpret_cast<const T*>(fData); }
-};
-
-SkAdvancedTypefaceMetrics* DWriteFontTypeface::onGetAdvancedTypefaceMetrics(
- SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
- const uint32_t* glyphIDs,
- uint32_t glyphIDsCount) const {
-
- SkAdvancedTypefaceMetrics* info = NULL;
-
- HRESULT hr = S_OK;
-
- const unsigned glyphCount = fDWriteFontFace->GetGlyphCount();
-
- DWRITE_FONT_METRICS dwfm;
- fDWriteFontFace->GetMetrics(&dwfm);
-
- info = new SkAdvancedTypefaceMetrics;
- info->fEmSize = dwfm.designUnitsPerEm;
- info->fMultiMaster = false;
- info->fLastGlyphID = SkToU16(glyphCount - 1);
- info->fStyle = 0;
-
-
- SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
- SkTScopedComPtr<IDWriteLocalizedStrings> faceNames;
- hr = fDWriteFontFamily->GetFamilyNames(&familyNames);
- hr = fDWriteFont->GetFaceNames(&faceNames);
-
- UINT32 familyNameLength;
- hr = familyNames->GetStringLength(0, &familyNameLength);
-
- UINT32 faceNameLength;
- hr = faceNames->GetStringLength(0, &faceNameLength);
-
- UINT32 size = familyNameLength+1+faceNameLength+1;
- SkSMallocWCHAR wFamilyName(size);
- hr = familyNames->GetString(0, wFamilyName.get(), size);
- wFamilyName[familyNameLength] = L' ';
- hr = faceNames->GetString(0, &wFamilyName[familyNameLength+1], size - faceNameLength + 1);
-
- hr = wchar_to_skstring(wFamilyName.get(), &info->fFontName);
-
- if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) {
- populate_glyph_to_unicode(fDWriteFontFace.get(), glyphCount, &(info->fGlyphToUnicode));
- }
-
- DWRITE_FONT_FACE_TYPE fontType = fDWriteFontFace->GetType();
- if (fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE ||
- fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION) {
- info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
- } else {
- info->fType = SkAdvancedTypefaceMetrics::kOther_Font;
- info->fItalicAngle = 0;
- info->fAscent = dwfm.ascent;;
- info->fDescent = dwfm.descent;
- info->fStemV = 0;
- info->fCapHeight = dwfm.capHeight;
- info->fBBox = SkIRect::MakeEmpty();
- return info;
- }
-
- AutoTDWriteTable<SkOTTableHead> headTable(fDWriteFontFace.get());
- AutoTDWriteTable<SkOTTablePostScript> postTable(fDWriteFontFace.get());
- AutoTDWriteTable<SkOTTableHorizontalHeader> hheaTable(fDWriteFontFace.get());
- AutoTDWriteTable<SkOTTableOS2> os2Table(fDWriteFontFace.get());
- if (!headTable.fExists || !postTable.fExists || !hheaTable.fExists || !os2Table.fExists) {
- info->fItalicAngle = 0;
- info->fAscent = dwfm.ascent;;
- info->fDescent = dwfm.descent;
- info->fStemV = 0;
- info->fCapHeight = dwfm.capHeight;
- info->fBBox = SkIRect::MakeEmpty();
- return info;
- }
-
- //There exist CJK fonts which set the IsFixedPitch and Monospace bits,
- //but have full width, latin half-width, and half-width kana.
- bool fixedWidth = (postTable->isFixedPitch &&
- (1 == SkEndian_SwapBE16(hheaTable->numberOfHMetrics)));
- //Monospace
- if (fixedWidth) {
- info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
- }
- //Italic
- if (os2Table->version.v0.fsSelection.field.Italic) {
- info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
- }
- //Script
- if (SkPanose::FamilyType::Script == os2Table->version.v0.panose.bFamilyType.value) {
- info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
- //Serif
- } else if (SkPanose::FamilyType::TextAndDisplay == os2Table->version.v0.panose.bFamilyType.value &&
- SkPanose::Data::TextAndDisplay::SerifStyle::Triangle <= os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value &&
- SkPanose::Data::TextAndDisplay::SerifStyle::NoFit != os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value) {
- info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
- }
-
- info->fItalicAngle = SkEndian_SwapBE32(postTable->italicAngle) >> 16;
-
- info->fAscent = SkToS16(dwfm.ascent);
- info->fDescent = SkToS16(dwfm.descent);
- info->fCapHeight = SkToS16(dwfm.capHeight);
-
- info->fBBox = SkIRect::MakeLTRB((int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMin),
- (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMax),
- (int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMax),
- (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMin));
-
- //TODO: is this even desired? It seems PDF only wants this value for Type1
- //fonts, and we only get here for TrueType fonts.
- info->fStemV = 0;
- /*
- // Figure out a good guess for StemV - Min width of i, I, !, 1.
- // This probably isn't very good with an italic font.
- int16_t min_width = SHRT_MAX;
- info->fStemV = 0;
- char stem_chars[] = {'i', 'I', '!', '1'};
- for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
- ABC abcWidths;
- if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) {
- int16_t width = abcWidths.abcB;
- if (width > 0 && width < min_width) {
- min_width = width;
- info->fStemV = min_width;
- }
- }
- }
- */
-
- // If Restricted, the font may not be embedded in a document.
- // If not Restricted, the font can be embedded.
- // If PreviewPrint, the embedding is read-only.
- if (os2Table->version.v0.fsType.field.Restricted) {
- info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
- } else if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) {
- if (fixedWidth) {
- appendRange(&info->fGlyphWidths, 0);
- int16_t advance;
- getWidthAdvance(fDWriteFontFace.get(), 1, &advance);
- info->fGlyphWidths->fAdvance.append(1, &advance);
- finishRange(info->fGlyphWidths.get(), 0,
- SkAdvancedTypefaceMetrics::WidthRange::kDefault);
- } else {
- info->fGlyphWidths.reset(
- getAdvanceData(fDWriteFontFace.get(),
- glyphCount,
- glyphIDs,
- glyphIDsCount,
- getWidthAdvance));
- }
- }
-
- return info;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-static void get_locale_string(IDWriteLocalizedStrings* names, const WCHAR* preferedLocale,
- SkString* skname) {
- UINT32 nameIndex = 0;
- if (preferedLocale) {
- // Ignore any errors and continue with index 0 if there is a problem.
- BOOL nameExists;
- names->FindLocaleName(preferedLocale, &nameIndex, &nameExists);
- if (!nameExists) {
- nameIndex = 0;
- }
- }
-
- UINT32 nameLength;
- HRVM(names->GetStringLength(nameIndex, &nameLength), "Could not get name length.");
- nameLength += 1;
-
- SkSMallocWCHAR name(nameLength);
- HRVM(names->GetString(nameIndex, name.get(), nameLength), "Could not get string.");
-
- HRV(wchar_to_skstring(name.get(), skname));
-}
-
-SkTypeface* SkFontMgr_DirectWrite::createTypefaceFromDWriteFont(
- IDWriteFontFace* fontFace,
- IDWriteFont* font,
- IDWriteFontFamily* fontFamily,
- StreamFontFileLoader* fontFileLoader,
- IDWriteFontCollectionLoader* fontCollectionLoader) {
- SkTypeface* face = FindByProcAndRef(FindByDWriteFont, font);
- if (NULL == face) {
- face = DWriteFontTypeface::Create(fontFace, font, fontFamily,
- fontFileLoader, fontCollectionLoader);
- if (face) {
- Add(face, get_style(font), fontCollectionLoader != NULL);
- }
- }
- return face;
-}
-
-int SkFontMgr_DirectWrite::onCountFamilies() {
- return fFontCollection->GetFontFamilyCount();
-}
-
-void SkFontMgr_DirectWrite::onGetFamilyName(int index, SkString* familyName) {
- SkTScopedComPtr<IDWriteFontFamily> fontFamily;
- HRVM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
-
- SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
- HRVM(fontFamily->GetFamilyNames(&familyNames), "Could not get family names.");
-
- get_locale_string(familyNames.get(), fLocaleName.get(), familyName);
-}
-
-SkFontStyleSet* SkFontMgr_DirectWrite::onCreateStyleSet(int index) {
- SkTScopedComPtr<IDWriteFontFamily> fontFamily;
- HRNM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
-
- return SkNEW_ARGS(SkFontStyleSet_DirectWrite, (this, fontFamily.get()));
-}
-
-SkFontStyleSet* SkFontMgr_DirectWrite::onMatchFamily(const char familyName[]) {
- SkSMallocWCHAR dwFamilyName;
- HRN(cstring_to_wchar(familyName, &dwFamilyName));
-
- UINT32 index;
- BOOL exists;
- HRNM(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists),
- "Failed while finding family by name.");
- if (!exists) {
- return NULL;
- }
-
- return this->onCreateStyleSet(index);
-}
-
-SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyle(const char familyName[],
- const SkFontStyle& fontstyle) {
- SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
- return sset->matchStyle(fontstyle);
-}
-
-SkTypeface* SkFontMgr_DirectWrite::onMatchFaceStyle(const SkTypeface* familyMember,
- const SkFontStyle& fontstyle) {
- SkString familyName;
- SkFontStyleSet_DirectWrite sset(
- this, ((DWriteFontTypeface*)familyMember)->fDWriteFontFamily.get()
- );
- return sset.matchStyle(fontstyle);
-}
-
-SkTypeface* SkFontMgr_DirectWrite::onCreateFromStream(SkStream* stream, int ttcIndex) {
- return create_from_stream(stream, ttcIndex);
-}
-
-SkTypeface* SkFontMgr_DirectWrite::onCreateFromData(SkData* data, int ttcIndex) {
- SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream, (data)));
- return this->createFromStream(stream, ttcIndex);
-}
-
-SkTypeface* SkFontMgr_DirectWrite::onCreateFromFile(const char path[], int ttcIndex) {
- SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
- return this->createFromStream(stream, ttcIndex);
-}
-
-HRESULT SkFontMgr_DirectWrite::getByFamilyName(const WCHAR wideFamilyName[],
- IDWriteFontFamily** fontFamily) {
- UINT32 index;
- BOOL exists;
- HR(fFontCollection->FindFamilyName(wideFamilyName, &index, &exists));
-
- if (exists) {
- HR(fFontCollection->GetFontFamily(index, fontFamily));
- return S_OK;
- }
- return S_FALSE;
-}
-
-HRESULT SkFontMgr_DirectWrite::getDefaultFontFamily(IDWriteFontFamily** fontFamily) {
- NONCLIENTMETRICSW metrics;
- metrics.cbSize = sizeof(metrics);
- if (0 == SystemParametersInfoW(SPI_GETNONCLIENTMETRICS,
- sizeof(metrics),
- &metrics,
- 0)) {
- return E_UNEXPECTED;
- }
- HRM(this->getByFamilyName(metrics.lfMessageFont.lfFaceName, fontFamily),
- "Could not create DWrite font family from LOGFONT.");
-
- return S_OK;
-}
-
-SkTypeface* SkFontMgr_DirectWrite::onLegacyCreateTypeface(const char familyName[],
- unsigned styleBits) {
- SkTScopedComPtr<IDWriteFontFamily> fontFamily;
- if (familyName) {
- SkSMallocWCHAR wideFamilyName;
- if (SUCCEEDED(cstring_to_wchar(familyName, &wideFamilyName))) {
- this->getByFamilyName(wideFamilyName, &fontFamily);
- }
- }
-
- if (NULL == fontFamily.get()) {
- // No family with given name, try default.
- HRNM(this->getDefaultFontFamily(&fontFamily), "Could not get default font family.");
- }
-
- SkTScopedComPtr<IDWriteFont> font;
- DWRITE_FONT_WEIGHT weight = (styleBits & SkTypeface::kBold)
- ? DWRITE_FONT_WEIGHT_BOLD
- : DWRITE_FONT_WEIGHT_NORMAL;
- DWRITE_FONT_STRETCH stretch = DWRITE_FONT_STRETCH_UNDEFINED;
- DWRITE_FONT_STYLE italic = (styleBits & SkTypeface::kItalic)
- ? DWRITE_FONT_STYLE_ITALIC
- : DWRITE_FONT_STYLE_NORMAL;
- HRNM(fontFamily->GetFirstMatchingFont(weight, stretch, italic, &font),
- "Could not get matching font.");
-
- SkTScopedComPtr<IDWriteFontFace> fontFace;
- HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
-
- return this->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get());
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-int SkFontStyleSet_DirectWrite::count() {
- return fFontFamily->GetFontCount();
-}
-
-SkTypeface* SkFontStyleSet_DirectWrite::createTypeface(int index) {
- SkTScopedComPtr<IDWriteFont> font;
- HRNM(fFontFamily->GetFont(index, &font), "Could not get font.");
-
- SkTScopedComPtr<IDWriteFontFace> fontFace;
- HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
-
- return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fFontFamily.get());
-}
-
-void SkFontStyleSet_DirectWrite::getStyle(int index, SkFontStyle* fs, SkString* styleName) {
- SkTScopedComPtr<IDWriteFont> font;
- HRVM(fFontFamily->GetFont(index, &font), "Could not get font.");
-
- SkFontStyle::Slant slant;
- switch (font->GetStyle()) {
- case DWRITE_FONT_STYLE_NORMAL:
- slant = SkFontStyle::kUpright_Slant;
- break;
- case DWRITE_FONT_STYLE_OBLIQUE:
- case DWRITE_FONT_STYLE_ITALIC:
- slant = SkFontStyle::kItalic_Slant;
- break;
- default:
- SkASSERT(false);
- }
-
- int weight = font->GetWeight();
- int width = font->GetStretch();
-
- *fs = SkFontStyle(weight, width, slant);
-
- SkTScopedComPtr<IDWriteLocalizedStrings> faceNames;
- if (SUCCEEDED(font->GetFaceNames(&faceNames))) {
- get_locale_string(faceNames.get(), fFontMgr->fLocaleName.get(), styleName);
- }
-}
-
-SkTypeface* SkFontStyleSet_DirectWrite::matchStyle(const SkFontStyle& pattern) {
- DWRITE_FONT_STYLE slant;
- switch (pattern.slant()) {
- case SkFontStyle::kUpright_Slant:
- slant = DWRITE_FONT_STYLE_NORMAL;
- break;
- case SkFontStyle::kItalic_Slant:
- slant = DWRITE_FONT_STYLE_ITALIC;
- break;
- default:
- SkASSERT(false);
- }
-
- DWRITE_FONT_WEIGHT weight = (DWRITE_FONT_WEIGHT)pattern.weight();
- DWRITE_FONT_STRETCH width = (DWRITE_FONT_STRETCH)pattern.width();
-
- SkTScopedComPtr<IDWriteFont> font;
- // TODO: perhaps use GetMatchingFonts and get the least simulated?
- HRNM(fFontFamily->GetFirstMatchingFont(weight, width, slant, &font),
- "Could not match font in family.");
-
- SkTScopedComPtr<IDWriteFontFace> fontFace;
- HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
-
- return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(),
- fFontFamily.get());
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-typedef decltype(GetUserDefaultLocaleName)* GetUserDefaultLocaleNameProc;
-static HRESULT GetGetUserDefaultLocaleNameProc(GetUserDefaultLocaleNameProc* proc) {
- *proc = reinterpret_cast<GetUserDefaultLocaleNameProc>(
- GetProcAddress(LoadLibraryW(L"Kernel32.dll"), "GetUserDefaultLocaleName")
- );
- if (!*proc) {
- HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
- if (!IS_ERROR(hr)) {
- hr = ERROR_PROC_NOT_FOUND;
- }
- return hr;
- }
- return S_OK;
-}
-
-SkFontMgr* SkFontMgr_New_DirectWrite() {
- IDWriteFactory* factory = get_dwrite_factory();
- if (NULL == factory) {
- return NULL;
- }
-
- SkTScopedComPtr<IDWriteFontCollection> sysFontCollection;
- HRNM(factory->GetSystemFontCollection(&sysFontCollection, FALSE),
- "Could not get system font collection.");
-
- WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH];
- WCHAR* localeName = NULL;
- int localeNameLen = 0;
-
- // Dynamically load GetUserDefaultLocaleName function, as it is not available on XP.
- GetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = NULL;
- HRESULT hr = GetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc);
- if (NULL == getUserDefaultLocaleNameProc) {
- SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName.");
- } else {
- localeNameLen = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_NAME_MAX_LENGTH);
- if (localeNameLen) {
- localeName = localeNameStorage;
- };
- }
-
- return SkNEW_ARGS(SkFontMgr_DirectWrite, (sysFontCollection.get(), localeName, localeNameLen));
-}
diff --git a/chromium/third_party/skia/src/ports/SkFontMgr_win_dw.cpp b/chromium/third_party/skia/src/ports/SkFontMgr_win_dw.cpp
new file mode 100644
index 00000000000..ecca57ff513
--- /dev/null
+++ b/chromium/third_party/skia/src/ports/SkFontMgr_win_dw.cpp
@@ -0,0 +1,764 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkDWrite.h"
+#include "SkDWriteFontFileStream.h"
+#include "SkFontMgr.h"
+#include "SkHRESULT.h"
+#include "SkStream.h"
+#include "SkTScopedComPtr.h"
+#include "SkThread.h"
+#include "SkTypeface.h"
+#include "SkTypefaceCache.h"
+#include "SkTypeface_win_dw.h"
+#include "SkTypes.h"
+
+#include <dwrite.h>
+
+////////////////////////////////////////////////////////////////////////////////
+
+class StreamFontFileLoader : public IDWriteFontFileLoader {
+public:
+ // IUnknown methods
+ virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
+ virtual ULONG STDMETHODCALLTYPE AddRef();
+ virtual ULONG STDMETHODCALLTYPE Release();
+
+ // IDWriteFontFileLoader methods
+ virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey(
+ void const* fontFileReferenceKey,
+ UINT32 fontFileReferenceKeySize,
+ IDWriteFontFileStream** fontFileStream);
+
+ static HRESULT Create(SkStream* stream, StreamFontFileLoader** streamFontFileLoader) {
+ *streamFontFileLoader = new StreamFontFileLoader(stream);
+ if (NULL == streamFontFileLoader) {
+ return E_OUTOFMEMORY;
+ }
+ return S_OK;
+ }
+
+ SkAutoTUnref<SkStream> fStream;
+
+private:
+ StreamFontFileLoader(SkStream* stream) : fRefCount(1), fStream(SkRef(stream)) { }
+ virtual ~StreamFontFileLoader() { }
+
+ ULONG fRefCount;
+};
+
+HRESULT StreamFontFileLoader::QueryInterface(REFIID iid, void** ppvObject) {
+ if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) {
+ *ppvObject = this;
+ AddRef();
+ return S_OK;
+ } else {
+ *ppvObject = NULL;
+ return E_NOINTERFACE;
+ }
+}
+
+ULONG StreamFontFileLoader::AddRef() {
+ return InterlockedIncrement(&fRefCount);
+}
+
+ULONG StreamFontFileLoader::Release() {
+ ULONG newCount = InterlockedDecrement(&fRefCount);
+ if (0 == newCount) {
+ delete this;
+ }
+ return newCount;
+}
+
+HRESULT StreamFontFileLoader::CreateStreamFromKey(
+ void const* fontFileReferenceKey,
+ UINT32 fontFileReferenceKeySize,
+ IDWriteFontFileStream** fontFileStream)
+{
+ SkTScopedComPtr<SkDWriteFontFileStreamWrapper> stream;
+ HR(SkDWriteFontFileStreamWrapper::Create(fStream, &stream));
+ *fontFileStream = stream.release();
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+class StreamFontFileEnumerator : public IDWriteFontFileEnumerator {
+public:
+ // IUnknown methods
+ virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
+ virtual ULONG STDMETHODCALLTYPE AddRef();
+ virtual ULONG STDMETHODCALLTYPE Release();
+
+ // IDWriteFontFileEnumerator methods
+ virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile);
+ virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** fontFile);
+
+ static HRESULT Create(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader,
+ StreamFontFileEnumerator** streamFontFileEnumerator) {
+ *streamFontFileEnumerator = new StreamFontFileEnumerator(factory, fontFileLoader);
+ if (NULL == streamFontFileEnumerator) {
+ return E_OUTOFMEMORY;
+ }
+ return S_OK;
+ }
+private:
+ StreamFontFileEnumerator(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader);
+ virtual ~StreamFontFileEnumerator() { }
+
+ ULONG fRefCount;
+
+ SkTScopedComPtr<IDWriteFactory> fFactory;
+ SkTScopedComPtr<IDWriteFontFile> fCurrentFile;
+ SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
+ bool fHasNext;
+};
+
+StreamFontFileEnumerator::StreamFontFileEnumerator(IDWriteFactory* factory,
+ IDWriteFontFileLoader* fontFileLoader)
+ : fRefCount(1)
+ , fFactory(SkRefComPtr(factory))
+ , fCurrentFile()
+ , fFontFileLoader(SkRefComPtr(fontFileLoader))
+ , fHasNext(true)
+{ }
+
+HRESULT StreamFontFileEnumerator::QueryInterface(REFIID iid, void** ppvObject) {
+ if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) {
+ *ppvObject = this;
+ AddRef();
+ return S_OK;
+ } else {
+ *ppvObject = NULL;
+ return E_NOINTERFACE;
+ }
+}
+
+ULONG StreamFontFileEnumerator::AddRef() {
+ return InterlockedIncrement(&fRefCount);
+}
+
+ULONG StreamFontFileEnumerator::Release() {
+ ULONG newCount = InterlockedDecrement(&fRefCount);
+ if (0 == newCount) {
+ delete this;
+ }
+ return newCount;
+}
+
+HRESULT StreamFontFileEnumerator::MoveNext(BOOL* hasCurrentFile) {
+ *hasCurrentFile = FALSE;
+
+ if (!fHasNext) {
+ return S_OK;
+ }
+ fHasNext = false;
+
+ UINT32 dummy = 0;
+ HR(fFactory->CreateCustomFontFileReference(
+ &dummy, //cannot be NULL
+ sizeof(dummy), //even if this is 0
+ fFontFileLoader.get(),
+ &fCurrentFile));
+
+ *hasCurrentFile = TRUE;
+ return S_OK;
+}
+
+HRESULT StreamFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile) {
+ if (fCurrentFile.get() == NULL) {
+ *fontFile = NULL;
+ return E_FAIL;
+ }
+
+ *fontFile = SkRefComPtr(fCurrentFile.get());
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+class StreamFontCollectionLoader : public IDWriteFontCollectionLoader {
+public:
+ // IUnknown methods
+ virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
+ virtual ULONG STDMETHODCALLTYPE AddRef();
+ virtual ULONG STDMETHODCALLTYPE Release();
+
+ // IDWriteFontCollectionLoader methods
+ virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey(
+ IDWriteFactory* factory,
+ void const* collectionKey,
+ UINT32 collectionKeySize,
+ IDWriteFontFileEnumerator** fontFileEnumerator);
+
+ static HRESULT Create(IDWriteFontFileLoader* fontFileLoader,
+ StreamFontCollectionLoader** streamFontCollectionLoader) {
+ *streamFontCollectionLoader = new StreamFontCollectionLoader(fontFileLoader);
+ if (NULL == streamFontCollectionLoader) {
+ return E_OUTOFMEMORY;
+ }
+ return S_OK;
+ }
+private:
+ StreamFontCollectionLoader(IDWriteFontFileLoader* fontFileLoader)
+ : fRefCount(1)
+ , fFontFileLoader(SkRefComPtr(fontFileLoader))
+ { }
+ virtual ~StreamFontCollectionLoader() { }
+
+ ULONG fRefCount;
+ SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
+};
+
+HRESULT StreamFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject) {
+ if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) {
+ *ppvObject = this;
+ AddRef();
+ return S_OK;
+ } else {
+ *ppvObject = NULL;
+ return E_NOINTERFACE;
+ }
+}
+
+ULONG StreamFontCollectionLoader::AddRef() {
+ return InterlockedIncrement(&fRefCount);
+}
+
+ULONG StreamFontCollectionLoader::Release() {
+ ULONG newCount = InterlockedDecrement(&fRefCount);
+ if (0 == newCount) {
+ delete this;
+ }
+ return newCount;
+}
+
+HRESULT StreamFontCollectionLoader::CreateEnumeratorFromKey(
+ IDWriteFactory* factory,
+ void const* collectionKey,
+ UINT32 collectionKeySize,
+ IDWriteFontFileEnumerator** fontFileEnumerator)
+{
+ SkTScopedComPtr<StreamFontFileEnumerator> enumerator;
+ HR(StreamFontFileEnumerator::Create(factory, fFontFileLoader.get(), &enumerator));
+ *fontFileEnumerator = enumerator.release();
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+class SkFontMgr_DirectWrite : public SkFontMgr {
+public:
+ /** localeNameLength must include the null terminator. */
+ SkFontMgr_DirectWrite(IDWriteFactory* factory, IDWriteFontCollection* fontCollection,
+ WCHAR* localeName, int localeNameLength)
+ : fFactory(SkRefComPtr(factory))
+ , fFontCollection(SkRefComPtr(fontCollection))
+ , fLocaleName(localeNameLength)
+ {
+ memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR));
+ }
+
+protected:
+ virtual int onCountFamilies() const SK_OVERRIDE;
+ virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE;
+ virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE;
+ virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE;
+ virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
+ const SkFontStyle& fontstyle) const SK_OVERRIDE;
+ virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
+ const SkFontStyle& fontstyle) const SK_OVERRIDE;
+ virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE;
+ virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE;
+ virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE;
+ virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
+ unsigned styleBits) const SK_OVERRIDE;
+
+private:
+ HRESULT getByFamilyName(const WCHAR familyName[], IDWriteFontFamily** fontFamily) const;
+ HRESULT getDefaultFontFamily(IDWriteFontFamily** fontFamily) const;
+
+ /** Creates a typeface using a typeface cache. */
+ SkTypeface* createTypefaceFromDWriteFont(IDWriteFontFace* fontFace,
+ IDWriteFont* font,
+ IDWriteFontFamily* fontFamily) const;
+
+ SkTScopedComPtr<IDWriteFactory> fFactory;
+ SkTScopedComPtr<IDWriteFontCollection> fFontCollection;
+ SkSMallocWCHAR fLocaleName;
+ mutable SkMutex fTFCacheMutex;
+ mutable SkTypefaceCache fTFCache;
+
+ friend class SkFontStyleSet_DirectWrite;
+};
+
+class SkFontStyleSet_DirectWrite : public SkFontStyleSet {
+public:
+ SkFontStyleSet_DirectWrite(const SkFontMgr_DirectWrite* fontMgr,
+ IDWriteFontFamily* fontFamily)
+ : fFontMgr(SkRef(fontMgr))
+ , fFontFamily(SkRefComPtr(fontFamily))
+ { }
+
+ virtual int count() SK_OVERRIDE;
+ virtual void getStyle(int index, SkFontStyle* fs, SkString* styleName) SK_OVERRIDE;
+ virtual SkTypeface* createTypeface(int index) SK_OVERRIDE;
+ virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE;
+
+private:
+ SkAutoTUnref<const SkFontMgr_DirectWrite> fFontMgr;
+ SkTScopedComPtr<IDWriteFontFamily> fFontFamily;
+};
+
+static HRESULT are_same(IUnknown* a, IUnknown* b, bool& same) {
+ SkTScopedComPtr<IUnknown> iunkA;
+ HRM(a->QueryInterface(&iunkA), "Failed to QI<IUnknown> for a.");
+
+ SkTScopedComPtr<IUnknown> iunkB;
+ HRM(b->QueryInterface(&iunkB), "Failed to QI<IUnknown> for b.");
+
+ same = (iunkA.get() == iunkB.get());
+ return S_OK;
+}
+
+struct ProtoDWriteTypeface {
+ IDWriteFontFace* fDWriteFontFace;
+ IDWriteFont* fDWriteFont;
+ IDWriteFontFamily* fDWriteFontFamily;
+};
+
+static bool FindByDWriteFont(SkTypeface* cached, SkTypeface::Style, void* ctx) {
+ DWriteFontTypeface* cshFace = reinterpret_cast<DWriteFontTypeface*>(cached);
+ ProtoDWriteTypeface* ctxFace = reinterpret_cast<ProtoDWriteTypeface*>(ctx);
+ bool same;
+
+ //Check to see if the two fonts are identical.
+ HRB(are_same(cshFace->fDWriteFont.get(), ctxFace->fDWriteFont, same));
+ if (same) {
+ return true;
+ }
+
+ HRB(are_same(cshFace->fDWriteFontFace.get(), ctxFace->fDWriteFontFace, same));
+ if (same) {
+ return true;
+ }
+
+ //Check if the two fonts share the same loader and have the same key.
+ UINT32 cshNumFiles;
+ UINT32 ctxNumFiles;
+ HRB(cshFace->fDWriteFontFace->GetFiles(&cshNumFiles, NULL));
+ HRB(ctxFace->fDWriteFontFace->GetFiles(&ctxNumFiles, NULL));
+ if (cshNumFiles != ctxNumFiles) {
+ return false;
+ }
+
+ SkTScopedComPtr<IDWriteFontFile> cshFontFile;
+ SkTScopedComPtr<IDWriteFontFile> ctxFontFile;
+ HRB(cshFace->fDWriteFontFace->GetFiles(&cshNumFiles, &cshFontFile));
+ HRB(ctxFace->fDWriteFontFace->GetFiles(&ctxNumFiles, &ctxFontFile));
+
+ //for (each file) { //we currently only admit fonts from one file.
+ SkTScopedComPtr<IDWriteFontFileLoader> cshFontFileLoader;
+ SkTScopedComPtr<IDWriteFontFileLoader> ctxFontFileLoader;
+ HRB(cshFontFile->GetLoader(&cshFontFileLoader));
+ HRB(ctxFontFile->GetLoader(&ctxFontFileLoader));
+ HRB(are_same(cshFontFileLoader.get(), ctxFontFileLoader.get(), same));
+ if (!same) {
+ return false;
+ }
+ //}
+
+ const void* cshRefKey;
+ UINT32 cshRefKeySize;
+ const void* ctxRefKey;
+ UINT32 ctxRefKeySize;
+ HRB(cshFontFile->GetReferenceKey(&cshRefKey, &cshRefKeySize));
+ HRB(ctxFontFile->GetReferenceKey(&ctxRefKey, &ctxRefKeySize));
+ if (cshRefKeySize != ctxRefKeySize) {
+ return false;
+ }
+ if (0 != memcmp(cshRefKey, ctxRefKey, ctxRefKeySize)) {
+ return false;
+ }
+
+ //TODO: better means than comparing name strings?
+ //NOTE: .ttc and fake bold/italic will end up here.
+ SkTScopedComPtr<IDWriteLocalizedStrings> cshFamilyNames;
+ SkTScopedComPtr<IDWriteLocalizedStrings> cshFaceNames;
+ HRB(cshFace->fDWriteFontFamily->GetFamilyNames(&cshFamilyNames));
+ HRB(cshFace->fDWriteFont->GetFaceNames(&cshFaceNames));
+ UINT32 cshFamilyNameLength;
+ UINT32 cshFaceNameLength;
+ HRB(cshFamilyNames->GetStringLength(0, &cshFamilyNameLength));
+ HRB(cshFaceNames->GetStringLength(0, &cshFaceNameLength));
+
+ SkTScopedComPtr<IDWriteLocalizedStrings> ctxFamilyNames;
+ SkTScopedComPtr<IDWriteLocalizedStrings> ctxFaceNames;
+ HRB(ctxFace->fDWriteFontFamily->GetFamilyNames(&ctxFamilyNames));
+ HRB(ctxFace->fDWriteFont->GetFaceNames(&ctxFaceNames));
+ UINT32 ctxFamilyNameLength;
+ UINT32 ctxFaceNameLength;
+ HRB(ctxFamilyNames->GetStringLength(0, &ctxFamilyNameLength));
+ HRB(ctxFaceNames->GetStringLength(0, &ctxFaceNameLength));
+
+ if (cshFamilyNameLength != ctxFamilyNameLength ||
+ cshFaceNameLength != ctxFaceNameLength)
+ {
+ return false;
+ }
+
+ SkSMallocWCHAR cshFamilyName(cshFamilyNameLength+1);
+ SkSMallocWCHAR cshFaceName(cshFaceNameLength+1);
+ HRB(cshFamilyNames->GetString(0, cshFamilyName.get(), cshFamilyNameLength+1));
+ HRB(cshFaceNames->GetString(0, cshFaceName.get(), cshFaceNameLength+1));
+
+ SkSMallocWCHAR ctxFamilyName(ctxFamilyNameLength+1);
+ SkSMallocWCHAR ctxFaceName(ctxFaceNameLength+1);
+ HRB(ctxFamilyNames->GetString(0, ctxFamilyName.get(), ctxFamilyNameLength+1));
+ HRB(ctxFaceNames->GetString(0, ctxFaceName.get(), ctxFaceNameLength+1));
+
+ return wcscmp(cshFamilyName.get(), ctxFamilyName.get()) == 0 &&
+ wcscmp(cshFaceName.get(), ctxFaceName.get()) == 0;
+}
+
+SkTypeface* SkFontMgr_DirectWrite::createTypefaceFromDWriteFont(
+ IDWriteFontFace* fontFace,
+ IDWriteFont* font,
+ IDWriteFontFamily* fontFamily) const {
+ SkAutoMutexAcquire ama(fTFCacheMutex);
+ ProtoDWriteTypeface spec = { fontFace, font, fontFamily };
+ SkTypeface* face = fTFCache.findByProcAndRef(FindByDWriteFont, &spec);
+ if (NULL == face) {
+ face = DWriteFontTypeface::Create(fFactory.get(), fontFace, font, fontFamily);
+ if (face) {
+ fTFCache.add(face, get_style(font), true);
+ }
+ }
+ return face;
+}
+
+int SkFontMgr_DirectWrite::onCountFamilies() const {
+ return fFontCollection->GetFontFamilyCount();
+}
+
+void SkFontMgr_DirectWrite::onGetFamilyName(int index, SkString* familyName) const {
+ SkTScopedComPtr<IDWriteFontFamily> fontFamily;
+ HRVM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
+
+ SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
+ HRVM(fontFamily->GetFamilyNames(&familyNames), "Could not get family names.");
+
+ sk_get_locale_string(familyNames.get(), fLocaleName.get(), familyName);
+}
+
+SkFontStyleSet* SkFontMgr_DirectWrite::onCreateStyleSet(int index) const {
+ SkTScopedComPtr<IDWriteFontFamily> fontFamily;
+ HRNM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
+
+ return SkNEW_ARGS(SkFontStyleSet_DirectWrite, (this, fontFamily.get()));
+}
+
+SkFontStyleSet* SkFontMgr_DirectWrite::onMatchFamily(const char familyName[]) const {
+ SkSMallocWCHAR dwFamilyName;
+ HRN(sk_cstring_to_wchar(familyName, &dwFamilyName));
+
+ UINT32 index;
+ BOOL exists;
+ HRNM(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists),
+ "Failed while finding family by name.");
+ if (!exists) {
+ return NULL;
+ }
+
+ return this->onCreateStyleSet(index);
+}
+
+SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyle(const char familyName[],
+ const SkFontStyle& fontstyle) const {
+ SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
+ return sset->matchStyle(fontstyle);
+}
+
+SkTypeface* SkFontMgr_DirectWrite::onMatchFaceStyle(const SkTypeface* familyMember,
+ const SkFontStyle& fontstyle) const {
+ SkString familyName;
+ SkFontStyleSet_DirectWrite sset(
+ this, ((DWriteFontTypeface*)familyMember)->fDWriteFontFamily.get()
+ );
+ return sset.matchStyle(fontstyle);
+}
+
+template <typename T> class SkAutoIDWriteUnregister {
+public:
+ SkAutoIDWriteUnregister(IDWriteFactory* factory, T* unregister)
+ : fFactory(factory), fUnregister(unregister)
+ { }
+
+ ~SkAutoIDWriteUnregister() {
+ if (fUnregister) {
+ unregister(fFactory, fUnregister);
+ }
+ }
+
+ T* detatch() {
+ T* old = fUnregister;
+ fUnregister = NULL;
+ return old;
+ }
+
+private:
+ HRESULT unregister(IDWriteFactory* factory, IDWriteFontFileLoader* unregister) {
+ return factory->UnregisterFontFileLoader(unregister);
+ }
+
+ HRESULT unregister(IDWriteFactory* factory, IDWriteFontCollectionLoader* unregister) {
+ return factory->UnregisterFontCollectionLoader(unregister);
+ }
+
+ IDWriteFactory* fFactory;
+ T* fUnregister;
+};
+
+SkTypeface* SkFontMgr_DirectWrite::onCreateFromStream(SkStream* stream, int ttcIndex) const {
+ SkTScopedComPtr<StreamFontFileLoader> fontFileLoader;
+ HRN(StreamFontFileLoader::Create(stream, &fontFileLoader));
+ HRN(fFactory->RegisterFontFileLoader(fontFileLoader.get()));
+ SkAutoIDWriteUnregister<StreamFontFileLoader> autoUnregisterFontFileLoader(
+ fFactory.get(), fontFileLoader.get());
+
+ SkTScopedComPtr<StreamFontCollectionLoader> fontCollectionLoader;
+ HRN(StreamFontCollectionLoader::Create(fontFileLoader.get(), &fontCollectionLoader));
+ HRN(fFactory->RegisterFontCollectionLoader(fontCollectionLoader.get()));
+ SkAutoIDWriteUnregister<StreamFontCollectionLoader> autoUnregisterFontCollectionLoader(
+ fFactory.get(), fontCollectionLoader.get());
+
+ SkTScopedComPtr<IDWriteFontCollection> fontCollection;
+ HRN(fFactory->CreateCustomFontCollection(fontCollectionLoader.get(), NULL, 0, &fontCollection));
+
+ // Find the first non-simulated font which has the given ttc index.
+ UINT32 familyCount = fontCollection->GetFontFamilyCount();
+ for (UINT32 familyIndex = 0; familyIndex < familyCount; ++familyIndex) {
+ SkTScopedComPtr<IDWriteFontFamily> fontFamily;
+ HRN(fontCollection->GetFontFamily(familyIndex, &fontFamily));
+
+ UINT32 fontCount = fontFamily->GetFontCount();
+ for (UINT32 fontIndex = 0; fontIndex < fontCount; ++fontIndex) {
+ SkTScopedComPtr<IDWriteFont> font;
+ HRN(fontFamily->GetFont(fontIndex, &font));
+ if (font->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) {
+ continue;
+ }
+
+ SkTScopedComPtr<IDWriteFontFace> fontFace;
+ HRN(font->CreateFontFace(&fontFace));
+
+ UINT32 faceIndex = fontFace->GetIndex();
+ if (faceIndex == ttcIndex) {
+ return DWriteFontTypeface::Create(fFactory.get(),
+ fontFace.get(), font.get(), fontFamily.get(),
+ autoUnregisterFontFileLoader.detatch(),
+ autoUnregisterFontCollectionLoader.detatch());
+ }
+ }
+ }
+
+ return NULL;
+}
+
+SkTypeface* SkFontMgr_DirectWrite::onCreateFromData(SkData* data, int ttcIndex) const {
+ SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream, (data)));
+ return this->createFromStream(stream, ttcIndex);
+}
+
+SkTypeface* SkFontMgr_DirectWrite::onCreateFromFile(const char path[], int ttcIndex) const {
+ SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
+ return this->createFromStream(stream, ttcIndex);
+}
+
+HRESULT SkFontMgr_DirectWrite::getByFamilyName(const WCHAR wideFamilyName[],
+ IDWriteFontFamily** fontFamily) const {
+ UINT32 index;
+ BOOL exists;
+ HR(fFontCollection->FindFamilyName(wideFamilyName, &index, &exists));
+
+ if (exists) {
+ HR(fFontCollection->GetFontFamily(index, fontFamily));
+ }
+ return S_OK;
+}
+
+HRESULT SkFontMgr_DirectWrite::getDefaultFontFamily(IDWriteFontFamily** fontFamily) const {
+ NONCLIENTMETRICSW metrics;
+ metrics.cbSize = sizeof(metrics);
+ if (0 == SystemParametersInfoW(SPI_GETNONCLIENTMETRICS,
+ sizeof(metrics),
+ &metrics,
+ 0)) {
+ return E_UNEXPECTED;
+ }
+ HRM(this->getByFamilyName(metrics.lfMessageFont.lfFaceName, fontFamily),
+ "Could not create DWrite font family from LOGFONT.");
+ return S_OK;
+}
+
+SkTypeface* SkFontMgr_DirectWrite::onLegacyCreateTypeface(const char familyName[],
+ unsigned styleBits) const {
+ SkTScopedComPtr<IDWriteFontFamily> fontFamily;
+ if (familyName) {
+ SkSMallocWCHAR wideFamilyName;
+ if (SUCCEEDED(sk_cstring_to_wchar(familyName, &wideFamilyName))) {
+ this->getByFamilyName(wideFamilyName, &fontFamily);
+ }
+ }
+
+ if (NULL == fontFamily.get()) {
+ // No family with given name, try default.
+ HRNM(this->getDefaultFontFamily(&fontFamily), "Could not get default font family.");
+ }
+
+ if (NULL == fontFamily.get()) {
+ // Could not obtain the default font.
+ HRNM(fFontCollection->GetFontFamily(0, &fontFamily),
+ "Could not get default-default font family.");
+ }
+
+ SkTScopedComPtr<IDWriteFont> font;
+ DWRITE_FONT_WEIGHT weight = (styleBits & SkTypeface::kBold)
+ ? DWRITE_FONT_WEIGHT_BOLD
+ : DWRITE_FONT_WEIGHT_NORMAL;
+ DWRITE_FONT_STRETCH stretch = DWRITE_FONT_STRETCH_NORMAL;
+ DWRITE_FONT_STYLE italic = (styleBits & SkTypeface::kItalic)
+ ? DWRITE_FONT_STYLE_ITALIC
+ : DWRITE_FONT_STYLE_NORMAL;
+ HRNM(fontFamily->GetFirstMatchingFont(weight, stretch, italic, &font),
+ "Could not get matching font.");
+
+ SkTScopedComPtr<IDWriteFontFace> fontFace;
+ HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
+
+ return this->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+int SkFontStyleSet_DirectWrite::count() {
+ return fFontFamily->GetFontCount();
+}
+
+SkTypeface* SkFontStyleSet_DirectWrite::createTypeface(int index) {
+ SkTScopedComPtr<IDWriteFont> font;
+ HRNM(fFontFamily->GetFont(index, &font), "Could not get font.");
+
+ SkTScopedComPtr<IDWriteFontFace> fontFace;
+ HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
+
+ return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fFontFamily.get());
+}
+
+void SkFontStyleSet_DirectWrite::getStyle(int index, SkFontStyle* fs, SkString* styleName) {
+ SkTScopedComPtr<IDWriteFont> font;
+ HRVM(fFontFamily->GetFont(index, &font), "Could not get font.");
+
+ if (fs) {
+ SkFontStyle::Slant slant;
+ switch (font->GetStyle()) {
+ case DWRITE_FONT_STYLE_NORMAL:
+ slant = SkFontStyle::kUpright_Slant;
+ break;
+ case DWRITE_FONT_STYLE_OBLIQUE:
+ case DWRITE_FONT_STYLE_ITALIC:
+ slant = SkFontStyle::kItalic_Slant;
+ break;
+ default:
+ SkASSERT(false);
+ }
+
+ int weight = font->GetWeight();
+ int width = font->GetStretch();
+
+ *fs = SkFontStyle(weight, width, slant);
+ }
+
+ if (styleName) {
+ SkTScopedComPtr<IDWriteLocalizedStrings> faceNames;
+ if (SUCCEEDED(font->GetFaceNames(&faceNames))) {
+ sk_get_locale_string(faceNames.get(), fFontMgr->fLocaleName.get(), styleName);
+ }
+ }
+}
+
+SkTypeface* SkFontStyleSet_DirectWrite::matchStyle(const SkFontStyle& pattern) {
+ DWRITE_FONT_STYLE slant;
+ switch (pattern.slant()) {
+ case SkFontStyle::kUpright_Slant:
+ slant = DWRITE_FONT_STYLE_NORMAL;
+ break;
+ case SkFontStyle::kItalic_Slant:
+ slant = DWRITE_FONT_STYLE_ITALIC;
+ break;
+ default:
+ SkASSERT(false);
+ }
+
+ DWRITE_FONT_WEIGHT weight = (DWRITE_FONT_WEIGHT)pattern.weight();
+ DWRITE_FONT_STRETCH width = (DWRITE_FONT_STRETCH)pattern.width();
+
+ SkTScopedComPtr<IDWriteFont> font;
+ // TODO: perhaps use GetMatchingFonts and get the least simulated?
+ HRNM(fFontFamily->GetFirstMatchingFont(weight, width, slant, &font),
+ "Could not match font in family.");
+
+ SkTScopedComPtr<IDWriteFontFace> fontFace;
+ HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
+
+ return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(),
+ fFontFamily.get());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+#include "SkTypeface_win.h"
+
+SK_API SkFontMgr* SkFontMgr_New_DirectWrite(IDWriteFactory* factory) {
+ if (NULL == factory) {
+ factory = sk_get_dwrite_factory();
+ if (NULL == factory) {
+ return NULL;
+ }
+ }
+
+ SkTScopedComPtr<IDWriteFontCollection> sysFontCollection;
+ HRNM(factory->GetSystemFontCollection(&sysFontCollection, FALSE),
+ "Could not get system font collection.");
+
+ WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH];
+ WCHAR* localeName = NULL;
+ int localeNameLen = 0;
+
+ // Dynamically load GetUserDefaultLocaleName function, as it is not available on XP.
+ SkGetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = NULL;
+ HRESULT hr = SkGetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc);
+ if (NULL == getUserDefaultLocaleNameProc) {
+ SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName.");
+ } else {
+ localeNameLen = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_NAME_MAX_LENGTH);
+ if (localeNameLen) {
+ localeName = localeNameStorage;
+ };
+ }
+
+ return SkNEW_ARGS(SkFontMgr_DirectWrite, (factory, sysFontCollection.get(),
+ localeName, localeNameLen));
+}
+
+#include "SkFontMgr_indirect.h"
+SK_API SkFontMgr* SkFontMgr_New_DirectWriteRenderer(SkRemotableFontMgr* proxy) {
+ SkAutoTUnref<SkFontMgr> impl(SkFontMgr_New_DirectWrite());
+ if (impl.get() == NULL) {
+ return NULL;
+ }
+ return SkNEW_ARGS(SkFontMgr_Indirect, (impl.get(), proxy));
+}
diff --git a/chromium/third_party/skia/src/ports/SkGlobalInitialization_chromium.cpp b/chromium/third_party/skia/src/ports/SkGlobalInitialization_chromium.cpp
index d402c02e21e..9721636bbab 100644
--- a/chromium/third_party/skia/src/ports/SkGlobalInitialization_chromium.cpp
+++ b/chromium/third_party/skia/src/ports/SkGlobalInitialization_chromium.cpp
@@ -37,11 +37,11 @@
#include "SkEmbossMaskFilter.h"
#include "SkFlattenable.h"
#include "SkGradientShader.h"
-#include "SkImages.h"
#include "SkLayerDrawLooper.h"
#include "SkLayerRasterizer.h"
#include "SkLerpXfermode.h"
#include "SkLightingImageFilter.h"
+#include "SkLocalMatrixShader.h"
#include "SkLumaColorFilter.h"
#include "SkMagnifierImageFilter.h"
#include "SkMatrixConvolutionImageFilter.h"
@@ -50,15 +50,18 @@
#include "SkOffsetImageFilter.h"
#include "SkOnce.h"
#include "SkPerlinNoiseShader.h"
+#include "SkPictureImageFilter.h"
+#include "SkPictureShader.h"
#include "SkPixelXorXfermode.h"
#include "SkRectShaderImageFilter.h"
#include "SkStippleMaskFilter.h"
#include "SkTableColorFilter.h"
#include "SkTestImageFilters.h"
#include "SkTileImageFilter.h"
+#include "SkMatrixImageFilter.h"
#include "SkXfermodeImageFilter.h"
-static void InitializeFlattenables(int*) {
+static void InitializeFlattenables() {
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkAvoidXfermode)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBicubicImageFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBitmapProcShader)
@@ -81,17 +84,21 @@ static void InitializeFlattenables(int*) {
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLayerDrawLooper)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLayerRasterizer)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLerpXfermode)
+ SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLocalMatrixShader)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLumaColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPath1DPathEffect)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(Sk2DPathEffect)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLine2DPathEffect)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPath2DPathEffect)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPerlinNoiseShader)
+ SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPictureImageFilter)
+ SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPictureShader)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPixelXorXfermode)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkRectShaderImageFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkStippleMaskFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSumPathEffect)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTileImageFilter)
+ SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkMatrixImageFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkXfermodeImageFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkMagnifierImageFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkMatrixConvolutionImageFilter)
@@ -107,14 +114,12 @@ static void InitializeFlattenables(int*) {
SkBlurMaskFilter::InitializeFlattenables();
SkColorFilter::InitializeFlattenables();
SkGradientShader::InitializeFlattenables();
- SkImages::InitializeFlattenables();
SkLightingImageFilter::InitializeFlattenables();
SkTableColorFilter::InitializeFlattenables();
SkXfermode::InitializeFlattenables();
}
void SkFlattenable::InitializeFlattenablesIfNeeded() {
- int dummy;
SK_DECLARE_STATIC_ONCE(once);
- SkOnce(&once, InitializeFlattenables, &dummy);
+ SkOnce(&once, InitializeFlattenables);
}
diff --git a/chromium/third_party/skia/src/ports/SkGlobalInitialization_default.cpp b/chromium/third_party/skia/src/ports/SkGlobalInitialization_default.cpp
index d402c02e21e..60c34f26f07 100644
--- a/chromium/third_party/skia/src/ports/SkGlobalInitialization_default.cpp
+++ b/chromium/third_party/skia/src/ports/SkGlobalInitialization_default.cpp
@@ -37,11 +37,11 @@
#include "SkEmbossMaskFilter.h"
#include "SkFlattenable.h"
#include "SkGradientShader.h"
-#include "SkImages.h"
#include "SkLayerDrawLooper.h"
#include "SkLayerRasterizer.h"
#include "SkLerpXfermode.h"
#include "SkLightingImageFilter.h"
+#include "SkLocalMatrixShader.h"
#include "SkLumaColorFilter.h"
#include "SkMagnifierImageFilter.h"
#include "SkMatrixConvolutionImageFilter.h"
@@ -50,15 +50,18 @@
#include "SkOffsetImageFilter.h"
#include "SkOnce.h"
#include "SkPerlinNoiseShader.h"
+#include "SkPictureImageFilter.h"
+#include "SkPictureShader.h"
#include "SkPixelXorXfermode.h"
#include "SkRectShaderImageFilter.h"
#include "SkStippleMaskFilter.h"
#include "SkTableColorFilter.h"
#include "SkTestImageFilters.h"
#include "SkTileImageFilter.h"
+#include "SkMatrixImageFilter.h"
#include "SkXfermodeImageFilter.h"
-static void InitializeFlattenables(int*) {
+static void InitializeFlattenables() {
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkAvoidXfermode)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBicubicImageFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBitmapProcShader)
@@ -81,17 +84,21 @@ static void InitializeFlattenables(int*) {
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLayerDrawLooper)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLayerRasterizer)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLerpXfermode)
+ SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLocalMatrixShader)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLumaColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPath1DPathEffect)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(Sk2DPathEffect)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLine2DPathEffect)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPath2DPathEffect)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPerlinNoiseShader)
+ SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPictureImageFilter)
+ SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPictureShader)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPixelXorXfermode)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkRectShaderImageFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkStippleMaskFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSumPathEffect)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTileImageFilter)
+ SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkMatrixImageFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkXfermodeImageFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkMagnifierImageFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkMatrixConvolutionImageFilter)
@@ -107,14 +114,13 @@ static void InitializeFlattenables(int*) {
SkBlurMaskFilter::InitializeFlattenables();
SkColorFilter::InitializeFlattenables();
SkGradientShader::InitializeFlattenables();
- SkImages::InitializeFlattenables();
SkLightingImageFilter::InitializeFlattenables();
SkTableColorFilter::InitializeFlattenables();
SkXfermode::InitializeFlattenables();
+
}
void SkFlattenable::InitializeFlattenablesIfNeeded() {
- int dummy;
SK_DECLARE_STATIC_ONCE(once);
- SkOnce(&once, InitializeFlattenables, &dummy);
+ SkOnce(&once, InitializeFlattenables);
}
diff --git a/chromium/third_party/skia/src/ports/SkHarfBuzzFont.cpp b/chromium/third_party/skia/src/ports/SkHarfBuzzFont.cpp
deleted file mode 100644
index 8f483f5d2f5..00000000000
--- a/chromium/third_party/skia/src/ports/SkHarfBuzzFont.cpp
+++ /dev/null
@@ -1,187 +0,0 @@
-
-/*
- * Copyright 2009 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#include "SkHarfBuzzFont.h"
-#include "SkFontHost.h"
-#include "SkPaint.h"
-#include "SkPath.h"
-
-// HB_Fixed is a 26.6 fixed point format.
-static inline HB_Fixed SkScalarToHarfbuzzFixed(SkScalar value) {
-#ifdef SK_SCALAR_IS_FLOAT
- return static_cast<HB_Fixed>(value * 64);
-#else
- // convert .16 to .6
- return value >> (16 - 6);
-#endif
-}
-
-static HB_Bool stringToGlyphs(HB_Font hbFont, const HB_UChar16* characters,
- hb_uint32 length, HB_Glyph* glyphs,
- hb_uint32* glyphsSize, HB_Bool isRTL) {
- SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(hbFont->userData);
- SkPaint paint;
-
- paint.setTypeface(font->getTypeface());
- paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
- int numGlyphs = paint.textToGlyphs(characters, length * sizeof(uint16_t),
- reinterpret_cast<uint16_t*>(glyphs));
-
- // HB_Glyph is 32-bit, but Skia outputs only 16-bit numbers. So our
- // |glyphs| array needs to be converted.
- for (int i = numGlyphs - 1; i >= 0; --i) {
- uint16_t value;
- // We use a memcpy to avoid breaking strict aliasing rules.
- memcpy(&value, reinterpret_cast<char*>(glyphs) + sizeof(uint16_t) * i, sizeof(uint16_t));
- glyphs[i] = value;
- }
-
- *glyphsSize = numGlyphs;
- return 1;
-}
-
-static void glyphsToAdvances(HB_Font hbFont, const HB_Glyph* glyphs,
- hb_uint32 numGlyphs, HB_Fixed* advances, int flags) {
- SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(hbFont->userData);
- SkPaint paint;
-
- font->setupPaint(&paint);
- paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
-
- SkAutoMalloc storage(numGlyphs * (sizeof(SkScalar) + sizeof(uint16_t)));
- SkScalar* scalarWidths = reinterpret_cast<SkScalar*>(storage.get());
- uint16_t* glyphs16 = reinterpret_cast<uint16_t*>(scalarWidths + numGlyphs);
-
- // convert HB 32bit glyphs to skia's 16bit
- for (hb_uint32 i = 0; i < numGlyphs; ++i) {
- glyphs16[i] = SkToU16(glyphs[i]);
- }
- paint.getTextWidths(glyphs16, numGlyphs * sizeof(uint16_t), scalarWidths);
-
- for (hb_uint32 i = 0; i < numGlyphs; ++i) {
- advances[i] = SkScalarToHarfbuzzFixed(scalarWidths[i]);
- }
-}
-
-static HB_Bool canRender(HB_Font hbFont, const HB_UChar16* characters,
- hb_uint32 length) {
- SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(hbFont->userData);
- SkPaint paint;
-
- paint.setTypeface(font->getTypeface());
- paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
- return paint.containsText(characters, length * sizeof(uint16_t));
-}
-
-static HB_Error getOutlinePoint(HB_Font hbFont, HB_Glyph glyph, int flags,
- hb_uint32 index, HB_Fixed* xPos, HB_Fixed* yPos,
- hb_uint32* resultingNumPoints) {
- SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(hbFont->userData);
- SkPaint paint;
-
- font->setupPaint(&paint);
- paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- if (flags & HB_ShaperFlag_UseDesignMetrics) {
- paint.setHinting(SkPaint::kNo_Hinting);
- }
-
- SkPath path;
- uint16_t glyph16 = SkToU16(glyph);
- paint.getTextPath(&glyph16, sizeof(glyph16), 0, 0, &path);
- int numPoints = path.countPoints();
- if (index >= numPoints) {
- return HB_Err_Invalid_SubTable;
- }
-
- SkPoint pt = path.getPoint(index);
- *xPos = SkScalarToHarfbuzzFixed(pt.fX);
- *yPos = SkScalarToHarfbuzzFixed(pt.fY);
- *resultingNumPoints = numPoints;
-
- return HB_Err_Ok;
-}
-
-static void getGlyphMetrics(HB_Font hbFont, HB_Glyph glyph,
- HB_GlyphMetrics* metrics) {
- SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(hbFont->userData);
- SkPaint paint;
-
- font->setupPaint(&paint);
- paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
-
- SkScalar width;
- SkRect bounds;
- uint16_t glyph16 = SkToU16(glyph);
- paint.getTextWidths(&glyph16, sizeof(glyph16), &width, &bounds);
-
- metrics->x = SkScalarToHarfbuzzFixed(bounds.fLeft);
- metrics->y = SkScalarToHarfbuzzFixed(bounds.fTop);
- metrics->width = SkScalarToHarfbuzzFixed(bounds.width());
- metrics->height = SkScalarToHarfbuzzFixed(bounds.height());
-
- metrics->xOffset = SkScalarToHarfbuzzFixed(width);
- // We can't actually get the |y| correct because Skia doesn't export
- // the vertical advance. However, nor we do ever render vertical text at
- // the moment so it's unimportant.
- metrics->yOffset = 0;
-}
-
-static HB_Fixed getFontMetric(HB_Font hbFont, HB_FontMetric metric)
-{
- SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(hbFont->userData);
- SkPaint paint;
- SkPaint::FontMetrics skiaMetrics;
-
- font->setupPaint(&paint);
- paint.getFontMetrics(&skiaMetrics);
-
- switch (metric) {
- case HB_FontAscent:
- return SkScalarToHarfbuzzFixed(-skiaMetrics.fAscent);
- default:
- SkDebugf("--- unknown harfbuzz metric enum %d\n", metric);
- return 0;
- }
-}
-
-static HB_FontClass gSkHarfBuzzFontClass = {
- stringToGlyphs,
- glyphsToAdvances,
- canRender,
- getOutlinePoint,
- getGlyphMetrics,
- getFontMetric,
-};
-
-const HB_FontClass& SkHarfBuzzFont::GetFontClass() {
- return gSkHarfBuzzFontClass;
-}
-
-HB_Error SkHarfBuzzFont::GetFontTableFunc(void* voidface, const HB_Tag tag,
- HB_Byte* buffer, HB_UInt* len) {
- SkHarfBuzzFont* font = reinterpret_cast<SkHarfBuzzFont*>(voidface);
- SkTypeface* typeface = font->getTypeface();
-
- const size_t tableSize = typeface->getTableSize(tag);
- if (!tableSize) {
- return HB_Err_Invalid_Argument;
- }
- // If Harfbuzz specified a NULL buffer then it's asking for the size.
- if (!buffer) {
- *len = tableSize;
- return HB_Err_Ok;
- }
-
- if (*len < tableSize) {
- // is this right, or should we just copy less than the full table?
- return HB_Err_Invalid_Argument;
- }
- typeface->getTableData(tag, 0, tableSize, buffer);
- return HB_Err_Ok;
-}
diff --git a/chromium/third_party/skia/src/ports/SkImageDecoder_CG.cpp b/chromium/third_party/skia/src/ports/SkImageDecoder_CG.cpp
index 9b93f81112d..8545ac8678a 100644
--- a/chromium/third_party/skia/src/ports/SkImageDecoder_CG.cpp
+++ b/chromium/third_party/skia/src/ports/SkImageDecoder_CG.cpp
@@ -50,17 +50,6 @@ protected:
virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
};
-// Returns an unpremultiplied version of color. It will have the same ordering and size as an
-// SkPMColor, but the alpha will not be premultiplied.
-static SkPMColor unpremultiply_pmcolor(SkPMColor color) {
- U8CPU a = SkGetPackedA32(color);
- const SkUnPreMultiply::Scale scale = SkUnPreMultiply::GetScale(a);
- return SkPackARGB32NoCheck(a,
- SkUnPreMultiply::ApplyScale(scale, SkGetPackedR32(color)),
- SkUnPreMultiply::ApplyScale(scale, SkGetPackedG32(color)),
- SkUnPreMultiply::ApplyScale(scale, SkGetPackedB32(color)));
-}
-
#define BITMAP_INFO (kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast)
bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
@@ -77,9 +66,10 @@ bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
}
SkAutoTCallVProc<CGImage, CGImageRelease> arimage(image);
- const int width = CGImageGetWidth(image);
- const int height = CGImageGetHeight(image);
- bm->setConfig(SkBitmap::kARGB_8888_Config, width, height);
+ const int width = SkToInt(CGImageGetWidth(image));
+ const int height = SkToInt(CGImageGetHeight(image));
+
+ bm->setInfo(SkImageInfo::MakeN32Premul(width, height));
if (SkImageDecoder::kDecodeBounds_Mode == mode) {
return true;
}
@@ -88,15 +78,11 @@ bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
return false;
}
- bm->lockPixels();
- bm->eraseColor(SK_ColorTRANSPARENT);
+ SkAutoLockPixels alp(*bm);
- CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
- CGContextRef cg = CGBitmapContextCreate(bm->getPixels(), width, height, 8, bm->rowBytes(), cs, BITMAP_INFO);
- CFRelease(cs);
-
- CGContextDrawImage(cg, CGRectMake(0, 0, width, height), image);
- CGContextRelease(cg);
+ if (!SkCopyPixelsFromCGImage(bm->info(), bm->rowBytes(), bm->getPixels(), image)) {
+ return false;
+ }
CGImageAlphaInfo info = CGImageGetAlphaInfo(image);
switch (info) {
@@ -118,12 +104,11 @@ bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
for (int i = 0; i < width; ++i) {
for (int j = 0; j < height; ++j) {
uint32_t* addr = bm->getAddr32(i, j);
- *addr = unpremultiply_pmcolor(*addr);
+ *addr = SkUnPreMultiply::UnPreMultiplyPreservingByteOrder(*addr);
}
}
bm->setAlphaType(kUnpremul_SkAlphaType);
}
- bm->unlockPixels();
return true;
}
@@ -219,8 +204,8 @@ bool SkImageEncoder_CG::onEncode(SkWStream* stream, const SkBitmap& bm,
// format.
// <Error>: CGImageDestinationFinalize image destination does not have enough images
// So instead we copy to 8888.
- if (bm.config() == SkBitmap::kARGB_4444_Config) {
- bm.copyTo(&bitmap8888, SkBitmap::kARGB_8888_Config);
+ if (bm.colorType() == kARGB_4444_SkColorType) {
+ bm.copyTo(&bitmap8888, kN32_SkColorType);
bmPtr = &bitmap8888;
}
type = kUTTypePNG;
diff --git a/chromium/third_party/skia/src/ports/SkImageDecoder_WIC.cpp b/chromium/third_party/skia/src/ports/SkImageDecoder_WIC.cpp
index 9aaed869e36..3309af4685c 100644
--- a/chromium/third_party/skia/src/ports/SkImageDecoder_WIC.cpp
+++ b/chromium/third_party/skia/src/ports/SkImageDecoder_WIC.cpp
@@ -186,7 +186,7 @@ bool SkImageDecoder_WIC::decodeStream(SkStream* stream, SkBitmap* bm, WICModes w
//Exit early if we're only looking for the bitmap bounds.
if (SUCCEEDED(hr)) {
- bm->setConfig(SkBitmap::kARGB_8888_Config, width, height);
+ bm->setInfo(SkImageInfo::MakeN32Premul(width, height));
if (kDecodeBounds_WICMode == wicMode) {
return true;
}
@@ -306,10 +306,10 @@ bool SkImageEncoder_WIC::onEncode(SkWStream* stream
//Convert to 8888 if needed.
const SkBitmap* bitmap;
SkBitmap bitmapCopy;
- if (SkBitmap::kARGB_8888_Config == bitmapOrig.config() && bitmapOrig.isOpaque()) {
+ if (kN32_SkColorType == bitmapOrig.colorType() && bitmapOrig.isOpaque()) {
bitmap = &bitmapOrig;
} else {
- if (!bitmapOrig.copyTo(&bitmapCopy, SkBitmap::kARGB_8888_Config)) {
+ if (!bitmapOrig.copyTo(&bitmapCopy, kN32_SkColorType)) {
return false;
}
bitmap = &bitmapCopy;
diff --git a/chromium/third_party/skia/src/ports/SkImageDecoder_empty.cpp b/chromium/third_party/skia/src/ports/SkImageDecoder_empty.cpp
index ae0fc363254..7824732bb93 100644
--- a/chromium/third_party/skia/src/ports/SkImageDecoder_empty.cpp
+++ b/chromium/third_party/skia/src/ports/SkImageDecoder_empty.cpp
@@ -28,24 +28,19 @@ SkImageDecoder* SkImageDecoder::Factory(SkStreamRewindable*) {
void SkImageDecoder::copyFieldsToOther(SkImageDecoder* ) {}
-bool SkImageDecoder::DecodeFile(const char[], SkBitmap*, SkBitmap::Config,
- SkImageDecoder::Mode, SkImageDecoder::Format*) {
+bool SkImageDecoder::DecodeFile(const char[], SkBitmap*, SkColorType, Mode, Format*) {
return false;
}
-bool SkImageDecoder::decode(SkStream*, SkBitmap*, SkBitmap::Config, Mode) {
+bool SkImageDecoder::decode(SkStream*, SkBitmap*, SkColorType, Mode) {
return false;
}
-bool SkImageDecoder::DecodeStream(SkStreamRewindable*, SkBitmap*, SkBitmap::Config,
- SkImageDecoder::Mode,
- SkImageDecoder::Format*) {
+bool SkImageDecoder::DecodeStream(SkStreamRewindable*, SkBitmap*, SkColorType, Mode, Format*) {
return false;
}
-bool SkImageDecoder::DecodeMemory(const void*, size_t, SkBitmap*,
- SkBitmap::Config, SkImageDecoder::Mode,
- SkImageDecoder::Format*) {
+bool SkImageDecoder::DecodeMemory(const void*, size_t, SkBitmap*, SkColorType, Mode, Format*) {
return false;
}
@@ -53,7 +48,7 @@ bool SkImageDecoder::buildTileIndex(SkStreamRewindable*, int *width, int *height
return false;
}
-bool SkImageDecoder::decodeSubset(SkBitmap*, const SkIRect&, SkBitmap::Config) {
+bool SkImageDecoder::decodeSubset(SkBitmap*, const SkIRect&, SkColorType) {
return false;
}
@@ -73,9 +68,11 @@ SkImageDecoder::Peeker* SkImageDecoder::setPeeker(Peeker*) {
return NULL;
}
+#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
SkImageDecoder::Chooser* SkImageDecoder::setChooser(Chooser*) {
return NULL;
}
+#endif
SkBitmap::Allocator* SkImageDecoder::setAllocator(SkBitmap::Allocator*) {
return NULL;
@@ -83,30 +80,21 @@ SkBitmap::Allocator* SkImageDecoder::setAllocator(SkBitmap::Allocator*) {
void SkImageDecoder::setSampleSize(int) {}
-SkBitmap::Config SkImageDecoder::GetDeviceConfig() {
- return SkBitmap::kNo_Config;
-}
-
-void SkImageDecoder::SetDeviceConfig(SkBitmap::Config) {}
-
bool SkImageDecoder::cropBitmap(SkBitmap*, SkBitmap*, int, int, int, int, int,
int, int) {
return false;
}
-bool SkImageDecoder::chooseFromOneChoice(SkBitmap::Config, int, int) const {
+#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
+bool SkImageDecoder::chooseFromOneChoice(SkColorType, int, int) const {
return false;
}
+#endif
bool SkImageDecoder::allocPixelRef(SkBitmap*, SkColorTable*) const {
return false;
}
-SkBitmap::Config SkImageDecoder::getPrefConfig(SrcDepth, bool) const {
- return SkBitmap::kNo_Config;
-}
-
-
/////////////////////////////////////////////////////////////////////////
// Empty implementation for SkMovie.
@@ -147,9 +135,3 @@ bool SkImageEncoder::encodeFile(const char file[], const SkBitmap& bm, int quali
return false;
}
/////////////////////////////////////////////////////////////////////////
-
-// Empty implementation for SkImages.
-
-#include "SkImages.h"
-
-void SkImages::InitializeFlattenables() {}
diff --git a/chromium/third_party/skia/src/ports/SkMutex_pthread.h b/chromium/third_party/skia/src/ports/SkMutex_pthread.h
new file mode 100644
index 00000000000..1904140c4cc
--- /dev/null
+++ b/chromium/third_party/skia/src/ports/SkMutex_pthread.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkMutex_pthread_DEFINED
+#define SkMutex_pthread_DEFINED
+
+/** Posix pthread_mutex based mutex. */
+
+#include <errno.h>
+#include <pthread.h>
+
+// A SkBaseMutex is a POD structure that can be directly initialized
+// at declaration time with SK_DECLARE_STATIC/GLOBAL_MUTEX. This avoids the
+// generation of a static initializer in the final machine code (and
+// a corresponding static finalizer).
+struct SkBaseMutex {
+ void acquire() {
+ pthread_mutex_lock(&fMutex);
+ SkDEBUGCODE(fOwner = pthread_self();)
+ }
+ void release() {
+ this->assertHeld();
+ SkDEBUGCODE(fOwner = 0;)
+ pthread_mutex_unlock(&fMutex);
+ }
+ void assertHeld() {
+ SkASSERT(pthread_self() == fOwner);
+ }
+
+ pthread_mutex_t fMutex;
+ SkDEBUGCODE(pthread_t fOwner;)
+};
+
+// A normal mutex that requires to be initialized through normal C++ construction,
+// i.e. when it's a member of another class, or allocated on the heap.
+class SkMutex : public SkBaseMutex {
+public:
+ SkMutex() {
+ SkDEBUGCODE(int status = )pthread_mutex_init(&fMutex, NULL);
+ SkDEBUGCODE(
+ if (status != 0) {
+ print_pthread_error(status);
+ SkASSERT(0 == status);
+ }
+ )
+ }
+
+ ~SkMutex() {
+ SkDEBUGCODE(int status = )pthread_mutex_destroy(&fMutex);
+ SkDEBUGCODE(
+ if (status != 0) {
+ print_pthread_error(status);
+ SkASSERT(0 == status);
+ }
+ )
+ }
+
+private:
+ SkMutex(const SkMutex&);
+ SkMutex& operator=(const SkMutex&);
+
+ static void print_pthread_error(int status) {
+ switch (status) {
+ case 0: // success
+ break;
+ case EINVAL:
+ SkDebugf("pthread error [%d] EINVAL\n", status);
+ break;
+ case EBUSY:
+ SkDebugf("pthread error [%d] EBUSY\n", status);
+ break;
+ default:
+ SkDebugf("pthread error [%d] unknown\n", status);
+ break;
+ }
+ }
+};
+
+#define SK_BASE_MUTEX_INIT { PTHREAD_MUTEX_INITIALIZER, SkDEBUGCODE(0) }
+
+// Using POD-style initialization prevents the generation of a static initializer.
+#define SK_DECLARE_STATIC_MUTEX(name) static SkBaseMutex name = SK_BASE_MUTEX_INIT
+
+// Special case used when the static mutex must be available globally.
+#define SK_DECLARE_GLOBAL_MUTEX(name) SkBaseMutex name = SK_BASE_MUTEX_INIT
+
+#endif
diff --git a/chromium/third_party/skia/src/ports/SkMutex_win.h b/chromium/third_party/skia/src/ports/SkMutex_win.h
new file mode 100644
index 00000000000..d12fd033f3d
--- /dev/null
+++ b/chromium/third_party/skia/src/ports/SkMutex_win.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkMutex_win_DEFINED
+#define SkMutex_win_DEFINED
+
+/** Windows CriticalSection based mutex. */
+
+#ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# define WIN32_IS_MEAN_WAS_LOCALLY_DEFINED
+#endif
+#ifndef NOMINMAX
+# define NOMINMAX
+# define NOMINMAX_WAS_LOCALLY_DEFINED
+#endif
+#
+#include <windows.h>
+#
+#ifdef WIN32_IS_MEAN_WAS_LOCALLY_DEFINED
+# undef WIN32_IS_MEAN_WAS_LOCALLY_DEFINED
+# undef WIN32_LEAN_AND_MEAN
+#endif
+#ifdef NOMINMAX_WAS_LOCALLY_DEFINED
+# undef NOMINMAX_WAS_LOCALLY_DEFINED
+# undef NOMINMAX
+#endif
+
+// On Windows, SkBaseMutex and SkMutex are the same thing,
+// we can't easily get rid of static initializers.
+class SkMutex {
+public:
+ SkMutex() {
+ InitializeCriticalSection(&fStorage);
+ SkDEBUGCODE(fOwner = 0;)
+ }
+
+ ~SkMutex() {
+ SkASSERT(0 == fOwner);
+ DeleteCriticalSection(&fStorage);
+ }
+
+ void acquire() {
+ EnterCriticalSection(&fStorage);
+ SkDEBUGCODE(fOwner = GetCurrentThreadId();)
+ }
+
+ void release() {
+ this->assertHeld();
+ SkDEBUGCODE(fOwner = 0;)
+ LeaveCriticalSection(&fStorage);
+ }
+
+ void assertHeld() {
+ SkASSERT(GetCurrentThreadId() == fOwner);
+ }
+
+private:
+ SkMutex(const SkMutex&);
+ SkMutex& operator=(const SkMutex&);
+
+ CRITICAL_SECTION fStorage;
+ SkDEBUGCODE(DWORD fOwner;)
+};
+
+typedef SkMutex SkBaseMutex;
+
+// Windows currently provides no documented means of POD initializing a CRITICAL_SECTION.
+#define SK_DECLARE_STATIC_MUTEX(name) static SkBaseMutex name
+#define SK_DECLARE_GLOBAL_MUTEX(name) SkBaseMutex name
+
+#endif
diff --git a/chromium/third_party/skia/src/ports/SkOSFile_win.cpp b/chromium/third_party/skia/src/ports/SkOSFile_win.cpp
index 7fec557987e..a0848915ba4 100644
--- a/chromium/third_party/skia/src/ports/SkOSFile_win.cpp
+++ b/chromium/third_party/skia/src/ports/SkOSFile_win.cpp
@@ -50,18 +50,16 @@ bool sk_fidentical(SkFILE* a, SkFILE* b) {
&& aID.fVolume == bID.fVolume;
}
-template <typename HandleType, HandleType InvalidValue, BOOL (WINAPI * Close)(HandleType)>
-class SkAutoTHandle : SkNoncopyable {
+class SkAutoNullKernelHandle : SkNoncopyable {
public:
- SkAutoTHandle(HandleType handle) : fHandle(handle) { }
- ~SkAutoTHandle() { Close(fHandle); }
- operator HandleType() { return fHandle; }
- bool isValid() { return InvalidValue != fHandle; }
+ SkAutoNullKernelHandle(const HANDLE handle) : fHandle(handle) { }
+ ~SkAutoNullKernelHandle() { CloseHandle(fHandle); }
+ operator HANDLE() const { return fHandle; }
+ bool isValid() const { return NULL != fHandle; }
private:
- HandleType fHandle;
+ HANDLE fHandle;
};
-typedef SkAutoTHandle<HANDLE, INVALID_HANDLE_VALUE, CloseHandle> SkAutoWinFile;
-typedef SkAutoTHandle<HANDLE, NULL, CloseHandle> SkAutoWinMMap;
+typedef SkAutoNullKernelHandle SkAutoWinMMap;
void sk_fmunmap(const void* addr, size_t) {
UnmapViewOfFile(addr);
diff --git a/chromium/third_party/skia/src/ports/SkPurgeableMemoryBlock_android.cpp b/chromium/third_party/skia/src/ports/SkPurgeableMemoryBlock_android.cpp
deleted file mode 100644
index acabb0d8088..00000000000
--- a/chromium/third_party/skia/src/ports/SkPurgeableMemoryBlock_android.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright 2013 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkPurgeableMemoryBlock.h"
-
-#include "android/ashmem.h"
-#include <sys/mman.h>
-#include <unistd.h>
-
-bool SkPurgeableMemoryBlock::IsSupported() {
- return true;
-}
-
-#ifdef SK_DEBUG
-bool SkPurgeableMemoryBlock::PlatformSupportsPurgingAllUnpinnedBlocks() {
- return false;
-}
-
-bool SkPurgeableMemoryBlock::PurgeAllUnpinnedBlocks() {
- return false;
-}
-
-bool SkPurgeableMemoryBlock::purge() {
- SkASSERT(!fPinned);
- if (-1 != fFD) {
- ashmem_purge_all_caches(fFD);
- return true;
- } else {
- return false;
- }
-}
-#endif
-
-// ashmem likes lengths on page boundaries.
-static size_t round_to_page_size(size_t size) {
- const size_t mask = getpagesize() - 1;
- size_t newSize = (size + mask) & ~mask;
- return newSize;
-}
-
-SkPurgeableMemoryBlock::SkPurgeableMemoryBlock(size_t size)
- : fAddr(NULL)
- , fSize(round_to_page_size(size))
- , fPinned(false)
- , fFD(-1) {
-}
-
-SkPurgeableMemoryBlock::~SkPurgeableMemoryBlock() {
- if (-1 != fFD) {
- munmap(fAddr, fSize);
- close(fFD);
- }
-}
-
-void* SkPurgeableMemoryBlock::pin(SkPurgeableMemoryBlock::PinResult* pinResult) {
- SkASSERT(!fPinned);
- if (-1 == fFD) {
- int fd = ashmem_create_region(NULL, fSize);
- if (-1 == fd) {
- SkDebugf("ashmem_create_region failed\n");
- return NULL;
- }
-
- int err = ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE);
- if (err != 0) {
- SkDebugf("ashmem_set_prot_region failed\n");
- close(fd);
- return NULL;
- }
-
- void* addr = mmap(NULL, fSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
- if (-1 == (long) addr) {
- SkDebugf("mmap failed\n");
- close(fd);
- return NULL;
- }
- fAddr = addr;
- fFD = fd;
- (void) ashmem_pin_region(fd, 0, 0);
- *pinResult = kUninitialized_PinResult;
- fPinned = true;
- } else {
- int pin = ashmem_pin_region(fFD, 0, 0);
- if (ASHMEM_NOT_PURGED == pin) {
- fPinned = true;
- *pinResult = kRetained_PinResult;
- } else if (ASHMEM_WAS_PURGED == pin) {
- fPinned = true;
- *pinResult = kUninitialized_PinResult;
- } else {
- // Failed.
- munmap(fAddr, fSize);
- close(fFD);
- fFD = -1;
- fAddr = NULL;
- }
- }
- return fAddr;
-}
-
-void SkPurgeableMemoryBlock::unpin() {
- if (-1 != fFD) {
- ashmem_unpin_region(fFD, 0, 0);
- fPinned = false;
- }
-}
diff --git a/chromium/third_party/skia/src/ports/SkPurgeableMemoryBlock_mac.cpp b/chromium/third_party/skia/src/ports/SkPurgeableMemoryBlock_mac.cpp
deleted file mode 100644
index da4cdff12ff..00000000000
--- a/chromium/third_party/skia/src/ports/SkPurgeableMemoryBlock_mac.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright 2013 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkPurgeableMemoryBlock.h"
-
-#include <mach/mach.h>
-
-bool SkPurgeableMemoryBlock::IsSupported() {
- return true;
-}
-
-#ifdef SK_DEBUG
-bool SkPurgeableMemoryBlock::PlatformSupportsPurgingAllUnpinnedBlocks() {
- return true;
-}
-
-bool SkPurgeableMemoryBlock::PurgeAllUnpinnedBlocks() {
- // Unused.
- int state = 0;
- kern_return_t ret = vm_purgable_control(mach_task_self(), 0, VM_PURGABLE_PURGE_ALL, &state);
- return ret == KERN_SUCCESS;
-}
-
-bool SkPurgeableMemoryBlock::purge() {
- return false;
-}
-#endif
-
-static size_t round_to_page_size(size_t size) {
- const size_t mask = 4096 - 1;
- return (size + mask) & ~mask;
-}
-
-SkPurgeableMemoryBlock::SkPurgeableMemoryBlock(size_t size)
- : fAddr(NULL)
- , fSize(round_to_page_size(size))
- , fPinned(false) {
-}
-
-SkPurgeableMemoryBlock::~SkPurgeableMemoryBlock() {
- SkDEBUGCODE(kern_return_t ret =) vm_deallocate(mach_task_self(),
- reinterpret_cast<vm_address_t>(fAddr),
- static_cast<vm_size_t>(fSize));
-#ifdef SK_DEBUG
- if (ret != KERN_SUCCESS) {
- SkDebugf("SkPurgeableMemoryBlock destructor failed to deallocate.\n");
- }
-#endif
-}
-
-void* SkPurgeableMemoryBlock::pin(SkPurgeableMemoryBlock::PinResult* pinResult) {
- SkASSERT(!fPinned);
- SkASSERT(pinResult != NULL);
- if (NULL == fAddr) {
- vm_address_t addr = 0;
- kern_return_t ret = vm_allocate(mach_task_self(), &addr, static_cast<vm_size_t>(fSize),
- VM_FLAGS_PURGABLE | VM_FLAGS_ANYWHERE);
- if (KERN_SUCCESS == ret) {
- fAddr = reinterpret_cast<void*>(addr);
- *pinResult = kUninitialized_PinResult;
- fPinned = true;
- } else {
- fAddr = NULL;
- }
- } else {
- int state = VM_PURGABLE_NONVOLATILE;
- kern_return_t ret = vm_purgable_control(mach_task_self(),
- reinterpret_cast<vm_address_t>(fAddr),
- VM_PURGABLE_SET_STATE, &state);
- if (ret != KERN_SUCCESS) {
- fAddr = NULL;
- fPinned = false;
- return NULL;
- }
-
- fPinned = true;
-
- if (state & VM_PURGABLE_EMPTY) {
- *pinResult = kUninitialized_PinResult;
- } else {
- *pinResult = kRetained_PinResult;
- }
- }
- return fAddr;
-}
-
-void SkPurgeableMemoryBlock::unpin() {
- SkASSERT(fPinned);
- int state = VM_PURGABLE_VOLATILE | VM_VOLATILE_GROUP_DEFAULT;
- SkDEBUGCODE(kern_return_t ret =) vm_purgable_control(mach_task_self(),
- reinterpret_cast<vm_address_t>(fAddr),
- VM_PURGABLE_SET_STATE, &state);
- fPinned = false;
-
-#ifdef SK_DEBUG
- if (ret != KERN_SUCCESS) {
- SkDebugf("SkPurgeableMemoryBlock::unpin() failed.\n");
- }
-#endif
-}
diff --git a/chromium/third_party/skia/src/ports/SkPurgeableMemoryBlock_none.cpp b/chromium/third_party/skia/src/ports/SkPurgeableMemoryBlock_none.cpp
deleted file mode 100644
index e10832e9a48..00000000000
--- a/chromium/third_party/skia/src/ports/SkPurgeableMemoryBlock_none.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2013 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkPurgeableMemoryBlock.h"
-
-bool SkPurgeableMemoryBlock::IsSupported() {
- return false;
-}
-
-#ifdef SK_DEBUG
-bool SkPurgeableMemoryBlock::PlatformSupportsPurgingAllUnpinnedBlocks() {
- return false;
-}
-
-bool SkPurgeableMemoryBlock::PurgeAllUnpinnedBlocks() {
- return false;
-}
-
-bool SkPurgeableMemoryBlock::purge() {
- return false;
-}
-#endif
-
-SkPurgeableMemoryBlock::SkPurgeableMemoryBlock(size_t size) {
- SkASSERT(false);
-}
-
-SkPurgeableMemoryBlock::~SkPurgeableMemoryBlock() {
-}
-
-void* SkPurgeableMemoryBlock::pin(SkPurgeableMemoryBlock::PinResult*) {
- return NULL;
-}
-
-void SkPurgeableMemoryBlock::unpin() {
-}
diff --git a/chromium/third_party/skia/src/ports/SkRemotableFontMgr_win_dw.cpp b/chromium/third_party/skia/src/ports/SkRemotableFontMgr_win_dw.cpp
new file mode 100644
index 00000000000..d9796832739
--- /dev/null
+++ b/chromium/third_party/skia/src/ports/SkRemotableFontMgr_win_dw.cpp
@@ -0,0 +1,527 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkDataTable.h"
+#include "SkDWrite.h"
+#include "SkDWriteFontFileStream.h"
+#include "SkHRESULT.h"
+#include "SkRemotableFontMgr.h"
+#include "SkStream.h"
+#include "SkString.h"
+#include "SkTArray.h"
+#include "SkThread.h"
+#include "SkTScopedComPtr.h"
+#include "SkTypeface_win.h"
+#include "SkTypes.h"
+#include "SkUtils.h"
+
+#include <dwrite.h>
+
+struct DWriteStyle {
+ explicit DWriteStyle(const SkFontStyle& pattern) {
+ switch (pattern.slant()) {
+ case SkFontStyle::kUpright_Slant:
+ fSlant = DWRITE_FONT_STYLE_NORMAL;
+ break;
+ case SkFontStyle::kItalic_Slant:
+ fSlant = DWRITE_FONT_STYLE_ITALIC;
+ break;
+ default:
+ SkASSERT(false);
+ }
+
+ fWeight = (DWRITE_FONT_WEIGHT)pattern.weight();
+ fWidth = (DWRITE_FONT_STRETCH)pattern.width();
+ }
+ DWRITE_FONT_STYLE fSlant;
+ DWRITE_FONT_WEIGHT fWeight;
+ DWRITE_FONT_STRETCH fWidth;
+};
+
+class SK_API SkRemotableFontMgr_DirectWrite : public SkRemotableFontMgr {
+private:
+ struct DataId {
+ IUnknown* fLoader; // In COM only IUnknown pointers may be safely used for identity.
+ void* fKey;
+ UINT32 fKeySize;
+
+ DataId() { }
+
+ // This is actually a move!!!
+ explicit DataId(DataId& that)
+ : fLoader(that.fLoader), fKey(that.fKey), fKeySize(that.fKeySize)
+ {
+ that.fLoader = NULL;
+ that.fKey = NULL;
+ SkDEBUGCODE(that.fKeySize = 0xFFFFFFFF;)
+ }
+
+ ~DataId() {
+ if (fLoader) {
+ fLoader->Release();
+ }
+ sk_free(fKey);
+ }
+ };
+
+ mutable SkTArray<DataId> fDataIdCache;
+ mutable SkMutex fDataIdCacheMutex;
+
+ int FindOrAdd(IDWriteFontFileLoader* fontFileLoader,
+ const void* refKey, UINT32 refKeySize) const
+ {
+ SkTScopedComPtr<IUnknown> fontFileLoaderId;
+ HR_GENERAL(fontFileLoader->QueryInterface(&fontFileLoaderId),
+ "Failed to re-convert to IDWriteFontFileLoader.",
+ SkFontIdentity::kInvalidDataId);
+
+ SkAutoMutexAcquire ama(fDataIdCacheMutex);
+ int count = fDataIdCache.count();
+ int i;
+ for (i = 0; i < count; ++i) {
+ const DataId& current = fDataIdCache[i];
+ if (fontFileLoaderId.get() == current.fLoader &&
+ refKeySize == current.fKeySize &&
+ 0 == memcmp(refKey, current.fKey, refKeySize))
+ {
+ return i;
+ }
+ }
+ DataId& added = fDataIdCache.push_back();
+ added.fLoader = fontFileLoaderId.release(); // Ref is passed.
+ added.fKey = sk_malloc_throw(refKeySize);
+ memcpy(added.fKey, refKey, refKeySize);
+ added.fKeySize = refKeySize;
+
+ return i;
+ }
+
+public:
+ SK_DECLARE_INST_COUNT(SkRemotableFontMgr_DirectWrite)
+
+ /** localeNameLength must include the null terminator. */
+ SkRemotableFontMgr_DirectWrite(IDWriteFontCollection* fontCollection,
+ WCHAR* localeName, int localeNameLength)
+ : fFontCollection(SkRefComPtr(fontCollection))
+ , fLocaleName(localeNameLength)
+ {
+ memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR));
+ }
+
+ virtual SkDataTable* getFamilyNames() const SK_OVERRIDE {
+ int count = fFontCollection->GetFontFamilyCount();
+
+ SkDataTableBuilder names(1024);
+ for (int index = 0; index < count; ++index) {
+ SkTScopedComPtr<IDWriteFontFamily> fontFamily;
+ HRNM(fFontCollection->GetFontFamily(index, &fontFamily),
+ "Could not get requested family.");
+
+ SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
+ HRNM(fontFamily->GetFamilyNames(&familyNames), "Could not get family names.");
+
+ SkString familyName;
+ sk_get_locale_string(familyNames.get(), fLocaleName.get(), &familyName);
+
+ names.appendString(familyName);
+ }
+ return names.detachDataTable();
+ }
+
+ HRESULT FontToIdentity(IDWriteFont* font, SkFontIdentity* fontId) const {
+ SkTScopedComPtr<IDWriteFontFace> fontFace;
+ HRM(font->CreateFontFace(&fontFace), "Could not create font face.");
+
+ UINT32 numFiles;
+ HR(fontFace->GetFiles(&numFiles, NULL));
+ if (numFiles > 1) {
+ return E_FAIL;
+ }
+
+ // data id
+ SkTScopedComPtr<IDWriteFontFile> fontFile;
+ HR(fontFace->GetFiles(&numFiles, &fontFile));
+
+ SkTScopedComPtr<IDWriteFontFileLoader> fontFileLoader;
+ HR(fontFile->GetLoader(&fontFileLoader));
+
+ const void* refKey;
+ UINT32 refKeySize;
+ HR(fontFile->GetReferenceKey(&refKey, &refKeySize));
+
+ fontId->fDataId = FindOrAdd(fontFileLoader.get(), refKey, refKeySize);
+
+ // index
+ fontId->fTtcIndex = fontFace->GetIndex();
+
+ // style
+ SkFontStyle::Slant slant;
+ switch (font->GetStyle()) {
+ case DWRITE_FONT_STYLE_NORMAL:
+ slant = SkFontStyle::kUpright_Slant;
+ break;
+ case DWRITE_FONT_STYLE_OBLIQUE:
+ case DWRITE_FONT_STYLE_ITALIC:
+ slant = SkFontStyle::kItalic_Slant;
+ break;
+ default:
+ SkASSERT(false);
+ }
+
+ int weight = font->GetWeight();
+ int width = font->GetStretch();
+
+ fontId->fFontStyle = SkFontStyle(weight, width, slant);
+ return S_OK;
+ }
+
+ virtual SkRemotableFontIdentitySet* getIndex(int familyIndex) const SK_OVERRIDE {
+ SkTScopedComPtr<IDWriteFontFamily> fontFamily;
+ HRNM(fFontCollection->GetFontFamily(familyIndex, &fontFamily),
+ "Could not get requested family.");
+
+ int count = fontFamily->GetFontCount();
+ SkFontIdentity* fontIds;
+ SkAutoTUnref<SkRemotableFontIdentitySet> fontIdSet(
+ new SkRemotableFontIdentitySet(count, &fontIds));
+ for (int fontIndex = 0; fontIndex < count; ++fontIndex) {
+ SkTScopedComPtr<IDWriteFont> font;
+ HRNM(fontFamily->GetFont(fontIndex, &font), "Could not get font.");
+
+ HRN(FontToIdentity(font.get(), &fontIds[fontIndex]));
+ }
+ return fontIdSet.detach();
+ }
+
+ virtual SkFontIdentity matchIndexStyle(int familyIndex,
+ const SkFontStyle& pattern) const SK_OVERRIDE
+ {
+ SkFontIdentity identity = { SkFontIdentity::kInvalidDataId };
+
+ SkTScopedComPtr<IDWriteFontFamily> fontFamily;
+ HR_GENERAL(fFontCollection->GetFontFamily(familyIndex, &fontFamily),
+ "Could not get requested family.",
+ identity);
+
+ const DWriteStyle dwStyle(pattern);
+ SkTScopedComPtr<IDWriteFont> font;
+ HR_GENERAL(fontFamily->GetFirstMatchingFont(dwStyle.fWeight, dwStyle.fWidth,
+ dwStyle.fSlant, &font),
+ "Could not match font in family.",
+ identity);
+
+ HR_GENERAL(FontToIdentity(font.get(), &identity), NULL, identity);
+
+ return identity;
+ }
+
+ static HRESULT getDefaultFontFamilyName(SkSMallocWCHAR* name) {
+ NONCLIENTMETRICSW metrics;
+ metrics.cbSize = sizeof(metrics);
+ if (0 == SystemParametersInfoW(SPI_GETNONCLIENTMETRICS,
+ sizeof(metrics),
+ &metrics,
+ 0)) {
+ return E_UNEXPECTED;
+ }
+
+ size_t len = wcsnlen_s(metrics.lfMessageFont.lfFaceName, LF_FACESIZE) + 1;
+ if (0 != wcsncpy_s(name->reset(len), len, metrics.lfMessageFont.lfFaceName, _TRUNCATE)) {
+ return E_UNEXPECTED;
+ }
+
+ return S_OK;
+ }
+
+ virtual SkRemotableFontIdentitySet* matchName(const char familyName[]) const SK_OVERRIDE {
+ SkSMallocWCHAR dwFamilyName;
+ if (NULL == familyName) {
+ HR_GENERAL(getDefaultFontFamilyName(&dwFamilyName),
+ NULL, SkRemotableFontIdentitySet::NewEmpty());
+ } else {
+ HR_GENERAL(sk_cstring_to_wchar(familyName, &dwFamilyName),
+ NULL, SkRemotableFontIdentitySet::NewEmpty());
+ }
+
+ UINT32 index;
+ BOOL exists;
+ HR_GENERAL(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists),
+ "Failed while finding family by name.",
+ SkRemotableFontIdentitySet::NewEmpty());
+ if (!exists) {
+ return SkRemotableFontIdentitySet::NewEmpty();
+ }
+
+ return this->getIndex(index);
+ }
+
+ virtual SkFontIdentity matchNameStyle(const char familyName[],
+ const SkFontStyle& style) const SK_OVERRIDE
+ {
+ SkFontIdentity identity = { SkFontIdentity::kInvalidDataId };
+
+ SkSMallocWCHAR dwFamilyName;
+ if (NULL == familyName) {
+ HR_GENERAL(getDefaultFontFamilyName(&dwFamilyName), NULL, identity);
+ } else {
+ HR_GENERAL(sk_cstring_to_wchar(familyName, &dwFamilyName), NULL, identity);
+ }
+
+ UINT32 index;
+ BOOL exists;
+ HR_GENERAL(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists),
+ "Failed while finding family by name.",
+ identity);
+ if (!exists) {
+ return identity;
+ }
+
+ return this->matchIndexStyle(index, style);
+ }
+
+ class FontFallbackRenderer : public IDWriteTextRenderer {
+ public:
+ FontFallbackRenderer(const SkRemotableFontMgr_DirectWrite* outer, UINT32 character)
+ : fRefCount(1), fOuter(SkSafeRef(outer)), fCharacter(character) {
+ fIdentity.fDataId = SkFontIdentity::kInvalidDataId;
+ }
+
+ virtual ~FontFallbackRenderer() { }
+
+ // IDWriteTextRenderer methods
+ virtual HRESULT STDMETHODCALLTYPE DrawGlyphRun(
+ void* clientDrawingContext,
+ FLOAT baselineOriginX,
+ FLOAT baselineOriginY,
+ DWRITE_MEASURING_MODE measuringMode,
+ DWRITE_GLYPH_RUN const* glyphRun,
+ DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
+ IUnknown* clientDrawingEffect) SK_OVERRIDE
+ {
+ SkTScopedComPtr<IDWriteFont> font;
+ HRM(fOuter->fFontCollection->GetFontFromFontFace(glyphRun->fontFace, &font),
+ "Could not get font from font face.");
+
+ // It is possible that the font passed does not actually have the requested character,
+ // due to no font being found and getting the fallback font.
+ // Check that the font actually contains the requested character.
+ BOOL exists;
+ HRM(font->HasCharacter(fCharacter, &exists), "Could not find character.");
+
+ if (exists) {
+ HR(fOuter->FontToIdentity(font.get(), &fIdentity));
+ }
+
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE DrawUnderline(
+ void* clientDrawingContext,
+ FLOAT baselineOriginX,
+ FLOAT baselineOriginY,
+ DWRITE_UNDERLINE const* underline,
+ IUnknown* clientDrawingEffect) SK_OVERRIDE
+ { return E_NOTIMPL; }
+
+ virtual HRESULT STDMETHODCALLTYPE DrawStrikethrough(
+ void* clientDrawingContext,
+ FLOAT baselineOriginX,
+ FLOAT baselineOriginY,
+ DWRITE_STRIKETHROUGH const* strikethrough,
+ IUnknown* clientDrawingEffect) SK_OVERRIDE
+ { return E_NOTIMPL; }
+
+ virtual HRESULT STDMETHODCALLTYPE DrawInlineObject(
+ void* clientDrawingContext,
+ FLOAT originX,
+ FLOAT originY,
+ IDWriteInlineObject* inlineObject,
+ BOOL isSideways,
+ BOOL isRightToLeft,
+ IUnknown* clientDrawingEffect) SK_OVERRIDE
+ { return E_NOTIMPL; }
+
+ // IDWritePixelSnapping methods
+ virtual HRESULT STDMETHODCALLTYPE IsPixelSnappingDisabled(
+ void* clientDrawingContext,
+ BOOL* isDisabled) SK_OVERRIDE
+ {
+ *isDisabled = FALSE;
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE GetCurrentTransform(
+ void* clientDrawingContext,
+ DWRITE_MATRIX* transform) SK_OVERRIDE
+ {
+ const DWRITE_MATRIX ident = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0};
+ *transform = ident;
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE GetPixelsPerDip(
+ void* clientDrawingContext,
+ FLOAT* pixelsPerDip) SK_OVERRIDE
+ {
+ *pixelsPerDip = 1.0f;
+ return S_OK;
+ }
+
+ // IUnknown methods
+ virtual ULONG STDMETHODCALLTYPE AddRef() SK_OVERRIDE {
+ return InterlockedIncrement(&fRefCount);
+ }
+
+ virtual ULONG STDMETHODCALLTYPE Release() SK_OVERRIDE {
+ ULONG newCount = InterlockedDecrement(&fRefCount);
+ if (0 == newCount) {
+ delete this;
+ }
+ return newCount;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE QueryInterface(
+ IID const& riid, void** ppvObject) SK_OVERRIDE
+ {
+ if (__uuidof(IUnknown) == riid ||
+ __uuidof(IDWritePixelSnapping) == riid ||
+ __uuidof(IDWriteTextRenderer) == riid)
+ {
+ *ppvObject = this;
+ this->AddRef();
+ return S_OK;
+ }
+ *ppvObject = NULL;
+ return E_FAIL;
+ }
+
+ const SkFontIdentity FallbackIdentity() { return fIdentity; }
+
+ protected:
+ ULONG fRefCount;
+ SkAutoTUnref<const SkRemotableFontMgr_DirectWrite> fOuter;
+ UINT32 fCharacter;
+ SkFontIdentity fIdentity;
+ };
+
+ virtual SkFontIdentity matchNameStyleCharacter(const char familyName[],
+ const SkFontStyle& pattern,
+ const char bpc47[],
+ SkUnichar character) const SK_OVERRIDE
+ {
+ SkFontIdentity identity = { SkFontIdentity::kInvalidDataId };
+
+ IDWriteFactory* dwFactory = sk_get_dwrite_factory();
+ if (NULL == dwFactory) {
+ return identity;
+ }
+
+ // TODO: use IDWriteFactory2::GetSystemFontFallback when available.
+
+ const DWriteStyle dwStyle(pattern);
+
+ SkSMallocWCHAR dwFamilyName;
+ if (NULL == familyName) {
+ HR_GENERAL(getDefaultFontFamilyName(&dwFamilyName), NULL, identity);
+ } else {
+ HR_GENERAL(sk_cstring_to_wchar(familyName, &dwFamilyName), NULL, identity);
+ }
+
+ const SkSMallocWCHAR* dwBpc47;
+ SkSMallocWCHAR dwBpc47Local;
+ if (NULL == bpc47) {
+ dwBpc47 = &fLocaleName;
+ } else {
+ HR_GENERAL(sk_cstring_to_wchar(bpc47, &dwBpc47Local), NULL, identity);
+ dwBpc47 = &dwBpc47Local;
+ }
+
+ SkTScopedComPtr<IDWriteTextFormat> fallbackFormat;
+ HR_GENERAL(dwFactory->CreateTextFormat(dwFamilyName,
+ fFontCollection.get(),
+ dwStyle.fWeight,
+ dwStyle.fSlant,
+ dwStyle.fWidth,
+ 72.0f,
+ *dwBpc47,
+ &fallbackFormat),
+ "Could not create text format.",
+ identity);
+
+ WCHAR str[16];
+ UINT32 strLen = static_cast<UINT32>(
+ SkUTF16_FromUnichar(character, reinterpret_cast<uint16_t*>(str)));
+ SkTScopedComPtr<IDWriteTextLayout> fallbackLayout;
+ HR_GENERAL(dwFactory->CreateTextLayout(str, strLen, fallbackFormat.get(),
+ 200.0f, 200.0f,
+ &fallbackLayout),
+ "Could not create text layout.",
+ identity);
+
+ SkTScopedComPtr<FontFallbackRenderer> fontFallbackRenderer(
+ new FontFallbackRenderer(this, character));
+
+ HR_GENERAL(fallbackLayout->Draw(NULL, fontFallbackRenderer.get(), 50.0f, 50.0f),
+ "Could not draw layout with renderer.",
+ identity);
+
+ return fontFallbackRenderer->FallbackIdentity();
+ }
+
+ virtual SkStreamAsset* getData(int dataId) const SK_OVERRIDE {
+ SkAutoMutexAcquire ama(fDataIdCacheMutex);
+ if (dataId >= fDataIdCache.count()) {
+ return NULL;
+ }
+ const DataId& id = fDataIdCache[dataId];
+
+ SkTScopedComPtr<IDWriteFontFileLoader> loader;
+ HRNM(id.fLoader->QueryInterface(&loader), "QuerryInterface IDWriteFontFileLoader failed");
+
+ SkTScopedComPtr<IDWriteFontFileStream> fontFileStream;
+ HRNM(loader->CreateStreamFromKey(id.fKey, id.fKeySize, &fontFileStream),
+ "Could not create font file stream.");
+
+ return SkNEW_ARGS(SkDWriteFontFileStream, (fontFileStream.get()));
+ }
+
+private:
+ SkTScopedComPtr<IDWriteFontCollection> fFontCollection;
+ SkSMallocWCHAR fLocaleName;
+
+ typedef SkRemotableFontMgr INHERITED;
+};
+
+SkRemotableFontMgr* SkRemotableFontMgr_New_DirectWrite() {
+ IDWriteFactory* factory = sk_get_dwrite_factory();
+ if (NULL == factory) {
+ return NULL;
+ }
+
+ SkTScopedComPtr<IDWriteFontCollection> sysFontCollection;
+ HRNM(factory->GetSystemFontCollection(&sysFontCollection, FALSE),
+ "Could not get system font collection.");
+
+ WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH];
+ WCHAR* localeName = NULL;
+ int localeNameLen = 0;
+
+ // Dynamically load GetUserDefaultLocaleName function, as it is not available on XP.
+ SkGetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = NULL;
+ HRESULT hr = SkGetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc);
+ if (NULL == getUserDefaultLocaleNameProc) {
+ SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName.");
+ } else {
+ localeNameLen = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_NAME_MAX_LENGTH);
+ if (localeNameLen) {
+ localeName = localeNameStorage;
+ };
+ }
+
+ return SkNEW_ARGS(SkRemotableFontMgr_DirectWrite, (sysFontCollection.get(),
+ localeName, localeNameLen));
+}
diff --git a/chromium/third_party/skia/src/ports/SkScalerContext_win_dw.cpp b/chromium/third_party/skia/src/ports/SkScalerContext_win_dw.cpp
new file mode 100644
index 00000000000..28d41c1b9e7
--- /dev/null
+++ b/chromium/third_party/skia/src/ports/SkScalerContext_win_dw.cpp
@@ -0,0 +1,747 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkTypes.h"
+#undef GetGlyphIndices
+
+#include "SkDWrite.h"
+#include "SkDWriteGeometrySink.h"
+#include "SkEndian.h"
+#include "SkGlyph.h"
+#include "SkHRESULT.h"
+#include "SkMaskGamma.h"
+#include "SkMatrix22.h"
+#include "SkOTTable_EBLC.h"
+#include "SkOTTable_EBSC.h"
+#include "SkOTTable_gasp.h"
+#include "SkOTTable_maxp.h"
+#include "SkPath.h"
+#include "SkScalerContext.h"
+#include "SkScalerContext_win_dw.h"
+#include "SkTScopedComPtr.h"
+#include "SkTypeface_win_dw.h"
+
+#include <dwrite.h>
+#include <dwrite_1.h>
+
+static bool isLCD(const SkScalerContext::Rec& rec) {
+ return SkMask::kLCD16_Format == rec.fMaskFormat ||
+ SkMask::kLCD32_Format == rec.fMaskFormat;
+}
+
+static bool is_hinted_without_gasp(DWriteFontTypeface* typeface) {
+ AutoTDWriteTable<SkOTTableMaximumProfile> maxp(typeface->fDWriteFontFace.get());
+ if (!maxp.fExists) {
+ return false;
+ }
+ if (maxp.fSize < sizeof(SkOTTableMaximumProfile::Version::TT)) {
+ return false;
+ }
+ if (maxp->version.version != SkOTTableMaximumProfile::Version::TT::VERSION) {
+ return false;
+ }
+
+ if (0 == maxp->version.tt.maxSizeOfInstructions) {
+ // No hints.
+ return false;
+ }
+
+ AutoTDWriteTable<SkOTTableGridAndScanProcedure> gasp(typeface->fDWriteFontFace.get());
+ return !gasp.fExists;
+}
+
+/** A PPEMRange is inclusive, [min, max]. */
+struct PPEMRange {
+ int min;
+ int max;
+};
+
+/** If the rendering mode for the specified 'size' is gridfit, then place
+ * the gridfit range into 'range'. Otherwise, leave 'range' alone.
+ */
+static void expand_range_if_gridfit_only(DWriteFontTypeface* typeface, int size, PPEMRange* range) {
+ AutoTDWriteTable<SkOTTableGridAndScanProcedure> gasp(typeface->fDWriteFontFace.get());
+ if (!gasp.fExists) {
+ return;
+ }
+ if (gasp.fSize < sizeof(SkOTTableGridAndScanProcedure)) {
+ return;
+ }
+ if (gasp->version != SkOTTableGridAndScanProcedure::version0 &&
+ gasp->version != SkOTTableGridAndScanProcedure::version1)
+ {
+ return ;
+ }
+
+ uint16_t numRanges = SkEndianSwap16(gasp->numRanges);
+ if (numRanges > 1024 ||
+ gasp.fSize < sizeof(SkOTTableGridAndScanProcedure) +
+ sizeof(SkOTTableGridAndScanProcedure::GaspRange) * numRanges)
+ {
+ return;
+ }
+
+ const SkOTTableGridAndScanProcedure::GaspRange* rangeTable =
+ SkTAfter<const SkOTTableGridAndScanProcedure::GaspRange>(gasp.get());
+ int minPPEM = -1;
+ for (uint16_t i = 0; i < numRanges; ++i, ++rangeTable) {
+ int maxPPEM = SkEndianSwap16(rangeTable->maxPPEM);
+ // Test that the size is in range and the range is gridfit only.
+ if (minPPEM < size && size <= maxPPEM &&
+ rangeTable->flags.raw.value == SkOTTableGridAndScanProcedure::GaspRange::behavior::Raw::GridfitMask)
+ {
+ range->min = minPPEM + 1;
+ range->max = maxPPEM;
+ return;
+ }
+ minPPEM = maxPPEM;
+ }
+
+ return;
+}
+
+static bool has_bitmap_strike(DWriteFontTypeface* typeface, PPEMRange range) {
+ {
+ AutoTDWriteTable<SkOTTableEmbeddedBitmapLocation> eblc(typeface->fDWriteFontFace.get());
+ if (!eblc.fExists) {
+ return false;
+ }
+ if (eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation)) {
+ return false;
+ }
+ if (eblc->version != SkOTTableEmbeddedBitmapLocation::version_initial) {
+ return false;
+ }
+
+ uint32_t numSizes = SkEndianSwap32(eblc->numSizes);
+ if (numSizes > 1024 ||
+ eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation) +
+ sizeof(SkOTTableEmbeddedBitmapLocation::BitmapSizeTable) * numSizes)
+ {
+ return false;
+ }
+
+ const SkOTTableEmbeddedBitmapLocation::BitmapSizeTable* sizeTable =
+ SkTAfter<const SkOTTableEmbeddedBitmapLocation::BitmapSizeTable>(eblc.get());
+ for (uint32_t i = 0; i < numSizes; ++i, ++sizeTable) {
+ if (sizeTable->ppemX == sizeTable->ppemY &&
+ range.min <= sizeTable->ppemX && sizeTable->ppemX <= range.max)
+ {
+ // TODO: determine if we should dig through IndexSubTableArray/IndexSubTable
+ // to determine the actual number of glyphs with bitmaps.
+
+ // TODO: Ensure that the bitmaps actually cover a significant portion of the strike.
+
+ // TODO: Ensure that the bitmaps are bi-level?
+ if (sizeTable->endGlyphIndex >= sizeTable->startGlyphIndex + 3) {
+ return true;
+ }
+ }
+ }
+ }
+
+ {
+ AutoTDWriteTable<SkOTTableEmbeddedBitmapScaling> ebsc(typeface->fDWriteFontFace.get());
+ if (!ebsc.fExists) {
+ return false;
+ }
+ if (ebsc.fSize < sizeof(SkOTTableEmbeddedBitmapScaling)) {
+ return false;
+ }
+ if (ebsc->version != SkOTTableEmbeddedBitmapScaling::version_initial) {
+ return false;
+ }
+
+ uint32_t numSizes = SkEndianSwap32(ebsc->numSizes);
+ if (numSizes > 1024 ||
+ ebsc.fSize < sizeof(SkOTTableEmbeddedBitmapScaling) +
+ sizeof(SkOTTableEmbeddedBitmapScaling::BitmapScaleTable) * numSizes)
+ {
+ return false;
+ }
+
+ const SkOTTableEmbeddedBitmapScaling::BitmapScaleTable* scaleTable =
+ SkTAfter<const SkOTTableEmbeddedBitmapScaling::BitmapScaleTable>(ebsc.get());
+ for (uint32_t i = 0; i < numSizes; ++i, ++scaleTable) {
+ if (scaleTable->ppemX == scaleTable->ppemY &&
+ range.min <= scaleTable->ppemX && scaleTable->ppemX <= range.max) {
+ // EBSC tables are normally only found in bitmap only fonts.
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static bool both_zero(SkScalar a, SkScalar b) {
+ return 0 == a && 0 == b;
+}
+
+// returns false if there is any non-90-rotation or skew
+static bool is_axis_aligned(const SkScalerContext::Rec& rec) {
+ return 0 == rec.fPreSkewX &&
+ (both_zero(rec.fPost2x2[0][1], rec.fPost2x2[1][0]) ||
+ both_zero(rec.fPost2x2[0][0], rec.fPost2x2[1][1]));
+}
+
+SkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface,
+ const SkDescriptor* desc)
+ : SkScalerContext(typeface, desc)
+ , fTypeface(SkRef(typeface))
+ , fGlyphCount(-1) {
+
+ // In general, all glyphs should use CLEARTYPE_NATURAL_SYMMETRIC
+ // except when bi-level rendering is requested or there are embedded
+ // bi-level bitmaps (and the embedded bitmap flag is set and no rotation).
+ //
+ // DirectWrite's IDWriteFontFace::GetRecommendedRenderingMode does not do
+ // this. As a result, determine the actual size of the text and then see if
+ // there are any embedded bi-level bitmaps of that size. If there are, then
+ // force bitmaps by requesting bi-level rendering.
+ //
+ // FreeType allows for separate ppemX and ppemY, but DirectWrite assumes
+ // square pixels and only uses ppemY. Therefore the transform must track any
+ // non-uniform x-scale.
+ //
+ // Also, rotated glyphs should have the same absolute advance widths as
+ // horizontal glyphs and the subpixel flag should not affect glyph shapes.
+
+ // A is the total matrix.
+ SkMatrix A;
+ fRec.getSingleMatrix(&A);
+
+ // h is where A maps the horizontal baseline.
+ SkPoint h = SkPoint::Make(SK_Scalar1, 0);
+ A.mapPoints(&h, 1);
+
+ // G is the Givens Matrix for A (rotational matrix where GA[0][1] == 0).
+ SkMatrix G;
+ SkComputeGivensRotation(h, &G);
+
+ // GA is the matrix A with rotation removed.
+ SkMatrix GA(G);
+ GA.preConcat(A);
+
+ // realTextSize is the actual device size we want (as opposed to the size the user requested).
+ // gdiTextSize is the size we request when GDI compatible.
+ // If the scale is negative, this means the matrix will do the flip anyway.
+ SkScalar realTextSize = SkScalarAbs(GA.get(SkMatrix::kMScaleY));
+ // Due to floating point math, the lower bits are suspect. Round carefully.
+ SkScalar gdiTextSize = SkScalarRoundToScalar(realTextSize * 64.0f) / 64.0f;
+ if (gdiTextSize == 0) {
+ gdiTextSize = SK_Scalar1;
+ }
+
+ bool bitmapRequested = SkToBool(fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag);
+ bool treatLikeBitmap = false;
+ bool axisAlignedBitmap = false;
+ if (bitmapRequested) {
+ // When embedded bitmaps are requested, treat the entire range like
+ // a bitmap strike if the range is gridfit only and contains a bitmap.
+ int bitmapPPEM = SkScalarTruncToInt(gdiTextSize);
+ PPEMRange range = { bitmapPPEM, bitmapPPEM };
+ expand_range_if_gridfit_only(typeface, bitmapPPEM, &range);
+ treatLikeBitmap = has_bitmap_strike(typeface, range);
+
+ axisAlignedBitmap = is_axis_aligned(fRec);
+ }
+
+ // If the user requested aliased, do so with aliased compatible metrics.
+ if (SkMask::kBW_Format == fRec.fMaskFormat) {
+ fTextSizeRender = gdiTextSize;
+ fRenderingMode = DWRITE_RENDERING_MODE_ALIASED;
+ fTextureType = DWRITE_TEXTURE_ALIASED_1x1;
+ fTextSizeMeasure = gdiTextSize;
+ fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
+
+ // If we can use a bitmap, use gdi classic rendering and measurement.
+ // This will not always provide a bitmap, but matches expected behavior.
+ } else if (treatLikeBitmap && axisAlignedBitmap) {
+ fTextSizeRender = gdiTextSize;
+ fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC;
+ fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
+ fTextSizeMeasure = gdiTextSize;
+ fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
+
+ // If rotated but the horizontal text could have used a bitmap,
+ // render high quality rotated glyphs but measure using bitmap metrics.
+ } else if (treatLikeBitmap) {
+ fTextSizeRender = gdiTextSize;
+ fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
+ fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
+ fTextSizeMeasure = gdiTextSize;
+ fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
+
+ // Fonts that have hints but no gasp table get non-symmetric rendering.
+ // Usually such fonts have low quality hints which were never tested
+ // with anything but GDI ClearType classic. Such fonts often rely on
+ // drop out control in the y direction in order to be legible.
+ } else if (is_hinted_without_gasp(typeface)) {
+ fTextSizeRender = gdiTextSize;
+ fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL;
+ fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
+ fTextSizeMeasure = realTextSize;
+ fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
+
+ // The normal case is to use natural symmetric rendering and linear metrics.
+ } else {
+ fTextSizeRender = realTextSize;
+ fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
+ fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
+ fTextSizeMeasure = realTextSize;
+ fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
+ }
+
+ if (this->isSubpixel()) {
+ fTextSizeMeasure = realTextSize;
+ fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
+ }
+
+ // Remove the realTextSize, as that is the text height scale currently in A.
+ SkScalar scale = SkScalarInvert(realTextSize);
+
+ // fSkXform is the total matrix A without the text height scale.
+ fSkXform = A;
+ fSkXform.preScale(scale, scale); //remove the text height scale.
+
+ fXform.m11 = SkScalarToFloat(fSkXform.getScaleX());
+ fXform.m12 = SkScalarToFloat(fSkXform.getSkewY());
+ fXform.m21 = SkScalarToFloat(fSkXform.getSkewX());
+ fXform.m22 = SkScalarToFloat(fSkXform.getScaleY());
+ fXform.dx = 0;
+ fXform.dy = 0;
+
+ // GsA is the non-rotational part of A without the text height scale.
+ SkMatrix GsA(GA);
+ GsA.preScale(scale, scale); //remove text height scale, G is rotational so reorders with scale.
+
+ fGsA.m11 = SkScalarToFloat(GsA.get(SkMatrix::kMScaleX));
+ fGsA.m12 = SkScalarToFloat(GsA.get(SkMatrix::kMSkewY)); // This should be ~0.
+ fGsA.m21 = SkScalarToFloat(GsA.get(SkMatrix::kMSkewX));
+ fGsA.m22 = SkScalarToFloat(GsA.get(SkMatrix::kMScaleY));
+ fGsA.dx = 0;
+ fGsA.dy = 0;
+
+ // fG_inv is G inverse, which is fairly simple since G is 2x2 rotational.
+ fG_inv.setAll(G.get(SkMatrix::kMScaleX), -G.get(SkMatrix::kMSkewX), G.get(SkMatrix::kMTransX),
+ -G.get(SkMatrix::kMSkewY), G.get(SkMatrix::kMScaleY), G.get(SkMatrix::kMTransY),
+ G.get(SkMatrix::kMPersp0), G.get(SkMatrix::kMPersp1), G.get(SkMatrix::kMPersp2));
+}
+
+SkScalerContext_DW::~SkScalerContext_DW() {
+}
+
+unsigned SkScalerContext_DW::generateGlyphCount() {
+ if (fGlyphCount < 0) {
+ fGlyphCount = fTypeface->fDWriteFontFace->GetGlyphCount();
+ }
+ return fGlyphCount;
+}
+
+uint16_t SkScalerContext_DW::generateCharToGlyph(SkUnichar uni) {
+ uint16_t index = 0;
+ fTypeface->fDWriteFontFace->GetGlyphIndices(reinterpret_cast<UINT32*>(&uni), 1, &index);
+ return index;
+}
+
+void SkScalerContext_DW::generateAdvance(SkGlyph* glyph) {
+ //Delta is the difference between the right/left side bearing metric
+ //and where the right/left side bearing ends up after hinting.
+ //DirectWrite does not provide this information.
+ glyph->fRsbDelta = 0;
+ glyph->fLsbDelta = 0;
+
+ glyph->fAdvanceX = 0;
+ glyph->fAdvanceY = 0;
+
+ uint16_t glyphId = glyph->getGlyphID();
+ DWRITE_GLYPH_METRICS gm;
+
+ if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
+ DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
+ {
+ HRVM(fTypeface->fDWriteFontFace->GetGdiCompatibleGlyphMetrics(
+ fTextSizeMeasure,
+ 1.0f, // pixelsPerDip
+ &fGsA,
+ DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode,
+ &glyphId, 1,
+ &gm),
+ "Could not get gdi compatible glyph metrics.");
+ } else {
+ HRVM(fTypeface->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm),
+ "Could not get design metrics.");
+ }
+
+ DWRITE_FONT_METRICS dwfm;
+ fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
+ SkScalar advanceX = SkScalarMulDiv(fTextSizeMeasure,
+ SkIntToScalar(gm.advanceWidth),
+ SkIntToScalar(dwfm.designUnitsPerEm));
+
+ if (!this->isSubpixel()) {
+ advanceX = SkScalarRoundToScalar(advanceX);
+ }
+
+ SkVector vecs[1] = { { advanceX, 0 } };
+ if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
+ DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
+ {
+ // DirectWrite produced 'compatible' metrics, but while close,
+ // the end result is not always an integer as it would be with GDI.
+ vecs[0].fX = SkScalarRoundToScalar(advanceX);
+ fG_inv.mapVectors(vecs, SK_ARRAY_COUNT(vecs));
+ } else {
+ fSkXform.mapVectors(vecs, SK_ARRAY_COUNT(vecs));
+ }
+
+ glyph->fAdvanceX = SkScalarToFixed(vecs[0].fX);
+ glyph->fAdvanceY = SkScalarToFixed(vecs[0].fY);
+}
+
+void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) {
+ glyph->fWidth = 0;
+
+ this->generateAdvance(glyph);
+
+ //Measure raster size.
+ fXform.dx = SkFixedToFloat(glyph->getSubXFixed());
+ fXform.dy = SkFixedToFloat(glyph->getSubYFixed());
+
+ FLOAT advance = 0;
+
+ UINT16 glyphId = glyph->getGlyphID();
+
+ DWRITE_GLYPH_OFFSET offset;
+ offset.advanceOffset = 0.0f;
+ offset.ascenderOffset = 0.0f;
+
+ DWRITE_GLYPH_RUN run;
+ run.glyphCount = 1;
+ run.glyphAdvances = &advance;
+ run.fontFace = fTypeface->fDWriteFontFace.get();
+ run.fontEmSize = SkScalarToFloat(fTextSizeRender);
+ run.bidiLevel = 0;
+ run.glyphIndices = &glyphId;
+ run.isSideways = FALSE;
+ run.glyphOffsets = &offset;
+
+ SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
+ HRVM(fTypeface->fFactory->CreateGlyphRunAnalysis(
+ &run,
+ 1.0f, // pixelsPerDip,
+ &fXform,
+ fRenderingMode,
+ fMeasuringMode,
+ 0.0f, // baselineOriginX,
+ 0.0f, // baselineOriginY,
+ &glyphRunAnalysis),
+ "Could not create glyph run analysis.");
+
+ RECT bbox;
+ HRVM(glyphRunAnalysis->GetAlphaTextureBounds(fTextureType, &bbox),
+ "Could not get texture bounds.");
+
+ glyph->fWidth = SkToU16(bbox.right - bbox.left);
+ glyph->fHeight = SkToU16(bbox.bottom - bbox.top);
+ glyph->fLeft = SkToS16(bbox.left);
+ glyph->fTop = SkToS16(bbox.top);
+}
+
+void SkScalerContext_DW::generateFontMetrics(SkPaint::FontMetrics* mx,
+ SkPaint::FontMetrics* my) {
+ if (!(mx || my))
+ return;
+
+ if (mx) {
+ sk_bzero(mx, sizeof(*mx));
+ }
+ if (my) {
+ sk_bzero(my, sizeof(*my));
+ }
+
+ DWRITE_FONT_METRICS dwfm;
+ if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
+ DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
+ {
+ fTypeface->fDWriteFontFace->GetGdiCompatibleMetrics(
+ fTextSizeRender,
+ 1.0f, // pixelsPerDip
+ &fXform,
+ &dwfm);
+ } else {
+ fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
+ }
+
+ SkScalar upem = SkIntToScalar(dwfm.designUnitsPerEm);
+ if (mx) {
+ mx->fTop = -fTextSizeRender * SkIntToScalar(dwfm.ascent) / upem;
+ mx->fAscent = mx->fTop;
+ mx->fDescent = fTextSizeRender * SkIntToScalar(dwfm.descent) / upem;
+ mx->fBottom = mx->fDescent;
+ mx->fLeading = fTextSizeRender * SkIntToScalar(dwfm.lineGap) / upem;
+ mx->fXHeight = fTextSizeRender * SkIntToScalar(dwfm.xHeight) / upem;
+ mx->fUnderlineThickness = fTextSizeRender * SkIntToScalar(dwfm.underlineThickness) / upem;
+ mx->fUnderlinePosition = -(fTextSizeRender * SkIntToScalar(dwfm.underlinePosition) / upem);
+
+ mx->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
+ mx->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
+ }
+
+ if (my) {
+ my->fAscent = -fTextSizeRender * SkIntToScalar(dwfm.ascent) / upem;
+ my->fDescent = fTextSizeRender * SkIntToScalar(dwfm.descent) / upem;
+ my->fLeading = fTextSizeRender * SkIntToScalar(dwfm.lineGap) / upem;
+ my->fXHeight = fTextSizeRender * SkIntToScalar(dwfm.xHeight) / upem;
+ my->fUnderlineThickness = fTextSizeRender * SkIntToScalar(dwfm.underlineThickness) / upem;
+ my->fUnderlinePosition = -(fTextSizeRender * SkIntToScalar(dwfm.underlinePosition) / upem);
+
+ my->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
+ my->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
+
+ if (NULL != fTypeface->fDWriteFontFace1.get()) {
+ DWRITE_FONT_METRICS1 dwfm1;
+ fTypeface->fDWriteFontFace1->GetMetrics(&dwfm1);
+ my->fTop = -fTextSizeRender * SkIntToScalar(dwfm1.glyphBoxTop) / upem;
+ my->fBottom = -fTextSizeRender * SkIntToScalar(dwfm1.glyphBoxBottom) / upem;
+ my->fXMin = fTextSizeRender * SkIntToScalar(dwfm1.glyphBoxLeft) / upem;
+ my->fXMax = fTextSizeRender * SkIntToScalar(dwfm1.glyphBoxRight) / upem;
+
+ my->fMaxCharWidth = my->fXMax - my->fXMin;
+ } else {
+ AutoTDWriteTable<SkOTTableHead> head(fTypeface->fDWriteFontFace.get());
+ if (head.fExists &&
+ head.fSize >= sizeof(SkOTTableHead) &&
+ head->version == SkOTTableHead::version1)
+ {
+ my->fTop = -fTextSizeRender * (int16_t)SkEndian_SwapBE16(head->yMax) / upem;
+ my->fBottom = -fTextSizeRender * (int16_t)SkEndian_SwapBE16(head->yMin) / upem;
+ my->fXMin = fTextSizeRender * (int16_t)SkEndian_SwapBE16(head->xMin) / upem;
+ my->fXMax = fTextSizeRender * (int16_t)SkEndian_SwapBE16(head->xMax) / upem;
+
+ my->fMaxCharWidth = my->fXMax - my->fXMin;
+ } else {
+ my->fTop = my->fAscent;
+ my->fBottom = my->fDescent;
+ }
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include "SkColorPriv.h"
+
+static void bilevel_to_bw(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph) {
+ const int width = glyph.fWidth;
+ const size_t dstRB = (width + 7) >> 3;
+ uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
+
+ int byteCount = width >> 3;
+ int bitCount = width & 7;
+
+ for (int y = 0; y < glyph.fHeight; ++y) {
+ if (byteCount > 0) {
+ for (int i = 0; i < byteCount; ++i) {
+ unsigned byte = 0;
+ byte |= src[0] & (1 << 7);
+ byte |= src[1] & (1 << 6);
+ byte |= src[2] & (1 << 5);
+ byte |= src[3] & (1 << 4);
+ byte |= src[4] & (1 << 3);
+ byte |= src[5] & (1 << 2);
+ byte |= src[6] & (1 << 1);
+ byte |= src[7] & (1 << 0);
+ dst[i] = byte;
+ src += 8;
+ }
+ }
+ if (bitCount > 0) {
+ unsigned byte = 0;
+ unsigned mask = 0x80;
+ for (int i = 0; i < bitCount; i++) {
+ byte |= (src[i]) & mask;
+ mask >>= 1;
+ }
+ dst[byteCount] = byte;
+ }
+ src += bitCount;
+ dst += dstRB;
+ }
+}
+
+template<bool APPLY_PREBLEND>
+static void rgb_to_a8(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, const uint8_t* table8) {
+ const size_t dstRB = glyph.rowBytes();
+ const U16CPU width = glyph.fWidth;
+ uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
+
+ for (U16CPU y = 0; y < glyph.fHeight; y++) {
+ for (U16CPU i = 0; i < width; i++) {
+ U8CPU r = *(src++);
+ U8CPU g = *(src++);
+ U8CPU b = *(src++);
+ dst[i] = sk_apply_lut_if<APPLY_PREBLEND>((r + g + b) / 3, table8);
+ }
+ dst = (uint8_t*)((char*)dst + dstRB);
+ }
+}
+
+template<bool APPLY_PREBLEND>
+static void rgb_to_lcd16(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
+ const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
+ const size_t dstRB = glyph.rowBytes();
+ const U16CPU width = glyph.fWidth;
+ uint16_t* SK_RESTRICT dst = static_cast<uint16_t*>(glyph.fImage);
+
+ for (U16CPU y = 0; y < glyph.fHeight; y++) {
+ for (U16CPU i = 0; i < width; i++) {
+ U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
+ U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
+ U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
+ dst[i] = SkPack888ToRGB16(r, g, b);
+ }
+ dst = (uint16_t*)((char*)dst + dstRB);
+ }
+}
+
+template<bool APPLY_PREBLEND>
+static void rgb_to_lcd32(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
+ const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
+ const size_t dstRB = glyph.rowBytes();
+ const U16CPU width = glyph.fWidth;
+ SkPMColor* SK_RESTRICT dst = static_cast<SkPMColor*>(glyph.fImage);
+
+ for (U16CPU y = 0; y < glyph.fHeight; y++) {
+ for (U16CPU i = 0; i < width; i++) {
+ U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
+ U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
+ U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
+ dst[i] = SkPackARGB32(0xFF, r, g, b);
+ }
+ dst = (SkPMColor*)((char*)dst + dstRB);
+ }
+}
+
+const void* SkScalerContext_DW::drawDWMask(const SkGlyph& glyph) {
+ int sizeNeeded = glyph.fWidth * glyph.fHeight;
+ if (DWRITE_RENDERING_MODE_ALIASED != fRenderingMode) {
+ sizeNeeded *= 3;
+ }
+ if (sizeNeeded > fBits.count()) {
+ fBits.setCount(sizeNeeded);
+ }
+
+ // erase
+ memset(fBits.begin(), 0, sizeNeeded);
+
+ fXform.dx = SkFixedToFloat(glyph.getSubXFixed());
+ fXform.dy = SkFixedToFloat(glyph.getSubYFixed());
+
+ FLOAT advance = 0.0f;
+
+ UINT16 index = glyph.getGlyphID();
+
+ DWRITE_GLYPH_OFFSET offset;
+ offset.advanceOffset = 0.0f;
+ offset.ascenderOffset = 0.0f;
+
+ DWRITE_GLYPH_RUN run;
+ run.glyphCount = 1;
+ run.glyphAdvances = &advance;
+ run.fontFace = fTypeface->fDWriteFontFace.get();
+ run.fontEmSize = SkScalarToFloat(fTextSizeRender);
+ run.bidiLevel = 0;
+ run.glyphIndices = &index;
+ run.isSideways = FALSE;
+ run.glyphOffsets = &offset;
+
+ SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
+ HRNM(fTypeface->fFactory->CreateGlyphRunAnalysis(&run,
+ 1.0f, // pixelsPerDip,
+ &fXform,
+ fRenderingMode,
+ fMeasuringMode,
+ 0.0f, // baselineOriginX,
+ 0.0f, // baselineOriginY,
+ &glyphRunAnalysis),
+ "Could not create glyph run analysis.");
+
+ //NOTE: this assumes that the glyph has already been measured
+ //with an exact same glyph run analysis.
+ RECT bbox;
+ bbox.left = glyph.fLeft;
+ bbox.top = glyph.fTop;
+ bbox.right = glyph.fLeft + glyph.fWidth;
+ bbox.bottom = glyph.fTop + glyph.fHeight;
+ HRNM(glyphRunAnalysis->CreateAlphaTexture(fTextureType,
+ &bbox,
+ fBits.begin(),
+ sizeNeeded),
+ "Could not draw mask.");
+ return fBits.begin();
+}
+
+void SkScalerContext_DW::generateImage(const SkGlyph& glyph) {
+ //Create the mask.
+ const void* bits = this->drawDWMask(glyph);
+ if (!bits) {
+ sk_bzero(glyph.fImage, glyph.computeImageSize());
+ return;
+ }
+
+ //Copy the mask into the glyph.
+ const uint8_t* src = (const uint8_t*)bits;
+ if (DWRITE_RENDERING_MODE_ALIASED == fRenderingMode) {
+ bilevel_to_bw(src, glyph);
+ const_cast<SkGlyph&>(glyph).fMaskFormat = SkMask::kBW_Format;
+ } else if (!isLCD(fRec)) {
+ if (fPreBlend.isApplicable()) {
+ rgb_to_a8<true>(src, glyph, fPreBlend.fG);
+ } else {
+ rgb_to_a8<false>(src, glyph, fPreBlend.fG);
+ }
+ } else if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
+ if (fPreBlend.isApplicable()) {
+ rgb_to_lcd16<true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
+ } else {
+ rgb_to_lcd16<false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
+ }
+ } else {
+ SkASSERT(SkMask::kLCD32_Format == glyph.fMaskFormat);
+ if (fPreBlend.isApplicable()) {
+ rgb_to_lcd32<true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
+ } else {
+ rgb_to_lcd32<false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
+ }
+ }
+}
+
+void SkScalerContext_DW::generatePath(const SkGlyph& glyph, SkPath* path) {
+ SkASSERT(&glyph && path);
+
+ path->reset();
+
+ SkTScopedComPtr<IDWriteGeometrySink> geometryToPath;
+ HRVM(SkDWriteGeometrySink::Create(path, &geometryToPath),
+ "Could not create geometry to path converter.");
+ uint16_t glyphId = glyph.getGlyphID();
+ //TODO: convert to<->from DIUs? This would make a difference if hinting.
+ //It may not be needed, it appears that DirectWrite only hints at em size.
+ HRVM(fTypeface->fDWriteFontFace->GetGlyphRunOutline(SkScalarToFloat(fTextSizeRender),
+ &glyphId,
+ NULL, //advances
+ NULL, //offsets
+ 1, //num glyphs
+ FALSE, //sideways
+ FALSE, //rtl
+ geometryToPath.get()),
+ "Could not create glyph outline.");
+
+ path->transform(fSkXform);
+}
diff --git a/chromium/third_party/skia/src/ports/SkScalerContext_win_dw.h b/chromium/third_party/skia/src/ports/SkScalerContext_win_dw.h
new file mode 100644
index 00000000000..e3dbd29543b
--- /dev/null
+++ b/chromium/third_party/skia/src/ports/SkScalerContext_win_dw.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkScalarContext_win_dw_DEFINED
+#define SkScalarContext_win_dw_DEFINED
+
+#include "SkScalar.h"
+#include "SkScalerContext.h"
+#include "SkTypeface_win_dw.h"
+#include "SkTypes.h"
+
+#include <dwrite.h>
+
+struct SkGlyph;
+class SkDescriptor;
+
+class SkScalerContext_DW : public SkScalerContext {
+public:
+ SkScalerContext_DW(DWriteFontTypeface*, const SkDescriptor* desc);
+ virtual ~SkScalerContext_DW();
+
+protected:
+ virtual unsigned generateGlyphCount() SK_OVERRIDE;
+ virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE;
+ virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE;
+ virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE;
+ virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE;
+ virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE;
+ virtual void generateFontMetrics(SkPaint::FontMetrics* mX,
+ SkPaint::FontMetrics* mY) SK_OVERRIDE;
+
+private:
+ const void* drawDWMask(const SkGlyph& glyph);
+
+ SkTDArray<uint8_t> fBits;
+ /** The total matrix without the text height scale. */
+ SkMatrix fSkXform;
+ /** The total matrix without the text height scale. */
+ DWRITE_MATRIX fXform;
+ /** The non-rotational part of total matrix without the text height scale.
+ * This is used to find the magnitude of gdi compatible advances.
+ */
+ DWRITE_MATRIX fGsA;
+ /** The inverse of the rotational part of the total matrix.
+ * This is used to find the direction of gdi compatible advances.
+ */
+ SkMatrix fG_inv;
+ /** The text size to render with. */
+ SkScalar fTextSizeRender;
+ /** The text size to measure with. */
+ SkScalar fTextSizeMeasure;
+ SkAutoTUnref<DWriteFontTypeface> fTypeface;
+ int fGlyphCount;
+ DWRITE_RENDERING_MODE fRenderingMode;
+ DWRITE_TEXTURE_TYPE fTextureType;
+ DWRITE_MEASURING_MODE fMeasuringMode;
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/ports/SkThread_none.cpp b/chromium/third_party/skia/src/ports/SkThread_none.cpp
deleted file mode 100644
index 638d7d017dd..00000000000
--- a/chromium/third_party/skia/src/ports/SkThread_none.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2006 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkThread.h"
-
-int32_t sk_atomic_inc(int32_t* addr) {
- int32_t value = *addr;
- *addr = value + 1;
- return value;
-}
-
-int32_t sk_atomic_add(int32_t* addr, int32_t inc) {
- int32_t value = *addr;
- *addr = value + inc;
- return value;
-}
-
-int32_t sk_atomic_dec(int32_t* addr) {
- int32_t value = *addr;
- *addr = value - 1;
- return value;
-}
-void sk_membar_aquire__after_atomic_dec() { }
-
-int32_t sk_atomic_conditional_inc(int32_t* addr) {
- int32_t value = *addr;
- if (value != 0) ++*addr;
- return value;
-}
-void sk_membar_aquire__after_atomic_conditional_inc() { }
-
-SkMutex::SkMutex() {}
-
-SkMutex::~SkMutex() {}
-
-#ifndef SK_USE_POSIX_THREADS
-void SkMutex::acquire() {}
-void SkMutex::release() {}
-#endif
diff --git a/chromium/third_party/skia/src/ports/SkThread_pthread.cpp b/chromium/third_party/skia/src/ports/SkThread_pthread.cpp
deleted file mode 100644
index a78c7b2f14e..00000000000
--- a/chromium/third_party/skia/src/ports/SkThread_pthread.cpp
+++ /dev/null
@@ -1,197 +0,0 @@
-
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "SkThread.h"
-
-#include <pthread.h>
-#include <errno.h>
-
-#ifndef SK_BUILD_FOR_ANDROID
-
-/**
- We prefer the GCC intrinsic implementation of the atomic operations over the
- SkMutex-based implementation. The SkMutex version suffers from static
- destructor ordering problems.
- Note clang also defines the GCC version macros and implements the intrinsics.
- TODO: Verify that gcc-style __sync_* intrinsics work on ARM
- According to this the intrinsics are supported on ARM in LLVM 2.7+
- http://llvm.org/releases/2.7/docs/ReleaseNotes.html
-*/
-#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || __GNUC__ > 4
- #if (defined(__x86_64) || defined(__i386__))
- #define GCC_INTRINSIC
- #endif
-#endif
-
-#if defined(GCC_INTRINSIC)
-
-int32_t sk_atomic_inc(int32_t* addr)
-{
- return __sync_fetch_and_add(addr, 1);
-}
-
-int32_t sk_atomic_add(int32_t* addr, int32_t inc)
-{
- return __sync_fetch_and_add(addr, inc);
-}
-
-int32_t sk_atomic_dec(int32_t* addr)
-{
- return __sync_fetch_and_add(addr, -1);
-}
-void sk_membar_aquire__after_atomic_dec() { }
-
-int32_t sk_atomic_conditional_inc(int32_t* addr)
-{
- int32_t value = *addr;
-
- while (true) {
- if (value == 0) {
- return 0;
- }
-
- int32_t before = __sync_val_compare_and_swap(addr, value, value + 1);
-
- if (before == value) {
- return value;
- } else {
- value = before;
- }
- }
-}
-void sk_membar_aquire__after_atomic_conditional_inc() { }
-
-#else
-
-SkMutex gAtomicMutex;
-
-int32_t sk_atomic_inc(int32_t* addr)
-{
- SkAutoMutexAcquire ac(gAtomicMutex);
-
- int32_t value = *addr;
- *addr = value + 1;
- return value;
-}
-
-int32_t sk_atomic_add(int32_t* addr, int32_t inc)
-{
- SkAutoMutexAcquire ac(gAtomicMutex);
-
- int32_t value = *addr;
- *addr = value + inc;
- return value;
-}
-
-int32_t sk_atomic_dec(int32_t* addr)
-{
- SkAutoMutexAcquire ac(gAtomicMutex);
-
- int32_t value = *addr;
- *addr = value - 1;
- return value;
-}
-void sk_membar_aquire__after_atomic_dec() { }
-
-int32_t sk_atomic_conditional_inc(int32_t* addr)
-{
- SkAutoMutexAcquire ac(gAtomicMutex);
-
- int32_t value = *addr;
- if (value != 0) ++*addr;
- return value;
-}
-void sk_membar_aquire__after_atomic_conditional_inc() { }
-
-#endif
-
-#endif // SK_BUILD_FOR_ANDROID
-
-//////////////////////////////////////////////////////////////////////////////
-
-static void print_pthread_error(int status) {
- switch (status) {
- case 0: // success
- break;
- case EINVAL:
- SkDebugf("pthread error [%d] EINVAL\n", status);
- break;
- case EBUSY:
- SkDebugf("pthread error [%d] EBUSY\n", status);
- break;
- default:
- SkDebugf("pthread error [%d] unknown\n", status);
- break;
- }
-}
-
-#ifdef SK_USE_POSIX_THREADS
-
-SkMutex::SkMutex() {
- int status;
-
- status = pthread_mutex_init(&fMutex, NULL);
- if (status != 0) {
- print_pthread_error(status);
- SkASSERT(0 == status);
- }
-}
-
-SkMutex::~SkMutex() {
- int status = pthread_mutex_destroy(&fMutex);
-
- // only report errors on non-global mutexes
- if (status != 0) {
- print_pthread_error(status);
- SkASSERT(0 == status);
- }
-}
-
-#else // !SK_USE_POSIX_THREADS
-
-SkMutex::SkMutex() {
- if (sizeof(pthread_mutex_t) > sizeof(fStorage)) {
- SkDEBUGF(("pthread mutex size = %d\n", sizeof(pthread_mutex_t)));
- SkDEBUGFAIL("mutex storage is too small");
- }
-
- int status;
- pthread_mutexattr_t attr;
-
- status = pthread_mutexattr_init(&attr);
- print_pthread_error(status);
- SkASSERT(0 == status);
-
- status = pthread_mutex_init((pthread_mutex_t*)fStorage, &attr);
- print_pthread_error(status);
- SkASSERT(0 == status);
-}
-
-SkMutex::~SkMutex() {
- int status = pthread_mutex_destroy((pthread_mutex_t*)fStorage);
-#if 0
- // only report errors on non-global mutexes
- if (!fIsGlobal) {
- print_pthread_error(status);
- SkASSERT(0 == status);
- }
-#endif
-}
-
-void SkMutex::acquire() {
- int status = pthread_mutex_lock((pthread_mutex_t*)fStorage);
- print_pthread_error(status);
- SkASSERT(0 == status);
-}
-
-void SkMutex::release() {
- int status = pthread_mutex_unlock((pthread_mutex_t*)fStorage);
- print_pthread_error(status);
- SkASSERT(0 == status);
-}
-
-#endif // !SK_USE_POSIX_THREADS
diff --git a/chromium/third_party/skia/src/ports/SkThread_win.cpp b/chromium/third_party/skia/src/ports/SkThread_win.cpp
deleted file mode 100644
index 708db24ab99..00000000000
--- a/chromium/third_party/skia/src/ports/SkThread_win.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2008 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include <windows.h>
-#include <intrin.h>
-#include "SkThread.h"
-
-//MSDN says in order to declare an interlocked function for use as an
-//intrinsic, include intrin.h and put the function in a #pragma intrinsic
-//directive.
-//The pragma appears to be unnecessary, but doesn't hurt.
-#pragma intrinsic(_InterlockedIncrement, _InterlockedExchangeAdd, _InterlockedDecrement)
-#pragma intrinsic(_InterlockedCompareExchange)
-
-int32_t sk_atomic_inc(int32_t* addr) {
- // InterlockedIncrement returns the new value, we want to return the old.
- return _InterlockedIncrement(reinterpret_cast<LONG*>(addr)) - 1;
-}
-
-int32_t sk_atomic_add(int32_t* addr, int32_t inc) {
- return _InterlockedExchangeAdd(reinterpret_cast<LONG*>(addr),
- static_cast<LONG>(inc));
-}
-
-int32_t sk_atomic_dec(int32_t* addr) {
- return _InterlockedDecrement(reinterpret_cast<LONG*>(addr)) + 1;
-}
-void sk_membar_aquire__after_atomic_dec() { }
-
-int32_t sk_atomic_conditional_inc(int32_t* addr) {
- while (true) {
- LONG value = static_cast<int32_t const volatile&>(*addr);
- if (value == 0) {
- return 0;
- }
- if (_InterlockedCompareExchange(reinterpret_cast<LONG*>(addr),
- value + 1,
- value) == value) {
- return value;
- }
- }
-}
-void sk_membar_aquire__after_atomic_conditional_inc() { }
-
-SkMutex::SkMutex() {
- SK_COMPILE_ASSERT(sizeof(fStorage) > sizeof(CRITICAL_SECTION),
- NotEnoughSizeForCriticalSection);
- InitializeCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&fStorage));
-}
-
-SkMutex::~SkMutex() {
- DeleteCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&fStorage));
-}
-
-void SkMutex::acquire() {
- EnterCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&fStorage));
-}
-
-void SkMutex::release() {
- LeaveCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&fStorage));
-}
diff --git a/chromium/third_party/skia/src/ports/SkTypeface_win_dw.cpp b/chromium/third_party/skia/src/ports/SkTypeface_win_dw.cpp
new file mode 100644
index 00000000000..6ff84128580
--- /dev/null
+++ b/chromium/third_party/skia/src/ports/SkTypeface_win_dw.cpp
@@ -0,0 +1,489 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkDWriteFontFileStream.h"
+#include "SkFontDescriptor.h"
+#include "SkFontStream.h"
+#include "SkOTTable_head.h"
+#include "SkOTTable_hhea.h"
+#include "SkOTTable_OS_2.h"
+#include "SkOTTable_post.h"
+#include "SkScalerContext.h"
+#include "SkScalerContext_win_dw.h"
+#include "SkTypeface_win_dw.h"
+#include "SkTypes.h"
+#include "SkUtils.h"
+
+void DWriteFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
+ bool* isLocalStream) const {
+ // Get the family name.
+ SkTScopedComPtr<IDWriteLocalizedStrings> dwFamilyNames;
+ HRV(fDWriteFontFamily->GetFamilyNames(&dwFamilyNames));
+
+ UINT32 dwFamilyNamesLength;
+ HRV(dwFamilyNames->GetStringLength(0, &dwFamilyNamesLength));
+
+ SkSMallocWCHAR dwFamilyNameChar(dwFamilyNamesLength+1);
+ HRV(dwFamilyNames->GetString(0, dwFamilyNameChar.get(), dwFamilyNamesLength+1));
+
+ SkString utf8FamilyName;
+ HRV(sk_wchar_to_skstring(dwFamilyNameChar.get(), &utf8FamilyName));
+
+ desc->setFamilyName(utf8FamilyName.c_str());
+ *isLocalStream = SkToBool(fDWriteFontFileLoader.get());
+}
+
+static SkUnichar next_utf8(const void** chars) {
+ return SkUTF8_NextUnichar((const char**)chars);
+}
+
+static SkUnichar next_utf16(const void** chars) {
+ return SkUTF16_NextUnichar((const uint16_t**)chars);
+}
+
+static SkUnichar next_utf32(const void** chars) {
+ const SkUnichar** uniChars = (const SkUnichar**)chars;
+ SkUnichar uni = **uniChars;
+ *uniChars += 1;
+ return uni;
+}
+
+typedef SkUnichar (*EncodingProc)(const void**);
+
+static EncodingProc find_encoding_proc(SkTypeface::Encoding enc) {
+ static const EncodingProc gProcs[] = {
+ next_utf8, next_utf16, next_utf32
+ };
+ SkASSERT((size_t)enc < SK_ARRAY_COUNT(gProcs));
+ return gProcs[enc];
+}
+
+int DWriteFontTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
+ uint16_t glyphs[], int glyphCount) const
+{
+ if (NULL == glyphs) {
+ EncodingProc next_ucs4_proc = find_encoding_proc(encoding);
+ for (int i = 0; i < glyphCount; ++i) {
+ const SkUnichar c = next_ucs4_proc(&chars);
+ BOOL exists;
+ fDWriteFont->HasCharacter(c, &exists);
+ if (!exists) {
+ return i;
+ }
+ }
+ return glyphCount;
+ }
+
+ switch (encoding) {
+ case SkTypeface::kUTF8_Encoding:
+ case SkTypeface::kUTF16_Encoding: {
+ static const int scratchCount = 256;
+ UINT32 scratch[scratchCount];
+ EncodingProc next_ucs4_proc = find_encoding_proc(encoding);
+ for (int baseGlyph = 0; baseGlyph < glyphCount; baseGlyph += scratchCount) {
+ int glyphsLeft = glyphCount - baseGlyph;
+ int limit = SkTMin(glyphsLeft, scratchCount);
+ for (int i = 0; i < limit; ++i) {
+ scratch[i] = next_ucs4_proc(&chars);
+ }
+ fDWriteFontFace->GetGlyphIndices(scratch, limit, &glyphs[baseGlyph]);
+ }
+ break;
+ }
+ case SkTypeface::kUTF32_Encoding: {
+ const UINT32* utf32 = reinterpret_cast<const UINT32*>(chars);
+ fDWriteFontFace->GetGlyphIndices(utf32, glyphCount, glyphs);
+ break;
+ }
+ default:
+ SK_CRASH();
+ }
+
+ for (int i = 0; i < glyphCount; ++i) {
+ if (0 == glyphs[i]) {
+ return i;
+ }
+ }
+ return glyphCount;
+}
+
+int DWriteFontTypeface::onCountGlyphs() const {
+ return fDWriteFontFace->GetGlyphCount();
+}
+
+int DWriteFontTypeface::onGetUPEM() const {
+ DWRITE_FONT_METRICS metrics;
+ fDWriteFontFace->GetMetrics(&metrics);
+ return metrics.designUnitsPerEm;
+}
+
+class LocalizedStrings_IDWriteLocalizedStrings : public SkTypeface::LocalizedStrings {
+public:
+ /** Takes ownership of the IDWriteLocalizedStrings. */
+ explicit LocalizedStrings_IDWriteLocalizedStrings(IDWriteLocalizedStrings* strings)
+ : fIndex(0), fStrings(strings)
+ { }
+
+ virtual bool next(SkTypeface::LocalizedString* localizedString) SK_OVERRIDE {
+ if (fIndex >= fStrings->GetCount()) {
+ return false;
+ }
+
+ // String
+ UINT32 stringLength;
+ HRBM(fStrings->GetStringLength(fIndex, &stringLength), "Could not get string length.");
+ stringLength += 1;
+
+ SkSMallocWCHAR wString(stringLength);
+ HRBM(fStrings->GetString(fIndex, wString.get(), stringLength), "Could not get string.");
+
+ HRB(sk_wchar_to_skstring(wString.get(), &localizedString->fString));
+
+ // Locale
+ UINT32 localeLength;
+ HRBM(fStrings->GetLocaleNameLength(fIndex, &localeLength), "Could not get locale length.");
+ localeLength += 1;
+
+ SkSMallocWCHAR wLocale(localeLength);
+ HRBM(fStrings->GetLocaleName(fIndex, wLocale.get(), localeLength), "Could not get locale.");
+
+ HRB(sk_wchar_to_skstring(wLocale.get(), &localizedString->fLanguage));
+
+ ++fIndex;
+ return true;
+ }
+
+private:
+ UINT32 fIndex;
+ SkTScopedComPtr<IDWriteLocalizedStrings> fStrings;
+};
+
+SkTypeface::LocalizedStrings* DWriteFontTypeface::onCreateFamilyNameIterator() const {
+ SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
+ HRNM(fDWriteFontFamily->GetFamilyNames(&familyNames), "Could not obtain family names.");
+
+ return new LocalizedStrings_IDWriteLocalizedStrings(familyNames.release());
+}
+
+int DWriteFontTypeface::onGetTableTags(SkFontTableTag tags[]) const {
+ DWRITE_FONT_FACE_TYPE type = fDWriteFontFace->GetType();
+ if (type != DWRITE_FONT_FACE_TYPE_CFF &&
+ type != DWRITE_FONT_FACE_TYPE_TRUETYPE &&
+ type != DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION)
+ {
+ return 0;
+ }
+
+ int ttcIndex;
+ SkAutoTUnref<SkStream> stream(this->openStream(&ttcIndex));
+ return stream.get() ? SkFontStream::GetTableTags(stream, ttcIndex, tags) : 0;
+}
+
+size_t DWriteFontTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
+ size_t length, void* data) const
+{
+ AutoDWriteTable table(fDWriteFontFace.get(), SkEndian_SwapBE32(tag));
+ if (!table.fExists) {
+ return 0;
+ }
+
+ if (offset > table.fSize) {
+ return 0;
+ }
+ size_t size = SkTMin(length, table.fSize - offset);
+ if (NULL != data) {
+ memcpy(data, table.fData + offset, size);
+ }
+
+ return size;
+}
+
+SkStream* DWriteFontTypeface::onOpenStream(int* ttcIndex) const {
+ *ttcIndex = fDWriteFontFace->GetIndex();
+
+ UINT32 numFiles;
+ HRNM(fDWriteFontFace->GetFiles(&numFiles, NULL),
+ "Could not get number of font files.");
+ if (numFiles != 1) {
+ return NULL;
+ }
+
+ SkTScopedComPtr<IDWriteFontFile> fontFile;
+ HRNM(fDWriteFontFace->GetFiles(&numFiles, &fontFile), "Could not get font files.");
+
+ const void* fontFileKey;
+ UINT32 fontFileKeySize;
+ HRNM(fontFile->GetReferenceKey(&fontFileKey, &fontFileKeySize),
+ "Could not get font file reference key.");
+
+ SkTScopedComPtr<IDWriteFontFileLoader> fontFileLoader;
+ HRNM(fontFile->GetLoader(&fontFileLoader), "Could not get font file loader.");
+
+ SkTScopedComPtr<IDWriteFontFileStream> fontFileStream;
+ HRNM(fontFileLoader->CreateStreamFromKey(fontFileKey, fontFileKeySize,
+ &fontFileStream),
+ "Could not create font file stream.");
+
+ return SkNEW_ARGS(SkDWriteFontFileStream, (fontFileStream.get()));
+}
+
+SkScalerContext* DWriteFontTypeface::onCreateScalerContext(const SkDescriptor* desc) const {
+ return SkNEW_ARGS(SkScalerContext_DW, (const_cast<DWriteFontTypeface*>(this), desc));
+}
+
+void DWriteFontTypeface::onFilterRec(SkScalerContext::Rec* rec) const {
+ if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag ||
+ rec->fFlags & SkScalerContext::kLCD_Vertical_Flag)
+ {
+ rec->fMaskFormat = SkMask::kA8_Format;
+ }
+
+ unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag |
+ SkScalerContext::kForceAutohinting_Flag |
+ SkScalerContext::kEmbolden_Flag |
+ SkScalerContext::kLCD_BGROrder_Flag |
+ SkScalerContext::kLCD_Vertical_Flag;
+ rec->fFlags &= ~flagsWeDontSupport;
+
+ SkPaint::Hinting h = rec->getHinting();
+ // DirectWrite does not provide for hinting hints.
+ h = SkPaint::kSlight_Hinting;
+ rec->setHinting(h);
+
+#if SK_FONT_HOST_USE_SYSTEM_SETTINGS
+ IDWriteFactory* factory = get_dwrite_factory();
+ if (factory != NULL) {
+ SkTScopedComPtr<IDWriteRenderingParams> defaultRenderingParams;
+ if (SUCCEEDED(factory->CreateRenderingParams(&defaultRenderingParams))) {
+ float gamma = defaultRenderingParams->GetGamma();
+ rec->setDeviceGamma(gamma);
+ rec->setPaintGamma(gamma);
+
+ rec->setContrast(defaultRenderingParams->GetEnhancedContrast());
+ }
+ }
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//PDF Support
+
+using namespace skia_advanced_typeface_metrics_utils;
+
+// Construct Glyph to Unicode table.
+// Unicode code points that require conjugate pairs in utf16 are not
+// supported.
+// TODO(arthurhsu): Add support for conjugate pairs. It looks like that may
+// require parsing the TTF cmap table (platform 4, encoding 12) directly instead
+// of calling GetFontUnicodeRange().
+// TODO(bungeman): This never does what anyone wants.
+// What is really wanted is the text to glyphs mapping
+static void populate_glyph_to_unicode(IDWriteFontFace* fontFace,
+ const unsigned glyphCount,
+ SkTDArray<SkUnichar>* glyphToUnicode) {
+ HRESULT hr = S_OK;
+
+ //Do this like free type instead
+ UINT32 count = 0;
+ for (UINT32 c = 0; c < 0x10FFFF; ++c) {
+ UINT16 glyph;
+ hr = fontFace->GetGlyphIndices(&c, 1, &glyph);
+ if (glyph > 0) {
+ ++count;
+ }
+ }
+
+ SkAutoTArray<UINT32> chars(count);
+ count = 0;
+ for (UINT32 c = 0; c < 0x10FFFF; ++c) {
+ UINT16 glyph;
+ hr = fontFace->GetGlyphIndices(&c, 1, &glyph);
+ if (glyph > 0) {
+ chars[count] = c;
+ ++count;
+ }
+ }
+
+ SkAutoTArray<UINT16> glyph(count);
+ fontFace->GetGlyphIndices(chars.get(), count, glyph.get());
+
+ USHORT maxGlyph = 0;
+ for (USHORT j = 0; j < count; ++j) {
+ if (glyph[j] > maxGlyph) maxGlyph = glyph[j];
+ }
+
+ glyphToUnicode->setCount(maxGlyph+1);
+ for (USHORT j = 0; j < maxGlyph+1u; ++j) {
+ (*glyphToUnicode)[j] = 0;
+ }
+
+ //'invert'
+ for (USHORT j = 0; j < count; ++j) {
+ if (glyph[j] < glyphCount && (*glyphToUnicode)[glyph[j]] == 0) {
+ (*glyphToUnicode)[glyph[j]] = chars[j];
+ }
+ }
+}
+
+static bool getWidthAdvance(IDWriteFontFace* fontFace, int gId, int16_t* advance) {
+ SkASSERT(advance);
+
+ UINT16 glyphId = gId;
+ DWRITE_GLYPH_METRICS gm;
+ HRESULT hr = fontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm);
+
+ if (FAILED(hr)) {
+ *advance = 0;
+ return false;
+ }
+
+ *advance = gm.advanceWidth;
+ return true;
+}
+
+SkAdvancedTypefaceMetrics* DWriteFontTypeface::onGetAdvancedTypefaceMetrics(
+ SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
+ const uint32_t* glyphIDs,
+ uint32_t glyphIDsCount) const {
+
+ SkAdvancedTypefaceMetrics* info = NULL;
+
+ HRESULT hr = S_OK;
+
+ const unsigned glyphCount = fDWriteFontFace->GetGlyphCount();
+
+ DWRITE_FONT_METRICS dwfm;
+ fDWriteFontFace->GetMetrics(&dwfm);
+
+ info = new SkAdvancedTypefaceMetrics;
+ info->fEmSize = dwfm.designUnitsPerEm;
+ info->fLastGlyphID = SkToU16(glyphCount - 1);
+ info->fStyle = 0;
+ info->fFlags = SkAdvancedTypefaceMetrics::kEmpty_FontFlag;
+
+ // SkAdvancedTypefaceMetrics::fFontName is in theory supposed to be
+ // the PostScript name of the font. However, due to the way it is currently
+ // used, it must actually be a family name.
+ SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
+ hr = fDWriteFontFamily->GetFamilyNames(&familyNames);
+
+ UINT32 familyNameLength;
+ hr = familyNames->GetStringLength(0, &familyNameLength);
+
+ UINT32 size = familyNameLength+1;
+ SkSMallocWCHAR wFamilyName(size);
+ hr = familyNames->GetString(0, wFamilyName.get(), size);
+
+ hr = sk_wchar_to_skstring(wFamilyName.get(), &info->fFontName);
+
+ if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) {
+ populate_glyph_to_unicode(fDWriteFontFace.get(), glyphCount, &(info->fGlyphToUnicode));
+ }
+
+ DWRITE_FONT_FACE_TYPE fontType = fDWriteFontFace->GetType();
+ if (fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE ||
+ fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION) {
+ info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
+ } else {
+ info->fType = SkAdvancedTypefaceMetrics::kOther_Font;
+ info->fItalicAngle = 0;
+ info->fAscent = dwfm.ascent;;
+ info->fDescent = dwfm.descent;
+ info->fStemV = 0;
+ info->fCapHeight = dwfm.capHeight;
+ info->fBBox = SkIRect::MakeEmpty();
+ return info;
+ }
+
+ AutoTDWriteTable<SkOTTableHead> headTable(fDWriteFontFace.get());
+ AutoTDWriteTable<SkOTTablePostScript> postTable(fDWriteFontFace.get());
+ AutoTDWriteTable<SkOTTableHorizontalHeader> hheaTable(fDWriteFontFace.get());
+ AutoTDWriteTable<SkOTTableOS2> os2Table(fDWriteFontFace.get());
+ if (!headTable.fExists || !postTable.fExists || !hheaTable.fExists || !os2Table.fExists) {
+ info->fItalicAngle = 0;
+ info->fAscent = dwfm.ascent;;
+ info->fDescent = dwfm.descent;
+ info->fStemV = 0;
+ info->fCapHeight = dwfm.capHeight;
+ info->fBBox = SkIRect::MakeEmpty();
+ return info;
+ }
+
+ //There exist CJK fonts which set the IsFixedPitch and Monospace bits,
+ //but have full width, latin half-width, and half-width kana.
+ bool fixedWidth = (postTable->isFixedPitch &&
+ (1 == SkEndian_SwapBE16(hheaTable->numberOfHMetrics)));
+ //Monospace
+ if (fixedWidth) {
+ info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
+ }
+ //Italic
+ if (os2Table->version.v0.fsSelection.field.Italic) {
+ info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
+ }
+ //Script
+ if (SkPanose::FamilyType::Script == os2Table->version.v0.panose.bFamilyType.value) {
+ info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
+ //Serif
+ } else if (SkPanose::FamilyType::TextAndDisplay == os2Table->version.v0.panose.bFamilyType.value &&
+ SkPanose::Data::TextAndDisplay::SerifStyle::Triangle <= os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value &&
+ SkPanose::Data::TextAndDisplay::SerifStyle::NoFit != os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value) {
+ info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
+ }
+
+ info->fItalicAngle = SkEndian_SwapBE32(postTable->italicAngle) >> 16;
+
+ info->fAscent = SkToS16(dwfm.ascent);
+ info->fDescent = SkToS16(dwfm.descent);
+ info->fCapHeight = SkToS16(dwfm.capHeight);
+
+ info->fBBox = SkIRect::MakeLTRB((int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMin),
+ (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMax),
+ (int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMax),
+ (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMin));
+
+ //TODO: is this even desired? It seems PDF only wants this value for Type1
+ //fonts, and we only get here for TrueType fonts.
+ info->fStemV = 0;
+ /*
+ // Figure out a good guess for StemV - Min width of i, I, !, 1.
+ // This probably isn't very good with an italic font.
+ int16_t min_width = SHRT_MAX;
+ info->fStemV = 0;
+ char stem_chars[] = {'i', 'I', '!', '1'};
+ for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
+ ABC abcWidths;
+ if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) {
+ int16_t width = abcWidths.abcB;
+ if (width > 0 && width < min_width) {
+ min_width = width;
+ info->fStemV = min_width;
+ }
+ }
+ }
+ */
+
+ if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) {
+ if (fixedWidth) {
+ appendRange(&info->fGlyphWidths, 0);
+ int16_t advance;
+ getWidthAdvance(fDWriteFontFace.get(), 1, &advance);
+ info->fGlyphWidths->fAdvance.append(1, &advance);
+ finishRange(info->fGlyphWidths.get(), 0,
+ SkAdvancedTypefaceMetrics::WidthRange::kDefault);
+ } else {
+ info->fGlyphWidths.reset(
+ getAdvanceData(fDWriteFontFace.get(),
+ glyphCount,
+ glyphIDs,
+ glyphIDsCount,
+ getWidthAdvance));
+ }
+ }
+
+ return info;
+}
diff --git a/chromium/third_party/skia/src/ports/SkTypeface_win_dw.h b/chromium/third_party/skia/src/ports/SkTypeface_win_dw.h
new file mode 100644
index 00000000000..465db3446bf
--- /dev/null
+++ b/chromium/third_party/skia/src/ports/SkTypeface_win_dw.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkTypeface_win_dw_DEFINED
+#define SkTypeface_win_dw_DEFINED
+
+#include "SkAdvancedTypefaceMetrics.h"
+#include "SkDWrite.h"
+#include "SkHRESULT.h"
+#include "SkTScopedComPtr.h"
+#include "SkTypeface.h"
+#include "SkTypefaceCache.h"
+#include "SkTypes.h"
+
+#include <dwrite.h>
+#include <dwrite_1.h>
+
+class SkFontDescriptor;
+struct SkScalerContextRec;
+
+static SkTypeface::Style get_style(IDWriteFont* font) {
+ int style = SkTypeface::kNormal;
+ DWRITE_FONT_WEIGHT weight = font->GetWeight();
+ if (DWRITE_FONT_WEIGHT_DEMI_BOLD <= weight) {
+ style |= SkTypeface::kBold;
+ }
+ DWRITE_FONT_STYLE angle = font->GetStyle();
+ if (DWRITE_FONT_STYLE_OBLIQUE == angle || DWRITE_FONT_STYLE_ITALIC == angle) {
+ style |= SkTypeface::kItalic;
+ }
+ return static_cast<SkTypeface::Style>(style);
+}
+
+class DWriteFontTypeface : public SkTypeface {
+private:
+ DWriteFontTypeface(SkTypeface::Style style, SkFontID fontID,
+ IDWriteFactory* factory,
+ IDWriteFontFace* fontFace,
+ IDWriteFont* font,
+ IDWriteFontFamily* fontFamily,
+ IDWriteFontFileLoader* fontFileLoader = NULL,
+ IDWriteFontCollectionLoader* fontCollectionLoader = NULL)
+ : SkTypeface(style, fontID, false)
+ , fFactory(SkRefComPtr(factory))
+ , fDWriteFontCollectionLoader(SkSafeRefComPtr(fontCollectionLoader))
+ , fDWriteFontFileLoader(SkSafeRefComPtr(fontFileLoader))
+ , fDWriteFontFamily(SkRefComPtr(fontFamily))
+ , fDWriteFont(SkRefComPtr(font))
+ , fDWriteFontFace(SkRefComPtr(fontFace))
+ {
+ if (!SUCCEEDED(fDWriteFontFace->QueryInterface(&fDWriteFontFace1))) {
+ // IUnknown::QueryInterface states that if it fails, punk will be set to NULL.
+ // http://blogs.msdn.com/b/oldnewthing/archive/2004/03/26/96777.aspx
+ SK_ALWAYSBREAK(NULL == fDWriteFontFace1.get());
+ }
+ }
+
+public:
+ SkTScopedComPtr<IDWriteFactory> fFactory;
+ SkTScopedComPtr<IDWriteFontCollectionLoader> fDWriteFontCollectionLoader;
+ SkTScopedComPtr<IDWriteFontFileLoader> fDWriteFontFileLoader;
+ SkTScopedComPtr<IDWriteFontFamily> fDWriteFontFamily;
+ SkTScopedComPtr<IDWriteFont> fDWriteFont;
+ SkTScopedComPtr<IDWriteFontFace> fDWriteFontFace;
+ SkTScopedComPtr<IDWriteFontFace1> fDWriteFontFace1;
+
+ static DWriteFontTypeface* Create(IDWriteFactory* factory,
+ IDWriteFontFace* fontFace,
+ IDWriteFont* font,
+ IDWriteFontFamily* fontFamily,
+ IDWriteFontFileLoader* fontFileLoader = NULL,
+ IDWriteFontCollectionLoader* fontCollectionLoader = NULL) {
+ SkTypeface::Style style = get_style(font);
+ SkFontID fontID = SkTypefaceCache::NewFontID();
+ return SkNEW_ARGS(DWriteFontTypeface, (style, fontID,
+ factory, fontFace, font, fontFamily,
+ fontFileLoader, fontCollectionLoader));
+ }
+
+protected:
+ virtual void weak_dispose() const SK_OVERRIDE {
+ if (fDWriteFontCollectionLoader.get()) {
+ HRV(fFactory->UnregisterFontCollectionLoader(fDWriteFontCollectionLoader.get()));
+ }
+ if (fDWriteFontFileLoader.get()) {
+ HRV(fFactory->UnregisterFontFileLoader(fDWriteFontFileLoader.get()));
+ }
+
+ //SkTypefaceCache::Remove(this);
+ INHERITED::weak_dispose();
+ }
+
+ virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE;
+ virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK_OVERRIDE;
+ virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE;
+ virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics(
+ SkAdvancedTypefaceMetrics::PerGlyphInfo,
+ const uint32_t*, uint32_t) const SK_OVERRIDE;
+ virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE;
+ virtual int onCharsToGlyphs(const void* chars, Encoding encoding,
+ uint16_t glyphs[], int glyphCount) const SK_OVERRIDE;
+ virtual int onCountGlyphs() const SK_OVERRIDE;
+ virtual int onGetUPEM() const SK_OVERRIDE;
+ virtual SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const SK_OVERRIDE;
+ virtual int onGetTableTags(SkFontTableTag tags[]) const SK_OVERRIDE;
+ virtual size_t onGetTableData(SkFontTableTag, size_t offset,
+ size_t length, void* data) const SK_OVERRIDE;
+
+private:
+ typedef SkTypeface INHERITED;
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/ports/SkXMLParser_expat.cpp b/chromium/third_party/skia/src/ports/SkXMLParser_expat.cpp
deleted file mode 100644
index 3eba2fe8e0c..00000000000
--- a/chromium/third_party/skia/src/ports/SkXMLParser_expat.cpp
+++ /dev/null
@@ -1,140 +0,0 @@
-
-/*
- * Copyright 2006 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#include "SkXMLParser.h"
-#include "SkString.h"
-#include "SkStream.h"
-
-#include "expat.h"
-
-#ifdef SK_BUILD_FOR_PPI
-#define CHAR_16_TO_9
-#endif
-
-#if defined CHAR_16_TO_9
-inline size_t sk_wcslen(const short* char16) {
- const short* start = char16;
- while (*char16)
- char16++;
- return char16 - start;
-}
-
-inline const char* ConvertUnicodeToChar(const short* ch16, size_t len, SkAutoMalloc& ch8Malloc) {
- char* ch8 = (char*) ch8Malloc.get();
- int index;
- for (index = 0; index < len; index++)
- ch8[index] = (char) ch16[index];
- ch8[index] = '\0';
- return ch8;
-}
-#endif
-
-static void XMLCALL start_proc(void *data, const char *el, const char **attr)
-{
-#if defined CHAR_16_TO_9
- size_t len = sk_wcslen((const short*) el);
- SkAutoMalloc el8(len + 1);
- el = ConvertUnicodeToChar((const short*) el, len, el8);
-#endif
- if (((SkXMLParser*)data)->startElement(el)) {
- XML_StopParser((XML_Parser) ((SkXMLParser*)data)->fParser, false);
- return;
- }
- while (*attr)
- {
- const char* attr0 = attr[0];
- const char* attr1 = attr[1];
-#if defined CHAR_16_TO_9
- size_t len0 = sk_wcslen((const short*) attr0);
- SkAutoMalloc attr0_8(len0 + 1);
- attr0 = ConvertUnicodeToChar((const short*) attr0, len0, attr0_8);
- size_t len1 = sk_wcslen((const short*) attr1);
- SkAutoMalloc attr1_8(len1 + 1);
- attr1 = ConvertUnicodeToChar((const short*) attr1, len1, attr1_8);
-#endif
- if (((SkXMLParser*)data)->addAttribute(attr0, attr1)) {
- XML_StopParser((XML_Parser) ((SkXMLParser*)data)->fParser, false);
- return;
- }
- attr += 2;
- }
-}
-
-static void XMLCALL end_proc(void *data, const char *el)
-{
-#if defined CHAR_16_TO_9
- size_t len = sk_wcslen((const short*) el);
- SkAutoMalloc el8(len + 1);
- el = ConvertUnicodeToChar((const short*) el, len, el8);
-#endif
- if (((SkXMLParser*)data)->endElement(el))
- XML_StopParser((XML_Parser) ((SkXMLParser*)data)->fParser, false);
-}
-
-static void XMLCALL text_proc(void* data, const char* text, int len)
-{
-#if defined CHAR_16_TO_9
- SkAutoMalloc text8(len + 1);
- text = ConvertUnicodeToChar((const short*) text, len, text8);
-#endif
- if (((SkXMLParser*)data)->text(text, len))
- XML_StopParser((XML_Parser) ((SkXMLParser*)data)->fParser, false);
-}
-
-bool SkXMLParser::parse(const char doc[], size_t len)
-{
- if (len == 0) {
- fError->fCode = SkXMLParserError::kEmptyFile;
- reportError(NULL);
- return false;
- }
- XML_Parser p = XML_ParserCreate(NULL);
- SkASSERT(p);
- fParser = p;
- XML_SetElementHandler(p, start_proc, end_proc);
- XML_SetCharacterDataHandler(p, text_proc);
- XML_SetUserData(p, this);
-
- bool success = true;
- int error = XML_Parse(p, doc, len, true);
- if (error == XML_STATUS_ERROR) {
- reportError(p);
- success = false;
- }
- XML_ParserFree(p);
- return success;
-}
-
-bool SkXMLParser::parse(SkStream& input)
-{
- size_t len = input.getLength();
- SkAutoMalloc am(len);
- char* doc = (char*)am.get();
-
- input.rewind();
- size_t len2 = input.read(doc, len);
- SkASSERT(len2 == len);
-
- return this->parse(doc, len2);
-}
-
-void SkXMLParser::reportError(void* p)
-{
- XML_Parser parser = (XML_Parser) p;
- if (fError && parser) {
- fError->fNativeCode = XML_GetErrorCode(parser);
- fError->fLineNumber = XML_GetCurrentLineNumber(parser);
- }
-}
-
-void SkXMLParser::GetNativeErrorString(int error, SkString* str)
-{
- if (str)
- str->set(XML_ErrorString((XML_Error) error));
-}
diff --git a/chromium/third_party/skia/src/ports/SkXMLParser_tinyxml.cpp b/chromium/third_party/skia/src/ports/SkXMLParser_tinyxml.cpp
deleted file mode 100644
index 5f9f3a68de8..00000000000
--- a/chromium/third_party/skia/src/ports/SkXMLParser_tinyxml.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-
-/*
- * Copyright 2006 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#include "SkXMLParser.h"
-#include "SkStream.h"
-#include "SkTemplates.h"
-#include "tinyxml.h"
-
-static void walk_elem(SkXMLParser* parser, const TiXmlElement* elem)
-{
- //printf("walk_elem(%s) ", elem->Value());
-
- parser->startElement(elem->Value());
-
- const TiXmlAttribute* attr = elem->FirstAttribute();
- while (attr)
- {
- //printf("walk_elem_attr(%s=\"%s\") ", attr->Name(), attr->Value());
-
- parser->addAttribute(attr->Name(), attr->Value());
- attr = attr->Next();
- }
- //printf("\n");
-
- const TiXmlNode* node = elem->FirstChild();
- while (node)
- {
- if (node->ToElement())
- walk_elem(parser, node->ToElement());
- else if (node->ToText())
- parser->text(node->Value(), strlen(node->Value()));
- node = node->NextSibling();
- }
-
- parser->endElement(elem->Value());
-}
-
-static bool load_buf(SkXMLParser* parser, const char buf[])
-{
- TiXmlDocument doc;
-
- (void)doc.Parse(buf);
- if (doc.Error())
- {
- printf("tinyxml error: <%s> row[%d] col[%d]\n", doc.ErrorDesc(), doc.ErrorRow(), doc.ErrorCol());
- return false;
- }
-
- walk_elem(parser, doc.RootElement());
- return true;
-}
-
-bool SkXMLParser::parse(SkStream& stream)
-{
- size_t size = stream.getLength();
-
- SkAutoMalloc buffer(size + 1);
- char* buf = (char*)buffer.get();
-
- stream.read(buf, size);
- buf[size] = 0;
-
- return load_buf(this, buf);
-}
-
-bool SkXMLParser::parse(const char doc[], size_t len)
-{
- SkAutoMalloc buffer(len + 1);
- char* buf = (char*)buffer.get();
-
- memcpy(buf, doc, len);
- buf[len] = 0;
-
- return load_buf(this, buf);
-}
-
-void SkXMLParser::GetNativeErrorString(int error, SkString* str)
-{
- if (str)
- str->set("GetNativeErrorString not implemented for TinyXml");
-}
diff --git a/chromium/third_party/skia/src/ports/SkXMLPullParser_expat.cpp b/chromium/third_party/skia/src/ports/SkXMLPullParser_expat.cpp
deleted file mode 100644
index 44a3c7f81ea..00000000000
--- a/chromium/third_party/skia/src/ports/SkXMLPullParser_expat.cpp
+++ /dev/null
@@ -1,213 +0,0 @@
-
-/*
- * Copyright 2006 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#include "SkXMLParser.h"
-#include "SkChunkAlloc.h"
-#include "SkString.h"
-#include "SkStream.h"
-
-#include "expat.h"
-
-static inline char* dupstr(SkChunkAlloc& chunk, const char src[], size_t len)
-{
- SkASSERT(src);
- char* dst = (char*)chunk.alloc(len + 1, SkChunkAlloc::kThrow_AllocFailType);
-
- memcpy(dst, src, len);
- dst[len] = 0;
- return dst;
-}
-
-static inline int count_pairs(const char** p)
-{
- const char** start = p;
- while (*p)
- {
- SkASSERT(p[1] != NULL);
- p += 2;
- }
- return (p - start) >> 1;
-}
-
-struct Data {
- Data() : fAlloc(2048), fState(NORMAL) {}
-
- XML_Parser fParser;
- SkXMLPullParser::Curr* fCurr;
- SkChunkAlloc fAlloc;
-
- enum State {
- NORMAL,
- MISSED_START_TAG,
- RETURN_END_TAG
- };
- State fState;
- const char* fEndTag; // if state is RETURN_END_TAG
-};
-
-static void XMLCALL start_proc(void *data, const char *el, const char **attr)
-{
- Data* p = (Data*)data;
- SkXMLPullParser::Curr* c = p->fCurr;
- SkChunkAlloc& alloc = p->fAlloc;
-
- c->fName = dupstr(alloc, el, strlen(el));
-
- int n = count_pairs(attr);
- SkXMLPullParser::AttrInfo* info = (SkXMLPullParser::AttrInfo*)alloc.alloc(n * sizeof(SkXMLPullParser::AttrInfo),
- SkChunkAlloc::kThrow_AllocFailType);
- c->fAttrInfoCount = n;
- c->fAttrInfos = info;
-
- for (int i = 0; i < n; i++)
- {
- info[i].fName = dupstr(alloc, attr[0], strlen(attr[0]));
- info[i].fValue = dupstr(alloc, attr[1], strlen(attr[1]));
- attr += 2;
- }
-
- c->fEventType = SkXMLPullParser::START_TAG;
- XML_StopParser(p->fParser, true);
-}
-
-static void XMLCALL end_proc(void *data, const char *el)
-{
- Data* p = (Data*)data;
- SkXMLPullParser::Curr* c = p->fCurr;
-
- if (c->fEventType == SkXMLPullParser::START_TAG)
- {
- /* if we get here, we were called with a start_tag immediately
- followed by this end_tag. The caller will only see the end_tag,
- so we set a flag to notify them of the missed start_tag
- */
- p->fState = Data::MISSED_START_TAG;
-
- SkASSERT(c->fName != NULL);
- SkASSERT(strcmp(c->fName, el) == 0);
- }
- else
- c->fName = dupstr(p->fAlloc, el, strlen(el));
-
- c->fEventType = SkXMLPullParser::END_TAG;
- XML_StopParser(p->fParser, true);
-}
-
-#include <ctype.h>
-
-static bool isws(const char s[])
-{
- for (; *s; s++)
- if (!isspace(*s))
- return false;
- return true;
-}
-
-static void XMLCALL text_proc(void* data, const char* text, int len)
-{
- Data* p = (Data*)data;
- SkXMLPullParser::Curr* c = p->fCurr;
-
- c->fName = dupstr(p->fAlloc, text, len);
- c->fIsWhitespace = isws(c->fName);
-
- c->fEventType = SkXMLPullParser::TEXT;
- XML_StopParser(p->fParser, true);
-}
-
-//////////////////////////////////////////////////////////////////////////
-
-struct SkXMLPullParser::Impl {
- Data fData;
- void* fBuffer;
- size_t fBufferLen;
-};
-
-static void reportError(XML_Parser parser)
-{
- XML_Error code = XML_GetErrorCode(parser);
- int lineNumber = XML_GetCurrentLineNumber(parser);
- const char* msg = XML_ErrorString(code);
-
- printf("-------- XML error [%d] on line %d, %s\n", code, lineNumber, msg);
-}
-
-bool SkXMLPullParser::onInit()
-{
- fImpl = new Impl;
-
- XML_Parser p = XML_ParserCreate(NULL);
- SkASSERT(p);
-
- fImpl->fData.fParser = p;
- fImpl->fData.fCurr = &fCurr;
-
- XML_SetElementHandler(p, start_proc, end_proc);
- XML_SetCharacterDataHandler(p, text_proc);
- XML_SetUserData(p, &fImpl->fData);
-
- size_t len = fStream->getLength();
- fImpl->fBufferLen = len;
- fImpl->fBuffer = sk_malloc_throw(len);
- fStream->rewind();
- size_t len2 = fStream->read(fImpl->fBuffer, len);
- return len2 == len;
-}
-
-void SkXMLPullParser::onExit()
-{
- sk_free(fImpl->fBuffer);
- XML_ParserFree(fImpl->fData.fParser);
- delete fImpl;
- fImpl = NULL;
-}
-
-SkXMLPullParser::EventType SkXMLPullParser::onNextToken()
-{
- if (Data::RETURN_END_TAG == fImpl->fData.fState)
- {
- fImpl->fData.fState = Data::NORMAL;
- fCurr.fName = fImpl->fData.fEndTag; // restore name from (below) save
- return SkXMLPullParser::END_TAG;
- }
-
- fImpl->fData.fAlloc.reset();
-
- XML_Parser p = fImpl->fData.fParser;
- XML_Status status;
-
- status = XML_ResumeParser(p);
-
-CHECK_STATUS:
- switch (status) {
- case XML_STATUS_OK:
- return SkXMLPullParser::END_DOCUMENT;
-
- case XML_STATUS_ERROR:
- if (XML_GetErrorCode(p) != XML_ERROR_NOT_SUSPENDED)
- {
- reportError(p);
- return SkXMLPullParser::ERROR;
- }
- status = XML_Parse(p, (const char*)fImpl->fBuffer, fImpl->fBufferLen, true);
- goto CHECK_STATUS;
-
- case XML_STATUS_SUSPENDED:
- if (Data::MISSED_START_TAG == fImpl->fData.fState)
- {
- // return a start_tag, and clear the flag so we return end_tag next
- SkASSERT(SkXMLPullParser::END_TAG == fCurr.fEventType);
- fImpl->fData.fState = Data::RETURN_END_TAG;
- fImpl->fData.fEndTag = fCurr.fName; // save this pointer
- return SkXMLPullParser::START_TAG;
- }
- break;
- }
- return fCurr.fEventType;
-}
diff --git a/chromium/third_party/skia/src/sfnt/SkOTTableTypes.h b/chromium/third_party/skia/src/sfnt/SkOTTableTypes.h
index 9adec9b81e4..1f49518d591 100644
--- a/chromium/third_party/skia/src/sfnt/SkOTTableTypes.h
+++ b/chromium/third_party/skia/src/sfnt/SkOTTableTypes.h
@@ -8,6 +8,7 @@
#ifndef SkOTTableTypes_DEFINED
#define SkOTTableTypes_DEFINED
+#include "SkTemplates.h"
#include "SkTypes.h"
#include "SkEndian.h"
@@ -45,4 +46,18 @@ public:
);
};
+/** SkOTSetUSHORTBit<N>::value is an SK_OT_USHORT with the Nth BE bit set. */
+template <unsigned N> struct SkOTSetUSHORTBit {
+ SK_COMPILE_ASSERT(N < 16, NTooBig);
+ static const uint16_t bit = 1u << N;
+ static const SK_OT_USHORT value = SkTEndian_SwapBE16(bit);
+};
+
+/** SkOTSetULONGBit<N>::value is an SK_OT_ULONG with the Nth BE bit set. */
+template <unsigned N> struct SkOTSetULONGBit {
+ SK_COMPILE_ASSERT(N < 32, NTooBig);
+ static const uint32_t bit = 1u << N;
+ static const SK_OT_ULONG value = SkTEndian_SwapBE32(bit);
+};
+
#endif
diff --git a/chromium/third_party/skia/src/sfnt/SkOTTable_EBDT.h b/chromium/third_party/skia/src/sfnt/SkOTTable_EBDT.h
new file mode 100644
index 00000000000..89d7a3abe24
--- /dev/null
+++ b/chromium/third_party/skia/src/sfnt/SkOTTable_EBDT.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkOTTable_EBDT_DEFINED
+#define SkOTTable_EBDT_DEFINED
+
+#include "SkEndian.h"
+#include "SkOTTableTypes.h"
+#include "SkOTTable_head.h"
+#include "SkOTTable_loca.h"
+#include "SkTypedEnum.h"
+
+#pragma pack(push, 1)
+
+struct SkOTTableEmbeddedBitmapData {
+ static const SK_OT_CHAR TAG0 = 'E';
+ static const SK_OT_CHAR TAG1 = 'B';
+ static const SK_OT_CHAR TAG2 = 'D';
+ static const SK_OT_CHAR TAG3 = 'T';
+ static const SK_OT_ULONG TAG = SkOTTableTAG<SkOTTableEmbeddedBitmapData>::value;
+
+ SK_OT_Fixed version;
+ static const SK_OT_Fixed version_initial = SkTEndian_SwapBE32(0x00020000);
+
+ struct BigGlyphMetrics {
+ SK_OT_BYTE height;
+ SK_OT_BYTE width;
+ SK_OT_CHAR horiBearingX;
+ SK_OT_CHAR horiBearingY;
+ SK_OT_BYTE horiAdvance;
+ SK_OT_CHAR vertBearingX;
+ SK_OT_CHAR vertBearingY;
+ SK_OT_BYTE vertAdvance;
+ };
+
+ struct SmallGlyphMetrics {
+ SK_OT_BYTE height;
+ SK_OT_BYTE width;
+ SK_OT_CHAR bearingX;
+ SK_OT_CHAR bearingY;
+ SK_OT_BYTE advance;
+ };
+
+ // Small metrics, byte-aligned data.
+ struct Format1 {
+ SmallGlyphMetrics smallGlyphMetrics;
+ //SK_OT_BYTE[] byteAlignedBitmap;
+ };
+
+ // Small metrics, bit-aligned data.
+ struct Format2 {
+ SmallGlyphMetrics smallGlyphMetrics;
+ //SK_OT_BYTE[] bitAlignedBitmap;
+ };
+
+ // Format 3 is not used.
+
+ // EBLC metrics (IndexSubTable::header::indexFormat 2 or 5), compressed data.
+ // Only used on Mac.
+ struct Format4 {
+ SK_OT_ULONG whiteTreeOffset;
+ SK_OT_ULONG blackTreeOffset;
+ SK_OT_ULONG glyphDataOffset;
+ };
+
+ // EBLC metrics (IndexSubTable::header::indexFormat 2 or 5), bit-aligned data.
+ struct Format5 {
+ //SK_OT_BYTE[] bitAlignedBitmap;
+ };
+
+ // Big metrics, byte-aligned data.
+ struct Format6 {
+ BigGlyphMetrics bigGlyphMetrics;
+ //SK_OT_BYTE[] byteAlignedBitmap;
+ };
+
+ // Big metrics, bit-aligned data.
+ struct Format7 {
+ BigGlyphMetrics bigGlyphMetrics;
+ //SK_OT_BYTE[] bitAlignedBitmap;
+ };
+
+ struct EBDTComponent {
+ SK_OT_USHORT glyphCode; // Component glyph code
+ SK_OT_CHAR xOffset; // Position of component left
+ SK_OT_CHAR yOffset; // Position of component top
+ };
+
+ struct Format8 {
+ SmallGlyphMetrics smallMetrics; // Metrics information for the glyph
+ SK_OT_BYTE pad; // Pad to short boundary
+ SK_OT_USHORT numComponents; // Number of components
+ //EBDTComponent componentArray[numComponents]; // Glyph code, offset array
+ };
+
+ struct Format9 {
+ BigGlyphMetrics bigMetrics; // Metrics information for the glyph
+ SK_OT_USHORT numComponents; // Number of components
+ //EBDTComponent componentArray[numComponents]; // Glyph code, offset array
+ };
+};
+
+#pragma pack(pop)
+
+#endif
diff --git a/chromium/third_party/skia/src/sfnt/SkOTTable_EBLC.h b/chromium/third_party/skia/src/sfnt/SkOTTable_EBLC.h
new file mode 100644
index 00000000000..845418d3e47
--- /dev/null
+++ b/chromium/third_party/skia/src/sfnt/SkOTTable_EBLC.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkOTTable_EBLC_DEFINED
+#define SkOTTable_EBLC_DEFINED
+
+#include "SkEndian.h"
+#include "SkOTTable_EBDT.h"
+#include "SkOTTableTypes.h"
+#include "SkTypedEnum.h"
+
+#pragma pack(push, 1)
+
+struct SkOTTableEmbeddedBitmapLocation {
+ static const SK_OT_CHAR TAG0 = 'E';
+ static const SK_OT_CHAR TAG1 = 'B';
+ static const SK_OT_CHAR TAG2 = 'L';
+ static const SK_OT_CHAR TAG3 = 'C';
+ static const SK_OT_ULONG TAG = SkOTTableTAG<SkOTTableEmbeddedBitmapLocation>::value;
+
+ SK_OT_Fixed version;
+ static const SK_OT_Fixed version_initial = SkTEndian_SwapBE32(0x00020000);
+
+ SK_OT_ULONG numSizes;
+
+ struct SbitLineMetrics {
+ SK_OT_CHAR ascender;
+ SK_OT_CHAR descender;
+ SK_OT_BYTE widthMax;
+ SK_OT_CHAR caretSlopeNumerator;
+ SK_OT_CHAR caretSlopeDenominator;
+ SK_OT_CHAR caretOffset;
+ SK_OT_CHAR minOriginSB;
+ SK_OT_CHAR minAdvanceSB;
+ SK_OT_CHAR maxBeforeBL;
+ SK_OT_CHAR minAfterBL;
+ SK_OT_CHAR pad1;
+ SK_OT_CHAR pad2;
+ };
+
+ struct BitmapSizeTable {
+ SK_OT_ULONG indexSubTableArrayOffset; //offset to indexSubtableArray from beginning of EBLC.
+ SK_OT_ULONG indexTablesSize; //number of bytes in corresponding index subtables and array
+ SK_OT_ULONG numberOfIndexSubTables; //an index subtable for each range or format change
+ SK_OT_ULONG colorRef; //not used; set to 0.
+ SbitLineMetrics hori; //line metrics for text rendered horizontally
+ SbitLineMetrics vert; //line metrics for text rendered vertically
+ SK_OT_USHORT startGlyphIndex; //lowest glyph index for this size
+ SK_OT_USHORT endGlyphIndex; //highest glyph index for this size
+ SK_OT_BYTE ppemX; //horizontal pixels per Em
+ SK_OT_BYTE ppemY; //vertical pixels per Em
+ struct BitDepth {
+ SK_TYPED_ENUM(Value, SK_OT_BYTE,
+ ((BW, 1))
+ ((Gray4, 2))
+ ((Gray16, 4))
+ ((Gray256, 8))
+ SK_SEQ_END,
+ SK_SEQ_END)
+ SK_OT_BYTE value;
+ } bitDepth; //the Microsoft rasterizer v.1.7 or greater supports
+ union Flags {
+ struct Field {
+ //0-7
+ SK_OT_BYTE_BITFIELD(
+ Horizontal, // Horizontal small glyph metrics
+ Vertical, // Vertical small glyph metrics
+ Reserved02,
+ Reserved03,
+ Reserved04,
+ Reserved05,
+ Reserved06,
+ Reserved07)
+ } field;
+ struct Raw {
+ static const SK_OT_CHAR Horizontal = 1u << 0;
+ static const SK_OT_CHAR Vertical = 1u << 1;
+ SK_OT_CHAR value;
+ } raw;
+ } flags;
+ }; //bitmapSizeTable[numSizes];
+
+ struct IndexSubTableArray {
+ SK_OT_USHORT firstGlyphIndex; //first glyph code of this range
+ SK_OT_USHORT lastGlyphIndex; //last glyph code of this range (inclusive)
+ SK_OT_ULONG additionalOffsetToIndexSubtable; //add to BitmapSizeTable::indexSubTableArrayOffset to get offset from beginning of 'EBLC'
+ }; //indexSubTableArray[BitmapSizeTable::numberOfIndexSubTables];
+
+ struct IndexSubHeader {
+ SK_OT_USHORT indexFormat; //format of this indexSubTable
+ SK_OT_USHORT imageFormat; //format of 'EBDT' image data
+ SK_OT_ULONG imageDataOffset; //offset to image data in 'EBDT' table
+ };
+
+ // Variable metrics glyphs with 4 byte offsets
+ struct IndexSubTable1 {
+ IndexSubHeader header;
+ //SK_OT_ULONG offsetArray[lastGlyphIndex - firstGlyphIndex + 1 + 1]; //last element points to one past end of last glyph
+ //glyphData = offsetArray[glyphIndex - firstGlyphIndex] + imageDataOffset
+ };
+
+ // All Glyphs have identical metrics
+ struct IndexSubTable2 {
+ IndexSubHeader header;
+ SK_OT_ULONG imageSize; // all glyphs are of the same size
+ SkOTTableEmbeddedBitmapData::BigGlyphMetrics bigMetrics; // all glyphs have the same metrics; glyph data may be compressed, byte-aligned, or bit-aligned
+ };
+
+ // Variable metrics glyphs with 2 byte offsets
+ struct IndexSubTable3 {
+ IndexSubHeader header;
+ //SK_OT_USHORT offsetArray[lastGlyphIndex - firstGlyphIndex + 1 + 1]; //last element points to one past end of last glyph, may have extra element to force even number of elements
+ //glyphData = offsetArray[glyphIndex - firstGlyphIndex] + imageDataOffset
+ };
+
+ // Variable metrics glyphs with sparse glyph codes
+ struct IndexSubTable4 {
+ IndexSubHeader header;
+ SK_OT_ULONG numGlyphs;
+ struct CodeOffsetPair {
+ SK_OT_USHORT glyphCode;
+ SK_OT_USHORT offset; //location in EBDT
+ }; //glyphArray[numGlyphs+1]
+ };
+
+ // Constant metrics glyphs with sparse glyph codes
+ struct IndexSubTable5 {
+ IndexSubHeader header;
+ SK_OT_ULONG imageSize; //all glyphs have the same data size
+ SkOTTableEmbeddedBitmapData::BigGlyphMetrics bigMetrics; //all glyphs have the same metrics
+ SK_OT_ULONG numGlyphs;
+ //SK_OT_USHORT glyphCodeArray[numGlyphs] //must have even number of entries (set pad to 0)
+ };
+
+ union IndexSubTable {
+ IndexSubHeader header;
+ IndexSubTable1 format1;
+ IndexSubTable2 format2;
+ IndexSubTable3 format3;
+ IndexSubTable4 format4;
+ IndexSubTable5 format5;
+ };
+
+};
+
+#pragma pack(pop)
+
+#endif
diff --git a/chromium/third_party/skia/src/sfnt/SkOTTable_EBSC.h b/chromium/third_party/skia/src/sfnt/SkOTTable_EBSC.h
new file mode 100644
index 00000000000..316c45d1c24
--- /dev/null
+++ b/chromium/third_party/skia/src/sfnt/SkOTTable_EBSC.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkOTTable_EBSC_DEFINED
+#define SkOTTable_EBSC_DEFINED
+
+#include "SkEndian.h"
+#include "SkOTTable_EBLC.h"
+#include "SkOTTableTypes.h"
+
+#pragma pack(push, 1)
+
+struct SkOTTableEmbeddedBitmapScaling {
+ static const SK_OT_CHAR TAG0 = 'E';
+ static const SK_OT_CHAR TAG1 = 'S';
+ static const SK_OT_CHAR TAG2 = 'B';
+ static const SK_OT_CHAR TAG3 = 'C';
+ static const SK_OT_ULONG TAG = SkOTTableTAG<SkOTTableEmbeddedBitmapScaling>::value;
+
+ SK_OT_Fixed version;
+ static const SK_OT_Fixed version_initial = SkTEndian_SwapBE32(0x00020000);
+
+ SK_OT_ULONG numSizes;
+
+ struct BitmapScaleTable {
+ SkOTTableEmbeddedBitmapLocation::SbitLineMetrics hori;
+ SkOTTableEmbeddedBitmapLocation::SbitLineMetrics vert;
+ SK_OT_BYTE ppemX; //target horizontal pixels per EM
+ SK_OT_BYTE ppemY; //target vertical pixels per EM
+ SK_OT_BYTE substitutePpemX; //use bitmaps of this size
+ SK_OT_BYTE substitutePpemY; //use bitmaps of this size
+ }; //bitmapScaleTable[numSizes];
+};
+
+#pragma pack(pop)
+
+#endif
diff --git a/chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_V0.h b/chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_V0.h
index 14d322f7ce0..b65bcf7f631 100644
--- a/chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_V0.h
+++ b/chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_V0.h
@@ -76,10 +76,10 @@ struct SkOTTableOS2_V0 {
Reserved07)
} field;
struct Raw {
- static const SK_OT_USHORT Installable = SkTEndian_SwapBE16(0);
- static const SK_OT_USHORT RestrictedMask = SkTEndian_SwapBE16(1 << 1);
- static const SK_OT_USHORT PreviewPrintMask = SkTEndian_SwapBE16(1 << 2);
- static const SK_OT_USHORT EditableMask = SkTEndian_SwapBE16(1 << 3);
+ static const SK_OT_USHORT Installable = 0;
+ static const SK_OT_USHORT RestrictedMask = SkOTSetUSHORTBit<1>::value;
+ static const SK_OT_USHORT PreviewPrintMask = SkOTSetUSHORTBit<2>::value;
+ static const SK_OT_USHORT EditableMask = SkOTSetUSHORTBit<3>::value;
SK_OT_USHORT value;
} raw;
} fsType;
@@ -121,13 +121,13 @@ struct SkOTTableOS2_V0 {
Reserved07)
} field;
struct Raw {
- static const SK_OT_USHORT ItalicMask = SkTEndian_SwapBE16(1 << 0);
- static const SK_OT_USHORT UnderscoreMask = SkTEndian_SwapBE16(1 << 1);
- static const SK_OT_USHORT NegativeMask = SkTEndian_SwapBE16(1 << 2);
- static const SK_OT_USHORT OutlinedMask = SkTEndian_SwapBE16(1 << 3);
- static const SK_OT_USHORT StrikeoutMask = SkTEndian_SwapBE16(1 << 4);
- static const SK_OT_USHORT BoldMask = SkTEndian_SwapBE16(1 << 5);
- static const SK_OT_USHORT RegularMask = SkTEndian_SwapBE16(1 << 6);
+ static const SK_OT_USHORT ItalicMask = SkOTSetUSHORTBit<0>::value;
+ static const SK_OT_USHORT UnderscoreMask = SkOTSetUSHORTBit<1>::value;
+ static const SK_OT_USHORT NegativeMask = SkOTSetUSHORTBit<2>::value;
+ static const SK_OT_USHORT OutlinedMask = SkOTSetUSHORTBit<3>::value;
+ static const SK_OT_USHORT StrikeoutMask = SkOTSetUSHORTBit<4>::value;
+ static const SK_OT_USHORT BoldMask = SkOTSetUSHORTBit<5>::value;
+ static const SK_OT_USHORT RegularMask = SkOTSetUSHORTBit<6>::value;
SK_OT_USHORT value;
} raw;
} fsSelection;
diff --git a/chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_V1.h b/chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_V1.h
index 52a60c0a4d4..e53c0e67a5e 100644
--- a/chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_V1.h
+++ b/chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_V1.h
@@ -74,10 +74,10 @@ struct SkOTTableOS2_V1 {
Reserved07)
} field;
struct Raw {
- static const SK_OT_USHORT Installable = SkTEndian_SwapBE16(0);
- static const SK_OT_USHORT RestrictedMask = SkTEndian_SwapBE16(1 << 1);
- static const SK_OT_USHORT PreviewPrintMask = SkTEndian_SwapBE16(1 << 2);
- static const SK_OT_USHORT EditableMask = SkTEndian_SwapBE16(1 << 3);
+ static const SK_OT_USHORT Installable = 0;
+ static const SK_OT_USHORT RestrictedMask = SkOTSetUSHORTBit<1>::value;
+ static const SK_OT_USHORT PreviewPrintMask = SkOTSetUSHORTBit<2>::value;
+ static const SK_OT_USHORT EditableMask = SkOTSetUSHORTBit<3>::value;
SK_OT_USHORT value;
} raw;
} fsType;
@@ -261,80 +261,80 @@ struct SkOTTableOS2_V1 {
} field;
struct Raw {
struct l0 {
- static const SK_OT_ULONG BasicLatinMask = SkTEndian_SwapBE32(1 << 0);
- static const SK_OT_ULONG Latin1SupplementMask = SkTEndian_SwapBE32(1 << 1);
- static const SK_OT_ULONG LatinExtendedAMask = SkTEndian_SwapBE32(1 << 2);
- static const SK_OT_ULONG LatinExtendedBMask = SkTEndian_SwapBE32(1 << 3);
- static const SK_OT_ULONG IPAExtensionsMask = SkTEndian_SwapBE32(1 << 4);
- static const SK_OT_ULONG SpacingModifierLettersMask = SkTEndian_SwapBE32(1 << 5);
- static const SK_OT_ULONG CombiningDiacriticalMarksMask = SkTEndian_SwapBE32(1 << 6);
- static const SK_OT_ULONG BasicGreekMask = SkTEndian_SwapBE32(1 << 7);
- static const SK_OT_ULONG GreekSymbolsAndCCopticMask = SkTEndian_SwapBE32(1 << 8);
- static const SK_OT_ULONG CyrillicMask = SkTEndian_SwapBE32(1 << 9);
- static const SK_OT_ULONG ArmenianMask = SkTEndian_SwapBE32(1 << 10);
- static const SK_OT_ULONG BasicHebrewMask = SkTEndian_SwapBE32(1 << 11);
- static const SK_OT_ULONG HebrewExtendedABMask = SkTEndian_SwapBE32(1 << 12);
- static const SK_OT_ULONG BasicArabicMask = SkTEndian_SwapBE32(1 << 13);
- static const SK_OT_ULONG ArabicExtendedMask = SkTEndian_SwapBE32(1 << 14);
- static const SK_OT_ULONG DevanagariMask = SkTEndian_SwapBE32(1 << 15);
- static const SK_OT_ULONG BengaliMask = SkTEndian_SwapBE32(1 << 16);
- static const SK_OT_ULONG GurmukhiMask = SkTEndian_SwapBE32(1 << 17);
- static const SK_OT_ULONG GujaratiMask = SkTEndian_SwapBE32(1 << 18);
- static const SK_OT_ULONG OriyaMask = SkTEndian_SwapBE32(1 << 19);
- static const SK_OT_ULONG TamilMask = SkTEndian_SwapBE32(1 << 20);
- static const SK_OT_ULONG TeluguMask = SkTEndian_SwapBE32(1 << 21);
- static const SK_OT_ULONG KannadaMask = SkTEndian_SwapBE32(1 << 22);
- static const SK_OT_ULONG MalayalamMask = SkTEndian_SwapBE32(1 << 23);
- static const SK_OT_ULONG ThaiMask = SkTEndian_SwapBE32(1 << 24);
- static const SK_OT_ULONG LaoMask = SkTEndian_SwapBE32(1 << 25);
- static const SK_OT_ULONG BasicGeorgianMask = SkTEndian_SwapBE32(1 << 26);
- static const SK_OT_ULONG GeorgianExtendedMask = SkTEndian_SwapBE32(1 << 27);
- static const SK_OT_ULONG HangulJamoMask = SkTEndian_SwapBE32(1 << 28);
- static const SK_OT_ULONG LatinExtendedAdditionalMask = SkTEndian_SwapBE32(1 << 29);
- static const SK_OT_ULONG GreekExtendedMask = SkTEndian_SwapBE32(1 << 30);
- static const SK_OT_ULONG GeneralPunctuationMask = SkTEndian_SwapBE32(1 << 31);
+ static const SK_OT_ULONG BasicLatinMask = SkOTSetULONGBit<0>::value;
+ static const SK_OT_ULONG Latin1SupplementMask = SkOTSetULONGBit<1>::value;
+ static const SK_OT_ULONG LatinExtendedAMask = SkOTSetULONGBit<2>::value;
+ static const SK_OT_ULONG LatinExtendedBMask = SkOTSetULONGBit<3>::value;
+ static const SK_OT_ULONG IPAExtensionsMask = SkOTSetULONGBit<4>::value;
+ static const SK_OT_ULONG SpacingModifierLettersMask = SkOTSetULONGBit<5>::value;
+ static const SK_OT_ULONG CombiningDiacriticalMarksMask = SkOTSetULONGBit<6>::value;
+ static const SK_OT_ULONG BasicGreekMask = SkOTSetULONGBit<7>::value;
+ static const SK_OT_ULONG GreekSymbolsAndCCopticMask = SkOTSetULONGBit<8>::value;
+ static const SK_OT_ULONG CyrillicMask = SkOTSetULONGBit<9>::value;
+ static const SK_OT_ULONG ArmenianMask = SkOTSetULONGBit<10>::value;
+ static const SK_OT_ULONG BasicHebrewMask = SkOTSetULONGBit<11>::value;
+ static const SK_OT_ULONG HebrewExtendedABMask = SkOTSetULONGBit<12>::value;
+ static const SK_OT_ULONG BasicArabicMask = SkOTSetULONGBit<13>::value;
+ static const SK_OT_ULONG ArabicExtendedMask = SkOTSetULONGBit<14>::value;
+ static const SK_OT_ULONG DevanagariMask = SkOTSetULONGBit<15>::value;
+ static const SK_OT_ULONG BengaliMask = SkOTSetULONGBit<16>::value;
+ static const SK_OT_ULONG GurmukhiMask = SkOTSetULONGBit<17>::value;
+ static const SK_OT_ULONG GujaratiMask = SkOTSetULONGBit<18>::value;
+ static const SK_OT_ULONG OriyaMask = SkOTSetULONGBit<19>::value;
+ static const SK_OT_ULONG TamilMask = SkOTSetULONGBit<20>::value;
+ static const SK_OT_ULONG TeluguMask = SkOTSetULONGBit<21>::value;
+ static const SK_OT_ULONG KannadaMask = SkOTSetULONGBit<22>::value;
+ static const SK_OT_ULONG MalayalamMask = SkOTSetULONGBit<23>::value;
+ static const SK_OT_ULONG ThaiMask = SkOTSetULONGBit<24>::value;
+ static const SK_OT_ULONG LaoMask = SkOTSetULONGBit<25>::value;
+ static const SK_OT_ULONG BasicGeorgianMask = SkOTSetULONGBit<26>::value;
+ static const SK_OT_ULONG GeorgianExtendedMask = SkOTSetULONGBit<27>::value;
+ static const SK_OT_ULONG HangulJamoMask = SkOTSetULONGBit<28>::value;
+ static const SK_OT_ULONG LatinExtendedAdditionalMask = SkOTSetULONGBit<29>::value;
+ static const SK_OT_ULONG GreekExtendedMask = SkOTSetULONGBit<30>::value;
+ static const SK_OT_ULONG GeneralPunctuationMask = SkOTSetULONGBit<31>::value;
};
struct l1 {
- static const SK_OT_ULONG SuperscriptsAndSubscriptsMask = SkTEndian_SwapBE32(1 << (32 - 32));
- static const SK_OT_ULONG CurrencySymbolsMask = SkTEndian_SwapBE32(1 << (33 - 32));
- static const SK_OT_ULONG CombiningDiacriticalMarksForSymbolsMask = SkTEndian_SwapBE32(1 << (34 - 32));
- static const SK_OT_ULONG LetterlikeSymbolsMask = SkTEndian_SwapBE32(1 << (35 - 32));
- static const SK_OT_ULONG NumberFormsMask = SkTEndian_SwapBE32(1 << (36 - 32));
- static const SK_OT_ULONG ArrowsMask = SkTEndian_SwapBE32(1 << (37 - 32));
- static const SK_OT_ULONG MathematicalOperatorsMask = SkTEndian_SwapBE32(1 << (38 - 32));
- static const SK_OT_ULONG MiscellaneousTechnicalMask = SkTEndian_SwapBE32(1 << (39 - 32));
- static const SK_OT_ULONG ControlPicturesMask = SkTEndian_SwapBE32(1 << (40 - 32));
- static const SK_OT_ULONG OpticalCharacterRecognitionMask = SkTEndian_SwapBE32(1 << (41 - 32));
- static const SK_OT_ULONG EnclosedAlphanumericsMask = SkTEndian_SwapBE32(1 << (42 - 32));
- static const SK_OT_ULONG BoxDrawingMask = SkTEndian_SwapBE32(1 << (43 - 32));
- static const SK_OT_ULONG BlockElementsMask = SkTEndian_SwapBE32(1 << (44 - 32));
- static const SK_OT_ULONG GeometricShapesMask = SkTEndian_SwapBE32(1 << (45 - 32));
- static const SK_OT_ULONG MiscellaneousSymbolsMask = SkTEndian_SwapBE32(1 << (46 - 32));
- static const SK_OT_ULONG DingbatsMask = SkTEndian_SwapBE32(1 << (47 - 32));
- static const SK_OT_ULONG CJKSymbolsAndPunctuationMask = SkTEndian_SwapBE32(1 << (48 - 32));
- static const SK_OT_ULONG HiraganaMask = SkTEndian_SwapBE32(1 << (49 - 32));
- static const SK_OT_ULONG KatakanaMask = SkTEndian_SwapBE32(1 << (50 - 32));
- static const SK_OT_ULONG BopomofoMask = SkTEndian_SwapBE32(1 << (51 - 32));
- static const SK_OT_ULONG HangulCompatibilityJamoMask = SkTEndian_SwapBE32(1 << (52 - 32));
- static const SK_OT_ULONG CJKMiscellaneousMask = SkTEndian_SwapBE32(1 << (53 - 32));
- static const SK_OT_ULONG EnclosedCJKLettersAndMonthsMask = SkTEndian_SwapBE32(1 << (54 - 32));
- static const SK_OT_ULONG CJKCompatibilityMask = SkTEndian_SwapBE32(1 << (55 - 32));
- static const SK_OT_ULONG HangulMask = SkTEndian_SwapBE32(1 << (56 - 32));
+ static const SK_OT_ULONG SuperscriptsAndSubscriptsMask = SkOTSetULONGBit<32 - 32>::value;
+ static const SK_OT_ULONG CurrencySymbolsMask = SkOTSetULONGBit<33 - 32>::value;
+ static const SK_OT_ULONG CombiningDiacriticalMarksForSymbolsMask = SkOTSetULONGBit<34 - 32>::value;
+ static const SK_OT_ULONG LetterlikeSymbolsMask = SkOTSetULONGBit<35 - 32>::value;
+ static const SK_OT_ULONG NumberFormsMask = SkOTSetULONGBit<36 - 32>::value;
+ static const SK_OT_ULONG ArrowsMask = SkOTSetULONGBit<37 - 32>::value;
+ static const SK_OT_ULONG MathematicalOperatorsMask = SkOTSetULONGBit<38 - 32>::value;
+ static const SK_OT_ULONG MiscellaneousTechnicalMask = SkOTSetULONGBit<39 - 32>::value;
+ static const SK_OT_ULONG ControlPicturesMask = SkOTSetULONGBit<40 - 32>::value;
+ static const SK_OT_ULONG OpticalCharacterRecognitionMask = SkOTSetULONGBit<41 - 32>::value;
+ static const SK_OT_ULONG EnclosedAlphanumericsMask = SkOTSetULONGBit<42 - 32>::value;
+ static const SK_OT_ULONG BoxDrawingMask = SkOTSetULONGBit<43 - 32>::value;
+ static const SK_OT_ULONG BlockElementsMask = SkOTSetULONGBit<44 - 32>::value;
+ static const SK_OT_ULONG GeometricShapesMask = SkOTSetULONGBit<45 - 32>::value;
+ static const SK_OT_ULONG MiscellaneousSymbolsMask = SkOTSetULONGBit<46 - 32>::value;
+ static const SK_OT_ULONG DingbatsMask = SkOTSetULONGBit<47 - 32>::value;
+ static const SK_OT_ULONG CJKSymbolsAndPunctuationMask = SkOTSetULONGBit<48 - 32>::value;
+ static const SK_OT_ULONG HiraganaMask = SkOTSetULONGBit<49 - 32>::value;
+ static const SK_OT_ULONG KatakanaMask = SkOTSetULONGBit<50 - 32>::value;
+ static const SK_OT_ULONG BopomofoMask = SkOTSetULONGBit<51 - 32>::value;
+ static const SK_OT_ULONG HangulCompatibilityJamoMask = SkOTSetULONGBit<52 - 32>::value;
+ static const SK_OT_ULONG CJKMiscellaneousMask = SkOTSetULONGBit<53 - 32>::value;
+ static const SK_OT_ULONG EnclosedCJKLettersAndMonthsMask = SkOTSetULONGBit<54 - 32>::value;
+ static const SK_OT_ULONG CJKCompatibilityMask = SkOTSetULONGBit<55 - 32>::value;
+ static const SK_OT_ULONG HangulMask = SkOTSetULONGBit<56 - 32>::value;
//Reserved
//Reserved
- static const SK_OT_ULONG CJKUnifiedIdeographsMask = SkTEndian_SwapBE32(1 << (59 - 32));
- static const SK_OT_ULONG PrivateUseAreaMask = SkTEndian_SwapBE32(1 << (60 - 32));
- static const SK_OT_ULONG CJKCompatibilityIdeographsMask = SkTEndian_SwapBE32(1 << (61 - 32));
- static const SK_OT_ULONG AlphabeticPresentationFormsMask = SkTEndian_SwapBE32(1 << (62 - 32));
- static const SK_OT_ULONG ArabicPresentationFormsAMask = SkTEndian_SwapBE32(1 << (63 - 32));
+ static const SK_OT_ULONG CJKUnifiedIdeographsMask = SkOTSetULONGBit<59 - 32>::value;
+ static const SK_OT_ULONG PrivateUseAreaMask = SkOTSetULONGBit<60 - 32>::value;
+ static const SK_OT_ULONG CJKCompatibilityIdeographsMask = SkOTSetULONGBit<61 - 32>::value;
+ static const SK_OT_ULONG AlphabeticPresentationFormsMask = SkOTSetULONGBit<62 - 32>::value;
+ static const SK_OT_ULONG ArabicPresentationFormsAMask = SkOTSetULONGBit<63 - 32>::value;
};
struct l2 {
- static const SK_OT_ULONG CombiningHalfMarksMask = SkTEndian_SwapBE32(1 << (64 - 64));
- static const SK_OT_ULONG CJKCompatibilityFormsMask = SkTEndian_SwapBE32(1 << (65 - 64));
- static const SK_OT_ULONG SmallFormVariantsMask = SkTEndian_SwapBE32(1 << (66 - 64));
- static const SK_OT_ULONG ArabicPresentationFormsBMask = SkTEndian_SwapBE32(1 << (67 - 64));
- static const SK_OT_ULONG HalfwidthAndFullwidthFormsMask = SkTEndian_SwapBE32(1 << (68 - 64));
- static const SK_OT_ULONG SpecialsMask = SkTEndian_SwapBE32(1 << (69 - 64));
+ static const SK_OT_ULONG CombiningHalfMarksMask = SkOTSetULONGBit<64 - 64>::value;
+ static const SK_OT_ULONG CJKCompatibilityFormsMask = SkOTSetULONGBit<65 - 64>::value;
+ static const SK_OT_ULONG SmallFormVariantsMask = SkOTSetULONGBit<66 - 64>::value;
+ static const SK_OT_ULONG ArabicPresentationFormsBMask = SkOTSetULONGBit<67 - 64>::value;
+ static const SK_OT_ULONG HalfwidthAndFullwidthFormsMask = SkOTSetULONGBit<68 - 64>::value;
+ static const SK_OT_ULONG SpecialsMask = SkOTSetULONGBit<69 - 64>::value;
};
SK_OT_ULONG value[4];
} raw;
@@ -364,13 +364,13 @@ struct SkOTTableOS2_V1 {
Reserved07)
} field;
struct Raw {
- static const SK_OT_USHORT ItalicMask = SkTEndian_SwapBE16(1 << 0);
- static const SK_OT_USHORT UnderscoreMask = SkTEndian_SwapBE16(1 << 1);
- static const SK_OT_USHORT NegativeMask = SkTEndian_SwapBE16(1 << 2);
- static const SK_OT_USHORT OutlinedMask = SkTEndian_SwapBE16(1 << 3);
- static const SK_OT_USHORT StrikeoutMask = SkTEndian_SwapBE16(1 << 4);
- static const SK_OT_USHORT BoldMask = SkTEndian_SwapBE16(1 << 5);
- static const SK_OT_USHORT RegularMask = SkTEndian_SwapBE16(1 << 6);
+ static const SK_OT_USHORT ItalicMask = SkOTSetUSHORTBit<0>::value;
+ static const SK_OT_USHORT UnderscoreMask = SkOTSetUSHORTBit<1>::value;
+ static const SK_OT_USHORT NegativeMask = SkOTSetUSHORTBit<2>::value;
+ static const SK_OT_USHORT OutlinedMask = SkOTSetUSHORTBit<3>::value;
+ static const SK_OT_USHORT StrikeoutMask = SkOTSetUSHORTBit<4>::value;
+ static const SK_OT_USHORT BoldMask = SkOTSetUSHORTBit<5>::value;
+ static const SK_OT_USHORT RegularMask = SkOTSetUSHORTBit<6>::value;
SK_OT_USHORT value;
} raw;
} fsSelection;
@@ -469,41 +469,41 @@ struct SkOTTableOS2_V1 {
} field;
struct Raw {
struct l0 {
- static const SK_OT_ULONG Latin1_1252Mask = SkTEndian_SwapBE32(1 << 0);
- static const SK_OT_ULONG Latin2EasternEurope_1250Mask = SkTEndian_SwapBE32(1 << 1);
- static const SK_OT_ULONG Cyrillic_1251Mask = SkTEndian_SwapBE32(1 << 2);
- static const SK_OT_ULONG Greek_1253Mask = SkTEndian_SwapBE32(1 << 3);
- static const SK_OT_ULONG Turkish_1254Mask = SkTEndian_SwapBE32(1 << 4);
- static const SK_OT_ULONG Hebrew_1255Mask = SkTEndian_SwapBE32(1 << 5);
- static const SK_OT_ULONG Arabic_1256Mask = SkTEndian_SwapBE32(1 << 6);
- static const SK_OT_ULONG WindowsBaltic_1257Mask = SkTEndian_SwapBE32(1 << 7);
- static const SK_OT_ULONG Thai_874Mask = SkTEndian_SwapBE32(1 << 16);
- static const SK_OT_ULONG JISJapan_932Mask = SkTEndian_SwapBE32(1 << 17);
- static const SK_OT_ULONG ChineseSimplified_936Mask = SkTEndian_SwapBE32(1 << 18);
- static const SK_OT_ULONG KoreanWansung_949Mask = SkTEndian_SwapBE32(1 << 19);
- static const SK_OT_ULONG ChineseTraditional_950Mask = SkTEndian_SwapBE32(1 << 20);
- static const SK_OT_ULONG KoreanJohab_1361Mask = SkTEndian_SwapBE32(1 << 21);
- static const SK_OT_ULONG MacintoshCharacterSetMask = SkTEndian_SwapBE32(1 << 29);
- static const SK_OT_ULONG OEMCharacterSetMask = SkTEndian_SwapBE32(1 << 30);
- static const SK_OT_ULONG SymbolCharacterSetMask = SkTEndian_SwapBE32(1 << 31);
+ static const SK_OT_ULONG Latin1_1252Mask = SkOTSetULONGBit<0>::value;
+ static const SK_OT_ULONG Latin2EasternEurope_1250Mask = SkOTSetULONGBit<1>::value;
+ static const SK_OT_ULONG Cyrillic_1251Mask = SkOTSetULONGBit<2>::value;
+ static const SK_OT_ULONG Greek_1253Mask = SkOTSetULONGBit<3>::value;
+ static const SK_OT_ULONG Turkish_1254Mask = SkOTSetULONGBit<4>::value;
+ static const SK_OT_ULONG Hebrew_1255Mask = SkOTSetULONGBit<5>::value;
+ static const SK_OT_ULONG Arabic_1256Mask = SkOTSetULONGBit<6>::value;
+ static const SK_OT_ULONG WindowsBaltic_1257Mask = SkOTSetULONGBit<7>::value;
+ static const SK_OT_ULONG Thai_874Mask = SkOTSetULONGBit<16>::value;
+ static const SK_OT_ULONG JISJapan_932Mask = SkOTSetULONGBit<17>::value;
+ static const SK_OT_ULONG ChineseSimplified_936Mask = SkOTSetULONGBit<18>::value;
+ static const SK_OT_ULONG KoreanWansung_949Mask = SkOTSetULONGBit<19>::value;
+ static const SK_OT_ULONG ChineseTraditional_950Mask = SkOTSetULONGBit<20>::value;
+ static const SK_OT_ULONG KoreanJohab_1361Mask = SkOTSetULONGBit<21>::value;
+ static const SK_OT_ULONG MacintoshCharacterSetMask = SkOTSetULONGBit<29>::value;
+ static const SK_OT_ULONG OEMCharacterSetMask = SkOTSetULONGBit<30>::value;
+ static const SK_OT_ULONG SymbolCharacterSetMask = SkOTSetULONGBit<31>::value;
};
struct l1 {
- static const SK_OT_ULONG IBMGreek_869Mask = SkTEndian_SwapBE32(1 << (48 - 32));
- static const SK_OT_ULONG MSDOSRussian_866Mask = SkTEndian_SwapBE32(1 << (49 - 32));
- static const SK_OT_ULONG MSDOSNordic_865Mask = SkTEndian_SwapBE32(1 << (50 - 32));
- static const SK_OT_ULONG Arabic_864Mask = SkTEndian_SwapBE32(1 << (51 - 32));
- static const SK_OT_ULONG MSDOSCanadianFrench_863Mask = SkTEndian_SwapBE32(1 << (52 - 32));
- static const SK_OT_ULONG Hebrew_862Mask = SkTEndian_SwapBE32(1 << (53 - 32));
- static const SK_OT_ULONG MSDOSIcelandic_861Mask = SkTEndian_SwapBE32(1 << (54 - 32));
- static const SK_OT_ULONG MSDOSPortuguese_860Mask = SkTEndian_SwapBE32(1 << (55 - 32));
- static const SK_OT_ULONG IBMTurkish_857Mask = SkTEndian_SwapBE32(1 << (56 - 32));
- static const SK_OT_ULONG IBMCyrillic_855Mask = SkTEndian_SwapBE32(1 << (57 - 32));
- static const SK_OT_ULONG Latin2_852Mask = SkTEndian_SwapBE32(1 << (58 - 32));
- static const SK_OT_ULONG MSDOSBaltic_775Mask = SkTEndian_SwapBE32(1 << (59 - 32));
- static const SK_OT_ULONG Greek_737Mask = SkTEndian_SwapBE32(1 << (60 - 32));
- static const SK_OT_ULONG Arabic_708Mask = SkTEndian_SwapBE32(1 << (61 - 32));
- static const SK_OT_ULONG WELatin1_850Mask = SkTEndian_SwapBE32(1 << (62 - 32));
- static const SK_OT_ULONG US_437Mask = SkTEndian_SwapBE32(1 << (63 - 32));
+ static const SK_OT_ULONG IBMGreek_869Mask = SkOTSetULONGBit<48 - 32>::value;
+ static const SK_OT_ULONG MSDOSRussian_866Mask = SkOTSetULONGBit<49 - 32>::value;
+ static const SK_OT_ULONG MSDOSNordic_865Mask = SkOTSetULONGBit<50 - 32>::value;
+ static const SK_OT_ULONG Arabic_864Mask = SkOTSetULONGBit<51 - 32>::value;
+ static const SK_OT_ULONG MSDOSCanadianFrench_863Mask = SkOTSetULONGBit<52 - 32>::value;
+ static const SK_OT_ULONG Hebrew_862Mask = SkOTSetULONGBit<53 - 32>::value;
+ static const SK_OT_ULONG MSDOSIcelandic_861Mask = SkOTSetULONGBit<54 - 32>::value;
+ static const SK_OT_ULONG MSDOSPortuguese_860Mask = SkOTSetULONGBit<55 - 32>::value;
+ static const SK_OT_ULONG IBMTurkish_857Mask = SkOTSetULONGBit<56 - 32>::value;
+ static const SK_OT_ULONG IBMCyrillic_855Mask = SkOTSetULONGBit<57 - 32>::value;
+ static const SK_OT_ULONG Latin2_852Mask = SkOTSetULONGBit<58 - 32>::value;
+ static const SK_OT_ULONG MSDOSBaltic_775Mask = SkOTSetULONGBit<59 - 32>::value;
+ static const SK_OT_ULONG Greek_737Mask = SkOTSetULONGBit<60 - 32>::value;
+ static const SK_OT_ULONG Arabic_708Mask = SkOTSetULONGBit<61 - 32>::value;
+ static const SK_OT_ULONG WELatin1_850Mask = SkOTSetULONGBit<62 - 32>::value;
+ static const SK_OT_ULONG US_437Mask = SkOTSetULONGBit<63 - 32>::value;
};
SK_OT_ULONG value[2];
} raw;
diff --git a/chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_V2.h b/chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_V2.h
index 4be2e199a6a..52f946057a8 100644
--- a/chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_V2.h
+++ b/chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_V2.h
@@ -73,12 +73,12 @@ struct SkOTTableOS2_V2 {
Reserved07)
} field;
struct Raw {
- static const SK_OT_USHORT Installable = SkTEndian_SwapBE16(0);
- static const SK_OT_USHORT RestrictedMask = SkTEndian_SwapBE16(1 << 1);
- static const SK_OT_USHORT PreviewPrintMask = SkTEndian_SwapBE16(1 << 2);
- static const SK_OT_USHORT EditableMask = SkTEndian_SwapBE16(1 << 3);
- static const SK_OT_USHORT NoSubsettingMask = SkTEndian_SwapBE16(1 << 8);
- static const SK_OT_USHORT BitmapMask = SkTEndian_SwapBE16(1 << 9);
+ static const SK_OT_USHORT Installable = 0;
+ static const SK_OT_USHORT RestrictedMask = SkOTSetUSHORTBit<1>::value;
+ static const SK_OT_USHORT PreviewPrintMask = SkOTSetUSHORTBit<2>::value;
+ static const SK_OT_USHORT EditableMask = SkOTSetUSHORTBit<3>::value;
+ static const SK_OT_USHORT NoSubsettingMask = SkOTSetUSHORTBit<8>::value;
+ static const SK_OT_USHORT BitmapMask = SkOTSetUSHORTBit<9>::value;
SK_OT_USHORT value;
} raw;
} fsType;
@@ -262,94 +262,94 @@ struct SkOTTableOS2_V2 {
} field;
struct Raw {
struct l0 {
- static const SK_OT_ULONG BasicLatinMask = SkTEndian_SwapBE32(1 << 0);
- static const SK_OT_ULONG Latin1SupplementMask = SkTEndian_SwapBE32(1 << 1);
- static const SK_OT_ULONG LatinExtendedAMask = SkTEndian_SwapBE32(1 << 2);
- static const SK_OT_ULONG LatinExtendedBMask = SkTEndian_SwapBE32(1 << 3);
- static const SK_OT_ULONG IPAExtensionsMask = SkTEndian_SwapBE32(1 << 4);
- static const SK_OT_ULONG SpacingModifierLettersMask = SkTEndian_SwapBE32(1 << 5);
- static const SK_OT_ULONG CombiningDiacriticalMarksMask = SkTEndian_SwapBE32(1 << 6);
- static const SK_OT_ULONG GreekMask = SkTEndian_SwapBE32(1 << 7);
+ static const SK_OT_ULONG BasicLatinMask = SkOTSetULONGBit<0>::value;
+ static const SK_OT_ULONG Latin1SupplementMask = SkOTSetULONGBit<1>::value;
+ static const SK_OT_ULONG LatinExtendedAMask = SkOTSetULONGBit<2>::value;
+ static const SK_OT_ULONG LatinExtendedBMask = SkOTSetULONGBit<3>::value;
+ static const SK_OT_ULONG IPAExtensionsMask = SkOTSetULONGBit<4>::value;
+ static const SK_OT_ULONG SpacingModifierLettersMask = SkOTSetULONGBit<5>::value;
+ static const SK_OT_ULONG CombiningDiacriticalMarksMask = SkOTSetULONGBit<6>::value;
+ static const SK_OT_ULONG GreekMask = SkOTSetULONGBit<7>::value;
//Reserved
- static const SK_OT_ULONG CyrillicMask = SkTEndian_SwapBE32(1 << 9);
- static const SK_OT_ULONG ArmenianMask = SkTEndian_SwapBE32(1 << 10);
- static const SK_OT_ULONG HebrewMask = SkTEndian_SwapBE32(1 << 11);
+ static const SK_OT_ULONG CyrillicMask = SkOTSetULONGBit<9>::value;
+ static const SK_OT_ULONG ArmenianMask = SkOTSetULONGBit<10>::value;
+ static const SK_OT_ULONG HebrewMask = SkOTSetULONGBit<11>::value;
//Reserved
- static const SK_OT_ULONG ArabicMask = SkTEndian_SwapBE32(1 << 13);
+ static const SK_OT_ULONG ArabicMask = SkOTSetULONGBit<13>::value;
//Reserved
- static const SK_OT_ULONG DevanagariMask = SkTEndian_SwapBE32(1 << 15);
- static const SK_OT_ULONG BengaliMask = SkTEndian_SwapBE32(1 << 16);
- static const SK_OT_ULONG GurmukhiMask = SkTEndian_SwapBE32(1 << 17);
- static const SK_OT_ULONG GujaratiMask = SkTEndian_SwapBE32(1 << 18);
- static const SK_OT_ULONG OriyaMask = SkTEndian_SwapBE32(1 << 19);
- static const SK_OT_ULONG TamilMask = SkTEndian_SwapBE32(1 << 20);
- static const SK_OT_ULONG TeluguMask = SkTEndian_SwapBE32(1 << 21);
- static const SK_OT_ULONG KannadaMask = SkTEndian_SwapBE32(1 << 22);
- static const SK_OT_ULONG MalayalamMask = SkTEndian_SwapBE32(1 << 23);
- static const SK_OT_ULONG ThaiMask = SkTEndian_SwapBE32(1 << 24);
- static const SK_OT_ULONG LaoMask = SkTEndian_SwapBE32(1 << 25);
- static const SK_OT_ULONG GeorgianMask = SkTEndian_SwapBE32(1 << 26);
+ static const SK_OT_ULONG DevanagariMask = SkOTSetULONGBit<15>::value;
+ static const SK_OT_ULONG BengaliMask = SkOTSetULONGBit<16>::value;
+ static const SK_OT_ULONG GurmukhiMask = SkOTSetULONGBit<17>::value;
+ static const SK_OT_ULONG GujaratiMask = SkOTSetULONGBit<18>::value;
+ static const SK_OT_ULONG OriyaMask = SkOTSetULONGBit<19>::value;
+ static const SK_OT_ULONG TamilMask = SkOTSetULONGBit<20>::value;
+ static const SK_OT_ULONG TeluguMask = SkOTSetULONGBit<21>::value;
+ static const SK_OT_ULONG KannadaMask = SkOTSetULONGBit<22>::value;
+ static const SK_OT_ULONG MalayalamMask = SkOTSetULONGBit<23>::value;
+ static const SK_OT_ULONG ThaiMask = SkOTSetULONGBit<24>::value;
+ static const SK_OT_ULONG LaoMask = SkOTSetULONGBit<25>::value;
+ static const SK_OT_ULONG GeorgianMask = SkOTSetULONGBit<26>::value;
//Reserved
- static const SK_OT_ULONG HangulJamoMask = SkTEndian_SwapBE32(1 << 28);
- static const SK_OT_ULONG LatinExtendedAdditionalMask = SkTEndian_SwapBE32(1 << 29);
- static const SK_OT_ULONG GreekExtendedMask = SkTEndian_SwapBE32(1 << 30);
- static const SK_OT_ULONG GeneralPunctuationMask = SkTEndian_SwapBE32(1 << 31);
+ static const SK_OT_ULONG HangulJamoMask = SkOTSetULONGBit<28>::value;
+ static const SK_OT_ULONG LatinExtendedAdditionalMask = SkOTSetULONGBit<29>::value;
+ static const SK_OT_ULONG GreekExtendedMask = SkOTSetULONGBit<30>::value;
+ static const SK_OT_ULONG GeneralPunctuationMask = SkOTSetULONGBit<31>::value;
};
struct l1 {
- static const SK_OT_ULONG SuperscriptsAndSubscriptsMask = SkTEndian_SwapBE32(1 << (32 - 32));
- static const SK_OT_ULONG CurrencySymbolsMask = SkTEndian_SwapBE32(1 << (33 - 32));
- static const SK_OT_ULONG CombiningDiacriticalMarksForSymbolsMask = SkTEndian_SwapBE32(1 << (34 - 32));
- static const SK_OT_ULONG LetterlikeSymbolsMask = SkTEndian_SwapBE32(1 << (35 - 32));
- static const SK_OT_ULONG NumberFormsMask = SkTEndian_SwapBE32(1 << (36 - 32));
- static const SK_OT_ULONG ArrowsMask = SkTEndian_SwapBE32(1 << (37 - 32));
- static const SK_OT_ULONG MathematicalOperatorsMask = SkTEndian_SwapBE32(1 << (38 - 32));
- static const SK_OT_ULONG MiscellaneousTechnicalMask = SkTEndian_SwapBE32(1 << (39 - 32));
- static const SK_OT_ULONG ControlPicturesMask = SkTEndian_SwapBE32(1 << (40 - 32));
- static const SK_OT_ULONG OpticalCharacterRecognitionMask = SkTEndian_SwapBE32(1 << (41 - 32));
- static const SK_OT_ULONG EnclosedAlphanumericsMask = SkTEndian_SwapBE32(1 << (42 - 32));
- static const SK_OT_ULONG BoxDrawingMask = SkTEndian_SwapBE32(1 << (43 - 32));
- static const SK_OT_ULONG BlockElementsMask = SkTEndian_SwapBE32(1 << (44 - 32));
- static const SK_OT_ULONG GeometricShapesMask = SkTEndian_SwapBE32(1 << (45 - 32));
- static const SK_OT_ULONG MiscellaneousSymbolsMask = SkTEndian_SwapBE32(1 << (46 - 32));
- static const SK_OT_ULONG DingbatsMask = SkTEndian_SwapBE32(1 << (47 - 32));
- static const SK_OT_ULONG CJKSymbolsAndPunctuationMask = SkTEndian_SwapBE32(1 << (48 - 32));
- static const SK_OT_ULONG HiraganaMask = SkTEndian_SwapBE32(1 << (49 - 32));
- static const SK_OT_ULONG KatakanaMask = SkTEndian_SwapBE32(1 << (50 - 32));
- static const SK_OT_ULONG BopomofoMask = SkTEndian_SwapBE32(1 << (51 - 32));
- static const SK_OT_ULONG HangulCompatibilityJamoMask = SkTEndian_SwapBE32(1 << (52 - 32));
- static const SK_OT_ULONG CJKMiscellaneousMask = SkTEndian_SwapBE32(1 << (53 - 32));
- static const SK_OT_ULONG EnclosedCJKLettersAndMonthsMask = SkTEndian_SwapBE32(1 << (54 - 32));
- static const SK_OT_ULONG CJKCompatibilityMask = SkTEndian_SwapBE32(1 << (55 - 32));
- static const SK_OT_ULONG HangulMask = SkTEndian_SwapBE32(1 << (56 - 32));
- static const SK_OT_ULONG SurrogatesMask = SkTEndian_SwapBE32(1 << (57 - 32));
+ static const SK_OT_ULONG SuperscriptsAndSubscriptsMask = SkOTSetULONGBit<32 - 32>::value;
+ static const SK_OT_ULONG CurrencySymbolsMask = SkOTSetULONGBit<33 - 32>::value;
+ static const SK_OT_ULONG CombiningDiacriticalMarksForSymbolsMask = SkOTSetULONGBit<34 - 32>::value;
+ static const SK_OT_ULONG LetterlikeSymbolsMask = SkOTSetULONGBit<35 - 32>::value;
+ static const SK_OT_ULONG NumberFormsMask = SkOTSetULONGBit<36 - 32>::value;
+ static const SK_OT_ULONG ArrowsMask = SkOTSetULONGBit<37 - 32>::value;
+ static const SK_OT_ULONG MathematicalOperatorsMask = SkOTSetULONGBit<38 - 32>::value;
+ static const SK_OT_ULONG MiscellaneousTechnicalMask = SkOTSetULONGBit<39 - 32>::value;
+ static const SK_OT_ULONG ControlPicturesMask = SkOTSetULONGBit<40 - 32>::value;
+ static const SK_OT_ULONG OpticalCharacterRecognitionMask = SkOTSetULONGBit<41 - 32>::value;
+ static const SK_OT_ULONG EnclosedAlphanumericsMask = SkOTSetULONGBit<42 - 32>::value;
+ static const SK_OT_ULONG BoxDrawingMask = SkOTSetULONGBit<43 - 32>::value;
+ static const SK_OT_ULONG BlockElementsMask = SkOTSetULONGBit<44 - 32>::value;
+ static const SK_OT_ULONG GeometricShapesMask = SkOTSetULONGBit<45 - 32>::value;
+ static const SK_OT_ULONG MiscellaneousSymbolsMask = SkOTSetULONGBit<46 - 32>::value;
+ static const SK_OT_ULONG DingbatsMask = SkOTSetULONGBit<47 - 32>::value;
+ static const SK_OT_ULONG CJKSymbolsAndPunctuationMask = SkOTSetULONGBit<48 - 32>::value;
+ static const SK_OT_ULONG HiraganaMask = SkOTSetULONGBit<49 - 32>::value;
+ static const SK_OT_ULONG KatakanaMask = SkOTSetULONGBit<50 - 32>::value;
+ static const SK_OT_ULONG BopomofoMask = SkOTSetULONGBit<51 - 32>::value;
+ static const SK_OT_ULONG HangulCompatibilityJamoMask = SkOTSetULONGBit<52 - 32>::value;
+ static const SK_OT_ULONG CJKMiscellaneousMask = SkOTSetULONGBit<53 - 32>::value;
+ static const SK_OT_ULONG EnclosedCJKLettersAndMonthsMask = SkOTSetULONGBit<54 - 32>::value;
+ static const SK_OT_ULONG CJKCompatibilityMask = SkOTSetULONGBit<55 - 32>::value;
+ static const SK_OT_ULONG HangulMask = SkOTSetULONGBit<56 - 32>::value;
+ static const SK_OT_ULONG SurrogatesMask = SkOTSetULONGBit<57 - 32>::value;
//Reserved
- static const SK_OT_ULONG CJKUnifiedIdeographsMask = SkTEndian_SwapBE32(1 << (59 - 32));
- static const SK_OT_ULONG PrivateUseAreaMask = SkTEndian_SwapBE32(1 << (60 - 32));
- static const SK_OT_ULONG CJKCompatibilityIdeographsMask = SkTEndian_SwapBE32(1 << (61 - 32));
- static const SK_OT_ULONG AlphabeticPresentationFormsMask = SkTEndian_SwapBE32(1 << (62 - 32));
- static const SK_OT_ULONG ArabicPresentationFormsAMask = SkTEndian_SwapBE32(1 << (63 - 32));
+ static const SK_OT_ULONG CJKUnifiedIdeographsMask = SkOTSetULONGBit<59 - 32>::value;
+ static const SK_OT_ULONG PrivateUseAreaMask = SkOTSetULONGBit<60 - 32>::value;
+ static const SK_OT_ULONG CJKCompatibilityIdeographsMask = SkOTSetULONGBit<61 - 32>::value;
+ static const SK_OT_ULONG AlphabeticPresentationFormsMask = SkOTSetULONGBit<62 - 32>::value;
+ static const SK_OT_ULONG ArabicPresentationFormsAMask = SkOTSetULONGBit<63 - 32>::value;
};
struct l2 {
- static const SK_OT_ULONG CombiningHalfMarksMask = SkTEndian_SwapBE32(1 << (64 - 64));
- static const SK_OT_ULONG CJKCompatibilityFormsMask = SkTEndian_SwapBE32(1 << (65 - 64));
- static const SK_OT_ULONG SmallFormVariantsMask = SkTEndian_SwapBE32(1 << (66 - 64));
- static const SK_OT_ULONG ArabicPresentationFormsBMask = SkTEndian_SwapBE32(1 << (67 - 64));
- static const SK_OT_ULONG HalfwidthAndFullwidthFormsMask = SkTEndian_SwapBE32(1 << (68 - 64));
- static const SK_OT_ULONG SpecialsMask = SkTEndian_SwapBE32(1 << (69 - 64));
- static const SK_OT_ULONG TibetanMask = SkTEndian_SwapBE32(1 << (70 - 64));
- static const SK_OT_ULONG SyriacMask = SkTEndian_SwapBE32(1 << (71 - 64));
- static const SK_OT_ULONG ThaanaMask = SkTEndian_SwapBE32(1 << (72 - 64));
- static const SK_OT_ULONG SinhalaMask = SkTEndian_SwapBE32(1 << (73 - 64));
- static const SK_OT_ULONG MyanmarMask = SkTEndian_SwapBE32(1 << (74 - 64));
- static const SK_OT_ULONG EthiopicMask = SkTEndian_SwapBE32(1 << (75 - 64));
- static const SK_OT_ULONG CherokeeMask = SkTEndian_SwapBE32(1 << (76 - 64));
- static const SK_OT_ULONG UnifiedCanadianSyllabicsMask = SkTEndian_SwapBE32(1 << (77 - 64));
- static const SK_OT_ULONG OghamMask = SkTEndian_SwapBE32(1 << (78 - 64));
- static const SK_OT_ULONG RunicMask = SkTEndian_SwapBE32(1 << (79 - 64));
- static const SK_OT_ULONG KhmerMask = SkTEndian_SwapBE32(1 << (80 - 64));
- static const SK_OT_ULONG MongolianMask = SkTEndian_SwapBE32(1 << (81 - 64));
- static const SK_OT_ULONG BrailleMask = SkTEndian_SwapBE32(1 << (82 - 64));
- static const SK_OT_ULONG YiMask = SkTEndian_SwapBE32(1 << (83 - 64));
+ static const SK_OT_ULONG CombiningHalfMarksMask = SkOTSetULONGBit<64 - 64>::value;
+ static const SK_OT_ULONG CJKCompatibilityFormsMask = SkOTSetULONGBit<65 - 64>::value;
+ static const SK_OT_ULONG SmallFormVariantsMask = SkOTSetULONGBit<66 - 64>::value;
+ static const SK_OT_ULONG ArabicPresentationFormsBMask = SkOTSetULONGBit<67 - 64>::value;
+ static const SK_OT_ULONG HalfwidthAndFullwidthFormsMask = SkOTSetULONGBit<68 - 64>::value;
+ static const SK_OT_ULONG SpecialsMask = SkOTSetULONGBit<69 - 64>::value;
+ static const SK_OT_ULONG TibetanMask = SkOTSetULONGBit<70 - 64>::value;
+ static const SK_OT_ULONG SyriacMask = SkOTSetULONGBit<71 - 64>::value;
+ static const SK_OT_ULONG ThaanaMask = SkOTSetULONGBit<72 - 64>::value;
+ static const SK_OT_ULONG SinhalaMask = SkOTSetULONGBit<73 - 64>::value;
+ static const SK_OT_ULONG MyanmarMask = SkOTSetULONGBit<74 - 64>::value;
+ static const SK_OT_ULONG EthiopicMask = SkOTSetULONGBit<75 - 64>::value;
+ static const SK_OT_ULONG CherokeeMask = SkOTSetULONGBit<76 - 64>::value;
+ static const SK_OT_ULONG UnifiedCanadianSyllabicsMask = SkOTSetULONGBit<77 - 64>::value;
+ static const SK_OT_ULONG OghamMask = SkOTSetULONGBit<78 - 64>::value;
+ static const SK_OT_ULONG RunicMask = SkOTSetULONGBit<79 - 64>::value;
+ static const SK_OT_ULONG KhmerMask = SkOTSetULONGBit<80 - 64>::value;
+ static const SK_OT_ULONG MongolianMask = SkOTSetULONGBit<81 - 64>::value;
+ static const SK_OT_ULONG BrailleMask = SkOTSetULONGBit<82 - 64>::value;
+ static const SK_OT_ULONG YiMask = SkOTSetULONGBit<83 - 64>::value;
};
SK_OT_ULONG value[4];
} raw;
@@ -379,13 +379,13 @@ struct SkOTTableOS2_V2 {
Reserved07)
} field;
struct Raw {
- static const SK_OT_USHORT ItalicMask = SkTEndian_SwapBE16(1 << 0);
- static const SK_OT_USHORT UnderscoreMask = SkTEndian_SwapBE16(1 << 1);
- static const SK_OT_USHORT NegativeMask = SkTEndian_SwapBE16(1 << 2);
- static const SK_OT_USHORT OutlinedMask = SkTEndian_SwapBE16(1 << 3);
- static const SK_OT_USHORT StrikeoutMask = SkTEndian_SwapBE16(1 << 4);
- static const SK_OT_USHORT BoldMask = SkTEndian_SwapBE16(1 << 5);
- static const SK_OT_USHORT RegularMask = SkTEndian_SwapBE16(1 << 6);
+ static const SK_OT_USHORT ItalicMask = SkOTSetUSHORTBit<0>::value;
+ static const SK_OT_USHORT UnderscoreMask = SkOTSetUSHORTBit<1>::value;
+ static const SK_OT_USHORT NegativeMask = SkOTSetUSHORTBit<2>::value;
+ static const SK_OT_USHORT OutlinedMask = SkOTSetUSHORTBit<3>::value;
+ static const SK_OT_USHORT StrikeoutMask = SkOTSetUSHORTBit<4>::value;
+ static const SK_OT_USHORT BoldMask = SkOTSetUSHORTBit<5>::value;
+ static const SK_OT_USHORT RegularMask = SkOTSetUSHORTBit<6>::value;
SK_OT_USHORT value;
} raw;
} fsSelection;
@@ -484,42 +484,42 @@ struct SkOTTableOS2_V2 {
} field;
struct Raw {
struct l0 {
- static const SK_OT_ULONG Latin1_1252Mask = SkTEndian_SwapBE32(1 << 0);
- static const SK_OT_ULONG Latin2EasternEurope_1250Mask = SkTEndian_SwapBE32(1 << 1);
- static const SK_OT_ULONG Cyrillic_1251Mask = SkTEndian_SwapBE32(1 << 2);
- static const SK_OT_ULONG Greek_1253Mask = SkTEndian_SwapBE32(1 << 3);
- static const SK_OT_ULONG Turkish_1254Mask = SkTEndian_SwapBE32(1 << 4);
- static const SK_OT_ULONG Hebrew_1255Mask = SkTEndian_SwapBE32(1 << 5);
- static const SK_OT_ULONG Arabic_1256Mask = SkTEndian_SwapBE32(1 << 6);
- static const SK_OT_ULONG WindowsBaltic_1257Mask = SkTEndian_SwapBE32(1 << 7);
- static const SK_OT_ULONG Vietnamese_1258Mask = SkTEndian_SwapBE32(1 << 8);
- static const SK_OT_ULONG Thai_874Mask = SkTEndian_SwapBE32(1 << 16);
- static const SK_OT_ULONG JISJapan_932Mask = SkTEndian_SwapBE32(1 << 17);
- static const SK_OT_ULONG ChineseSimplified_936Mask = SkTEndian_SwapBE32(1 << 18);
- static const SK_OT_ULONG KoreanWansung_949Mask = SkTEndian_SwapBE32(1 << 19);
- static const SK_OT_ULONG ChineseTraditional_950Mask = SkTEndian_SwapBE32(1 << 20);
- static const SK_OT_ULONG KoreanJohab_1361Mask = SkTEndian_SwapBE32(1 << 21);
- static const SK_OT_ULONG MacintoshCharacterSetMask = SkTEndian_SwapBE32(1 << 29);
- static const SK_OT_ULONG OEMCharacterSetMask = SkTEndian_SwapBE32(1 << 30);
- static const SK_OT_ULONG SymbolCharacterSetMask = SkTEndian_SwapBE32(1 << 31);
+ static const SK_OT_ULONG Latin1_1252Mask = SkOTSetULONGBit<0>::value;
+ static const SK_OT_ULONG Latin2EasternEurope_1250Mask = SkOTSetULONGBit<1>::value;
+ static const SK_OT_ULONG Cyrillic_1251Mask = SkOTSetULONGBit<2>::value;
+ static const SK_OT_ULONG Greek_1253Mask = SkOTSetULONGBit<3>::value;
+ static const SK_OT_ULONG Turkish_1254Mask = SkOTSetULONGBit<4>::value;
+ static const SK_OT_ULONG Hebrew_1255Mask = SkOTSetULONGBit<5>::value;
+ static const SK_OT_ULONG Arabic_1256Mask = SkOTSetULONGBit<6>::value;
+ static const SK_OT_ULONG WindowsBaltic_1257Mask = SkOTSetULONGBit<7>::value;
+ static const SK_OT_ULONG Vietnamese_1258Mask = SkOTSetULONGBit<8>::value;
+ static const SK_OT_ULONG Thai_874Mask = SkOTSetULONGBit<16>::value;
+ static const SK_OT_ULONG JISJapan_932Mask = SkOTSetULONGBit<17>::value;
+ static const SK_OT_ULONG ChineseSimplified_936Mask = SkOTSetULONGBit<18>::value;
+ static const SK_OT_ULONG KoreanWansung_949Mask = SkOTSetULONGBit<19>::value;
+ static const SK_OT_ULONG ChineseTraditional_950Mask = SkOTSetULONGBit<20>::value;
+ static const SK_OT_ULONG KoreanJohab_1361Mask = SkOTSetULONGBit<21>::value;
+ static const SK_OT_ULONG MacintoshCharacterSetMask = SkOTSetULONGBit<29>::value;
+ static const SK_OT_ULONG OEMCharacterSetMask = SkOTSetULONGBit<30>::value;
+ static const SK_OT_ULONG SymbolCharacterSetMask = SkOTSetULONGBit<31>::value;
};
struct l1 {
- static const SK_OT_ULONG IBMGreek_869Mask = SkTEndian_SwapBE32(1 << (48 - 32));
- static const SK_OT_ULONG MSDOSRussian_866Mask = SkTEndian_SwapBE32(1 << (49 - 32));
- static const SK_OT_ULONG MSDOSNordic_865Mask = SkTEndian_SwapBE32(1 << (50 - 32));
- static const SK_OT_ULONG Arabic_864Mask = SkTEndian_SwapBE32(1 << (51 - 32));
- static const SK_OT_ULONG MSDOSCanadianFrench_863Mask = SkTEndian_SwapBE32(1 << (52 - 32));
- static const SK_OT_ULONG Hebrew_862Mask = SkTEndian_SwapBE32(1 << (53 - 32));
- static const SK_OT_ULONG MSDOSIcelandic_861Mask = SkTEndian_SwapBE32(1 << (54 - 32));
- static const SK_OT_ULONG MSDOSPortuguese_860Mask = SkTEndian_SwapBE32(1 << (55 - 32));
- static const SK_OT_ULONG IBMTurkish_857Mask = SkTEndian_SwapBE32(1 << (56 - 32));
- static const SK_OT_ULONG IBMCyrillic_855Mask = SkTEndian_SwapBE32(1 << (57 - 32));
- static const SK_OT_ULONG Latin2_852Mask = SkTEndian_SwapBE32(1 << (58 - 32));
- static const SK_OT_ULONG MSDOSBaltic_775Mask = SkTEndian_SwapBE32(1 << (59 - 32));
- static const SK_OT_ULONG Greek_737Mask = SkTEndian_SwapBE32(1 << (60 - 32));
- static const SK_OT_ULONG Arabic_708Mask = SkTEndian_SwapBE32(1 << (61 - 32));
- static const SK_OT_ULONG WELatin1_850Mask = SkTEndian_SwapBE32(1 << (62 - 32));
- static const SK_OT_ULONG US_437Mask = SkTEndian_SwapBE32(1 << (63 - 32));
+ static const SK_OT_ULONG IBMGreek_869Mask = SkOTSetULONGBit<48 - 32>::value;
+ static const SK_OT_ULONG MSDOSRussian_866Mask = SkOTSetULONGBit<49 - 32>::value;
+ static const SK_OT_ULONG MSDOSNordic_865Mask = SkOTSetULONGBit<50 - 32>::value;
+ static const SK_OT_ULONG Arabic_864Mask = SkOTSetULONGBit<51 - 32>::value;
+ static const SK_OT_ULONG MSDOSCanadianFrench_863Mask = SkOTSetULONGBit<52 - 32>::value;
+ static const SK_OT_ULONG Hebrew_862Mask = SkOTSetULONGBit<53 - 32>::value;
+ static const SK_OT_ULONG MSDOSIcelandic_861Mask = SkOTSetULONGBit<54 - 32>::value;
+ static const SK_OT_ULONG MSDOSPortuguese_860Mask = SkOTSetULONGBit<55 - 32>::value;
+ static const SK_OT_ULONG IBMTurkish_857Mask = SkOTSetULONGBit<56 - 32>::value;
+ static const SK_OT_ULONG IBMCyrillic_855Mask = SkOTSetULONGBit<57 - 32>::value;
+ static const SK_OT_ULONG Latin2_852Mask = SkOTSetULONGBit<58 - 32>::value;
+ static const SK_OT_ULONG MSDOSBaltic_775Mask = SkOTSetULONGBit<59 - 32>::value;
+ static const SK_OT_ULONG Greek_737Mask = SkOTSetULONGBit<60 - 32>::value;
+ static const SK_OT_ULONG Arabic_708Mask = SkOTSetULONGBit<61 - 32>::value;
+ static const SK_OT_ULONG WELatin1_850Mask = SkOTSetULONGBit<62 - 32>::value;
+ static const SK_OT_ULONG US_437Mask = SkOTSetULONGBit<63 - 32>::value;
};
SK_OT_ULONG value[2];
} raw;
diff --git a/chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_V3.h b/chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_V3.h
index 637eb378ad6..8d4fa6b574c 100644
--- a/chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_V3.h
+++ b/chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_V3.h
@@ -74,12 +74,12 @@ struct SkOTTableOS2_V3 {
Reserved07)
} field;
struct Raw {
- static const SK_OT_USHORT Installable = SkTEndian_SwapBE16(0);
- static const SK_OT_USHORT RestrictedMask = SkTEndian_SwapBE16(1 << 1);
- static const SK_OT_USHORT PreviewPrintMask = SkTEndian_SwapBE16(1 << 2);
- static const SK_OT_USHORT EditableMask = SkTEndian_SwapBE16(1 << 3);
- static const SK_OT_USHORT NoSubsettingMask = SkTEndian_SwapBE16(1 << 8);
- static const SK_OT_USHORT BitmapMask = SkTEndian_SwapBE16(1 << 9);
+ static const SK_OT_USHORT Installable = 0;
+ static const SK_OT_USHORT RestrictedMask = SkOTSetUSHORTBit<1>::value;
+ static const SK_OT_USHORT PreviewPrintMask = SkOTSetUSHORTBit<2>::value;
+ static const SK_OT_USHORT EditableMask = SkOTSetUSHORTBit<3>::value;
+ static const SK_OT_USHORT NoSubsettingMask = SkOTSetUSHORTBit<8>::value;
+ static const SK_OT_USHORT BitmapMask = SkOTSetUSHORTBit<9>::value;
SK_OT_USHORT value;
} raw;
} fsType;
@@ -263,103 +263,103 @@ struct SkOTTableOS2_V3 {
} field;
struct Raw {
struct l0 {
- static const SK_OT_ULONG BasicLatinMask = SkTEndian_SwapBE32(1 << 0);
- static const SK_OT_ULONG Latin1SupplementMask = SkTEndian_SwapBE32(1 << 1);
- static const SK_OT_ULONG LatinExtendedAMask = SkTEndian_SwapBE32(1 << 2);
- static const SK_OT_ULONG LatinExtendedBMask = SkTEndian_SwapBE32(1 << 3);
- static const SK_OT_ULONG IPAExtensionsMask = SkTEndian_SwapBE32(1 << 4);
- static const SK_OT_ULONG SpacingModifierLettersMask = SkTEndian_SwapBE32(1 << 5);
- static const SK_OT_ULONG CombiningDiacriticalMarksMask = SkTEndian_SwapBE32(1 << 6);
- static const SK_OT_ULONG GreekAndCopticMask = SkTEndian_SwapBE32(1 << 7);
+ static const SK_OT_ULONG BasicLatinMask = SkOTSetULONGBit<0>::value;
+ static const SK_OT_ULONG Latin1SupplementMask = SkOTSetULONGBit<1>::value;
+ static const SK_OT_ULONG LatinExtendedAMask = SkOTSetULONGBit<2>::value;
+ static const SK_OT_ULONG LatinExtendedBMask = SkOTSetULONGBit<3>::value;
+ static const SK_OT_ULONG IPAExtensionsMask = SkOTSetULONGBit<4>::value;
+ static const SK_OT_ULONG SpacingModifierLettersMask = SkOTSetULONGBit<5>::value;
+ static const SK_OT_ULONG CombiningDiacriticalMarksMask = SkOTSetULONGBit<6>::value;
+ static const SK_OT_ULONG GreekAndCopticMask = SkOTSetULONGBit<7>::value;
//Reserved
- static const SK_OT_ULONG CyrillicMask = SkTEndian_SwapBE32(1 << 9);
- static const SK_OT_ULONG ArmenianMask = SkTEndian_SwapBE32(1 << 10);
- static const SK_OT_ULONG HebrewMask = SkTEndian_SwapBE32(1 << 11);
+ static const SK_OT_ULONG CyrillicMask = SkOTSetULONGBit<9>::value;
+ static const SK_OT_ULONG ArmenianMask = SkOTSetULONGBit<10>::value;
+ static const SK_OT_ULONG HebrewMask = SkOTSetULONGBit<11>::value;
//Reserved
- static const SK_OT_ULONG ArabicMask = SkTEndian_SwapBE32(1 << 13);
+ static const SK_OT_ULONG ArabicMask = SkOTSetULONGBit<13>::value;
//Reserved
- static const SK_OT_ULONG DevanagariMask = SkTEndian_SwapBE32(1 << 15);
- static const SK_OT_ULONG BengaliMask = SkTEndian_SwapBE32(1 << 16);
- static const SK_OT_ULONG GurmukhiMask = SkTEndian_SwapBE32(1 << 17);
- static const SK_OT_ULONG GujaratiMask = SkTEndian_SwapBE32(1 << 18);
- static const SK_OT_ULONG OriyaMask = SkTEndian_SwapBE32(1 << 19);
- static const SK_OT_ULONG TamilMask = SkTEndian_SwapBE32(1 << 20);
- static const SK_OT_ULONG TeluguMask = SkTEndian_SwapBE32(1 << 21);
- static const SK_OT_ULONG KannadaMask = SkTEndian_SwapBE32(1 << 22);
- static const SK_OT_ULONG MalayalamMask = SkTEndian_SwapBE32(1 << 23);
- static const SK_OT_ULONG ThaiMask = SkTEndian_SwapBE32(1 << 24);
- static const SK_OT_ULONG LaoMask = SkTEndian_SwapBE32(1 << 25);
- static const SK_OT_ULONG GeorgianMask = SkTEndian_SwapBE32(1 << 26);
+ static const SK_OT_ULONG DevanagariMask = SkOTSetULONGBit<15>::value;
+ static const SK_OT_ULONG BengaliMask = SkOTSetULONGBit<16>::value;
+ static const SK_OT_ULONG GurmukhiMask = SkOTSetULONGBit<17>::value;
+ static const SK_OT_ULONG GujaratiMask = SkOTSetULONGBit<18>::value;
+ static const SK_OT_ULONG OriyaMask = SkOTSetULONGBit<19>::value;
+ static const SK_OT_ULONG TamilMask = SkOTSetULONGBit<20>::value;
+ static const SK_OT_ULONG TeluguMask = SkOTSetULONGBit<21>::value;
+ static const SK_OT_ULONG KannadaMask = SkOTSetULONGBit<22>::value;
+ static const SK_OT_ULONG MalayalamMask = SkOTSetULONGBit<23>::value;
+ static const SK_OT_ULONG ThaiMask = SkOTSetULONGBit<24>::value;
+ static const SK_OT_ULONG LaoMask = SkOTSetULONGBit<25>::value;
+ static const SK_OT_ULONG GeorgianMask = SkOTSetULONGBit<26>::value;
//Reserved
- static const SK_OT_ULONG HangulJamoMask = SkTEndian_SwapBE32(1 << 28);
- static const SK_OT_ULONG LatinExtendedAdditionalMask = SkTEndian_SwapBE32(1 << 29);
- static const SK_OT_ULONG GreekExtendedMask = SkTEndian_SwapBE32(1 << 30);
- static const SK_OT_ULONG GeneralPunctuationMask = SkTEndian_SwapBE32(1 << 31);
+ static const SK_OT_ULONG HangulJamoMask = SkOTSetULONGBit<28>::value;
+ static const SK_OT_ULONG LatinExtendedAdditionalMask = SkOTSetULONGBit<29>::value;
+ static const SK_OT_ULONG GreekExtendedMask = SkOTSetULONGBit<30>::value;
+ static const SK_OT_ULONG GeneralPunctuationMask = SkOTSetULONGBit<31>::value;
};
struct l1 {
- static const SK_OT_ULONG SuperscriptsAndSubscriptsMask = SkTEndian_SwapBE32(1 << (32 - 32));
- static const SK_OT_ULONG CurrencySymbolsMask = SkTEndian_SwapBE32(1 << (33 - 32));
- static const SK_OT_ULONG CombiningDiacriticalMarksForSymbolsMask = SkTEndian_SwapBE32(1 << (34 - 32));
- static const SK_OT_ULONG LetterlikeSymbolsMask = SkTEndian_SwapBE32(1 << (35 - 32));
- static const SK_OT_ULONG NumberFormsMask = SkTEndian_SwapBE32(1 << (36 - 32));
- static const SK_OT_ULONG ArrowsMask = SkTEndian_SwapBE32(1 << (37 - 32));
- static const SK_OT_ULONG MathematicalOperatorsMask = SkTEndian_SwapBE32(1 << (38 - 32));
- static const SK_OT_ULONG MiscellaneousTechnicalMask = SkTEndian_SwapBE32(1 << (39 - 32));
- static const SK_OT_ULONG ControlPicturesMask = SkTEndian_SwapBE32(1 << (40 - 32));
- static const SK_OT_ULONG OpticalCharacterRecognitionMask = SkTEndian_SwapBE32(1 << (41 - 32));
- static const SK_OT_ULONG EnclosedAlphanumericsMask = SkTEndian_SwapBE32(1 << (42 - 32));
- static const SK_OT_ULONG BoxDrawingMask = SkTEndian_SwapBE32(1 << (43 - 32));
- static const SK_OT_ULONG BlockElementsMask = SkTEndian_SwapBE32(1 << (44 - 32));
- static const SK_OT_ULONG GeometricShapesMask = SkTEndian_SwapBE32(1 << (45 - 32));
- static const SK_OT_ULONG MiscellaneousSymbolsMask = SkTEndian_SwapBE32(1 << (46 - 32));
- static const SK_OT_ULONG DingbatsMask = SkTEndian_SwapBE32(1 << (47 - 32));
- static const SK_OT_ULONG CJKSymbolsAndPunctuationMask = SkTEndian_SwapBE32(1 << (48 - 32));
- static const SK_OT_ULONG HiraganaMask = SkTEndian_SwapBE32(1 << (49 - 32));
- static const SK_OT_ULONG KatakanaMask = SkTEndian_SwapBE32(1 << (50 - 32));
- static const SK_OT_ULONG BopomofoMask = SkTEndian_SwapBE32(1 << (51 - 32));
- static const SK_OT_ULONG HangulCompatibilityJamoMask = SkTEndian_SwapBE32(1 << (52 - 32));
+ static const SK_OT_ULONG SuperscriptsAndSubscriptsMask = SkOTSetULONGBit<32 - 32>::value;
+ static const SK_OT_ULONG CurrencySymbolsMask = SkOTSetULONGBit<33 - 32>::value;
+ static const SK_OT_ULONG CombiningDiacriticalMarksForSymbolsMask = SkOTSetULONGBit<34 - 32>::value;
+ static const SK_OT_ULONG LetterlikeSymbolsMask = SkOTSetULONGBit<35 - 32>::value;
+ static const SK_OT_ULONG NumberFormsMask = SkOTSetULONGBit<36 - 32>::value;
+ static const SK_OT_ULONG ArrowsMask = SkOTSetULONGBit<37 - 32>::value;
+ static const SK_OT_ULONG MathematicalOperatorsMask = SkOTSetULONGBit<38 - 32>::value;
+ static const SK_OT_ULONG MiscellaneousTechnicalMask = SkOTSetULONGBit<39 - 32>::value;
+ static const SK_OT_ULONG ControlPicturesMask = SkOTSetULONGBit<40 - 32>::value;
+ static const SK_OT_ULONG OpticalCharacterRecognitionMask = SkOTSetULONGBit<41 - 32>::value;
+ static const SK_OT_ULONG EnclosedAlphanumericsMask = SkOTSetULONGBit<42 - 32>::value;
+ static const SK_OT_ULONG BoxDrawingMask = SkOTSetULONGBit<43 - 32>::value;
+ static const SK_OT_ULONG BlockElementsMask = SkOTSetULONGBit<44 - 32>::value;
+ static const SK_OT_ULONG GeometricShapesMask = SkOTSetULONGBit<45 - 32>::value;
+ static const SK_OT_ULONG MiscellaneousSymbolsMask = SkOTSetULONGBit<46 - 32>::value;
+ static const SK_OT_ULONG DingbatsMask = SkOTSetULONGBit<47 - 32>::value;
+ static const SK_OT_ULONG CJKSymbolsAndPunctuationMask = SkOTSetULONGBit<48 - 32>::value;
+ static const SK_OT_ULONG HiraganaMask = SkOTSetULONGBit<49 - 32>::value;
+ static const SK_OT_ULONG KatakanaMask = SkOTSetULONGBit<50 - 32>::value;
+ static const SK_OT_ULONG BopomofoMask = SkOTSetULONGBit<51 - 32>::value;
+ static const SK_OT_ULONG HangulCompatibilityJamoMask = SkOTSetULONGBit<52 - 32>::value;
//Reserved
- static const SK_OT_ULONG EnclosedCJKLettersAndMonthsMask = SkTEndian_SwapBE32(1 << (54 - 32));
- static const SK_OT_ULONG CJKCompatibilityMask = SkTEndian_SwapBE32(1 << (55 - 32));
- static const SK_OT_ULONG HangulMask = SkTEndian_SwapBE32(1 << (56 - 32));
- static const SK_OT_ULONG NonPlane0Mask = SkTEndian_SwapBE32(1 << (57 - 32));
+ static const SK_OT_ULONG EnclosedCJKLettersAndMonthsMask = SkOTSetULONGBit<54 - 32>::value;
+ static const SK_OT_ULONG CJKCompatibilityMask = SkOTSetULONGBit<55 - 32>::value;
+ static const SK_OT_ULONG HangulMask = SkOTSetULONGBit<56 - 32>::value;
+ static const SK_OT_ULONG NonPlane0Mask = SkOTSetULONGBit<57 - 32>::value;
//Reserved
- static const SK_OT_ULONG CJKUnifiedIdeographsMask = SkTEndian_SwapBE32(1 << (59 - 32));
- static const SK_OT_ULONG PrivateUseAreaMask = SkTEndian_SwapBE32(1 << (60 - 32));
- static const SK_OT_ULONG CJKCompatibilityIdeographsMask = SkTEndian_SwapBE32(1 << (61 - 32));
- static const SK_OT_ULONG AlphabeticPresentationFormsMask = SkTEndian_SwapBE32(1 << (62 - 32));
- static const SK_OT_ULONG ArabicPresentationFormsAMask = SkTEndian_SwapBE32(1 << (63 - 32));
+ static const SK_OT_ULONG CJKUnifiedIdeographsMask = SkOTSetULONGBit<59 - 32>::value;
+ static const SK_OT_ULONG PrivateUseAreaMask = SkOTSetULONGBit<60 - 32>::value;
+ static const SK_OT_ULONG CJKCompatibilityIdeographsMask = SkOTSetULONGBit<61 - 32>::value;
+ static const SK_OT_ULONG AlphabeticPresentationFormsMask = SkOTSetULONGBit<62 - 32>::value;
+ static const SK_OT_ULONG ArabicPresentationFormsAMask = SkOTSetULONGBit<63 - 32>::value;
};
struct l2 {
- static const SK_OT_ULONG CombiningHalfMarksMask = SkTEndian_SwapBE32(1 << (64 - 64));
- static const SK_OT_ULONG CJKCompatibilityFormsMask = SkTEndian_SwapBE32(1 << (65 - 64));
- static const SK_OT_ULONG SmallFormVariantsMask = SkTEndian_SwapBE32(1 << (66 - 64));
- static const SK_OT_ULONG ArabicPresentationFormsBMask = SkTEndian_SwapBE32(1 << (67 - 64));
- static const SK_OT_ULONG HalfwidthAndFullwidthFormsMask = SkTEndian_SwapBE32(1 << (68 - 64));
- static const SK_OT_ULONG SpecialsMask = SkTEndian_SwapBE32(1 << (69 - 64));
- static const SK_OT_ULONG TibetanMask = SkTEndian_SwapBE32(1 << (70 - 64));
- static const SK_OT_ULONG SyriacMask = SkTEndian_SwapBE32(1 << (71 - 64));
- static const SK_OT_ULONG ThaanaMask = SkTEndian_SwapBE32(1 << (72 - 64));
- static const SK_OT_ULONG SinhalaMask = SkTEndian_SwapBE32(1 << (73 - 64));
- static const SK_OT_ULONG MyanmarMask = SkTEndian_SwapBE32(1 << (74 - 64));
- static const SK_OT_ULONG EthiopicMask = SkTEndian_SwapBE32(1 << (75 - 64));
- static const SK_OT_ULONG CherokeeMask = SkTEndian_SwapBE32(1 << (76 - 64));
- static const SK_OT_ULONG UnifiedCanadianSyllabicsMask = SkTEndian_SwapBE32(1 << (77 - 64));
- static const SK_OT_ULONG OghamMask = SkTEndian_SwapBE32(1 << (78 - 64));
- static const SK_OT_ULONG RunicMask = SkTEndian_SwapBE32(1 << (79 - 64));
- static const SK_OT_ULONG KhmerMask = SkTEndian_SwapBE32(1 << (80 - 64));
- static const SK_OT_ULONG MongolianMask = SkTEndian_SwapBE32(1 << (81 - 64));
- static const SK_OT_ULONG BrailleMask = SkTEndian_SwapBE32(1 << (82 - 64));
- static const SK_OT_ULONG YiMask = SkTEndian_SwapBE32(1 << (83 - 64));
- static const SK_OT_ULONG Tagalog_Hanunoo_Buhid_TagbanwaMask = SkTEndian_SwapBE32(1 << (84 - 64));
- static const SK_OT_ULONG OldItalicMask = SkTEndian_SwapBE32(1 << (85 - 64));
- static const SK_OT_ULONG GothicMask = SkTEndian_SwapBE32(1 << (86 - 64));
- static const SK_OT_ULONG DeseretMask = SkTEndian_SwapBE32(1 << (87 - 64));
- static const SK_OT_ULONG MusicalSymbolsMask = SkTEndian_SwapBE32(1 << (88 - 64));
- static const SK_OT_ULONG MathematicalAlphanumericSymbolsMask = SkTEndian_SwapBE32(1 << (89 - 64));
- static const SK_OT_ULONG PrivateUseMask = SkTEndian_SwapBE32(1 << (90 - 64));
- static const SK_OT_ULONG VariationSelectorsMask = SkTEndian_SwapBE32(1 << (91 - 64));
- static const SK_OT_ULONG TagsMask = SkTEndian_SwapBE32(1 << (92 - 64));
+ static const SK_OT_ULONG CombiningHalfMarksMask = SkOTSetULONGBit<64 - 64>::value;
+ static const SK_OT_ULONG CJKCompatibilityFormsMask = SkOTSetULONGBit<65 - 64>::value;
+ static const SK_OT_ULONG SmallFormVariantsMask = SkOTSetULONGBit<66 - 64>::value;
+ static const SK_OT_ULONG ArabicPresentationFormsBMask = SkOTSetULONGBit<67 - 64>::value;
+ static const SK_OT_ULONG HalfwidthAndFullwidthFormsMask = SkOTSetULONGBit<68 - 64>::value;
+ static const SK_OT_ULONG SpecialsMask = SkOTSetULONGBit<69 - 64>::value;
+ static const SK_OT_ULONG TibetanMask = SkOTSetULONGBit<70 - 64>::value;
+ static const SK_OT_ULONG SyriacMask = SkOTSetULONGBit<71 - 64>::value;
+ static const SK_OT_ULONG ThaanaMask = SkOTSetULONGBit<72 - 64>::value;
+ static const SK_OT_ULONG SinhalaMask = SkOTSetULONGBit<73 - 64>::value;
+ static const SK_OT_ULONG MyanmarMask = SkOTSetULONGBit<74 - 64>::value;
+ static const SK_OT_ULONG EthiopicMask = SkOTSetULONGBit<75 - 64>::value;
+ static const SK_OT_ULONG CherokeeMask = SkOTSetULONGBit<76 - 64>::value;
+ static const SK_OT_ULONG UnifiedCanadianSyllabicsMask = SkOTSetULONGBit<77 - 64>::value;
+ static const SK_OT_ULONG OghamMask = SkOTSetULONGBit<78 - 64>::value;
+ static const SK_OT_ULONG RunicMask = SkOTSetULONGBit<79 - 64>::value;
+ static const SK_OT_ULONG KhmerMask = SkOTSetULONGBit<80 - 64>::value;
+ static const SK_OT_ULONG MongolianMask = SkOTSetULONGBit<81 - 64>::value;
+ static const SK_OT_ULONG BrailleMask = SkOTSetULONGBit<82 - 64>::value;
+ static const SK_OT_ULONG YiMask = SkOTSetULONGBit<83 - 64>::value;
+ static const SK_OT_ULONG Tagalog_Hanunoo_Buhid_TagbanwaMask = SkOTSetULONGBit<84 - 64>::value;
+ static const SK_OT_ULONG OldItalicMask = SkOTSetULONGBit<85 - 64>::value;
+ static const SK_OT_ULONG GothicMask = SkOTSetULONGBit<86 - 64>::value;
+ static const SK_OT_ULONG DeseretMask = SkOTSetULONGBit<87 - 64>::value;
+ static const SK_OT_ULONG MusicalSymbolsMask = SkOTSetULONGBit<88 - 64>::value;
+ static const SK_OT_ULONG MathematicalAlphanumericSymbolsMask = SkOTSetULONGBit<89 - 64>::value;
+ static const SK_OT_ULONG PrivateUseMask = SkOTSetULONGBit<90 - 64>::value;
+ static const SK_OT_ULONG VariationSelectorsMask = SkOTSetULONGBit<91 - 64>::value;
+ static const SK_OT_ULONG TagsMask = SkOTSetULONGBit<92 - 64>::value;
};
SK_OT_ULONG value[4];
} raw;
@@ -389,13 +389,13 @@ struct SkOTTableOS2_V3 {
Reserved07)
} field;
struct Raw {
- static const SK_OT_USHORT ItalicMask = SkTEndian_SwapBE16(1 << 0);
- static const SK_OT_USHORT UnderscoreMask = SkTEndian_SwapBE16(1 << 1);
- static const SK_OT_USHORT NegativeMask = SkTEndian_SwapBE16(1 << 2);
- static const SK_OT_USHORT OutlinedMask = SkTEndian_SwapBE16(1 << 3);
- static const SK_OT_USHORT StrikeoutMask = SkTEndian_SwapBE16(1 << 4);
- static const SK_OT_USHORT BoldMask = SkTEndian_SwapBE16(1 << 5);
- static const SK_OT_USHORT RegularMask = SkTEndian_SwapBE16(1 << 6);
+ static const SK_OT_USHORT ItalicMask = SkOTSetUSHORTBit<0>::value;
+ static const SK_OT_USHORT UnderscoreMask = SkOTSetUSHORTBit<1>::value;
+ static const SK_OT_USHORT NegativeMask = SkOTSetUSHORTBit<2>::value;
+ static const SK_OT_USHORT OutlinedMask = SkOTSetUSHORTBit<3>::value;
+ static const SK_OT_USHORT StrikeoutMask = SkOTSetUSHORTBit<4>::value;
+ static const SK_OT_USHORT BoldMask = SkOTSetUSHORTBit<5>::value;
+ static const SK_OT_USHORT RegularMask = SkOTSetUSHORTBit<6>::value;
SK_OT_USHORT value;
} raw;
} fsSelection;
@@ -494,42 +494,42 @@ struct SkOTTableOS2_V3 {
} field;
struct Raw {
struct l0 {
- static const SK_OT_ULONG Latin1_1252Mask = SkTEndian_SwapBE32(1 << 0);
- static const SK_OT_ULONG Latin2EasternEurope_1250Mask = SkTEndian_SwapBE32(1 << 1);
- static const SK_OT_ULONG Cyrillic_1251Mask = SkTEndian_SwapBE32(1 << 2);
- static const SK_OT_ULONG Greek_1253Mask = SkTEndian_SwapBE32(1 << 3);
- static const SK_OT_ULONG Turkish_1254Mask = SkTEndian_SwapBE32(1 << 4);
- static const SK_OT_ULONG Hebrew_1255Mask = SkTEndian_SwapBE32(1 << 5);
- static const SK_OT_ULONG Arabic_1256Mask = SkTEndian_SwapBE32(1 << 6);
- static const SK_OT_ULONG WindowsBaltic_1257Mask = SkTEndian_SwapBE32(1 << 7);
- static const SK_OT_ULONG Vietnamese_1258Mask = SkTEndian_SwapBE32(1 << 8);
- static const SK_OT_ULONG Thai_874Mask = SkTEndian_SwapBE32(1 << 16);
- static const SK_OT_ULONG JISJapan_932Mask = SkTEndian_SwapBE32(1 << 17);
- static const SK_OT_ULONG ChineseSimplified_936Mask = SkTEndian_SwapBE32(1 << 18);
- static const SK_OT_ULONG KoreanWansung_949Mask = SkTEndian_SwapBE32(1 << 19);
- static const SK_OT_ULONG ChineseTraditional_950Mask = SkTEndian_SwapBE32(1 << 20);
- static const SK_OT_ULONG KoreanJohab_1361Mask = SkTEndian_SwapBE32(1 << 21);
- static const SK_OT_ULONG MacintoshCharacterSetMask = SkTEndian_SwapBE32(1 << 29);
- static const SK_OT_ULONG OEMCharacterSetMask = SkTEndian_SwapBE32(1 << 30);
- static const SK_OT_ULONG SymbolCharacterSetMask = SkTEndian_SwapBE32(1 << 31);
+ static const SK_OT_ULONG Latin1_1252Mask = SkOTSetULONGBit<0>::value;
+ static const SK_OT_ULONG Latin2EasternEurope_1250Mask = SkOTSetULONGBit<1>::value;
+ static const SK_OT_ULONG Cyrillic_1251Mask = SkOTSetULONGBit<2>::value;
+ static const SK_OT_ULONG Greek_1253Mask = SkOTSetULONGBit<3>::value;
+ static const SK_OT_ULONG Turkish_1254Mask = SkOTSetULONGBit<4>::value;
+ static const SK_OT_ULONG Hebrew_1255Mask = SkOTSetULONGBit<5>::value;
+ static const SK_OT_ULONG Arabic_1256Mask = SkOTSetULONGBit<6>::value;
+ static const SK_OT_ULONG WindowsBaltic_1257Mask = SkOTSetULONGBit<7>::value;
+ static const SK_OT_ULONG Vietnamese_1258Mask = SkOTSetULONGBit<8>::value;
+ static const SK_OT_ULONG Thai_874Mask = SkOTSetULONGBit<16>::value;
+ static const SK_OT_ULONG JISJapan_932Mask = SkOTSetULONGBit<17>::value;
+ static const SK_OT_ULONG ChineseSimplified_936Mask = SkOTSetULONGBit<18>::value;
+ static const SK_OT_ULONG KoreanWansung_949Mask = SkOTSetULONGBit<19>::value;
+ static const SK_OT_ULONG ChineseTraditional_950Mask = SkOTSetULONGBit<20>::value;
+ static const SK_OT_ULONG KoreanJohab_1361Mask = SkOTSetULONGBit<21>::value;
+ static const SK_OT_ULONG MacintoshCharacterSetMask = SkOTSetULONGBit<29>::value;
+ static const SK_OT_ULONG OEMCharacterSetMask = SkOTSetULONGBit<30>::value;
+ static const SK_OT_ULONG SymbolCharacterSetMask = SkOTSetULONGBit<31>::value;
};
struct l1 {
- static const SK_OT_ULONG IBMGreek_869Mask = SkTEndian_SwapBE32(1 << (48 - 32));
- static const SK_OT_ULONG MSDOSRussian_866Mask = SkTEndian_SwapBE32(1 << (49 - 32));
- static const SK_OT_ULONG MSDOSNordic_865Mask = SkTEndian_SwapBE32(1 << (50 - 32));
- static const SK_OT_ULONG Arabic_864Mask = SkTEndian_SwapBE32(1 << (51 - 32));
- static const SK_OT_ULONG MSDOSCanadianFrench_863Mask = SkTEndian_SwapBE32(1 << (52 - 32));
- static const SK_OT_ULONG Hebrew_862Mask = SkTEndian_SwapBE32(1 << (53 - 32));
- static const SK_OT_ULONG MSDOSIcelandic_861Mask = SkTEndian_SwapBE32(1 << (54 - 32));
- static const SK_OT_ULONG MSDOSPortuguese_860Mask = SkTEndian_SwapBE32(1 << (55 - 32));
- static const SK_OT_ULONG IBMTurkish_857Mask = SkTEndian_SwapBE32(1 << (56 - 32));
- static const SK_OT_ULONG IBMCyrillic_855Mask = SkTEndian_SwapBE32(1 << (57 - 32));
- static const SK_OT_ULONG Latin2_852Mask = SkTEndian_SwapBE32(1 << (58 - 32));
- static const SK_OT_ULONG MSDOSBaltic_775Mask = SkTEndian_SwapBE32(1 << (59 - 32));
- static const SK_OT_ULONG Greek_737Mask = SkTEndian_SwapBE32(1 << (60 - 32));
- static const SK_OT_ULONG Arabic_708Mask = SkTEndian_SwapBE32(1 << (61 - 32));
- static const SK_OT_ULONG WELatin1_850Mask = SkTEndian_SwapBE32(1 << (62 - 32));
- static const SK_OT_ULONG US_437Mask = SkTEndian_SwapBE32(1 << (63 - 32));
+ static const SK_OT_ULONG IBMGreek_869Mask = SkOTSetULONGBit<48 - 32>::value;
+ static const SK_OT_ULONG MSDOSRussian_866Mask = SkOTSetULONGBit<49 - 32>::value;
+ static const SK_OT_ULONG MSDOSNordic_865Mask = SkOTSetULONGBit<50 - 32>::value;
+ static const SK_OT_ULONG Arabic_864Mask = SkOTSetULONGBit<51 - 32>::value;
+ static const SK_OT_ULONG MSDOSCanadianFrench_863Mask = SkOTSetULONGBit<52 - 32>::value;
+ static const SK_OT_ULONG Hebrew_862Mask = SkOTSetULONGBit<53 - 32>::value;
+ static const SK_OT_ULONG MSDOSIcelandic_861Mask = SkOTSetULONGBit<54 - 32>::value;
+ static const SK_OT_ULONG MSDOSPortuguese_860Mask = SkOTSetULONGBit<55 - 32>::value;
+ static const SK_OT_ULONG IBMTurkish_857Mask = SkOTSetULONGBit<56 - 32>::value;
+ static const SK_OT_ULONG IBMCyrillic_855Mask = SkOTSetULONGBit<57 - 32>::value;
+ static const SK_OT_ULONG Latin2_852Mask = SkOTSetULONGBit<58 - 32>::value;
+ static const SK_OT_ULONG MSDOSBaltic_775Mask = SkOTSetULONGBit<59 - 32>::value;
+ static const SK_OT_ULONG Greek_737Mask = SkOTSetULONGBit<60 - 32>::value;
+ static const SK_OT_ULONG Arabic_708Mask = SkOTSetULONGBit<61 - 32>::value;
+ static const SK_OT_ULONG WELatin1_850Mask = SkOTSetULONGBit<62 - 32>::value;
+ static const SK_OT_ULONG US_437Mask = SkOTSetULONGBit<63 - 32>::value;
};
SK_OT_ULONG value[2];
} raw;
diff --git a/chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_V4.h b/chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_V4.h
index fc6ed5daada..fc64b2257bb 100644
--- a/chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_V4.h
+++ b/chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_V4.h
@@ -74,12 +74,12 @@ struct SkOTTableOS2_V4 {
Reserved07)
} field;
struct Raw {
- static const SK_OT_USHORT Installable = SkTEndian_SwapBE16(0);
- static const SK_OT_USHORT RestrictedMask = SkTEndian_SwapBE16(1 << 1);
- static const SK_OT_USHORT PreviewPrintMask = SkTEndian_SwapBE16(1 << 2);
- static const SK_OT_USHORT EditableMask = SkTEndian_SwapBE16(1 << 3);
- static const SK_OT_USHORT NoSubsettingMask = SkTEndian_SwapBE16(1 << 8);
- static const SK_OT_USHORT BitmapMask = SkTEndian_SwapBE16(1 << 9);
+ static const SK_OT_USHORT Installable = 0;
+ static const SK_OT_USHORT RestrictedMask = SkOTSetUSHORTBit<1>::value;
+ static const SK_OT_USHORT PreviewPrintMask = SkOTSetUSHORTBit<2>::value;
+ static const SK_OT_USHORT EditableMask = SkOTSetUSHORTBit<3>::value;
+ static const SK_OT_USHORT NoSubsettingMask = SkOTSetUSHORTBit<8>::value;
+ static const SK_OT_USHORT BitmapMask = SkOTSetUSHORTBit<9>::value;
SK_OT_USHORT value;
} raw;
} fsType;
@@ -263,135 +263,135 @@ struct SkOTTableOS2_V4 {
} field;
struct Raw {
struct l0 {
- static const SK_OT_ULONG BasicLatinMask = SkTEndian_SwapBE32(1 << 0);
- static const SK_OT_ULONG Latin1SupplementMask = SkTEndian_SwapBE32(1 << 1);
- static const SK_OT_ULONG LatinExtendedAMask = SkTEndian_SwapBE32(1 << 2);
- static const SK_OT_ULONG LatinExtendedBMask = SkTEndian_SwapBE32(1 << 3);
- static const SK_OT_ULONG IPAExtensionsMask = SkTEndian_SwapBE32(1 << 4);
- static const SK_OT_ULONG SpacingModifierLettersMask = SkTEndian_SwapBE32(1 << 5);
- static const SK_OT_ULONG CombiningDiacriticalMarksMask = SkTEndian_SwapBE32(1 << 6);
- static const SK_OT_ULONG GreekAndCopticMask = SkTEndian_SwapBE32(1 << 7);
- static const SK_OT_ULONG CopticMask = SkTEndian_SwapBE32(1 << 8);
- static const SK_OT_ULONG CyrillicMask = SkTEndian_SwapBE32(1 << 9);
- static const SK_OT_ULONG ArmenianMask = SkTEndian_SwapBE32(1 << 10);
- static const SK_OT_ULONG HebrewMask = SkTEndian_SwapBE32(1 << 11);
- static const SK_OT_ULONG VaiMask = SkTEndian_SwapBE32(1 << 12);
- static const SK_OT_ULONG ArabicMask = SkTEndian_SwapBE32(1 << 13);
- static const SK_OT_ULONG NKoMask = SkTEndian_SwapBE32(1 << 14);
- static const SK_OT_ULONG DevanagariMask = SkTEndian_SwapBE32(1 << 15);
- static const SK_OT_ULONG BengaliMask = SkTEndian_SwapBE32(1 << 16);
- static const SK_OT_ULONG GurmukhiMask = SkTEndian_SwapBE32(1 << 17);
- static const SK_OT_ULONG GujaratiMask = SkTEndian_SwapBE32(1 << 18);
- static const SK_OT_ULONG OriyaMask = SkTEndian_SwapBE32(1 << 19);
- static const SK_OT_ULONG TamilMask = SkTEndian_SwapBE32(1 << 20);
- static const SK_OT_ULONG TeluguMask = SkTEndian_SwapBE32(1 << 21);
- static const SK_OT_ULONG KannadaMask = SkTEndian_SwapBE32(1 << 22);
- static const SK_OT_ULONG MalayalamMask = SkTEndian_SwapBE32(1 << 23);
- static const SK_OT_ULONG ThaiMask = SkTEndian_SwapBE32(1 << 24);
- static const SK_OT_ULONG LaoMask = SkTEndian_SwapBE32(1 << 25);
- static const SK_OT_ULONG GeorgianMask = SkTEndian_SwapBE32(1 << 26);
- static const SK_OT_ULONG BalineseMask = SkTEndian_SwapBE32(1 << 27);
- static const SK_OT_ULONG HangulJamoMask = SkTEndian_SwapBE32(1 << 28);
- static const SK_OT_ULONG LatinExtendedAdditionalMask = SkTEndian_SwapBE32(1 << 29);
- static const SK_OT_ULONG GreekExtendedMask = SkTEndian_SwapBE32(1 << 30);
- static const SK_OT_ULONG GeneralPunctuationMask = SkTEndian_SwapBE32(1 << 31);
+ static const SK_OT_ULONG BasicLatinMask = SkOTSetULONGBit<0>::value;
+ static const SK_OT_ULONG Latin1SupplementMask = SkOTSetULONGBit<1>::value;
+ static const SK_OT_ULONG LatinExtendedAMask = SkOTSetULONGBit<2>::value;
+ static const SK_OT_ULONG LatinExtendedBMask = SkOTSetULONGBit<3>::value;
+ static const SK_OT_ULONG IPAExtensionsMask = SkOTSetULONGBit<4>::value;
+ static const SK_OT_ULONG SpacingModifierLettersMask = SkOTSetULONGBit<5>::value;
+ static const SK_OT_ULONG CombiningDiacriticalMarksMask = SkOTSetULONGBit<6>::value;
+ static const SK_OT_ULONG GreekAndCopticMask = SkOTSetULONGBit<7>::value;
+ static const SK_OT_ULONG CopticMask = SkOTSetULONGBit<8>::value;
+ static const SK_OT_ULONG CyrillicMask = SkOTSetULONGBit<9>::value;
+ static const SK_OT_ULONG ArmenianMask = SkOTSetULONGBit<10>::value;
+ static const SK_OT_ULONG HebrewMask = SkOTSetULONGBit<11>::value;
+ static const SK_OT_ULONG VaiMask = SkOTSetULONGBit<12>::value;
+ static const SK_OT_ULONG ArabicMask = SkOTSetULONGBit<13>::value;
+ static const SK_OT_ULONG NKoMask = SkOTSetULONGBit<14>::value;
+ static const SK_OT_ULONG DevanagariMask = SkOTSetULONGBit<15>::value;
+ static const SK_OT_ULONG BengaliMask = SkOTSetULONGBit<16>::value;
+ static const SK_OT_ULONG GurmukhiMask = SkOTSetULONGBit<17>::value;
+ static const SK_OT_ULONG GujaratiMask = SkOTSetULONGBit<18>::value;
+ static const SK_OT_ULONG OriyaMask = SkOTSetULONGBit<19>::value;
+ static const SK_OT_ULONG TamilMask = SkOTSetULONGBit<20>::value;
+ static const SK_OT_ULONG TeluguMask = SkOTSetULONGBit<21>::value;
+ static const SK_OT_ULONG KannadaMask = SkOTSetULONGBit<22>::value;
+ static const SK_OT_ULONG MalayalamMask = SkOTSetULONGBit<23>::value;
+ static const SK_OT_ULONG ThaiMask = SkOTSetULONGBit<24>::value;
+ static const SK_OT_ULONG LaoMask = SkOTSetULONGBit<25>::value;
+ static const SK_OT_ULONG GeorgianMask = SkOTSetULONGBit<26>::value;
+ static const SK_OT_ULONG BalineseMask = SkOTSetULONGBit<27>::value;
+ static const SK_OT_ULONG HangulJamoMask = SkOTSetULONGBit<28>::value;
+ static const SK_OT_ULONG LatinExtendedAdditionalMask = SkOTSetULONGBit<29>::value;
+ static const SK_OT_ULONG GreekExtendedMask = SkOTSetULONGBit<30>::value;
+ static const SK_OT_ULONG GeneralPunctuationMask = SkOTSetULONGBit<31>::value;
};
struct l1 {
- static const SK_OT_ULONG SuperscriptsAndSubscriptsMask = SkTEndian_SwapBE32(1 << (32 - 32));
- static const SK_OT_ULONG CurrencySymbolsMask = SkTEndian_SwapBE32(1 << (33 - 32));
- static const SK_OT_ULONG CombiningDiacriticalMarksForSymbolsMask = SkTEndian_SwapBE32(1 << (34 - 32));
- static const SK_OT_ULONG LetterlikeSymbolsMask = SkTEndian_SwapBE32(1 << (35 - 32));
- static const SK_OT_ULONG NumberFormsMask = SkTEndian_SwapBE32(1 << (36 - 32));
- static const SK_OT_ULONG ArrowsMask = SkTEndian_SwapBE32(1 << (37 - 32));
- static const SK_OT_ULONG MathematicalOperatorsMask = SkTEndian_SwapBE32(1 << (38 - 32));
- static const SK_OT_ULONG MiscellaneousTechnicalMask = SkTEndian_SwapBE32(1 << (39 - 32));
- static const SK_OT_ULONG ControlPicturesMask = SkTEndian_SwapBE32(1 << (40 - 32));
- static const SK_OT_ULONG OpticalCharacterRecognitionMask = SkTEndian_SwapBE32(1 << (41 - 32));
- static const SK_OT_ULONG EnclosedAlphanumericsMask = SkTEndian_SwapBE32(1 << (42 - 32));
- static const SK_OT_ULONG BoxDrawingMask = SkTEndian_SwapBE32(1 << (43 - 32));
- static const SK_OT_ULONG BlockElementsMask = SkTEndian_SwapBE32(1 << (44 - 32));
- static const SK_OT_ULONG GeometricShapesMask = SkTEndian_SwapBE32(1 << (45 - 32));
- static const SK_OT_ULONG MiscellaneousSymbolsMask = SkTEndian_SwapBE32(1 << (46 - 32));
- static const SK_OT_ULONG DingbatsMask = SkTEndian_SwapBE32(1 << (47 - 32));
- static const SK_OT_ULONG CJKSymbolsAndPunctuationMask = SkTEndian_SwapBE32(1 << (48 - 32));
- static const SK_OT_ULONG HiraganaMask = SkTEndian_SwapBE32(1 << (49 - 32));
- static const SK_OT_ULONG KatakanaMask = SkTEndian_SwapBE32(1 << (50 - 32));
- static const SK_OT_ULONG BopomofoMask = SkTEndian_SwapBE32(1 << (51 - 32));
- static const SK_OT_ULONG HangulCompatibilityJamoMask = SkTEndian_SwapBE32(1 << (52 - 32));
- static const SK_OT_ULONG PhagsPaMask = SkTEndian_SwapBE32(1 << (53 - 32));
- static const SK_OT_ULONG EnclosedCJKLettersAndMonthsMask = SkTEndian_SwapBE32(1 << (54 - 32));
- static const SK_OT_ULONG CJKCompatibilityMask = SkTEndian_SwapBE32(1 << (55 - 32));
- static const SK_OT_ULONG HangulMask = SkTEndian_SwapBE32(1 << (56 - 32));
- static const SK_OT_ULONG NonPlane0Mask = SkTEndian_SwapBE32(1 << (57 - 32));
- static const SK_OT_ULONG PhoenicianMask = SkTEndian_SwapBE32(1 << (58 - 32));
- static const SK_OT_ULONG CJKUnifiedIdeographsMask = SkTEndian_SwapBE32(1 << (59 - 32));
- static const SK_OT_ULONG PrivateUseAreaMask = SkTEndian_SwapBE32(1 << (60 - 32));
- static const SK_OT_ULONG CJKCompatibilityIdeographsMask = SkTEndian_SwapBE32(1 << (61 - 32));
- static const SK_OT_ULONG AlphabeticPresentationFormsMask = SkTEndian_SwapBE32(1 << (62 - 32));
- static const SK_OT_ULONG ArabicPresentationFormsAMask = SkTEndian_SwapBE32(1 << (63 - 32));
+ static const SK_OT_ULONG SuperscriptsAndSubscriptsMask = SkOTSetULONGBit<32 - 32>::value;
+ static const SK_OT_ULONG CurrencySymbolsMask = SkOTSetULONGBit<33 - 32>::value;
+ static const SK_OT_ULONG CombiningDiacriticalMarksForSymbolsMask = SkOTSetULONGBit<34 - 32>::value;
+ static const SK_OT_ULONG LetterlikeSymbolsMask = SkOTSetULONGBit<35 - 32>::value;
+ static const SK_OT_ULONG NumberFormsMask = SkOTSetULONGBit<36 - 32>::value;
+ static const SK_OT_ULONG ArrowsMask = SkOTSetULONGBit<37 - 32>::value;
+ static const SK_OT_ULONG MathematicalOperatorsMask = SkOTSetULONGBit<38 - 32>::value;
+ static const SK_OT_ULONG MiscellaneousTechnicalMask = SkOTSetULONGBit<39 - 32>::value;
+ static const SK_OT_ULONG ControlPicturesMask = SkOTSetULONGBit<40 - 32>::value;
+ static const SK_OT_ULONG OpticalCharacterRecognitionMask = SkOTSetULONGBit<41 - 32>::value;
+ static const SK_OT_ULONG EnclosedAlphanumericsMask = SkOTSetULONGBit<42 - 32>::value;
+ static const SK_OT_ULONG BoxDrawingMask = SkOTSetULONGBit<43 - 32>::value;
+ static const SK_OT_ULONG BlockElementsMask = SkOTSetULONGBit<44 - 32>::value;
+ static const SK_OT_ULONG GeometricShapesMask = SkOTSetULONGBit<45 - 32>::value;
+ static const SK_OT_ULONG MiscellaneousSymbolsMask = SkOTSetULONGBit<46 - 32>::value;
+ static const SK_OT_ULONG DingbatsMask = SkOTSetULONGBit<47 - 32>::value;
+ static const SK_OT_ULONG CJKSymbolsAndPunctuationMask = SkOTSetULONGBit<48 - 32>::value;
+ static const SK_OT_ULONG HiraganaMask = SkOTSetULONGBit<49 - 32>::value;
+ static const SK_OT_ULONG KatakanaMask = SkOTSetULONGBit<50 - 32>::value;
+ static const SK_OT_ULONG BopomofoMask = SkOTSetULONGBit<51 - 32>::value;
+ static const SK_OT_ULONG HangulCompatibilityJamoMask = SkOTSetULONGBit<52 - 32>::value;
+ static const SK_OT_ULONG PhagsPaMask = SkOTSetULONGBit<53 - 32>::value;
+ static const SK_OT_ULONG EnclosedCJKLettersAndMonthsMask = SkOTSetULONGBit<54 - 32>::value;
+ static const SK_OT_ULONG CJKCompatibilityMask = SkOTSetULONGBit<55 - 32>::value;
+ static const SK_OT_ULONG HangulMask = SkOTSetULONGBit<56 - 32>::value;
+ static const SK_OT_ULONG NonPlane0Mask = SkOTSetULONGBit<57 - 32>::value;
+ static const SK_OT_ULONG PhoenicianMask = SkOTSetULONGBit<58 - 32>::value;
+ static const SK_OT_ULONG CJKUnifiedIdeographsMask = SkOTSetULONGBit<59 - 32>::value;
+ static const SK_OT_ULONG PrivateUseAreaMask = SkOTSetULONGBit<60 - 32>::value;
+ static const SK_OT_ULONG CJKCompatibilityIdeographsMask = SkOTSetULONGBit<61 - 32>::value;
+ static const SK_OT_ULONG AlphabeticPresentationFormsMask = SkOTSetULONGBit<62 - 32>::value;
+ static const SK_OT_ULONG ArabicPresentationFormsAMask = SkOTSetULONGBit<63 - 32>::value;
};
struct l2 {
- static const SK_OT_ULONG CombiningHalfMarksMask = SkTEndian_SwapBE32(1 << (64 - 64));
- static const SK_OT_ULONG CJKCompatibilityFormsMask = SkTEndian_SwapBE32(1 << (65 - 64));
- static const SK_OT_ULONG SmallFormVariantsMask = SkTEndian_SwapBE32(1 << (66 - 64));
- static const SK_OT_ULONG ArabicPresentationFormsBMask = SkTEndian_SwapBE32(1 << (67 - 64));
- static const SK_OT_ULONG HalfwidthAndFullwidthFormsMask = SkTEndian_SwapBE32(1 << (68 - 64));
- static const SK_OT_ULONG SpecialsMask = SkTEndian_SwapBE32(1 << (69 - 64));
- static const SK_OT_ULONG TibetanMask = SkTEndian_SwapBE32(1 << (70 - 64));
- static const SK_OT_ULONG SyriacMask = SkTEndian_SwapBE32(1 << (71 - 64));
- static const SK_OT_ULONG ThaanaMask = SkTEndian_SwapBE32(1 << (72 - 64));
- static const SK_OT_ULONG SinhalaMask = SkTEndian_SwapBE32(1 << (73 - 64));
- static const SK_OT_ULONG MyanmarMask = SkTEndian_SwapBE32(1 << (74 - 64));
- static const SK_OT_ULONG EthiopicMask = SkTEndian_SwapBE32(1 << (75 - 64));
- static const SK_OT_ULONG CherokeeMask = SkTEndian_SwapBE32(1 << (76 - 64));
- static const SK_OT_ULONG UnifiedCanadianSyllabicsMask = SkTEndian_SwapBE32(1 << (77 - 64));
- static const SK_OT_ULONG OghamMask = SkTEndian_SwapBE32(1 << (78 - 64));
- static const SK_OT_ULONG RunicMask = SkTEndian_SwapBE32(1 << (79 - 64));
- static const SK_OT_ULONG KhmerMask = SkTEndian_SwapBE32(1 << (80 - 64));
- static const SK_OT_ULONG MongolianMask = SkTEndian_SwapBE32(1 << (81 - 64));
- static const SK_OT_ULONG BrailleMask = SkTEndian_SwapBE32(1 << (82 - 64));
- static const SK_OT_ULONG YiMask = SkTEndian_SwapBE32(1 << (83 - 64));
- static const SK_OT_ULONG Tagalog_Hanunoo_Buhid_TagbanwaMask = SkTEndian_SwapBE32(1 << (84 - 64));
- static const SK_OT_ULONG OldItalicMask = SkTEndian_SwapBE32(1 << (85 - 64));
- static const SK_OT_ULONG GothicMask = SkTEndian_SwapBE32(1 << (86 - 64));
- static const SK_OT_ULONG DeseretMask = SkTEndian_SwapBE32(1 << (87 - 64));
- static const SK_OT_ULONG MusicalSymbolsMask = SkTEndian_SwapBE32(1 << (88 - 64));
- static const SK_OT_ULONG MathematicalAlphanumericSymbolsMask = SkTEndian_SwapBE32(1 << (89 - 64));
- static const SK_OT_ULONG PrivateUseMask = SkTEndian_SwapBE32(1 << (90 - 64));
- static const SK_OT_ULONG VariationSelectorsMask = SkTEndian_SwapBE32(1 << (91 - 64));
- static const SK_OT_ULONG TagsMask = SkTEndian_SwapBE32(1 << (92 - 64));
- static const SK_OT_ULONG LimbuMask = SkTEndian_SwapBE32(1 << (93 - 64));
- static const SK_OT_ULONG TaiLeMask = SkTEndian_SwapBE32(1 << (94 - 64));
- static const SK_OT_ULONG NewTaiLueMask = SkTEndian_SwapBE32(1 << (95 - 64));
+ static const SK_OT_ULONG CombiningHalfMarksMask = SkOTSetULONGBit<64 - 64>::value;
+ static const SK_OT_ULONG CJKCompatibilityFormsMask = SkOTSetULONGBit<65 - 64>::value;
+ static const SK_OT_ULONG SmallFormVariantsMask = SkOTSetULONGBit<66 - 64>::value;
+ static const SK_OT_ULONG ArabicPresentationFormsBMask = SkOTSetULONGBit<67 - 64>::value;
+ static const SK_OT_ULONG HalfwidthAndFullwidthFormsMask = SkOTSetULONGBit<68 - 64>::value;
+ static const SK_OT_ULONG SpecialsMask = SkOTSetULONGBit<69 - 64>::value;
+ static const SK_OT_ULONG TibetanMask = SkOTSetULONGBit<70 - 64>::value;
+ static const SK_OT_ULONG SyriacMask = SkOTSetULONGBit<71 - 64>::value;
+ static const SK_OT_ULONG ThaanaMask = SkOTSetULONGBit<72 - 64>::value;
+ static const SK_OT_ULONG SinhalaMask = SkOTSetULONGBit<73 - 64>::value;
+ static const SK_OT_ULONG MyanmarMask = SkOTSetULONGBit<74 - 64>::value;
+ static const SK_OT_ULONG EthiopicMask = SkOTSetULONGBit<75 - 64>::value;
+ static const SK_OT_ULONG CherokeeMask = SkOTSetULONGBit<76 - 64>::value;
+ static const SK_OT_ULONG UnifiedCanadianSyllabicsMask = SkOTSetULONGBit<77 - 64>::value;
+ static const SK_OT_ULONG OghamMask = SkOTSetULONGBit<78 - 64>::value;
+ static const SK_OT_ULONG RunicMask = SkOTSetULONGBit<79 - 64>::value;
+ static const SK_OT_ULONG KhmerMask = SkOTSetULONGBit<80 - 64>::value;
+ static const SK_OT_ULONG MongolianMask = SkOTSetULONGBit<81 - 64>::value;
+ static const SK_OT_ULONG BrailleMask = SkOTSetULONGBit<82 - 64>::value;
+ static const SK_OT_ULONG YiMask = SkOTSetULONGBit<83 - 64>::value;
+ static const SK_OT_ULONG Tagalog_Hanunoo_Buhid_TagbanwaMask = SkOTSetULONGBit<84 - 64>::value;
+ static const SK_OT_ULONG OldItalicMask = SkOTSetULONGBit<85 - 64>::value;
+ static const SK_OT_ULONG GothicMask = SkOTSetULONGBit<86 - 64>::value;
+ static const SK_OT_ULONG DeseretMask = SkOTSetULONGBit<87 - 64>::value;
+ static const SK_OT_ULONG MusicalSymbolsMask = SkOTSetULONGBit<88 - 64>::value;
+ static const SK_OT_ULONG MathematicalAlphanumericSymbolsMask = SkOTSetULONGBit<89 - 64>::value;
+ static const SK_OT_ULONG PrivateUseMask = SkOTSetULONGBit<90 - 64>::value;
+ static const SK_OT_ULONG VariationSelectorsMask = SkOTSetULONGBit<91 - 64>::value;
+ static const SK_OT_ULONG TagsMask = SkOTSetULONGBit<92 - 64>::value;
+ static const SK_OT_ULONG LimbuMask = SkOTSetULONGBit<93 - 64>::value;
+ static const SK_OT_ULONG TaiLeMask = SkOTSetULONGBit<94 - 64>::value;
+ static const SK_OT_ULONG NewTaiLueMask = SkOTSetULONGBit<95 - 64>::value;
};
struct l3 {
- static const SK_OT_ULONG BugineseMask = SkTEndian_SwapBE32(1 << (96 - 96));
- static const SK_OT_ULONG GlagoliticMask = SkTEndian_SwapBE32(1 << (97 - 96));
- static const SK_OT_ULONG TifinaghMask = SkTEndian_SwapBE32(1 << (98 - 96));
- static const SK_OT_ULONG YijingHexagramSymbolsMask = SkTEndian_SwapBE32(1 << (99 - 96));
- static const SK_OT_ULONG SylotiNagriMask = SkTEndian_SwapBE32(1 << (100 - 96));
- static const SK_OT_ULONG LinearB_AegeanNumbersMask = SkTEndian_SwapBE32(1 << (101 - 96));
- static const SK_OT_ULONG AncientGreekNumbersMask = SkTEndian_SwapBE32(1 << (102 - 96));
- static const SK_OT_ULONG UgariticMask = SkTEndian_SwapBE32(1 << (103 - 96));
- static const SK_OT_ULONG OldPersianMask = SkTEndian_SwapBE32(1 << (104 - 96));
- static const SK_OT_ULONG ShavianMask = SkTEndian_SwapBE32(1 << (105 - 96));
- static const SK_OT_ULONG OsmanyaMask = SkTEndian_SwapBE32(1 << (106 - 96));
- static const SK_OT_ULONG CypriotSyllabaryMask = SkTEndian_SwapBE32(1 << (107 - 96));
- static const SK_OT_ULONG KharoshthiMask = SkTEndian_SwapBE32(1 << (108 - 96));
- static const SK_OT_ULONG TaiXuanJingSymbolsMask = SkTEndian_SwapBE32(1 << (109 - 96));
- static const SK_OT_ULONG CuneiformMask = SkTEndian_SwapBE32(1 << (110 - 96));
- static const SK_OT_ULONG CountingRodNumeralsMask = SkTEndian_SwapBE32(1 << (111 - 96));
- static const SK_OT_ULONG SundaneseMask = SkTEndian_SwapBE32(1 << (112 - 96));
- static const SK_OT_ULONG LepchaMask = SkTEndian_SwapBE32(1 << (113 - 96));
- static const SK_OT_ULONG OlChikiMask = SkTEndian_SwapBE32(1 << (114 - 96));
- static const SK_OT_ULONG SaurashtraMask = SkTEndian_SwapBE32(1 << (115 - 96));
- static const SK_OT_ULONG KayahLiMask = SkTEndian_SwapBE32(1 << (116 - 96));
- static const SK_OT_ULONG RejangMask = SkTEndian_SwapBE32(1 << (117 - 96));
- static const SK_OT_ULONG ChamMask = SkTEndian_SwapBE32(1 << (118 - 96));
- static const SK_OT_ULONG AncientSymbolsMask = SkTEndian_SwapBE32(1 << (119 - 96));
- static const SK_OT_ULONG PhaistosDiscMask = SkTEndian_SwapBE32(1 << (120 - 96));
- static const SK_OT_ULONG Carian_Lycian_LydianMask = SkTEndian_SwapBE32(1 << (121 - 96));
- static const SK_OT_ULONG DominoTiles_MahjongTilesMask = SkTEndian_SwapBE32(1 << (122 - 96));
+ static const SK_OT_ULONG BugineseMask = SkOTSetULONGBit<96 - 96>::value;
+ static const SK_OT_ULONG GlagoliticMask = SkOTSetULONGBit<97 - 96>::value;
+ static const SK_OT_ULONG TifinaghMask = SkOTSetULONGBit<98 - 96>::value;
+ static const SK_OT_ULONG YijingHexagramSymbolsMask = SkOTSetULONGBit<99 - 96>::value;
+ static const SK_OT_ULONG SylotiNagriMask = SkOTSetULONGBit<100 - 96>::value;
+ static const SK_OT_ULONG LinearB_AegeanNumbersMask = SkOTSetULONGBit<101 - 96>::value;
+ static const SK_OT_ULONG AncientGreekNumbersMask = SkOTSetULONGBit<102 - 96>::value;
+ static const SK_OT_ULONG UgariticMask = SkOTSetULONGBit<103 - 96>::value;
+ static const SK_OT_ULONG OldPersianMask = SkOTSetULONGBit<104 - 96>::value;
+ static const SK_OT_ULONG ShavianMask = SkOTSetULONGBit<105 - 96>::value;
+ static const SK_OT_ULONG OsmanyaMask = SkOTSetULONGBit<106 - 96>::value;
+ static const SK_OT_ULONG CypriotSyllabaryMask = SkOTSetULONGBit<107 - 96>::value;
+ static const SK_OT_ULONG KharoshthiMask = SkOTSetULONGBit<108 - 96>::value;
+ static const SK_OT_ULONG TaiXuanJingSymbolsMask = SkOTSetULONGBit<109 - 96>::value;
+ static const SK_OT_ULONG CuneiformMask = SkOTSetULONGBit<110 - 96>::value;
+ static const SK_OT_ULONG CountingRodNumeralsMask = SkOTSetULONGBit<111 - 96>::value;
+ static const SK_OT_ULONG SundaneseMask = SkOTSetULONGBit<112 - 96>::value;
+ static const SK_OT_ULONG LepchaMask = SkOTSetULONGBit<113 - 96>::value;
+ static const SK_OT_ULONG OlChikiMask = SkOTSetULONGBit<114 - 96>::value;
+ static const SK_OT_ULONG SaurashtraMask = SkOTSetULONGBit<115 - 96>::value;
+ static const SK_OT_ULONG KayahLiMask = SkOTSetULONGBit<116 - 96>::value;
+ static const SK_OT_ULONG RejangMask = SkOTSetULONGBit<117 - 96>::value;
+ static const SK_OT_ULONG ChamMask = SkOTSetULONGBit<118 - 96>::value;
+ static const SK_OT_ULONG AncientSymbolsMask = SkOTSetULONGBit<119 - 96>::value;
+ static const SK_OT_ULONG PhaistosDiscMask = SkOTSetULONGBit<120 - 96>::value;
+ static const SK_OT_ULONG Carian_Lycian_LydianMask = SkOTSetULONGBit<121 - 96>::value;
+ static const SK_OT_ULONG DominoTiles_MahjongTilesMask = SkOTSetULONGBit<122 - 96>::value;
};
SK_OT_ULONG value[4];
} raw;
@@ -421,16 +421,16 @@ struct SkOTTableOS2_V4 {
UseTypoMetrics)
} field;
struct Raw {
- static const SK_OT_USHORT ItalicMask = SkTEndian_SwapBE16(1 << 0);
- static const SK_OT_USHORT UnderscoreMask = SkTEndian_SwapBE16(1 << 1);
- static const SK_OT_USHORT NegativeMask = SkTEndian_SwapBE16(1 << 2);
- static const SK_OT_USHORT OutlinedMask = SkTEndian_SwapBE16(1 << 3);
- static const SK_OT_USHORT StrikeoutMask = SkTEndian_SwapBE16(1 << 4);
- static const SK_OT_USHORT BoldMask = SkTEndian_SwapBE16(1 << 5);
- static const SK_OT_USHORT RegularMask = SkTEndian_SwapBE16(1 << 6);
- static const SK_OT_USHORT UseTypoMetricsMask = SkTEndian_SwapBE16(1 << 7);
- static const SK_OT_USHORT WWSMask = SkTEndian_SwapBE16(1 << 8);
- static const SK_OT_USHORT ObliqueMask = SkTEndian_SwapBE16(1 << 9);
+ static const SK_OT_USHORT ItalicMask = SkOTSetUSHORTBit<0>::value;
+ static const SK_OT_USHORT UnderscoreMask = SkOTSetUSHORTBit<1>::value;
+ static const SK_OT_USHORT NegativeMask = SkOTSetUSHORTBit<2>::value;
+ static const SK_OT_USHORT OutlinedMask = SkOTSetUSHORTBit<3>::value;
+ static const SK_OT_USHORT StrikeoutMask = SkOTSetUSHORTBit<4>::value;
+ static const SK_OT_USHORT BoldMask = SkOTSetUSHORTBit<5>::value;
+ static const SK_OT_USHORT RegularMask = SkOTSetUSHORTBit<6>::value;
+ static const SK_OT_USHORT UseTypoMetricsMask = SkOTSetUSHORTBit<7>::value;
+ static const SK_OT_USHORT WWSMask = SkOTSetUSHORTBit<8>::value;
+ static const SK_OT_USHORT ObliqueMask = SkOTSetUSHORTBit<9>::value;
SK_OT_USHORT value;
} raw;
} fsSelection;
@@ -529,42 +529,42 @@ struct SkOTTableOS2_V4 {
} field;
struct Raw {
struct l0 {
- static const SK_OT_ULONG Latin1_1252Mask = SkTEndian_SwapBE32(1 << 0);
- static const SK_OT_ULONG Latin2EasternEurope_1250Mask = SkTEndian_SwapBE32(1 << 1);
- static const SK_OT_ULONG Cyrillic_1251Mask = SkTEndian_SwapBE32(1 << 2);
- static const SK_OT_ULONG Greek_1253Mask = SkTEndian_SwapBE32(1 << 3);
- static const SK_OT_ULONG Turkish_1254Mask = SkTEndian_SwapBE32(1 << 4);
- static const SK_OT_ULONG Hebrew_1255Mask = SkTEndian_SwapBE32(1 << 5);
- static const SK_OT_ULONG Arabic_1256Mask = SkTEndian_SwapBE32(1 << 6);
- static const SK_OT_ULONG WindowsBaltic_1257Mask = SkTEndian_SwapBE32(1 << 7);
- static const SK_OT_ULONG Vietnamese_1258Mask = SkTEndian_SwapBE32(1 << 8);
- static const SK_OT_ULONG Thai_874Mask = SkTEndian_SwapBE32(1 << 16);
- static const SK_OT_ULONG JISJapan_932Mask = SkTEndian_SwapBE32(1 << 17);
- static const SK_OT_ULONG ChineseSimplified_936Mask = SkTEndian_SwapBE32(1 << 18);
- static const SK_OT_ULONG KoreanWansung_949Mask = SkTEndian_SwapBE32(1 << 19);
- static const SK_OT_ULONG ChineseTraditional_950Mask = SkTEndian_SwapBE32(1 << 20);
- static const SK_OT_ULONG KoreanJohab_1361Mask = SkTEndian_SwapBE32(1 << 21);
- static const SK_OT_ULONG MacintoshCharacterSetMask = SkTEndian_SwapBE32(1 << 29);
- static const SK_OT_ULONG OEMCharacterSetMask = SkTEndian_SwapBE32(1 << 30);
- static const SK_OT_ULONG SymbolCharacterSetMask = SkTEndian_SwapBE32(1 << 31);
+ static const SK_OT_ULONG Latin1_1252Mask = SkOTSetULONGBit<0>::value;
+ static const SK_OT_ULONG Latin2EasternEurope_1250Mask = SkOTSetULONGBit<1>::value;
+ static const SK_OT_ULONG Cyrillic_1251Mask = SkOTSetULONGBit<2>::value;
+ static const SK_OT_ULONG Greek_1253Mask = SkOTSetULONGBit<3>::value;
+ static const SK_OT_ULONG Turkish_1254Mask = SkOTSetULONGBit<4>::value;
+ static const SK_OT_ULONG Hebrew_1255Mask = SkOTSetULONGBit<5>::value;
+ static const SK_OT_ULONG Arabic_1256Mask = SkOTSetULONGBit<6>::value;
+ static const SK_OT_ULONG WindowsBaltic_1257Mask = SkOTSetULONGBit<7>::value;
+ static const SK_OT_ULONG Vietnamese_1258Mask = SkOTSetULONGBit<8>::value;
+ static const SK_OT_ULONG Thai_874Mask = SkOTSetULONGBit<16>::value;
+ static const SK_OT_ULONG JISJapan_932Mask = SkOTSetULONGBit<17>::value;
+ static const SK_OT_ULONG ChineseSimplified_936Mask = SkOTSetULONGBit<18>::value;
+ static const SK_OT_ULONG KoreanWansung_949Mask = SkOTSetULONGBit<19>::value;
+ static const SK_OT_ULONG ChineseTraditional_950Mask = SkOTSetULONGBit<20>::value;
+ static const SK_OT_ULONG KoreanJohab_1361Mask = SkOTSetULONGBit<21>::value;
+ static const SK_OT_ULONG MacintoshCharacterSetMask = SkOTSetULONGBit<29>::value;
+ static const SK_OT_ULONG OEMCharacterSetMask = SkOTSetULONGBit<30>::value;
+ static const SK_OT_ULONG SymbolCharacterSetMask = SkOTSetULONGBit<31>::value;
};
struct l1 {
- static const SK_OT_ULONG IBMGreek_869Mask = SkTEndian_SwapBE32(1 << (48 - 32));
- static const SK_OT_ULONG MSDOSRussian_866Mask = SkTEndian_SwapBE32(1 << (49 - 32));
- static const SK_OT_ULONG MSDOSNordic_865Mask = SkTEndian_SwapBE32(1 << (50 - 32));
- static const SK_OT_ULONG Arabic_864Mask = SkTEndian_SwapBE32(1 << (51 - 32));
- static const SK_OT_ULONG MSDOSCanadianFrench_863Mask = SkTEndian_SwapBE32(1 << (52 - 32));
- static const SK_OT_ULONG Hebrew_862Mask = SkTEndian_SwapBE32(1 << (53 - 32));
- static const SK_OT_ULONG MSDOSIcelandic_861Mask = SkTEndian_SwapBE32(1 << (54 - 32));
- static const SK_OT_ULONG MSDOSPortuguese_860Mask = SkTEndian_SwapBE32(1 << (55 - 32));
- static const SK_OT_ULONG IBMTurkish_857Mask = SkTEndian_SwapBE32(1 << (56 - 32));
- static const SK_OT_ULONG IBMCyrillic_855Mask = SkTEndian_SwapBE32(1 << (57 - 32));
- static const SK_OT_ULONG Latin2_852Mask = SkTEndian_SwapBE32(1 << (58 - 32));
- static const SK_OT_ULONG MSDOSBaltic_775Mask = SkTEndian_SwapBE32(1 << (59 - 32));
- static const SK_OT_ULONG Greek_737Mask = SkTEndian_SwapBE32(1 << (60 - 32));
- static const SK_OT_ULONG Arabic_708Mask = SkTEndian_SwapBE32(1 << (61 - 32));
- static const SK_OT_ULONG WELatin1_850Mask = SkTEndian_SwapBE32(1 << (62 - 32));
- static const SK_OT_ULONG US_437Mask = SkTEndian_SwapBE32(1 << (63 - 32));
+ static const SK_OT_ULONG IBMGreek_869Mask = SkOTSetULONGBit<48 - 32>::value;
+ static const SK_OT_ULONG MSDOSRussian_866Mask = SkOTSetULONGBit<49 - 32>::value;
+ static const SK_OT_ULONG MSDOSNordic_865Mask = SkOTSetULONGBit<50 - 32>::value;
+ static const SK_OT_ULONG Arabic_864Mask = SkOTSetULONGBit<51 - 32>::value;
+ static const SK_OT_ULONG MSDOSCanadianFrench_863Mask = SkOTSetULONGBit<52 - 32>::value;
+ static const SK_OT_ULONG Hebrew_862Mask = SkOTSetULONGBit<53 - 32>::value;
+ static const SK_OT_ULONG MSDOSIcelandic_861Mask = SkOTSetULONGBit<54 - 32>::value;
+ static const SK_OT_ULONG MSDOSPortuguese_860Mask = SkOTSetULONGBit<55 - 32>::value;
+ static const SK_OT_ULONG IBMTurkish_857Mask = SkOTSetULONGBit<56 - 32>::value;
+ static const SK_OT_ULONG IBMCyrillic_855Mask = SkOTSetULONGBit<57 - 32>::value;
+ static const SK_OT_ULONG Latin2_852Mask = SkOTSetULONGBit<58 - 32>::value;
+ static const SK_OT_ULONG MSDOSBaltic_775Mask = SkOTSetULONGBit<59 - 32>::value;
+ static const SK_OT_ULONG Greek_737Mask = SkOTSetULONGBit<60 - 32>::value;
+ static const SK_OT_ULONG Arabic_708Mask = SkOTSetULONGBit<61 - 32>::value;
+ static const SK_OT_ULONG WELatin1_850Mask = SkOTSetULONGBit<62 - 32>::value;
+ static const SK_OT_ULONG US_437Mask = SkOTSetULONGBit<63 - 32>::value;
};
SK_OT_ULONG value[2];
} raw;
diff --git a/chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_VA.h b/chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_VA.h
index 146e83b67e7..bc45da20217 100644
--- a/chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_VA.h
+++ b/chromium/third_party/skia/src/sfnt/SkOTTable_OS_2_VA.h
@@ -76,10 +76,10 @@ struct SkOTTableOS2_VA {
Reserved07)
} field;
struct Raw {
- static const SK_OT_USHORT Installable = SkTEndian_SwapBE16(0);
- static const SK_OT_USHORT RestrictedMask = SkTEndian_SwapBE16(1 << 1);
- static const SK_OT_USHORT PreviewPrintMask = SkTEndian_SwapBE16(1 << 2);
- static const SK_OT_USHORT EditableMask = SkTEndian_SwapBE16(1 << 3);
+ static const SK_OT_USHORT Installable = 0;
+ static const SK_OT_USHORT RestrictedMask = SkOTSetUSHORTBit<1>::value;
+ static const SK_OT_USHORT PreviewPrintMask = SkOTSetUSHORTBit<2>::value;
+ static const SK_OT_USHORT EditableMask = SkOTSetUSHORTBit<3>::value;
SK_OT_USHORT value;
} raw;
} fsType;
@@ -121,12 +121,12 @@ struct SkOTTableOS2_VA {
Reserved07)
} field;
struct Raw {
- static const SK_OT_USHORT ItalicMask = SkTEndian_SwapBE16(1 << 0);
- static const SK_OT_USHORT UnderscoreMask = SkTEndian_SwapBE16(1 << 1);
- static const SK_OT_USHORT NegativeMask = SkTEndian_SwapBE16(1 << 2);
- static const SK_OT_USHORT OutlinedMask = SkTEndian_SwapBE16(1 << 3);
- static const SK_OT_USHORT StrikeoutMask = SkTEndian_SwapBE16(1 << 4);
- static const SK_OT_USHORT BoldMask = SkTEndian_SwapBE16(1 << 5);
+ static const SK_OT_USHORT ItalicMask = SkOTSetUSHORTBit<0>::value;
+ static const SK_OT_USHORT UnderscoreMask = SkOTSetUSHORTBit<1>::value;
+ static const SK_OT_USHORT NegativeMask = SkOTSetUSHORTBit<2>::value;
+ static const SK_OT_USHORT OutlinedMask = SkOTSetUSHORTBit<3>::value;
+ static const SK_OT_USHORT StrikeoutMask = SkOTSetUSHORTBit<4>::value;
+ static const SK_OT_USHORT BoldMask = SkOTSetUSHORTBit<5>::value;
SK_OT_USHORT value;
} raw;
} fsSelection;
diff --git a/chromium/third_party/skia/src/sfnt/SkOTTable_gasp.h b/chromium/third_party/skia/src/sfnt/SkOTTable_gasp.h
new file mode 100644
index 00000000000..ca2d265e22e
--- /dev/null
+++ b/chromium/third_party/skia/src/sfnt/SkOTTable_gasp.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkOTTable_gasp_DEFINED
+#define SkOTTable_gasp_DEFINED
+
+#include "SkEndian.h"
+#include "SkOTTableTypes.h"
+#include "SkTypedEnum.h"
+
+#pragma pack(push, 1)
+
+struct SkOTTableGridAndScanProcedure {
+ static const SK_OT_CHAR TAG0 = 'g';
+ static const SK_OT_CHAR TAG1 = 'a';
+ static const SK_OT_CHAR TAG2 = 's';
+ static const SK_OT_CHAR TAG3 = 'p';
+ static const SK_OT_ULONG TAG = SkOTTableTAG<SkOTTableGridAndScanProcedure>::value;
+
+ SK_OT_USHORT version;
+ static const SK_OT_USHORT version0 = SkTEndian_SwapBE16(0);
+ static const SK_OT_USHORT version1 = SkTEndian_SwapBE16(1);
+
+ SK_OT_USHORT numRanges;
+
+ struct GaspRange {
+ SK_OT_USHORT maxPPEM;
+ union behavior {
+ struct Field {
+ //8-15
+ SK_OT_BYTE_BITFIELD(
+ Reserved08,
+ Reserved09,
+ Reserved10,
+ Reserved11,
+ Reserved12,
+ Reserved13,
+ Reserved14,
+ Reserved15)
+ //0-7
+ SK_OT_BYTE_BITFIELD(
+ Gridfit,
+ DoGray,
+ SymmetricGridfit, // Version 1
+ SymmetricSmoothing, // Version 1
+ Reserved04,
+ Reserved05,
+ Reserved06,
+ Reserved07)
+ } field;
+ struct Raw {
+ static const SK_OT_USHORT GridfitMask = SkTEndian_SwapBE16(1 << 0);
+ static const SK_OT_USHORT DoGrayMask = SkTEndian_SwapBE16(1 << 1);
+ static const SK_OT_USHORT SymmetricGridfitMask = SkTEndian_SwapBE16(1 << 2);
+ static const SK_OT_USHORT SymmetricSmoothingMask = SkTEndian_SwapBE16(1 << 3);
+ SK_OT_USHORT value;
+ } raw;
+ } flags;
+ }; //gaspRange[numRanges]
+};
+
+#pragma pack(pop)
+
+
+#include <stddef.h>
+SK_COMPILE_ASSERT(offsetof(SkOTTableGridAndScanProcedure, numRanges) == 2, SkOTTableGridAndScanProcedure_numRanges_not_at_2);
+SK_COMPILE_ASSERT(sizeof(SkOTTableGridAndScanProcedure) == 4, sizeof_SkOTTableGridAndScanProcedure_not_4);
+
+#endif
diff --git a/chromium/third_party/skia/src/sfnt/SkOTUtils.cpp b/chromium/third_party/skia/src/sfnt/SkOTUtils.cpp
index 004a8883108..e76d1da08c4 100644
--- a/chromium/third_party/skia/src/sfnt/SkOTUtils.cpp
+++ b/chromium/third_party/skia/src/sfnt/SkOTUtils.cpp
@@ -103,7 +103,7 @@ SkData* SkOTUtils::RenameFont(SkStream* fontData, const char* fontName, int font
for (; currentEntry < endEntry; ++currentEntry) {
uint32_t oldOffset = SkEndian_SwapBE32(currentEntry->offset);
if (oldOffset > oldNameTableOffset) {
- currentEntry->offset = SkEndian_SwapBE32(oldOffset - oldNameTablePhysicalSize);
+ currentEntry->offset = SkEndian_SwapBE32(SkToU32(oldOffset - oldNameTablePhysicalSize));
}
if (SkOTTableHead::TAG == currentEntry->tag) {
headTableEntry = currentEntry;
@@ -112,8 +112,8 @@ SkData* SkOTUtils::RenameFont(SkStream* fontData, const char* fontName, int font
// Make the table directory entry point to the new 'name' table.
SkSFNTHeader::TableDirectoryEntry* nameTableEntry = reinterpret_cast<SkSFNTHeader::TableDirectoryEntry*>(data + sizeof(SkSFNTHeader)) + tableIndex;
- nameTableEntry->logicalLength = SkEndian_SwapBE32(nameTableLogicalSize);
- nameTableEntry->offset = SkEndian_SwapBE32(originalDataSize);
+ nameTableEntry->logicalLength = SkEndian_SwapBE32(SkToU32(nameTableLogicalSize));
+ nameTableEntry->offset = SkEndian_SwapBE32(SkToU32(originalDataSize));
// Write the new 'name' table after the original font data.
SkOTTableName* nameTable = reinterpret_cast<SkOTTableName*>(data + originalDataSize);
diff --git a/chromium/third_party/skia/src/text/SkTextLayout.cpp b/chromium/third_party/skia/src/text/SkTextLayout.cpp
deleted file mode 100644
index 6f8bca562ab..00000000000
--- a/chromium/third_party/skia/src/text/SkTextLayout.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "SkTextLayout.h"
-
-SkTextStyle::SkTextStyle() {
- fPaint.setAntiAlias(true);
-}
-
-SkTextStyle::SkTextStyle(const SkTextStyle& src) : fPaint(src.fPaint) {}
-
-SkTextStyle::SkTextStyle(const SkPaint& paint) : fPaint(paint) {}
-
-SkTextStyle::~SkTextStyle() {}
-
-///////////////////////////////////////////////////////////////////////////////
-
-SkTextLayout::SkTextLayout() {
- fBounds.setEmpty();
- fDefaultStyle = new SkTextStyle;
-}
-
-SkTextLayout::~SkTextLayout() {
- fDefaultStyle->unref();
- fLines.deleteAll();
-}
-
-void SkTextLayout::setText(const char text[], size_t length) {
- fText.setCount(length);
- memcpy(fText.begin(), text, length);
-}
-
-void SkTextLayout::setBounds(const SkRect& bounds) {
- fBounds = bounds;
- // if width changed, inval cache
-}
-
-SkTextStyle* SkTextLayout::setDefaultStyle(SkTextStyle* style) {
- SkRefCnt_SafeAssign(fDefaultStyle, style);
- return style;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-struct SkTextLayout::GlyphRun {
- GlyphRun();
- ~GlyphRun();
-
- SkPoint* fLocs;
- uint16_t* fGlyphIDs;
- int fCount;
-};
-
-SkTextLayout::GlyphRun::GlyphRun() : fLocs(NULL), fGlyphIDs(NULL), fCount(0) {}
-
-SkTextLayout::GlyphRun::~GlyphRun() {
- delete[] fLocs;
- delete[] fGlyphIDs;
-}
-
-struct SkTextLayout::Line {
- Line() {}
- ~Line();
-
- SkScalar fBaselineY;
- SkTDArray<GlyphRun*> fRuns;
-};
-
-SkTextLayout::Line::~Line() {
- fRuns.deleteAll();
-}
-
-void SkTextLayout::draw(SkCanvas* canvas) {
-}
diff --git a/chromium/third_party/skia/src/utils/SkBase64.cpp b/chromium/third_party/skia/src/utils/SkBase64.cpp
index 11b647fe9a5..545a8ebb216 100644
--- a/chromium/third_party/skia/src/utils/SkBase64.cpp
+++ b/chromium/third_party/skia/src/utils/SkBase64.cpp
@@ -162,24 +162,3 @@ SkBase64::Error SkBase64::decode(const char* src, size_t len) {
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, NULL);
- 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/chromium/third_party/skia/src/utils/SkBase64.h b/chromium/third_party/skia/src/utils/SkBase64.h
index 5bf90066327..ba66dd2f477 100644
--- a/chromium/third_party/skia/src/utils/SkBase64.h
+++ b/chromium/third_party/skia/src/utils/SkBase64.h
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -6,7 +5,6 @@
* found in the LICENSE file.
*/
-
#ifndef SkBase64_DEFINED
#define SkBase64_DEFINED
@@ -30,9 +28,6 @@ public:
*/
static size_t Encode(const void* src, size_t length, void* dest, const char* encode = NULL);
-#ifdef SK_SUPPORT_UNITTEST
- static void UnitTest();
-#endif
private:
Error decode(const void* srcPtr, size_t length, bool writeDestination);
diff --git a/chromium/third_party/skia/src/utils/SkBitSet.h b/chromium/third_party/skia/src/utils/SkBitSet.h
index e113fd70044..e113fd70044 100755..100644
--- a/chromium/third_party/skia/src/utils/SkBitSet.h
+++ b/chromium/third_party/skia/src/utils/SkBitSet.h
diff --git a/chromium/third_party/skia/src/utils/SkBitmapHasher.cpp b/chromium/third_party/skia/src/utils/SkBitmapHasher.cpp
index 9f0affdea7d..32ff1cb0816 100644
--- a/chromium/third_party/skia/src/utils/SkBitmapHasher.cpp
+++ b/chromium/third_party/skia/src/utils/SkBitmapHasher.cpp
@@ -55,9 +55,9 @@ static inline uint64_t first_8_bytes_as_uint64(const uint8_t *bytearray) {
}
// Hmm, that didn't work. Maybe if we create a new
- // kARGB_8888_Config version of the bitmap it will work better?
+ // version of the bitmap it will work better?
SkBitmap copyBitmap;
- if (!bitmap.copyTo(&copyBitmap, SkBitmap::kARGB_8888_Config)) {
+ if (!bitmap.copyTo(&copyBitmap, kN32_SkColorType)) {
return false;
}
return ComputeDigestInternal(copyBitmap, result);
diff --git a/chromium/third_party/skia/src/utils/SkBitmapHasher.h b/chromium/third_party/skia/src/utils/SkBitmapHasher.h
index d52a6d739c1..c8a5c0406f4 100644
--- a/chromium/third_party/skia/src/utils/SkBitmapHasher.h
+++ b/chromium/third_party/skia/src/utils/SkBitmapHasher.h
@@ -22,7 +22,7 @@ public:
* If this is unable to compute the hash for some reason,
* it returns false.
*
- * Note: depending on the bitmap config, we may need to create an
+ * Note: depending on the bitmap colortype, we may need to create an
* intermediate SkBitmap and copy the pixels over to it... so in some
* cases, performance and memory usage can suffer.
*/
diff --git a/chromium/third_party/skia/src/utils/SkCamera.cpp b/chromium/third_party/skia/src/utils/SkCamera.cpp
index f5b51d52595..d9f9cf54503 100644
--- a/chromium/third_party/skia/src/utils/SkCamera.cpp
+++ b/chromium/third_party/skia/src/utils/SkCamera.cpp
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -6,99 +5,48 @@
* found in the LICENSE file.
*/
-
#include "SkCamera.h"
static SkScalar SkScalarDotDiv(int count, const SkScalar a[], int step_a,
const SkScalar b[], int step_b,
SkScalar denom) {
-#ifdef SK_SCALAR_IS_FLOAT
- float prod = 0;
+ SkScalar prod = 0;
for (int i = 0; i < count; i++) {
prod += a[0] * b[0];
a += step_a;
b += step_b;
}
return prod / denom;
-#else
- Sk64 prod, tmp;
-
- prod.set(0);
- for (int i = 0; i < count; i++) {
- tmp.setMul(a[0], b[0]);
- prod.add(tmp);
- a += step_a;
- b += step_b;
- }
- prod.div(denom, Sk64::kRound_DivOption);
- return prod.get32();
-#endif
}
static SkScalar SkScalarDot(int count, const SkScalar a[], int step_a,
const SkScalar b[], int step_b) {
-#ifdef SK_SCALAR_IS_FLOAT
- float prod = 0;
+ SkScalar prod = 0;
for (int i = 0; i < count; i++) {
prod += a[0] * b[0];
a += step_a;
b += step_b;
}
return prod;
-#else
- Sk64 prod, tmp;
-
- prod.set(0);
- for (int i = 0; i < count; i++) {
- tmp.setMul(a[0], b[0]);
- prod.add(tmp);
- a += step_a;
- b += step_b;
- }
- return prod.getFixed();
-#endif
}
///////////////////////////////////////////////////////////////////////////////
-SkUnitScalar SkPoint3D::normalize(SkUnit3D* unit) const {
-#ifdef SK_SCALAR_IS_FLOAT
- float mag = sk_float_sqrt(fX*fX + fY*fY + fZ*fZ);
+SkScalar SkPoint3D::normalize(SkUnit3D* unit) const {
+ SkScalar mag = SkScalarSqrt(fX*fX + fY*fY + fZ*fZ);
if (mag) {
- float scale = 1.0f / mag;
+ SkScalar scale = SkScalarInvert(mag);
unit->fX = fX * scale;
unit->fY = fY * scale;
unit->fZ = fZ * scale;
} else {
unit->fX = unit->fY = unit->fZ = 0;
}
-#else
- Sk64 tmp1, tmp2;
-
- tmp1.setMul(fX, fX);
- tmp2.setMul(fY, fY);
- tmp1.add(tmp2);
- tmp2.setMul(fZ, fZ);
- tmp1.add(tmp2);
-
- SkFixed mag = tmp1.getSqrt();
- if (mag) {
- // what if mag < SK_Fixed1 ??? we will underflow the fixdiv
- SkFixed scale = SkFixedDiv(SK_Fract1, mag);
- unit->fX = SkFixedMul(fX, scale);
- unit->fY = SkFixedMul(fY, scale);
- unit->fZ = SkFixedMul(fZ, scale);
- } else {
- unit->fX = unit->fY = unit->fZ = 0;
- }
-#endif
return mag;
}
-SkUnitScalar SkUnit3D::Dot(const SkUnit3D& a, const SkUnit3D& b) {
- return SkUnitScalarMul(a.fX, b.fX) +
- SkUnitScalarMul(a.fY, b.fY) +
- SkUnitScalarMul(a.fZ, b.fZ);
+SkScalar SkUnit3D::Dot(const SkUnit3D& a, const SkUnit3D& b) {
+ return a.fX * b.fX + a.fY * b.fY + a.fZ * b.fZ;
}
void SkUnit3D::Cross(const SkUnit3D& a, const SkUnit3D& b, SkUnit3D* cross) {
@@ -106,9 +54,9 @@ void SkUnit3D::Cross(const SkUnit3D& a, const SkUnit3D& b, SkUnit3D* cross) {
// use x,y,z, in case &a == cross or &b == cross
- SkScalar x = SkUnitScalarMul(a.fY, b.fZ) - SkUnitScalarMul(a.fZ, b.fY);
- SkScalar y = SkUnitScalarMul(a.fZ, b.fX) - SkUnitScalarMul(a.fX, b.fY);
- SkScalar z = SkUnitScalarMul(a.fX, b.fY) - SkUnitScalarMul(a.fY, b.fX);
+ SkScalar x = a.fY * b.fZ - a.fZ * b.fY;
+ SkScalar y = a.fZ * b.fX - a.fX * b.fY;
+ SkScalar z = a.fX * b.fY - a.fY * b.fX;
cross->set(x, y, z);
}
@@ -271,9 +219,9 @@ void SkCamera3D::doUpdate() const {
{
SkScalar dot = SkUnit3D::Dot(*SkTCast<const SkUnit3D*>(&fZenith), axis);
- zenith.fX = fZenith.fX - SkUnitScalarMul(dot, axis.fX);
- zenith.fY = fZenith.fY - SkUnitScalarMul(dot, axis.fY);
- zenith.fZ = fZenith.fZ - SkUnitScalarMul(dot, axis.fZ);
+ zenith.fX = fZenith.fX - dot * axis.fX;
+ zenith.fY = fZenith.fY - dot * axis.fY;
+ zenith.fZ = fZenith.fZ - dot * axis.fZ;
SkTCast<SkPoint3D*>(&zenith)->normalize(&zenith);
}
@@ -286,12 +234,12 @@ void SkCamera3D::doUpdate() const {
SkScalar y = fObserver.fY;
SkScalar z = fObserver.fZ;
- orien->set(SkMatrix::kMScaleX, SkUnitScalarMul(x, axis.fX) - SkUnitScalarMul(z, cross.fX));
- orien->set(SkMatrix::kMSkewX, SkUnitScalarMul(x, axis.fY) - SkUnitScalarMul(z, cross.fY));
- orien->set(SkMatrix::kMTransX, SkUnitScalarMul(x, axis.fZ) - SkUnitScalarMul(z, cross.fZ));
- orien->set(SkMatrix::kMSkewY, SkUnitScalarMul(y, axis.fX) - SkUnitScalarMul(z, zenith.fX));
- orien->set(SkMatrix::kMScaleY, SkUnitScalarMul(y, axis.fY) - SkUnitScalarMul(z, zenith.fY));
- orien->set(SkMatrix::kMTransY, SkUnitScalarMul(y, axis.fZ) - SkUnitScalarMul(z, zenith.fZ));
+ orien->set(SkMatrix::kMScaleX, x * axis.fX - z * cross.fX);
+ orien->set(SkMatrix::kMSkewX, x * axis.fY - z * cross.fY);
+ orien->set(SkMatrix::kMTransX, x * axis.fZ - z * cross.fZ);
+ orien->set(SkMatrix::kMSkewY, y * axis.fX - z * zenith.fX);
+ orien->set(SkMatrix::kMScaleY, y * axis.fY - z * zenith.fY);
+ orien->set(SkMatrix::kMTransY, y * axis.fZ - z * zenith.fZ);
orien->set(SkMatrix::kMPersp0, axis.fX);
orien->set(SkMatrix::kMPersp1, axis.fY);
orien->set(SkMatrix::kMPersp2, axis.fZ);
@@ -329,7 +277,7 @@ void SkCamera3D::patchToMatrix(const SkPatch3D& quilt, SkMatrix* matrix) const {
patchPtr = (const SkScalar*)(const void*)&diff;
matrix->set(SkMatrix::kMTransX, SkScalarDotDiv(3, patchPtr, 1, mapPtr, 1, dot));
matrix->set(SkMatrix::kMTransY, SkScalarDotDiv(3, patchPtr, 1, mapPtr+3, 1, dot));
- matrix->set(SkMatrix::kMPersp2, SK_UnitScalar1);
+ matrix->set(SkMatrix::kMPersp2, SK_Scalar1);
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/third_party/skia/src/utils/SkCanvasStack.cpp b/chromium/third_party/skia/src/utils/SkCanvasStack.cpp
index 8951149b421..87e8f653e21 100644
--- a/chromium/third_party/skia/src/utils/SkCanvasStack.cpp
+++ b/chromium/third_party/skia/src/utils/SkCanvasStack.cpp
@@ -65,7 +65,7 @@ void SkCanvasStack::clipToZOrderedBounds() {
* canvas unlike all other matrix operations (i.e. translate, scale, etc) which
* just pre-concatenate with the existing matrix.
*/
-void SkCanvasStack::setMatrix(const SkMatrix& matrix) {
+void SkCanvasStack::didSetMatrix(const SkMatrix& matrix) {
SkASSERT(fList.count() == fCanvasData.count());
for (int i = 0; i < fList.count(); ++i) {
@@ -74,28 +74,25 @@ void SkCanvasStack::setMatrix(const SkMatrix& matrix) {
SkIntToScalar(-fCanvasData[i].origin.y()));
fList[i]->setMatrix(tempMatrix);
}
- this->SkCanvas::setMatrix(matrix);
+ this->SkCanvas::didSetMatrix(matrix);
}
-bool SkCanvasStack::clipRect(const SkRect& r, SkRegion::Op op, bool aa) {
- bool result = this->INHERITED::clipRect(r, op, aa);
+void SkCanvasStack::onClipRect(const SkRect& r, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
+ this->INHERITED::onClipRect(r, op, edgeStyle);
this->clipToZOrderedBounds();
- return result;
}
-bool SkCanvasStack::clipRRect(const SkRRect& rr, SkRegion::Op op, bool aa) {
- bool result = this->INHERITED::clipRRect(rr, op, aa);
+void SkCanvasStack::onClipRRect(const SkRRect& rr, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
+ this->INHERITED::onClipRRect(rr, op, edgeStyle);
this->clipToZOrderedBounds();
- return result;
}
-bool SkCanvasStack::clipPath(const SkPath& p, SkRegion::Op op, bool aa) {
- bool result = this->INHERITED::clipPath(p, op, aa);
+void SkCanvasStack::onClipPath(const SkPath& p, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
+ this->INHERITED::onClipPath(p, op, edgeStyle);
this->clipToZOrderedBounds();
- return result;
}
-bool SkCanvasStack::clipRegion(const SkRegion& deviceRgn, SkRegion::Op op) {
+void SkCanvasStack::onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op) {
SkASSERT(fList.count() == fCanvasData.count());
for (int i = 0; i < fList.count(); ++i) {
SkRegion tempRegion;
@@ -104,5 +101,5 @@ bool SkCanvasStack::clipRegion(const SkRegion& deviceRgn, SkRegion::Op op) {
tempRegion.op(fCanvasData[i].requiredClip, SkRegion::kIntersect_Op);
fList[i]->clipRegion(tempRegion, op);
}
- return this->SkCanvas::clipRegion(deviceRgn, op);
+ this->SkCanvas::onClipRegion(deviceRgn, op);
}
diff --git a/chromium/third_party/skia/src/utils/SkCanvasStack.h b/chromium/third_party/skia/src/utils/SkCanvasStack.h
index 53111182703..028e5260486 100644
--- a/chromium/third_party/skia/src/utils/SkCanvasStack.h
+++ b/chromium/third_party/skia/src/utils/SkCanvasStack.h
@@ -29,12 +29,13 @@ public:
virtual void addCanvas(SkCanvas*) SK_OVERRIDE { SkDEBUGFAIL("Invalid Op"); }
virtual void removeCanvas(SkCanvas*) SK_OVERRIDE { SkDEBUGFAIL("Invalid Op"); }
- virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE;
- virtual bool clipRect(const SkRect&, SkRegion::Op, bool) SK_OVERRIDE;
- virtual bool clipRRect(const SkRRect&, SkRegion::Op, bool) SK_OVERRIDE;
- virtual bool clipPath(const SkPath&, SkRegion::Op, bool) SK_OVERRIDE;
- virtual bool clipRegion(const SkRegion& deviceRgn,
- SkRegion::Op) SK_OVERRIDE;
+protected:
+ virtual void didSetMatrix(const SkMatrix&) SK_OVERRIDE;
+
+ virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
+ virtual void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
+ virtual void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
+ virtual void onClipRegion(const SkRegion&, SkRegion::Op) SK_OVERRIDE;
private:
void clipToZOrderedBounds();
diff --git a/chromium/third_party/skia/src/utils/SkCanvasStateUtils.cpp b/chromium/third_party/skia/src/utils/SkCanvasStateUtils.cpp
index 9c7d8fab3a1..e286c9138fd 100644
--- a/chromium/third_party/skia/src/utils/SkCanvasStateUtils.cpp
+++ b/chromium/third_party/skia/src/utils/SkCanvasStateUtils.cpp
@@ -13,14 +13,13 @@
#include "SkErrorInternals.h"
#include "SkWriter32.h"
-#define CANVAS_STATE_VERSION 1
/*
* WARNING: The structs below are part of a stable ABI and as such we explicitly
* use unambigious primitives (e.g. int32_t instead of an enum).
*
- * ANY CHANGES TO THE STRUCTS BELOW THAT IMPACT THE ABI SHOULD RESULT IN AN
- * UPDATE OF THE CANVAS_STATE_VERSION. SUCH CHANGES SHOULD ONLY BE MADE IF
- * ABSOLUTELY NECESSARY!
+ * ANY CHANGES TO THE STRUCTS BELOW THAT IMPACT THE ABI SHOULD RESULT IN A NEW
+ * NEW SUBCLASS OF SkCanvasState. SUCH CHANGES SHOULD ONLY BE MADE IF ABSOLUTELY
+ * NECESSARY!
*/
enum RasterConfigs {
kUnknown_RasterConfig = 0,
@@ -48,7 +47,8 @@ struct SkMCState {
ClipRect* clipRects;
};
-// NOTE: If you add more members, bump CanvasState::version.
+// NOTE: If you add more members, create a new subclass of SkCanvasState with a
+// new CanvasState::version.
struct SkCanvasLayerState {
CanvasBackend type;
int32_t x, y;
@@ -60,7 +60,7 @@ struct SkCanvasLayerState {
union {
struct {
RasterConfig config; // pixel format: a value from RasterConfigs.
- size_t rowBytes; // Number of bytes from start of one line to next.
+ uint64_t rowBytes; // Number of bytes from start of one line to next.
void* pixels; // The pixels, all (height * rowBytes) of them.
} raster;
struct {
@@ -71,20 +71,41 @@ struct SkCanvasLayerState {
class SkCanvasState {
public:
- SkCanvasState(SkCanvas* canvas) {
+ SkCanvasState(int32_t version, SkCanvas* canvas) {
SkASSERT(canvas);
- version = CANVAS_STATE_VERSION;
- width = canvas->getDeviceSize().width();
- height = canvas->getDeviceSize().height();
+ this->version = version;
+ width = canvas->getBaseLayerSize().width();
+ height = canvas->getBaseLayerSize().height();
+
+ }
+
+ /**
+ * The version this struct was built with. This field must always appear
+ * first in the struct so that when the versions don't match (and the
+ * remaining contents and size are potentially different) we can still
+ * compare the version numbers.
+ */
+ int32_t version;
+ int32_t width;
+ int32_t height;
+ int32_t alignmentPadding;
+};
+
+class SkCanvasState_v1 : public SkCanvasState {
+public:
+ static const int32_t kVersion = 1;
+
+ SkCanvasState_v1(SkCanvas* canvas)
+ : INHERITED(kVersion, canvas)
+ {
layerCount = 0;
layers = NULL;
- originalCanvas = SkRef(canvas);
-
mcState.clipRectCount = 0;
mcState.clipRects = NULL;
+ originalCanvas = SkRef(canvas);
}
- ~SkCanvasState() {
+ ~SkCanvasState_v1() {
// loop through the layers and free the data allocated to the clipRects
for (int i = 0; i < layerCount; ++i) {
sk_free(layers[i].mcState.clipRects);
@@ -98,24 +119,13 @@ public:
originalCanvas->unref();
}
- /**
- * The version this struct was built with. This field must always appear
- * first in the struct so that when the versions don't match (and the
- * remaining contents and size are potentially different) we can still
- * compare the version numbers.
- */
- int32_t version;
-
- int32_t width;
- int32_t height;
-
SkMCState mcState;
int32_t layerCount;
SkCanvasLayerState* layers;
-
private:
SkCanvas* originalCanvas;
+ typedef SkCanvasState INHERITED;
};
////////////////////////////////////////////////////////////////////////////////
@@ -130,6 +140,10 @@ public:
fFailed |= antialias;
}
+ virtual void clipRRect(const SkRRect& rrect, SkRegion::Op op, bool antialias) SK_OVERRIDE {
+ fFailed |= antialias;
+ }
+
virtual void clipPath(const SkPath&, SkRegion::Op, bool antialias) SK_OVERRIDE {
fFailed |= antialias;
}
@@ -155,9 +169,7 @@ static void setup_MC_state(SkMCState* state, const SkMatrix& matrix, const SkReg
* and some more common complex clips (e.g. a clipRect with a sub-rect
* clipped out of its interior) without needing to malloc any additional memory.
*/
- const int clipBufferSize = 4 * sizeof(ClipRect);
- char clipBuffer[clipBufferSize];
- SkWriter32 clipWriter(sizeof(ClipRect), clipBuffer, clipBufferSize);
+ SkSWriter32<4*sizeof(ClipRect)> clipWriter;
if (!clip.isEmpty()) {
// only returns the b/w clip so aa clips fail
@@ -189,10 +201,11 @@ SkCanvasState* SkCanvasStateUtils::CaptureCanvasState(SkCanvas* canvas) {
return NULL;
}
- SkAutoTDelete<SkCanvasState> canvasState(SkNEW_ARGS(SkCanvasState, (canvas)));
+ SkAutoTDelete<SkCanvasState_v1> canvasState(SkNEW_ARGS(SkCanvasState_v1, (canvas)));
// decompose the total matrix and clip
- setup_MC_state(&canvasState->mcState, canvas->getTotalMatrix(), canvas->getTotalClip());
+ setup_MC_state(&canvasState->mcState, canvas->getTotalMatrix(),
+ canvas->internal_private_getTotalClip());
/*
* decompose the layers
@@ -201,9 +214,7 @@ SkCanvasState* SkCanvasStateUtils::CaptureCanvasState(SkCanvas* canvas) {
* some view systems (e.g. Android) that a few non-clipped layers are present
* and we will not need to malloc any additional memory in those cases.
*/
- const int layerBufferSize = 3 * sizeof(SkCanvasLayerState);
- char layerBuffer[layerBufferSize];
- SkWriter32 layerWriter(sizeof(SkCanvasLayerState), layerBuffer, layerBufferSize);
+ SkSWriter32<3*sizeof(SkCanvasLayerState)> layerWriter;
int layerCount = 0;
for (SkCanvas::LayerIter layer(canvas, true/*skipEmptyClips*/); !layer.done(); layer.next()) {
@@ -221,11 +232,11 @@ SkCanvasState* SkCanvasStateUtils::CaptureCanvasState(SkCanvas* canvas) {
layerState->width = bitmap.width();
layerState->height = bitmap.height();
- switch (bitmap.config()) {
- case SkBitmap::kARGB_8888_Config:
+ switch (bitmap.colorType()) {
+ case kN32_SkColorType:
layerState->raster.config = kARGB_8888_RasterConfig;
break;
- case SkBitmap::kRGB_565_Config:
+ case kRGB_565_SkColorType:
layerState->raster.config = kRGB_565_RasterConfig;
break;
default:
@@ -246,7 +257,7 @@ SkCanvasState* SkCanvasStateUtils::CaptureCanvasState(SkCanvas* canvas) {
// for now, just ignore any client supplied DrawFilter.
if (canvas->getDrawFilter()) {
-// SkDEBUGF(("CaptureCanvasState will ignore the canvases draw filter.\n"));
+// SkDEBUGF(("CaptureCanvasState will ignore the canvas's draw filter.\n"));
}
return canvasState.detach();
@@ -279,25 +290,23 @@ static SkCanvas* create_canvas_from_canvas_layer(const SkCanvasLayerState& layer
SkASSERT(kRaster_CanvasBackend == layerState.type);
SkBitmap bitmap;
- SkBitmap::Config config =
- layerState.raster.config == kARGB_8888_RasterConfig ? SkBitmap::kARGB_8888_Config :
- layerState.raster.config == kRGB_565_RasterConfig ? SkBitmap::kRGB_565_Config :
- SkBitmap::kNo_Config;
+ SkColorType colorType =
+ layerState.raster.config == kARGB_8888_RasterConfig ? kN32_SkColorType :
+ layerState.raster.config == kRGB_565_RasterConfig ? kRGB_565_SkColorType :
+ kUnknown_SkColorType;
- if (config == SkBitmap::kNo_Config) {
+ if (colorType == kUnknown_SkColorType) {
return NULL;
}
- bitmap.setConfig(config, layerState.width, layerState.height,
- layerState.raster.rowBytes);
- bitmap.setPixels(layerState.raster.pixels);
+ bitmap.installPixels(SkImageInfo::Make(layerState.width, layerState.height,
+ colorType, kPremul_SkAlphaType),
+ layerState.raster.pixels, (size_t) layerState.raster.rowBytes);
SkASSERT(!bitmap.empty());
SkASSERT(!bitmap.isNull());
- // create a device & canvas
- SkAutoTUnref<SkBitmapDevice> device(SkNEW_ARGS(SkBitmapDevice, (bitmap)));
- SkAutoTUnref<SkCanvas> canvas(SkNEW_ARGS(SkCanvas, (device.get())));
+ SkAutoTUnref<SkCanvas> canvas(SkNEW_ARGS(SkCanvas, (bitmap)));
// setup the matrix and clip
setup_canvas_from_MC_state(layerState.mcState, canvas.get());
@@ -307,30 +316,28 @@ static SkCanvas* create_canvas_from_canvas_layer(const SkCanvasLayerState& layer
SkCanvas* SkCanvasStateUtils::CreateFromCanvasState(const SkCanvasState* state) {
SkASSERT(state);
+ // Currently there is only one possible version.
+ SkASSERT(SkCanvasState_v1::kVersion == state->version);
- // check that the versions match
- if (CANVAS_STATE_VERSION != state->version) {
- SkDebugf("CreateFromCanvasState version does not match the one use to create the input");
- return NULL;
- }
+ const SkCanvasState_v1* state_v1 = static_cast<const SkCanvasState_v1*>(state);
- if (state->layerCount < 1) {
+ if (state_v1->layerCount < 1) {
return NULL;
}
SkAutoTUnref<SkCanvasStack> canvas(SkNEW_ARGS(SkCanvasStack, (state->width, state->height)));
// setup the matrix and clip on the n-way canvas
- setup_canvas_from_MC_state(state->mcState, canvas);
+ setup_canvas_from_MC_state(state_v1->mcState, canvas);
// Iterate over the layers and add them to the n-way canvas
- for (int i = state->layerCount - 1; i >= 0; --i) {
- SkAutoTUnref<SkCanvas> canvasLayer(create_canvas_from_canvas_layer(state->layers[i]));
+ for (int i = state_v1->layerCount - 1; i >= 0; --i) {
+ SkAutoTUnref<SkCanvas> canvasLayer(create_canvas_from_canvas_layer(state_v1->layers[i]));
if (!canvasLayer.get()) {
return NULL;
}
- canvas->pushCanvas(canvasLayer.get(), SkIPoint::Make(state->layers[i].x,
- state->layers[i].y));
+ canvas->pushCanvas(canvasLayer.get(), SkIPoint::Make(state_v1->layers[i].x,
+ state_v1->layers[i].y));
}
return canvas.detach();
@@ -339,5 +346,9 @@ SkCanvas* SkCanvasStateUtils::CreateFromCanvasState(const SkCanvasState* state)
////////////////////////////////////////////////////////////////////////////////
void SkCanvasStateUtils::ReleaseCanvasState(SkCanvasState* state) {
- SkDELETE(state);
+ SkASSERT(!state || SkCanvasState_v1::kVersion == state->version);
+ // Upcast to the correct version of SkCanvasState. This avoids having a virtual destructor on
+ // SkCanvasState. That would be strange since SkCanvasState has no other virtual functions, and
+ // instead uses the field "version" to determine how to behave.
+ SkDELETE(static_cast<SkCanvasState_v1*>(state));
}
diff --git a/chromium/third_party/skia/src/utils/SkCullPoints.cpp b/chromium/third_party/skia/src/utils/SkCullPoints.cpp
index efb94f48703..76e63c71a9c 100644
--- a/chromium/third_party/skia/src/utils/SkCullPoints.cpp
+++ b/chromium/third_party/skia/src/utils/SkCullPoints.cpp
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -6,20 +5,13 @@
* found in the LICENSE file.
*/
-
#include "SkCullPoints.h"
-#include "Sk64.h"
static bool cross_product_is_neg(const SkIPoint& v, int dx, int dy) {
#if 0
return v.fX * dy - v.fY * dx < 0;
#else
- Sk64 tmp0, tmp1;
-
- tmp0.setMul(v.fX, dy);
- tmp1.setMul(dx, v.fY);
- tmp0.sub(tmp1);
- return tmp0.isNeg() != 0;
+ return sk_64_mul(v.fX, dy) < sk_64_mul(dx, v.fY);
#endif
}
diff --git a/chromium/third_party/skia/src/utils/SkDashPath.cpp b/chromium/third_party/skia/src/utils/SkDashPath.cpp
new file mode 100644
index 00000000000..3c4aef343d3
--- /dev/null
+++ b/chromium/third_party/skia/src/utils/SkDashPath.cpp
@@ -0,0 +1,328 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkDashPathPriv.h"
+#include "SkPathMeasure.h"
+
+static inline int is_even(int x) {
+ return (~x) << 31;
+}
+
+static SkScalar find_first_interval(const SkScalar intervals[], SkScalar phase,
+ int32_t* index, int count) {
+ for (int i = 0; i < count; ++i) {
+ if (phase > intervals[i]) {
+ phase -= intervals[i];
+ } else {
+ *index = i;
+ return intervals[i] - phase;
+ }
+ }
+ // If we get here, phase "appears" to be larger than our length. This
+ // shouldn't happen with perfect precision, but we can accumulate errors
+ // during the initial length computation (rounding can make our sum be too
+ // big or too small. In that event, we just have to eat the error here.
+ *index = 0;
+ return intervals[0];
+}
+
+void SkDashPath::CalcDashParameters(SkScalar phase, const SkScalar intervals[], int32_t count,
+ SkScalar* initialDashLength, int32_t* initialDashIndex,
+ SkScalar* intervalLength, SkScalar* adjustedPhase) {
+ SkScalar len = 0;
+ for (int i = 0; i < count; i++) {
+ len += intervals[i];
+ }
+ *intervalLength = len;
+
+ // watch out for values that might make us go out of bounds
+ if ((len > 0) && SkScalarIsFinite(phase) && SkScalarIsFinite(len)) {
+
+ // Adjust phase to be between 0 and len, "flipping" phase if negative.
+ // e.g., if len is 100, then phase of -20 (or -120) is equivalent to 80
+ if (adjustedPhase) {
+ if (phase < 0) {
+ phase = -phase;
+ if (phase > len) {
+ phase = SkScalarMod(phase, len);
+ }
+ phase = len - phase;
+
+ // Due to finite precision, it's possible that phase == len,
+ // even after the subtract (if len >>> phase), so fix that here.
+ // This fixes http://crbug.com/124652 .
+ SkASSERT(phase <= len);
+ if (phase == len) {
+ phase = 0;
+ }
+ } else if (phase >= len) {
+ phase = SkScalarMod(phase, len);
+ }
+ *adjustedPhase = phase;
+ }
+ SkASSERT(phase >= 0 && phase < len);
+
+ *initialDashLength = find_first_interval(intervals, phase,
+ initialDashIndex, count);
+
+ SkASSERT(*initialDashLength >= 0);
+ SkASSERT(*initialDashIndex >= 0 && *initialDashIndex < count);
+ } else {
+ *initialDashLength = -1; // signal bad dash intervals
+ }
+}
+
+static void outset_for_stroke(SkRect* rect, const SkStrokeRec& rec) {
+ SkScalar radius = SkScalarHalf(rec.getWidth());
+ if (0 == radius) {
+ radius = SK_Scalar1; // hairlines
+ }
+ if (SkPaint::kMiter_Join == rec.getJoin()) {
+ radius = SkScalarMul(radius, rec.getMiter());
+ }
+ rect->outset(radius, radius);
+}
+
+// Only handles lines for now. If returns true, dstPath is the new (smaller)
+// path. If returns false, then dstPath parameter is ignored.
+static bool cull_path(const SkPath& srcPath, const SkStrokeRec& rec,
+ const SkRect* cullRect, SkScalar intervalLength,
+ SkPath* dstPath) {
+ if (NULL == cullRect) {
+ return false;
+ }
+
+ SkPoint pts[2];
+ if (!srcPath.isLine(pts)) {
+ return false;
+ }
+
+ SkRect bounds = *cullRect;
+ outset_for_stroke(&bounds, rec);
+
+ SkScalar dx = pts[1].x() - pts[0].x();
+ SkScalar dy = pts[1].y() - pts[0].y();
+
+ // just do horizontal lines for now (lazy)
+ if (dy) {
+ return false;
+ }
+
+ SkScalar minX = pts[0].fX;
+ SkScalar maxX = pts[1].fX;
+
+ if (maxX < bounds.fLeft || minX > bounds.fRight) {
+ return false;
+ }
+
+ if (dx < 0) {
+ SkTSwap(minX, maxX);
+ }
+
+ // Now we actually perform the chop, removing the excess to the left and
+ // right of the bounds (keeping our new line "in phase" with the dash,
+ // hence the (mod intervalLength).
+
+ if (minX < bounds.fLeft) {
+ minX = bounds.fLeft - SkScalarMod(bounds.fLeft - minX,
+ intervalLength);
+ }
+ if (maxX > bounds.fRight) {
+ maxX = bounds.fRight + SkScalarMod(maxX - bounds.fRight,
+ intervalLength);
+ }
+
+ SkASSERT(maxX >= minX);
+ if (dx < 0) {
+ SkTSwap(minX, maxX);
+ }
+ pts[0].fX = minX;
+ pts[1].fX = maxX;
+
+ dstPath->moveTo(pts[0]);
+ dstPath->lineTo(pts[1]);
+ return true;
+}
+
+class SpecialLineRec {
+public:
+ bool init(const SkPath& src, SkPath* dst, SkStrokeRec* rec,
+ int intervalCount, SkScalar intervalLength) {
+ if (rec->isHairlineStyle() || !src.isLine(fPts)) {
+ return false;
+ }
+
+ // can relax this in the future, if we handle square and round caps
+ if (SkPaint::kButt_Cap != rec->getCap()) {
+ return false;
+ }
+
+ SkScalar pathLength = SkPoint::Distance(fPts[0], fPts[1]);
+
+ fTangent = fPts[1] - fPts[0];
+ if (fTangent.isZero()) {
+ return false;
+ }
+
+ fPathLength = pathLength;
+ fTangent.scale(SkScalarInvert(pathLength));
+ fTangent.rotateCCW(&fNormal);
+ fNormal.scale(SkScalarHalf(rec->getWidth()));
+
+ // now estimate how many quads will be added to the path
+ // resulting segments = pathLen * intervalCount / intervalLen
+ // resulting points = 4 * segments
+
+ SkScalar ptCount = SkScalarMulDiv(pathLength,
+ SkIntToScalar(intervalCount),
+ intervalLength);
+ int n = SkScalarCeilToInt(ptCount) << 2;
+ dst->incReserve(n);
+
+ // we will take care of the stroking
+ rec->setFillStyle();
+ return true;
+ }
+
+ void addSegment(SkScalar d0, SkScalar d1, SkPath* path) const {
+ SkASSERT(d0 < fPathLength);
+ // clamp the segment to our length
+ if (d1 > fPathLength) {
+ d1 = fPathLength;
+ }
+
+ SkScalar x0 = fPts[0].fX + SkScalarMul(fTangent.fX, d0);
+ SkScalar x1 = fPts[0].fX + SkScalarMul(fTangent.fX, d1);
+ SkScalar y0 = fPts[0].fY + SkScalarMul(fTangent.fY, d0);
+ SkScalar y1 = fPts[0].fY + SkScalarMul(fTangent.fY, d1);
+
+ SkPoint pts[4];
+ pts[0].set(x0 + fNormal.fX, y0 + fNormal.fY); // moveTo
+ pts[1].set(x1 + fNormal.fX, y1 + fNormal.fY); // lineTo
+ pts[2].set(x1 - fNormal.fX, y1 - fNormal.fY); // lineTo
+ pts[3].set(x0 - fNormal.fX, y0 - fNormal.fY); // lineTo
+
+ path->addPoly(pts, SK_ARRAY_COUNT(pts), false);
+ }
+
+private:
+ SkPoint fPts[2];
+ SkVector fTangent;
+ SkVector fNormal;
+ SkScalar fPathLength;
+};
+
+
+bool SkDashPath::FilterDashPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec,
+ const SkRect* cullRect, const SkScalar aIntervals[],
+ int32_t count, SkScalar initialDashLength, int32_t initialDashIndex,
+ SkScalar intervalLength) {
+
+ // we do nothing if the src wants to be filled, or if our dashlength is 0
+ if (rec->isFillStyle() || initialDashLength < 0) {
+ return false;
+ }
+
+ const SkScalar* intervals = aIntervals;
+ SkScalar dashCount = 0;
+ int segCount = 0;
+
+ SkPath cullPathStorage;
+ const SkPath* srcPtr = &src;
+ if (cull_path(src, *rec, cullRect, intervalLength, &cullPathStorage)) {
+ srcPtr = &cullPathStorage;
+ }
+
+ SpecialLineRec lineRec;
+ bool specialLine = lineRec.init(*srcPtr, dst, rec, count >> 1, intervalLength);
+
+ SkPathMeasure meas(*srcPtr, false);
+
+ do {
+ bool skipFirstSegment = meas.isClosed();
+ bool addedSegment = false;
+ SkScalar length = meas.getLength();
+ int index = initialDashIndex;
+
+ // Since the path length / dash length ratio may be arbitrarily large, we can exert
+ // significant memory pressure while attempting to build the filtered path. To avoid this,
+ // we simply give up dashing beyond a certain threshold.
+ //
+ // The original bug report (http://crbug.com/165432) is based on a path yielding more than
+ // 90 million dash segments and crashing the memory allocator. A limit of 1 million
+ // segments seems reasonable: at 2 verbs per segment * 9 bytes per verb, this caps the
+ // maximum dash memory overhead at roughly 17MB per path.
+ static const SkScalar kMaxDashCount = 1000000;
+ dashCount += length * (count >> 1) / intervalLength;
+ if (dashCount > kMaxDashCount) {
+ dst->reset();
+ return false;
+ }
+
+ // Using double precision to avoid looping indefinitely due to single precision rounding
+ // (for extreme path_length/dash_length ratios). See test_infinite_dash() unittest.
+ double distance = 0;
+ double dlen = initialDashLength;
+
+ while (distance < length) {
+ SkASSERT(dlen >= 0);
+ addedSegment = false;
+ if (is_even(index) && dlen > 0 && !skipFirstSegment) {
+ addedSegment = true;
+ ++segCount;
+
+ if (specialLine) {
+ lineRec.addSegment(SkDoubleToScalar(distance),
+ SkDoubleToScalar(distance + dlen),
+ dst);
+ } else {
+ meas.getSegment(SkDoubleToScalar(distance),
+ SkDoubleToScalar(distance + dlen),
+ dst, true);
+ }
+ }
+ distance += dlen;
+
+ // clear this so we only respect it the first time around
+ skipFirstSegment = false;
+
+ // wrap around our intervals array if necessary
+ index += 1;
+ SkASSERT(index <= count);
+ if (index == count) {
+ index = 0;
+ }
+
+ // fetch our next dlen
+ dlen = intervals[index];
+ }
+
+ // extend if we ended on a segment and we need to join up with the (skipped) initial segment
+ if (meas.isClosed() && is_even(initialDashIndex) &&
+ initialDashLength > 0) {
+ meas.getSegment(0, initialDashLength, dst, !addedSegment);
+ ++segCount;
+ }
+ } while (meas.nextContour());
+
+ if (segCount > 1) {
+ dst->setConvexity(SkPath::kConcave_Convexity);
+ }
+
+ return true;
+}
+
+bool SkDashPath::FilterDashPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec,
+ const SkRect* cullRect, const SkPathEffect::DashInfo& info) {
+ SkScalar initialDashLength = 0;
+ int32_t initialDashIndex = 0;
+ SkScalar intervalLength = 0;
+ CalcDashParameters(info.fPhase, info.fIntervals, info.fCount,
+ &initialDashLength, &initialDashIndex, &intervalLength);
+ return FilterDashPath(dst, src, rec, cullRect, info.fIntervals, info.fCount, initialDashLength,
+ initialDashIndex, intervalLength);
+}
diff --git a/chromium/third_party/skia/src/utils/SkDashPathPriv.h b/chromium/third_party/skia/src/utils/SkDashPathPriv.h
new file mode 100644
index 00000000000..94222a271a6
--- /dev/null
+++ b/chromium/third_party/skia/src/utils/SkDashPathPriv.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkDashPathPriv_DEFINED
+#define SkDashPathPriv_DEFINED
+
+#include "SkPathEffect.h"
+
+namespace SkDashPath {
+ /*
+ * Calculates the initialDashLength, initialDashIndex, and intervalLength based on the
+ * inputed phase and intervals. If adjustedPhase is passed in, then the phase will be
+ * adjusted to be between 0 and intervalLength. The result will be stored in adjustedPhase.
+ * If adjustedPhase is NULL then it is assumed phase is already between 0 and intervalLength
+ */
+ void CalcDashParameters(SkScalar phase, const SkScalar intervals[], int32_t count,
+ SkScalar* initialDashLength, int32_t* initialDashIndex,
+ SkScalar* intervalLength, SkScalar* adjustedPhase = NULL);
+
+ bool FilterDashPath(SkPath* dst, const SkPath& src, SkStrokeRec*, const SkRect*,
+ const SkScalar aIntervals[], int32_t count, SkScalar initialDashLength,
+ int32_t initialDashIndex, SkScalar intervalLength);
+
+ bool FilterDashPath(SkPath* dst, const SkPath& src, SkStrokeRec*, const SkRect*,
+ const SkPathEffect::DashInfo& info);
+}
+
+#endif
diff --git a/chromium/third_party/skia/src/utils/SkDebugTrace.h b/chromium/third_party/skia/src/utils/SkDebugTrace.h
deleted file mode 100644
index 5ec3e1c4772..00000000000
--- a/chromium/third_party/skia/src/utils/SkDebugTrace.h
+++ /dev/null
@@ -1,24 +0,0 @@
-
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkUserTrace_DEFINED
-#define SkUserTrace_DEFINED
-
-/* Sample implementation of SkUserTrace that routes all of the
- trace macros to debug output stream.
- To use this, redefine SK_USER_TRACE_INCLUDE_FILE in
- include/config/SkUserConfig.h to point to this file
-*/
-#define SK_TRACE_EVENT0(event) \
- SkDebugf("Trace: %s\n", event)
-#define SK_TRACE_EVENT1(event, name1, value1) \
- SkDebugf("Trace: %s (%s=%s)\n", event, name1, value1)
-#define SK_TRACE_EVENT2(event, name1, value1, name2, value2) \
- SkDebugf("Trace: %s (%s=%s, %s=%s)\n", event, name1, value1, name2, value2)
-
-#endif
diff --git a/chromium/third_party/skia/src/utils/SkDeferredCanvas.cpp b/chromium/third_party/skia/src/utils/SkDeferredCanvas.cpp
index 27627ab82ec..641974b1ed1 100644
--- a/chromium/third_party/skia/src/utils/SkDeferredCanvas.cpp
+++ b/chromium/third_party/skia/src/utils/SkDeferredCanvas.cpp
@@ -30,8 +30,7 @@ enum PlaybackMode {
kSilent_PlaybackMode,
};
-namespace {
-bool shouldDrawImmediately(const SkBitmap* bitmap, const SkPaint* paint,
+static bool shouldDrawImmediately(const SkBitmap* bitmap, const SkPaint* paint,
size_t bitmapSizeThreshold) {
if (bitmap && ((bitmap->getTexture() && !bitmap->isImmutable()) ||
(bitmap->getSize() > bitmapSizeThreshold))) {
@@ -54,7 +53,6 @@ bool shouldDrawImmediately(const SkBitmap* bitmap, const SkPaint* paint,
}
return false;
}
-}
//-----------------------------------------------------------------------------
// DeferredPipeController
@@ -135,14 +133,12 @@ void DeferredPipeController::playback(bool silent) {
}
//-----------------------------------------------------------------------------
-// DeferredDevice
+// SkDeferredDevice
//-----------------------------------------------------------------------------
-// FIXME: Derive from SkBaseDevice.
-class DeferredDevice : public SkBitmapDevice {
+class SkDeferredDevice : public SkBaseDevice {
public:
- explicit DeferredDevice(SkBaseDevice* immediateDevice);
- explicit DeferredDevice(SkSurface* surface);
- ~DeferredDevice();
+ explicit SkDeferredDevice(SkSurface* surface);
+ ~SkDeferredDevice();
void setNotificationClient(SkDeferredCanvas::NotificationClient* notificationClient);
SkCanvas* recordingCanvas();
@@ -161,24 +157,18 @@ public:
void setMaxRecordingStorage(size_t);
void recordedDrawCommand();
- virtual uint32_t getDeviceCapabilities() SK_OVERRIDE;
- virtual int width() const SK_OVERRIDE;
- virtual int height() const SK_OVERRIDE;
+ virtual SkImageInfo imageInfo() const SK_OVERRIDE;
+
virtual GrRenderTarget* accessRenderTarget() SK_OVERRIDE;
- virtual SkBaseDevice* onCreateCompatibleDevice(SkBitmap::Config config,
- int width, int height,
- bool isOpaque,
- Usage usage) SK_OVERRIDE;
+ virtual SkBaseDevice* onCreateDevice(const SkImageInfo&, Usage) SK_OVERRIDE;
- virtual void writePixels(const SkBitmap& bitmap, int x, int y,
- SkCanvas::Config8888 config8888) SK_OVERRIDE;
+ virtual SkSurface* newSurface(const SkImageInfo&) SK_OVERRIDE;
protected:
virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE;
- virtual bool onReadPixels(const SkBitmap& bitmap,
- int x, int y,
- SkCanvas::Config8888 config8888) SK_OVERRIDE;
+ virtual bool onReadPixels(const SkImageInfo&, void*, size_t, int x, int y) SK_OVERRIDE;
+ virtual bool onWritePixels(const SkImageInfo&, const void*, size_t, int x, int y) SK_OVERRIDE;
// The following methods are no-ops on a deferred device
virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) SK_OVERRIDE {
@@ -198,9 +188,11 @@ protected:
virtual void drawRect(const SkDraw&, const SkRect& r,
const SkPaint& paint) SK_OVERRIDE
{SkASSERT(0);}
+ virtual void drawOval(const SkDraw&, const SkRect&, const SkPaint&) SK_OVERRIDE
+ {SkASSERT(0);}
virtual void drawRRect(const SkDraw&, const SkRRect& rr,
const SkPaint& paint) SK_OVERRIDE
- {SkASSERT(0);}
+ {SkASSERT(0);}
virtual void drawPath(const SkDraw&, const SkPath& path,
const SkPaint& paint,
const SkMatrix* prePathMatrix = NULL,
@@ -209,6 +201,10 @@ protected:
virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
const SkMatrix& matrix, const SkPaint& paint) SK_OVERRIDE
{SkASSERT(0);}
+ virtual void drawBitmapRect(const SkDraw&, const SkBitmap&, const SkRect*,
+ const SkRect&, const SkPaint&,
+ SkCanvas::DrawBitmapRectFlags) SK_OVERRIDE
+ {SkASSERT(0);}
virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
int x, int y, const SkPaint& paint) SK_OVERRIDE
{SkASSERT(0);}
@@ -233,8 +229,24 @@ protected:
virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
const SkPaint&) SK_OVERRIDE
{SkASSERT(0);}
+
+ virtual void lockPixels() SK_OVERRIDE {}
+ virtual void unlockPixels() SK_OVERRIDE {}
+
+ virtual bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE {
+ return false;
+ }
+ virtual bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE {
+ return false;
+ }
+ virtual bool filterImage(const SkImageFilter*, const SkBitmap&,
+ const SkImageFilter::Context&, SkBitmap*, SkIPoint*) SK_OVERRIDE {
+ return false;
+ }
+
private:
virtual void flush() SK_OVERRIDE;
+ virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE {}
void beginRecording();
void init();
@@ -254,23 +266,7 @@ private:
size_t fBitmapSizeThreshold;
};
-DeferredDevice::DeferredDevice(SkBaseDevice* immediateDevice)
- : SkBitmapDevice(SkBitmap::kNo_Config,
- immediateDevice->width(), immediateDevice->height(),
- immediateDevice->isOpaque(),
- immediateDevice->getDeviceProperties()) {
- fSurface = NULL;
- fImmediateCanvas = SkNEW_ARGS(SkCanvas, (immediateDevice));
- fPipeController.setPlaybackCanvas(fImmediateCanvas);
- this->init();
-}
-
-DeferredDevice::DeferredDevice(SkSurface* surface)
- : SkBitmapDevice(SkBitmap::kNo_Config,
- surface->getCanvas()->getDevice()->width(),
- surface->getCanvas()->getDevice()->height(),
- surface->getCanvas()->getDevice()->isOpaque(),
- surface->getCanvas()->getDevice()->getDeviceProperties()) {
+SkDeferredDevice::SkDeferredDevice(SkSurface* surface) {
fMaxRecordingStorageBytes = kDefaultMaxRecordingStorageBytes;
fNotificationClient = NULL;
fImmediateCanvas = NULL;
@@ -279,13 +275,13 @@ DeferredDevice::DeferredDevice(SkSurface* surface)
this->init();
}
-void DeferredDevice::setSurface(SkSurface* surface) {
+void SkDeferredDevice::setSurface(SkSurface* surface) {
SkRefCnt_SafeAssign(fImmediateCanvas, surface->getCanvas());
SkRefCnt_SafeAssign(fSurface, surface);
fPipeController.setPlaybackCanvas(fImmediateCanvas);
}
-void DeferredDevice::init() {
+void SkDeferredDevice::init() {
fRecordingCanvas = NULL;
fFreshFrame = true;
fCanDiscardCanvasContents = false;
@@ -296,52 +292,49 @@ void DeferredDevice::init() {
this->beginRecording();
}
-DeferredDevice::~DeferredDevice() {
+SkDeferredDevice::~SkDeferredDevice() {
this->flushPendingCommands(kSilent_PlaybackMode);
SkSafeUnref(fImmediateCanvas);
SkSafeUnref(fSurface);
}
-void DeferredDevice::setMaxRecordingStorage(size_t maxStorage) {
+void SkDeferredDevice::setMaxRecordingStorage(size_t maxStorage) {
fMaxRecordingStorageBytes = maxStorage;
this->recordingCanvas(); // Accessing the recording canvas applies the new limit.
}
-void DeferredDevice::beginRecording() {
+void SkDeferredDevice::beginRecording() {
SkASSERT(NULL == fRecordingCanvas);
fRecordingCanvas = fPipeWriter.startRecording(&fPipeController, 0,
immediateDevice()->width(), immediateDevice()->height());
}
-void DeferredDevice::setNotificationClient(
+void SkDeferredDevice::setNotificationClient(
SkDeferredCanvas::NotificationClient* notificationClient) {
fNotificationClient = notificationClient;
}
-void DeferredDevice::skipPendingCommands() {
+void SkDeferredDevice::skipPendingCommands() {
if (!fRecordingCanvas->isDrawingToLayer()) {
fCanDiscardCanvasContents = true;
if (fPipeController.hasPendingCommands()) {
fFreshFrame = true;
flushPendingCommands(kSilent_PlaybackMode);
- if (fNotificationClient) {
- fNotificationClient->skippedPendingDrawCommands();
- }
}
}
}
-bool DeferredDevice::isFreshFrame() {
+bool SkDeferredDevice::isFreshFrame() {
bool ret = fFreshFrame;
fFreshFrame = false;
return ret;
}
-bool DeferredDevice::hasPendingCommands() {
+bool SkDeferredDevice::hasPendingCommands() {
return fPipeController.hasPendingCommands();
}
-void DeferredDevice::aboutToDraw()
+void SkDeferredDevice::aboutToDraw()
{
if (NULL != fNotificationClient) {
fNotificationClient->prepareForDraw();
@@ -354,7 +347,7 @@ void DeferredDevice::aboutToDraw()
}
}
-void DeferredDevice::flushPendingCommands(PlaybackMode playbackMode) {
+void SkDeferredDevice::flushPendingCommands(PlaybackMode playbackMode) {
if (!fPipeController.hasPendingCommands()) {
return;
}
@@ -363,37 +356,42 @@ void DeferredDevice::flushPendingCommands(PlaybackMode playbackMode) {
}
fPipeWriter.flushRecording(true);
fPipeController.playback(kSilent_PlaybackMode == playbackMode);
- if (playbackMode == kNormal_PlaybackMode && fNotificationClient) {
- fNotificationClient->flushedDrawCommands();
+ if (fNotificationClient) {
+ if (playbackMode == kSilent_PlaybackMode) {
+ fNotificationClient->skippedPendingDrawCommands();
+ } else {
+ fNotificationClient->flushedDrawCommands();
+ }
}
+
fPreviousStorageAllocated = storageAllocatedForRecording();
}
-void DeferredDevice::flush() {
+void SkDeferredDevice::flush() {
this->flushPendingCommands(kNormal_PlaybackMode);
fImmediateCanvas->flush();
}
-size_t DeferredDevice::freeMemoryIfPossible(size_t bytesToFree) {
+size_t SkDeferredDevice::freeMemoryIfPossible(size_t bytesToFree) {
size_t val = fPipeWriter.freeMemoryIfPossible(bytesToFree);
fPreviousStorageAllocated = storageAllocatedForRecording();
return val;
}
-size_t DeferredDevice::getBitmapSizeThreshold() const {
+size_t SkDeferredDevice::getBitmapSizeThreshold() const {
return fBitmapSizeThreshold;
}
-void DeferredDevice::setBitmapSizeThreshold(size_t sizeThreshold) {
+void SkDeferredDevice::setBitmapSizeThreshold(size_t sizeThreshold) {
fBitmapSizeThreshold = sizeThreshold;
}
-size_t DeferredDevice::storageAllocatedForRecording() const {
+size_t SkDeferredDevice::storageAllocatedForRecording() const {
return (fPipeController.storageAllocatedForRecording()
+ fPipeWriter.storageAllocatedForRecording());
}
-void DeferredDevice::recordedDrawCommand() {
+void SkDeferredDevice::recordedDrawCommand() {
size_t storageAllocated = this->storageAllocatedForRecording();
if (storageAllocated > fMaxRecordingStorageBytes) {
@@ -416,33 +414,25 @@ void DeferredDevice::recordedDrawCommand() {
}
}
-SkCanvas* DeferredDevice::recordingCanvas() {
+SkCanvas* SkDeferredDevice::recordingCanvas() {
return fRecordingCanvas;
}
-SkImage* DeferredDevice::newImageSnapshot() {
+SkImage* SkDeferredDevice::newImageSnapshot() {
this->flush();
return fSurface ? fSurface->newImageSnapshot() : NULL;
}
-uint32_t DeferredDevice::getDeviceCapabilities() {
- return immediateDevice()->getDeviceCapabilities();
-}
-
-int DeferredDevice::width() const {
- return immediateDevice()->width();
-}
-
-int DeferredDevice::height() const {
- return immediateDevice()->height();
+SkImageInfo SkDeferredDevice::imageInfo() const {
+ return immediateDevice()->imageInfo();
}
-GrRenderTarget* DeferredDevice::accessRenderTarget() {
+GrRenderTarget* SkDeferredDevice::accessRenderTarget() {
this->flushPendingCommands(kNormal_PlaybackMode);
return immediateDevice()->accessRenderTarget();
}
-void DeferredDevice::prepareForImmediatePixelWrite() {
+void SkDeferredDevice::prepareForImmediatePixelWrite() {
// The purpose of the following code is to make sure commands are flushed, that
// aboutToDraw() is called and that notifyContentWillChange is called, without
// calling anything redundantly.
@@ -459,59 +449,47 @@ void DeferredDevice::prepareForImmediatePixelWrite() {
fImmediateCanvas->flush();
}
-void DeferredDevice::writePixels(const SkBitmap& bitmap,
- int x, int y, SkCanvas::Config8888 config8888) {
+bool SkDeferredDevice::onWritePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes,
+ int x, int y) {
+ SkASSERT(x >= 0 && y >= 0);
+ SkASSERT(x + info.width() <= width());
+ SkASSERT(y + info.height() <= height());
- if (x <= 0 && y <= 0 && (x + bitmap.width()) >= width() &&
- (y + bitmap.height()) >= height()) {
- this->skipPendingCommands();
- }
+ this->flushPendingCommands(kNormal_PlaybackMode);
- if (SkBitmap::kARGB_8888_Config == bitmap.config() &&
- SkCanvas::kNative_Premul_Config8888 != config8888 &&
- kPMColorAlias != config8888) {
- //Special case config: no deferral
- prepareForImmediatePixelWrite();
- immediateDevice()->writePixels(bitmap, x, y, config8888);
- return;
+ const SkImageInfo deviceInfo = this->imageInfo();
+ if (info.width() == deviceInfo.width() && info.height() == deviceInfo.height()) {
+ this->skipPendingCommands();
}
- SkPaint paint;
- paint.setXfermodeMode(SkXfermode::kSrc_Mode);
- if (shouldDrawImmediately(&bitmap, NULL, getBitmapSizeThreshold())) {
- prepareForImmediatePixelWrite();
- fImmediateCanvas->drawSprite(bitmap, x, y, &paint);
- } else {
- this->recordingCanvas()->drawSprite(bitmap, x, y, &paint);
- this->recordedDrawCommand();
-
- }
+ this->prepareForImmediatePixelWrite();
+ return immediateDevice()->onWritePixels(info, pixels, rowBytes, x, y);
}
-const SkBitmap& DeferredDevice::onAccessBitmap() {
+const SkBitmap& SkDeferredDevice::onAccessBitmap() {
this->flushPendingCommands(kNormal_PlaybackMode);
return immediateDevice()->accessBitmap(false);
}
-SkBaseDevice* DeferredDevice::onCreateCompatibleDevice(
- SkBitmap::Config config, int width, int height, bool isOpaque,
- Usage usage) {
-
+SkBaseDevice* SkDeferredDevice::onCreateDevice(const SkImageInfo& info, Usage usage) {
// Save layer usage not supported, and not required by SkDeferredCanvas.
SkASSERT(usage != kSaveLayer_Usage);
// Create a compatible non-deferred device.
// We do not create a deferred device because we know the new device
// will not be used with a deferred canvas (there is no API for that).
- // And connecting a DeferredDevice to non-deferred canvas can result
+ // And connecting a SkDeferredDevice to non-deferred canvas can result
// in unpredictable behavior.
- return immediateDevice()->createCompatibleDevice(config, width, height, isOpaque);
+ return immediateDevice()->createCompatibleDevice(info);
}
-bool DeferredDevice::onReadPixels(
- const SkBitmap& bitmap, int x, int y, SkCanvas::Config8888 config8888) {
+SkSurface* SkDeferredDevice::newSurface(const SkImageInfo& info) {
+ return this->immediateDevice()->newSurface(info);
+}
+
+bool SkDeferredDevice::onReadPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
+ int x, int y) {
this->flushPendingCommands(kNormal_PlaybackMode);
- return fImmediateCanvas->readPixels(const_cast<SkBitmap*>(&bitmap),
- x, y, config8888);
+ return fImmediateCanvas->readPixels(info, pixels, rowBytes, x, y);
}
class AutoImmediateDrawIfNeeded {
@@ -533,7 +511,7 @@ public:
private:
void init(SkDeferredCanvas& canvas, const SkBitmap* bitmap, const SkPaint* paint)
{
- DeferredDevice* device = static_cast<DeferredDevice*>(canvas.getDevice());
+ SkDeferredDevice* device = static_cast<SkDeferredDevice*>(canvas.getDevice());
if (canvas.isDeferredDrawing() && (NULL != device) &&
shouldDrawImmediately(bitmap, paint, device->getBitmapSizeThreshold())) {
canvas.setDeferredDrawing(false);
@@ -547,16 +525,11 @@ private:
};
SkDeferredCanvas* SkDeferredCanvas::Create(SkSurface* surface) {
- SkAutoTUnref<DeferredDevice> deferredDevice(SkNEW_ARGS(DeferredDevice, (surface)));
+ SkAutoTUnref<SkDeferredDevice> deferredDevice(SkNEW_ARGS(SkDeferredDevice, (surface)));
return SkNEW_ARGS(SkDeferredCanvas, (deferredDevice));
}
-SkDeferredCanvas* SkDeferredCanvas::Create(SkBaseDevice* device) {
- SkAutoTUnref<DeferredDevice> deferredDevice(SkNEW_ARGS(DeferredDevice, (device)));
- return SkNEW_ARGS(SkDeferredCanvas, (deferredDevice));
-}
-
-SkDeferredCanvas::SkDeferredCanvas(DeferredDevice* device) : SkCanvas (device) {
+SkDeferredCanvas::SkDeferredCanvas(SkDeferredDevice* device) : SkCanvas (device) {
this->init();
}
@@ -578,7 +551,7 @@ size_t SkDeferredCanvas::freeMemoryIfPossible(size_t bytesToFree) {
}
void SkDeferredCanvas::setBitmapSizeThreshold(size_t sizeThreshold) {
- DeferredDevice* deferredDevice = this->getDeferredDevice();
+ SkDeferredDevice* deferredDevice = this->getDeferredDevice();
SkASSERT(deferredDevice);
deferredDevice->setBitmapSizeThreshold(sizeThreshold);
}
@@ -604,8 +577,8 @@ SkCanvas* SkDeferredCanvas::immediateCanvas() const {
return this->getDeferredDevice()->immediateCanvas();
}
-DeferredDevice* SkDeferredCanvas::getDeferredDevice() const {
- return static_cast<DeferredDevice*>(this->getDevice());
+SkDeferredDevice* SkDeferredCanvas::getDeferredDevice() const {
+ return static_cast<SkDeferredDevice*>(this->getDevice());
}
void SkDeferredCanvas::setDeferredDrawing(bool val) {
@@ -641,7 +614,7 @@ SkDeferredCanvas::~SkDeferredCanvas() {
}
SkSurface* SkDeferredCanvas::setSurface(SkSurface* surface) {
- DeferredDevice* deferredDevice = this->getDeferredDevice();
+ SkDeferredDevice* deferredDevice = this->getDeferredDevice();
SkASSERT(NULL != deferredDevice);
// By swapping the surface into the existing device, we preserve
// all pending commands, which can help to seamlessly recover from
@@ -653,7 +626,7 @@ SkSurface* SkDeferredCanvas::setSurface(SkSurface* surface) {
SkDeferredCanvas::NotificationClient* SkDeferredCanvas::setNotificationClient(
NotificationClient* notificationClient) {
- DeferredDevice* deferredDevice = this->getDeferredDevice();
+ SkDeferredDevice* deferredDevice = this->getDeferredDevice();
SkASSERT(deferredDevice);
if (deferredDevice) {
deferredDevice->setNotificationClient(notificationClient);
@@ -662,7 +635,7 @@ SkDeferredCanvas::NotificationClient* SkDeferredCanvas::setNotificationClient(
}
SkImage* SkDeferredCanvas::newImageSnapshot() {
- DeferredDevice* deferredDevice = this->getDeferredDevice();
+ SkDeferredDevice* deferredDevice = this->getDeferredDevice();
SkASSERT(deferredDevice);
return deferredDevice ? deferredDevice->newImageSnapshot() : NULL;
}
@@ -705,108 +678,71 @@ bool SkDeferredCanvas::isFullFrame(const SkRect* rect,
SkIntToScalar(canvasSize.fWidth), SkIntToScalar(canvasSize.fHeight)));
}
-int SkDeferredCanvas::save(SaveFlags flags) {
+void SkDeferredCanvas::willSave(SaveFlags flags) {
this->drawingCanvas()->save(flags);
- int val = this->INHERITED::save(flags);
this->recordedDrawCommand();
-
- return val;
+ this->INHERITED::willSave(flags);
}
-int SkDeferredCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
- SaveFlags flags) {
+SkCanvas::SaveLayerStrategy SkDeferredCanvas::willSaveLayer(const SkRect* bounds,
+ const SkPaint* paint, SaveFlags flags) {
this->drawingCanvas()->saveLayer(bounds, paint, flags);
- int count = this->INHERITED::save(flags);
- this->clipRectBounds(bounds, flags, NULL);
this->recordedDrawCommand();
-
- return count;
+ this->INHERITED::willSaveLayer(bounds, paint, flags);
+ // No need for a full layer.
+ return kNoLayer_SaveLayerStrategy;
}
-void SkDeferredCanvas::restore() {
+void SkDeferredCanvas::willRestore() {
this->drawingCanvas()->restore();
- this->INHERITED::restore();
this->recordedDrawCommand();
+ this->INHERITED::willRestore();
}
bool SkDeferredCanvas::isDrawingToLayer() const {
return this->drawingCanvas()->isDrawingToLayer();
}
-bool SkDeferredCanvas::translate(SkScalar dx, SkScalar dy) {
- this->drawingCanvas()->translate(dx, dy);
- bool val = this->INHERITED::translate(dx, dy);
- this->recordedDrawCommand();
- return val;
-}
-
-bool SkDeferredCanvas::scale(SkScalar sx, SkScalar sy) {
- this->drawingCanvas()->scale(sx, sy);
- bool val = this->INHERITED::scale(sx, sy);
- this->recordedDrawCommand();
- return val;
-}
-
-bool SkDeferredCanvas::rotate(SkScalar degrees) {
- this->drawingCanvas()->rotate(degrees);
- bool val = this->INHERITED::rotate(degrees);
- this->recordedDrawCommand();
- return val;
-}
-
-bool SkDeferredCanvas::skew(SkScalar sx, SkScalar sy) {
- this->drawingCanvas()->skew(sx, sy);
- bool val = this->INHERITED::skew(sx, sy);
- this->recordedDrawCommand();
- return val;
-}
-
-bool SkDeferredCanvas::concat(const SkMatrix& matrix) {
+void SkDeferredCanvas::didConcat(const SkMatrix& matrix) {
this->drawingCanvas()->concat(matrix);
- bool val = this->INHERITED::concat(matrix);
this->recordedDrawCommand();
- return val;
+ this->INHERITED::didConcat(matrix);
}
-void SkDeferredCanvas::setMatrix(const SkMatrix& matrix) {
+void SkDeferredCanvas::didSetMatrix(const SkMatrix& matrix) {
this->drawingCanvas()->setMatrix(matrix);
- this->INHERITED::setMatrix(matrix);
this->recordedDrawCommand();
+ this->INHERITED::didSetMatrix(matrix);
}
-bool SkDeferredCanvas::clipRect(const SkRect& rect,
- SkRegion::Op op,
- bool doAntiAlias) {
- this->drawingCanvas()->clipRect(rect, op, doAntiAlias);
- bool val = this->INHERITED::clipRect(rect, op, doAntiAlias);
+void SkDeferredCanvas::onClipRect(const SkRect& rect,
+ SkRegion::Op op,
+ ClipEdgeStyle edgeStyle) {
+ this->drawingCanvas()->clipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
+ this->INHERITED::onClipRect(rect, op, edgeStyle);
this->recordedDrawCommand();
- return val;
}
-bool SkDeferredCanvas::clipRRect(const SkRRect& rrect,
- SkRegion::Op op,
- bool doAntiAlias) {
- this->drawingCanvas()->clipRRect(rrect, op, doAntiAlias);
- bool val = this->INHERITED::clipRRect(rrect, op, doAntiAlias);
+void SkDeferredCanvas::onClipRRect(const SkRRect& rrect,
+ SkRegion::Op op,
+ ClipEdgeStyle edgeStyle) {
+ this->drawingCanvas()->clipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
+ this->INHERITED::onClipRRect(rrect, op, edgeStyle);
this->recordedDrawCommand();
- return val;
}
-bool SkDeferredCanvas::clipPath(const SkPath& path,
- SkRegion::Op op,
- bool doAntiAlias) {
- this->drawingCanvas()->clipPath(path, op, doAntiAlias);
- bool val = this->INHERITED::clipPath(path, op, doAntiAlias);
+void SkDeferredCanvas::onClipPath(const SkPath& path,
+ SkRegion::Op op,
+ ClipEdgeStyle edgeStyle) {
+ this->drawingCanvas()->clipPath(path, op, kSoft_ClipEdgeStyle == edgeStyle);
+ this->INHERITED::onClipPath(path, op, edgeStyle);
this->recordedDrawCommand();
- return val;
}
-bool SkDeferredCanvas::clipRegion(const SkRegion& deviceRgn,
- SkRegion::Op op) {
+void SkDeferredCanvas::onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op) {
this->drawingCanvas()->clipRegion(deviceRgn, op);
- bool val = this->INHERITED::clipRegion(deviceRgn, op);
+ this->INHERITED::onClipRegion(deviceRgn, op);
this->recordedDrawCommand();
- return val;
}
void SkDeferredCanvas::clear(SkColor color) {
@@ -865,6 +801,13 @@ void SkDeferredCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
}
}
+void SkDeferredCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
+ const SkPaint& paint) {
+ AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
+ this->drawingCanvas()->drawDRRect(outer, inner, paint);
+ this->recordedDrawCommand();
+}
+
void SkDeferredCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
this->drawingCanvas()->drawPath(path, paint);
@@ -941,38 +884,35 @@ void SkDeferredCanvas::drawSprite(const SkBitmap& bitmap, int left, int top,
this->recordedDrawCommand();
}
-void SkDeferredCanvas::drawText(const void* text, size_t byteLength,
- SkScalar x, SkScalar y, const SkPaint& paint) {
+void SkDeferredCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
+ const SkPaint& paint) {
AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
this->drawingCanvas()->drawText(text, byteLength, x, y, paint);
this->recordedDrawCommand();
}
-void SkDeferredCanvas::drawPosText(const void* text, size_t byteLength,
- const SkPoint pos[], const SkPaint& paint) {
+void SkDeferredCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
+ const SkPaint& paint) {
AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
this->drawingCanvas()->drawPosText(text, byteLength, pos, paint);
this->recordedDrawCommand();
}
-void SkDeferredCanvas::drawPosTextH(const void* text, size_t byteLength,
- const SkScalar xpos[], SkScalar constY,
- const SkPaint& paint) {
+void SkDeferredCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
+ SkScalar constY, const SkPaint& paint) {
AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
this->drawingCanvas()->drawPosTextH(text, byteLength, xpos, constY, paint);
this->recordedDrawCommand();
}
-void SkDeferredCanvas::drawTextOnPath(const void* text, size_t byteLength,
- const SkPath& path,
- const SkMatrix* matrix,
- const SkPaint& paint) {
+void SkDeferredCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
+ const SkMatrix* matrix, const SkPaint& paint) {
AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
this->drawingCanvas()->drawTextOnPath(text, byteLength, path, matrix, paint);
this->recordedDrawCommand();
}
-void SkDeferredCanvas::drawPicture(SkPicture& picture) {
+void SkDeferredCanvas::onDrawPicture(const SkPicture* picture) {
this->drawingCanvas()->drawPicture(picture);
this->recordedDrawCommand();
}
@@ -989,13 +929,6 @@ void SkDeferredCanvas::drawVertices(VertexMode vmode, int vertexCount,
this->recordedDrawCommand();
}
-SkBounder* SkDeferredCanvas::setBounder(SkBounder* bounder) {
- this->drawingCanvas()->setBounder(bounder);
- this->INHERITED::setBounder(bounder);
- this->recordedDrawCommand();
- return bounder;
-}
-
SkDrawFilter* SkDeferredCanvas::setDrawFilter(SkDrawFilter* filter) {
this->drawingCanvas()->setDrawFilter(filter);
this->INHERITED::setDrawFilter(filter);
diff --git a/chromium/third_party/skia/src/utils/SkDumpCanvas.cpp b/chromium/third_party/skia/src/utils/SkDumpCanvas.cpp
index dabf0d79890..4dfed395e0e 100644
--- a/chromium/third_party/skia/src/utils/SkDumpCanvas.cpp
+++ b/chromium/third_party/skia/src/utils/SkDumpCanvas.cpp
@@ -163,15 +163,9 @@ static void toString(const void* text, size_t byteLen, SkPaint::TextEncoding enc
///////////////////////////////////////////////////////////////////////////////
-static SkBitmap make_wideopen_bm() {
- static const int WIDE_OPEN = 16384;
+#define WIDE_OPEN 16384
- SkBitmap bm;
- bm.setConfig(SkBitmap::kNo_Config, WIDE_OPEN, WIDE_OPEN);
- return bm;
-}
-
-SkDumpCanvas::SkDumpCanvas(Dumper* dumper) : INHERITED(make_wideopen_bm()) {
+SkDumpCanvas::SkDumpCanvas(Dumper* dumper) : INHERITED(WIDE_OPEN, WIDE_OPEN) {
fNestLevel = 0;
SkSafeRef(dumper);
fDumper = dumper;
@@ -198,13 +192,13 @@ void SkDumpCanvas::dump(Verb verb, const SkPaint* paint,
///////////////////////////////////////////////////////////////////////////////
-int SkDumpCanvas::save(SaveFlags flags) {
+void SkDumpCanvas::willSave(SaveFlags flags) {
this->dump(kSave_Verb, NULL, "save(0x%X)", flags);
- return this->INHERITED::save(flags);
+ this->INHERITED::willSave(flags);
}
-int SkDumpCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
- SaveFlags flags) {
+SkCanvas::SaveLayerStrategy SkDumpCanvas::willSaveLayer(const SkRect* bounds, const SkPaint* paint,
+ SaveFlags flags) {
SkString str;
str.printf("saveLayer(0x%X)", flags);
if (bounds) {
@@ -220,89 +214,91 @@ int SkDumpCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
}
}
this->dump(kSave_Verb, paint, str.c_str());
- return this->INHERITED::saveLayer(bounds, paint, flags);
+ return this->INHERITED::willSaveLayer(bounds, paint, flags);
}
-void SkDumpCanvas::restore() {
- this->INHERITED::restore();
+void SkDumpCanvas::willRestore() {
this->dump(kRestore_Verb, NULL, "restore");
+ this->INHERITED::willRestore();
}
-bool SkDumpCanvas::translate(SkScalar dx, SkScalar dy) {
- this->dump(kMatrix_Verb, NULL, "translate(%g %g)",
- SkScalarToFloat(dx), SkScalarToFloat(dy));
- return this->INHERITED::translate(dx, dy);
-}
-
-bool SkDumpCanvas::scale(SkScalar sx, SkScalar sy) {
- this->dump(kMatrix_Verb, NULL, "scale(%g %g)",
- SkScalarToFloat(sx), SkScalarToFloat(sy));
- return this->INHERITED::scale(sx, sy);
-}
-
-bool SkDumpCanvas::rotate(SkScalar degrees) {
- this->dump(kMatrix_Verb, NULL, "rotate(%g)", SkScalarToFloat(degrees));
- return this->INHERITED::rotate(degrees);
-}
+void SkDumpCanvas::didConcat(const SkMatrix& matrix) {
+ SkString str;
-bool SkDumpCanvas::skew(SkScalar sx, SkScalar sy) {
- this->dump(kMatrix_Verb, NULL, "skew(%g %g)",
- SkScalarToFloat(sx), SkScalarToFloat(sy));
- return this->INHERITED::skew(sx, sy);
-}
+ switch (matrix.getType()) {
+ case SkMatrix::kTranslate_Mask:
+ this->dump(kMatrix_Verb, NULL, "translate(%g %g)",
+ SkScalarToFloat(matrix.getTranslateX()),
+ SkScalarToFloat(matrix.getTranslateY()));
+ break;
+ case SkMatrix::kScale_Mask:
+ this->dump(kMatrix_Verb, NULL, "scale(%g %g)",
+ SkScalarToFloat(matrix.getScaleX()),
+ SkScalarToFloat(matrix.getScaleY()));
+ break;
+ default:
+ matrix.toString(&str);
+ this->dump(kMatrix_Verb, NULL, "concat(%s)", str.c_str());
+ break;
+ }
-bool SkDumpCanvas::concat(const SkMatrix& matrix) {
- SkString str;
- matrix.toString(&str);
- this->dump(kMatrix_Verb, NULL, "concat(%s)", str.c_str());
- return this->INHERITED::concat(matrix);
+ this->INHERITED::didConcat(matrix);
}
-void SkDumpCanvas::setMatrix(const SkMatrix& matrix) {
+void SkDumpCanvas::didSetMatrix(const SkMatrix& matrix) {
SkString str;
matrix.toString(&str);
this->dump(kMatrix_Verb, NULL, "setMatrix(%s)", str.c_str());
- this->INHERITED::setMatrix(matrix);
+ this->INHERITED::didSetMatrix(matrix);
}
///////////////////////////////////////////////////////////////////////////////
-static const char* bool_to_aastring(bool doAA) {
- return doAA ? "AA" : "BW";
+const char* SkDumpCanvas::EdgeStyleToAAString(ClipEdgeStyle edgeStyle) {
+ return kSoft_ClipEdgeStyle == edgeStyle ? "AA" : "BW";
}
-bool SkDumpCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
+void SkDumpCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
SkString str;
toString(rect, &str);
this->dump(kClip_Verb, NULL, "clipRect(%s %s %s)", str.c_str(), toString(op),
- bool_to_aastring(doAA));
- return this->INHERITED::clipRect(rect, op, doAA);
+ EdgeStyleToAAString(edgeStyle));
+ this->INHERITED::onClipRect(rect, op, edgeStyle);
}
-bool SkDumpCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
+void SkDumpCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
SkString str;
toString(rrect, &str);
this->dump(kClip_Verb, NULL, "clipRRect(%s %s %s)", str.c_str(), toString(op),
- bool_to_aastring(doAA));
- return this->INHERITED::clipRRect(rrect, op, doAA);
+ EdgeStyleToAAString(edgeStyle));
+ this->INHERITED::onClipRRect(rrect, op, edgeStyle);
}
-bool SkDumpCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
+void SkDumpCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
SkString str;
toString(path, &str);
this->dump(kClip_Verb, NULL, "clipPath(%s %s %s)", str.c_str(), toString(op),
- bool_to_aastring(doAA));
- return this->INHERITED::clipPath(path, op, doAA);
+ EdgeStyleToAAString(edgeStyle));
+ this->INHERITED::onClipPath(path, op, edgeStyle);
}
-bool SkDumpCanvas::clipRegion(const SkRegion& deviceRgn, SkRegion::Op op) {
+void SkDumpCanvas::onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op) {
SkString str;
toString(deviceRgn, &str);
this->dump(kClip_Verb, NULL, "clipRegion(%s %s)", str.c_str(),
toString(op));
- return this->INHERITED::clipRegion(deviceRgn, op);
+ this->INHERITED::onClipRegion(deviceRgn, op);
+}
+
+void SkDumpCanvas::onPushCull(const SkRect& cullRect) {
+ SkString str;
+ toString(cullRect, &str);
+ this->dump(kCull_Verb, NULL, "pushCull(%s)", str.c_str());
}
+void SkDumpCanvas::onPopCull() {
+ this->dump(kCull_Verb, NULL, "popCull()");
+}
///////////////////////////////////////////////////////////////////////////////
void SkDumpCanvas::drawPaint(const SkPaint& paint) {
@@ -330,7 +326,16 @@ void SkDumpCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
void SkDumpCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
SkString str;
toString(rrect, &str);
- this->dump(kDrawRRect_Verb, &paint, "drawRRect(%s)", str.c_str());
+ this->dump(kDrawDRRect_Verb, &paint, "drawRRect(%s)", str.c_str());
+}
+
+void SkDumpCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
+ const SkPaint& paint) {
+ SkString str0, str1;
+ toString(outer, &str0);
+ toString(inner, &str0);
+ this->dump(kDrawRRect_Verb, &paint, "drawDRRect(%s,%s)",
+ str0.c_str(), str1.c_str());
}
void SkDumpCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
@@ -383,16 +388,16 @@ void SkDumpCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
x, y);
}
-void SkDumpCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
- SkScalar y, const SkPaint& paint) {
+void SkDumpCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
+ const SkPaint& paint) {
SkString str;
toString(text, byteLength, paint.getTextEncoding(), &str);
this->dump(kDrawText_Verb, &paint, "drawText(%s [%d] %g %g)", str.c_str(),
byteLength, SkScalarToFloat(x), SkScalarToFloat(y));
}
-void SkDumpCanvas::drawPosText(const void* text, size_t byteLength,
- const SkPoint pos[], const SkPaint& paint) {
+void SkDumpCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
+ const SkPaint& paint) {
SkString str;
toString(text, byteLength, paint.getTextEncoding(), &str);
this->dump(kDrawText_Verb, &paint, "drawPosText(%s [%d] %g %g ...)",
@@ -400,9 +405,8 @@ void SkDumpCanvas::drawPosText(const void* text, size_t byteLength,
SkScalarToFloat(pos[0].fY));
}
-void SkDumpCanvas::drawPosTextH(const void* text, size_t byteLength,
- const SkScalar xpos[], SkScalar constY,
- const SkPaint& paint) {
+void SkDumpCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
+ SkScalar constY, const SkPaint& paint) {
SkString str;
toString(text, byteLength, paint.getTextEncoding(), &str);
this->dump(kDrawText_Verb, &paint, "drawPosTextH(%s [%d] %g %g ...)",
@@ -410,23 +414,22 @@ void SkDumpCanvas::drawPosTextH(const void* text, size_t byteLength,
SkScalarToFloat(constY));
}
-void SkDumpCanvas::drawTextOnPath(const void* text, size_t byteLength,
- const SkPath& path, const SkMatrix* matrix,
- const SkPaint& paint) {
+void SkDumpCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
+ const SkMatrix* matrix, const SkPaint& paint) {
SkString str;
toString(text, byteLength, paint.getTextEncoding(), &str);
this->dump(kDrawText_Verb, &paint, "drawTextOnPath(%s [%d])",
str.c_str(), byteLength);
}
-void SkDumpCanvas::drawPicture(SkPicture& picture) {
- this->dump(kDrawPicture_Verb, NULL, "drawPicture(%p) %d:%d", &picture,
- picture.width(), picture.height());
+void SkDumpCanvas::onDrawPicture(const SkPicture* picture) {
+ this->dump(kDrawPicture_Verb, NULL, "drawPicture(%p) %d:%d", picture,
+ picture->width(), picture->height());
fNestLevel += 1;
- this->INHERITED::drawPicture(picture);
+ this->INHERITED::onDrawPicture(picture);
fNestLevel -= 1;
this->dump(kDrawPicture_Verb, NULL, "endPicture(%p) %d:%d", &picture,
- picture.width(), picture.height());
+ picture->width(), picture->height());
}
void SkDumpCanvas::drawVertices(VertexMode vmode, int vertexCount,
diff --git a/chromium/third_party/skia/src/utils/SkEventTracer.cpp b/chromium/third_party/skia/src/utils/SkEventTracer.cpp
new file mode 100644
index 00000000000..65e83723959
--- /dev/null
+++ b/chromium/third_party/skia/src/utils/SkEventTracer.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkEventTracer.h"
+#include "SkOnce.h"
+
+class SkDefaultEventTracer: public SkEventTracer {
+ virtual SkEventTracer::Handle
+ addTraceEvent(char phase,
+ const uint8_t* categoryEnabledFlag,
+ const char* name,
+ uint64_t id,
+ int numArgs,
+ const char** argNames,
+ const uint8_t* argTypes,
+ const uint64_t* argValues,
+ uint8_t flags) SK_OVERRIDE { return 0; }
+
+ virtual void
+ updateTraceEventDuration(const uint8_t* categoryEnabledFlag,
+ const char* name,
+ SkEventTracer::Handle handle) SK_OVERRIDE {};
+
+ virtual const uint8_t* getCategoryGroupEnabled(const char* name) SK_OVERRIDE {
+ static uint8_t no = 0;
+ return &no;
+ };
+ virtual const char* getCategoryGroupName(
+ const uint8_t* categoryEnabledFlag) SK_OVERRIDE {
+ static const char* dummy = "dummy";
+ return dummy;
+ };
+};
+
+SkEventTracer* SkEventTracer::gInstance;
+
+static void cleanup_tracer() {
+ // calling SetInstance will delete the existing instance.
+ SkEventTracer::SetInstance(NULL);
+}
+
+static void intialize_default_tracer(SkEventTracer* current_instance) {
+ if (NULL == current_instance) {
+ SkEventTracer::SetInstance(SkNEW(SkDefaultEventTracer));
+ }
+ atexit(cleanup_tracer);
+}
+
+
+SkEventTracer* SkEventTracer::GetInstance() {
+ SK_DECLARE_STATIC_ONCE(once);
+ SkOnce(&once, intialize_default_tracer, SkEventTracer::gInstance);
+ SkASSERT(NULL != SkEventTracer::gInstance);
+ return SkEventTracer::gInstance;
+}
diff --git a/chromium/third_party/skia/src/utils/SkFrontBufferedStream.cpp b/chromium/third_party/skia/src/utils/SkFrontBufferedStream.cpp
index d44389b7c81..8cb3931082c 100644
--- a/chromium/third_party/skia/src/utils/SkFrontBufferedStream.cpp
+++ b/chromium/third_party/skia/src/utils/SkFrontBufferedStream.cpp
@@ -24,14 +24,16 @@ public:
virtual size_t getPosition() const SK_OVERRIDE { return fOffset; }
- virtual bool hasLength() const SK_OVERRIDE;
+ virtual bool hasLength() const SK_OVERRIDE { return fHasLength; }
- virtual size_t getLength() const SK_OVERRIDE;
+ virtual size_t getLength() const SK_OVERRIDE { return fLength; }
virtual SkStreamRewindable* duplicate() const SK_OVERRIDE { return NULL; }
private:
SkAutoTUnref<SkStream> fStream;
+ const bool fHasLength;
+ const size_t fLength;
// Current offset into the stream. Always >= 0.
size_t fOffset;
// Amount that has been buffered by calls to read. Will always be less than
@@ -70,6 +72,8 @@ SkStreamRewindable* SkFrontBufferedStream::Create(SkStream* stream, size_t buffe
FrontBufferedStream::FrontBufferedStream(SkStream* stream, size_t bufferSize)
: fStream(SkRef(stream))
+ , fHasLength(stream->hasPosition() && stream->hasLength())
+ , fLength(stream->getLength() - stream->getPosition())
, fOffset(0)
, fBufferedSoFar(0)
, fBufferSize(bufferSize)
@@ -94,14 +98,6 @@ bool FrontBufferedStream::rewind() {
return false;
}
-bool FrontBufferedStream::hasLength() const {
- return fStream->hasLength();
-}
-
-size_t FrontBufferedStream::getLength() const {
- return fStream->getLength();
-}
-
size_t FrontBufferedStream::readFromBuffer(char* dst, size_t size) {
SkASSERT(fOffset < fBufferedSoFar);
// Some data has already been copied to fBuffer. Read up to the
diff --git a/chromium/third_party/skia/src/utils/SkGatherPixelRefsAndRects.cpp b/chromium/third_party/skia/src/utils/SkGatherPixelRefsAndRects.cpp
new file mode 100644
index 00000000000..f46fe8ed42f
--- /dev/null
+++ b/chromium/third_party/skia/src/utils/SkGatherPixelRefsAndRects.cpp
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkGatherPixelRefsAndRects.h"
+#include "SkNoSaveLayerCanvas.h"
+#include "SkPictureUtils.h"
+
+void SkPictureUtils::GatherPixelRefsAndRects(SkPicture* pict,
+ SkPictureUtils::SkPixelRefContainer* prCont) {
+ if (0 == pict->width() || 0 == pict->height()) {
+ return ;
+ }
+
+ SkGatherPixelRefsAndRectsDevice device(pict->width(), pict->height(), prCont);
+ SkNoSaveLayerCanvas canvas(&device);
+
+ canvas.clipRect(SkRect::MakeWH(SkIntToScalar(pict->width()),
+ SkIntToScalar(pict->height())),
+ SkRegion::kIntersect_Op, false);
+ canvas.drawPicture(pict);
+}
diff --git a/chromium/third_party/skia/src/utils/SkGatherPixelRefsAndRects.h b/chromium/third_party/skia/src/utils/SkGatherPixelRefsAndRects.h
new file mode 100644
index 00000000000..df3651e2e52
--- /dev/null
+++ b/chromium/third_party/skia/src/utils/SkGatherPixelRefsAndRects.h
@@ -0,0 +1,333 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkGatherPixelRefsAndRects_DEFINED
+#define SkGatherPixelRefsAndRects_DEFINED
+
+#include "SkBitmap.h"
+#include "SkDevice.h"
+#include "SkDraw.h"
+#include "SkPictureUtils.h"
+#include "SkRasterClip.h"
+#include "SkRefCnt.h"
+#include "SkRRect.h"
+#include "SkTypes.h"
+
+// This GatherPixelRefs device passes all discovered pixel refs and their
+// device bounds to the user provided SkPixelRefContainer-derived object
+class SkGatherPixelRefsAndRectsDevice : public SkBaseDevice {
+public:
+ SK_DECLARE_INST_COUNT(SkGatherPixelRefsAndRectsDevice)
+
+ SkGatherPixelRefsAndRectsDevice(int width, int height,
+ SkPictureUtils::SkPixelRefContainer* prCont) {
+ fSize.set(width, height);
+ fPRCont = prCont;
+ SkSafeRef(fPRCont);
+ fEmptyBitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
+ }
+
+ virtual ~SkGatherPixelRefsAndRectsDevice() {
+ SkSafeUnref(fPRCont);
+ }
+
+ virtual SkImageInfo imageInfo() const SK_OVERRIDE {
+ return fEmptyBitmap.info();
+ }
+
+ virtual GrRenderTarget* accessRenderTarget() SK_OVERRIDE { return NULL; }
+
+protected:
+ virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) SK_OVERRIDE {
+ return false;
+ }
+ virtual void clear(SkColor color) SK_OVERRIDE {
+ NothingToDo();
+ }
+ virtual void drawPaint(const SkDraw& draw, const SkPaint& paint) SK_OVERRIDE {
+ SkBitmap bm;
+
+ if (GetBitmapFromPaint(paint, &bm)) {
+ SkRect clipRect = SkRect::Make(draw.fRC->getBounds());
+ fPRCont->add(bm.pixelRef(), clipRect);
+ }
+ }
+ virtual void drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count,
+ const SkPoint points[], const SkPaint& paint) SK_OVERRIDE {
+ SkBitmap bm;
+ if (!GetBitmapFromPaint(paint, &bm)) {
+ return;
+ }
+
+ if (0 == count) {
+ return;
+ }
+
+ SkPoint min = points[0];
+ SkPoint max = points[0];
+ for (size_t i = 1; i < count; ++i) {
+ const SkPoint& point = points[i];
+
+ min.set(SkMinScalar(min.x(), point.x()), SkMinScalar(min.y(), point.y()));
+ max.set(SkMaxScalar(max.x(), point.x()), SkMaxScalar(max.y(), point.y()));
+ }
+
+ SkRect bounds = SkRect::MakeLTRB(min.x(), min.y(), max.x()+1, max.y()+1);
+
+ this->drawRect(draw, bounds, paint);
+ }
+ virtual void drawRect(const SkDraw& draw, const SkRect& rect,
+ const SkPaint& paint) SK_OVERRIDE {
+ SkBitmap bm;
+ if (GetBitmapFromPaint(paint, &bm)) {
+ SkRect mappedRect;
+ draw.fMatrix->mapRect(&mappedRect, rect);
+ SkRect clipRect = SkRect::Make(draw.fRC->getBounds());
+ mappedRect.intersect(clipRect);
+ fPRCont->add(bm.pixelRef(), mappedRect);
+ }
+ }
+ virtual void drawOval(const SkDraw& draw, const SkRect& rect,
+ const SkPaint& paint) SK_OVERRIDE {
+ this->drawRect(draw, rect, paint);
+ }
+ virtual void drawRRect(const SkDraw& draw, const SkRRect& rrect,
+ const SkPaint& paint) SK_OVERRIDE {
+ this->drawRect(draw, rrect.rect(), paint);
+ }
+ virtual void drawPath(const SkDraw& draw, const SkPath& path,
+ const SkPaint& paint, const SkMatrix* prePathMatrix,
+ bool pathIsMutable) SK_OVERRIDE {
+ SkBitmap bm;
+ if (!GetBitmapFromPaint(paint, &bm)) {
+ return;
+ }
+
+ SkRect pathBounds = path.getBounds();
+ if (NULL != prePathMatrix) {
+ prePathMatrix->mapRect(&pathBounds);
+ }
+
+ this->drawRect(draw, pathBounds, paint);
+ }
+ virtual void drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
+ const SkMatrix& matrix, const SkPaint& paint) SK_OVERRIDE {
+ SkMatrix totMatrix;
+ totMatrix.setConcat(*draw.fMatrix, matrix);
+
+ SkRect bitmapRect = SkRect::MakeWH(SkIntToScalar(bitmap.width()),
+ SkIntToScalar(bitmap.height()));
+ SkRect mappedRect;
+ totMatrix.mapRect(&mappedRect, bitmapRect);
+ fPRCont->add(bitmap.pixelRef(), mappedRect);
+
+ SkBitmap paintBitmap;
+ if (GetBitmapFromPaint(paint, &paintBitmap)) {
+ fPRCont->add(paintBitmap.pixelRef(), mappedRect);
+ }
+ }
+ virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
+ int x, int y, const SkPaint& paint) SK_OVERRIDE {
+ // Sprites aren't affected by current matrix, so we can't reuse drawRect.
+ SkMatrix matrix;
+ matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y));
+
+ SkRect bitmapRect = SkRect::MakeWH(SkIntToScalar(bitmap.width()),
+ SkIntToScalar(bitmap.height()));
+ SkRect mappedRect;
+ matrix.mapRect(&mappedRect, bitmapRect);
+ fPRCont->add(bitmap.pixelRef(), mappedRect);
+
+ SkBitmap paintBitmap;
+ if (GetBitmapFromPaint(paint, &paintBitmap)) {
+ fPRCont->add(paintBitmap.pixelRef(), mappedRect);
+ }
+ }
+ virtual void drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
+ const SkRect* srcOrNull, const SkRect& dst,
+ const SkPaint& paint,
+ SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE {
+ SkRect bitmapRect = SkRect::MakeWH(SkIntToScalar(bitmap.width()),
+ SkIntToScalar(bitmap.height()));
+ SkMatrix matrix;
+ matrix.setRectToRect(bitmapRect, dst, SkMatrix::kFill_ScaleToFit);
+ this->drawBitmap(draw, bitmap, matrix, paint);
+ }
+ virtual void drawText(const SkDraw& draw, const void* text, size_t len,
+ SkScalar x, SkScalar y,
+ const SkPaint& paint) SK_OVERRIDE {
+ SkBitmap bitmap;
+ if (!GetBitmapFromPaint(paint, &bitmap)) {
+ return;
+ }
+
+ // Math is borrowed from SkBBoxRecord
+ SkRect bounds;
+ paint.measureText(text, len, &bounds);
+ SkPaint::FontMetrics metrics;
+ paint.getFontMetrics(&metrics);
+
+ if (paint.isVerticalText()) {
+ SkScalar h = bounds.fBottom - bounds.fTop;
+ if (paint.getTextAlign() == SkPaint::kCenter_Align) {
+ bounds.fTop -= h / 2;
+ bounds.fBottom -= h / 2;
+ }
+ bounds.fBottom += metrics.fBottom;
+ bounds.fTop += metrics.fTop;
+ } else {
+ SkScalar w = bounds.fRight - bounds.fLeft;
+ if (paint.getTextAlign() == SkPaint::kCenter_Align) {
+ bounds.fLeft -= w / 2;
+ bounds.fRight -= w / 2;
+ } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
+ bounds.fLeft -= w;
+ bounds.fRight -= w;
+ }
+ bounds.fTop = metrics.fTop;
+ bounds.fBottom = metrics.fBottom;
+ }
+
+ SkScalar pad = (metrics.fBottom - metrics.fTop) / 2;
+ bounds.fLeft -= pad;
+ bounds.fRight += pad;
+ bounds.offset(x, y);
+
+ this->drawRect(draw, bounds, paint);
+ }
+ virtual void drawPosText(const SkDraw& draw, const void* text, size_t len,
+ const SkScalar pos[], SkScalar constY,
+ int scalarsPerPos, const SkPaint& paint) SK_OVERRIDE {
+ SkBitmap bitmap;
+ if (!GetBitmapFromPaint(paint, &bitmap)) {
+ return;
+ }
+
+ if (0 == len) {
+ return;
+ }
+
+ // Similar to SkDraw asserts.
+ SkASSERT(scalarsPerPos == 1 || scalarsPerPos == 2);
+
+ SkScalar y = scalarsPerPos == 1 ? constY : constY + pos[1];
+
+ SkPoint min, max;
+ min.set(pos[0], y);
+ max.set(pos[0], y);
+
+ for (size_t i = 1; i < len; ++i) {
+ SkScalar x = pos[i * scalarsPerPos];
+ SkScalar y = constY;
+ if (2 == scalarsPerPos) {
+ y += pos[i * scalarsPerPos + 1];
+ }
+
+ min.set(SkMinScalar(x, min.x()), SkMinScalar(y, min.y()));
+ max.set(SkMaxScalar(x, max.x()), SkMaxScalar(y, max.y()));
+ }
+
+ SkRect bounds = SkRect::MakeLTRB(min.x(), min.y(), max.x(), max.y());
+
+ // Math is borrowed from SkBBoxRecord
+ SkPaint::FontMetrics metrics;
+ paint.getFontMetrics(&metrics);
+
+ bounds.fTop += metrics.fTop;
+ bounds.fBottom += metrics.fBottom;
+
+ SkScalar pad = (metrics.fTop - metrics.fBottom) / 2;
+ bounds.fLeft -= pad;
+ bounds.fRight += pad;
+
+ this->drawRect(draw, bounds, paint);
+ }
+ virtual void drawTextOnPath(const SkDraw& draw, const void* text, size_t len,
+ const SkPath& path, const SkMatrix* matrix,
+ const SkPaint& paint) SK_OVERRIDE {
+ SkBitmap bitmap;
+ if (!GetBitmapFromPaint(paint, &bitmap)) {
+ return;
+ }
+
+ // Math is borrowed from SkBBoxRecord
+ SkRect bounds = path.getBounds();
+ SkPaint::FontMetrics metrics;
+ paint.getFontMetrics(&metrics);
+
+ SkScalar pad = metrics.fTop;
+ // TODO: inset?!
+ bounds.fLeft += pad;
+ bounds.fRight -= pad;
+ bounds.fTop += pad;
+ bounds.fBottom -= pad;
+
+ this->drawRect(draw, bounds, paint);
+ }
+ virtual void drawVertices(const SkDraw& draw, SkCanvas::VertexMode, int vertexCount,
+ const SkPoint verts[], const SkPoint texs[],
+ const SkColor colors[], SkXfermode* xmode,
+ const uint16_t indices[], int indexCount,
+ const SkPaint& paint) SK_OVERRIDE {
+ this->drawPoints(draw, SkCanvas::kPolygon_PointMode, vertexCount, verts, paint);
+ }
+ virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
+ const SkPaint&) SK_OVERRIDE {
+ NothingToDo();
+ }
+ // TODO: allow this call to return failure, or move to SkBitmapDevice only.
+ virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE {
+ return fEmptyBitmap;
+ }
+ virtual void lockPixels() SK_OVERRIDE { NothingToDo(); }
+ virtual void unlockPixels() SK_OVERRIDE { NothingToDo(); }
+ virtual bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
+ virtual bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
+ virtual bool filterImage(const SkImageFilter*, const SkBitmap&, const SkImageFilter::Context&,
+ SkBitmap* result, SkIPoint* offset) SK_OVERRIDE {
+ return false;
+ }
+
+private:
+ SkPictureUtils::SkPixelRefContainer* fPRCont;
+ SkISize fSize;
+
+ SkBitmap fEmptyBitmap; // legacy -- need to remove
+
+ static bool GetBitmapFromPaint(const SkPaint &paint, SkBitmap* bitmap) {
+ SkShader* shader = paint.getShader();
+ if (NULL != shader) {
+ if (SkShader::kNone_GradientType == shader->asAGradient(NULL)) {
+ return SkShader::kNone_BitmapType != shader->asABitmap(bitmap, NULL, NULL);
+ }
+ }
+ return false;
+ }
+
+ virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE {
+ NotSupported();
+ }
+
+ virtual SkBaseDevice* onCreateDevice(const SkImageInfo& info, Usage usage) SK_OVERRIDE {
+ // we expect to only get called via savelayer, in which case it is fine.
+ SkASSERT(kSaveLayer_Usage == usage);
+ return SkNEW_ARGS(SkGatherPixelRefsAndRectsDevice,
+ (info.width(), info.height(), fPRCont));
+ }
+
+ virtual void flush() SK_OVERRIDE {}
+
+ static void NotSupported() {
+ SkDEBUGFAIL("this method should never be called");
+ }
+
+ static void NothingToDo() {}
+
+ typedef SkBaseDevice INHERITED;
+};
+
+#endif // SkGatherPixelRefsAndRects_DEFINED
diff --git a/chromium/third_party/skia/src/utils/SkInterpolator.cpp b/chromium/third_party/skia/src/utils/SkInterpolator.cpp
index 2853b0703a6..dd884b881cc 100644
--- a/chromium/third_party/skia/src/utils/SkInterpolator.cpp
+++ b/chromium/third_party/skia/src/utils/SkInterpolator.cpp
@@ -77,11 +77,11 @@ SkInterpolatorBase::Result SkInterpolatorBase::timeToT(SkMSec time, SkScalar* T,
this->getDuration(&startTime, &endTime);
SkMSec totalTime = endTime - startTime;
SkMSec offsetTime = time - startTime;
- endTime = SkScalarMulFloor(fRepeat, totalTime);
+ endTime = SkScalarFloorToInt(fRepeat * totalTime);
if (offsetTime >= endTime) {
SkScalar fraction = SkScalarFraction(fRepeat);
offsetTime = fraction == 0 && fRepeat > 0 ? totalTime :
- (SkMSec) SkScalarMulFloor(fraction, totalTime);
+ (SkMSec) SkScalarFloorToInt(fraction * totalTime);
result = kFreezeEnd_Result;
} else {
int mirror = fFlags & kMirror;
@@ -155,11 +155,7 @@ void SkInterpolator::reset(int elemCount, int frameCount) {
#define SK_Fixed2Third (SK_Fixed1*2/3)
static const SkScalar gIdentityBlend[4] = {
-#ifdef SK_SCALAR_IS_FLOAT
0.33333333f, 0.33333333f, 0.66666667f, 0.66666667f
-#else
- SK_Fixed1Third, SK_Fixed1Third, SK_Fixed2Third, SK_Fixed2Third
-#endif
};
bool SkInterpolator::setKeyFrame(int index, SkMSec time,
diff --git a/chromium/third_party/skia/src/utils/SkJSON.cpp b/chromium/third_party/skia/src/utils/SkJSON.cpp
deleted file mode 100644
index 1aedf58d8b6..00000000000
--- a/chromium/third_party/skia/src/utils/SkJSON.cpp
+++ /dev/null
@@ -1,634 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkJSON.h"
-#include "SkString.h"
-
-#ifdef SK_DEBUG
-// #define TRACE_SKJSON_LEAKS
-#endif
-
-#ifdef TRACE_SKJSON_LEAKS
- static int gStringCount;
- static int gSlotCount;
- static int gObjectCount;
- static int gArrayCount;
- #define LEAK_CODE(code) code
-#else
- #define LEAK_CODE(code)
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-
-static char* alloc_string(size_t len) {
- LEAK_CODE(SkDebugf(" string[%d]\n", gStringCount++);)
- char* str = (char*)sk_malloc_throw(len + 1);
- str[len] = 0;
- return str;
-}
-
-static char* dup_string(const char src[]) {
- if (NULL == src) {
- return NULL;
- }
- size_t len = strlen(src);
- char* dst = alloc_string(len);
- memcpy(dst, src, len);
- return dst;
-}
-
-static void free_string(char* str) {
- if (str) {
- sk_free(str);
- LEAK_CODE(SkASSERT(gStringCount > 0); SkDebugf("~string[%d]\n", --gStringCount);)
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-struct SkJSON::Object::Slot {
- Slot(const char name[], Type type) {
- LEAK_CODE(SkDebugf(" slot[%d]\n", gSlotCount++);)
- SkASSERT(name);
-
- fNext = NULL;
-
- size_t len = strlen(name);
- // extra 1 for str[0] which stores the type
- char* str = alloc_string(1 + len);
- str[0] = (char)type;
- // str[1] skips the type, len+1 includes the terminating 0 byte.
- memcpy(&str[1], name, len + 1);
- fName = str;
-
- // fValue is uninitialized
- }
- ~Slot();
-
- Type type() const { return (Type)fName[0]; }
- const char* name() const { return &fName[1]; }
-
- Slot* fNext;
- char* fName; // fName[0] is the type, &fName[1] is the "name"
- union {
- Object* fObject;
- Array* fArray;
- char* fString;
- int32_t fInt;
- float fFloat;
- bool fBool;
- } fValue;
-};
-
-SkJSON::Object::Slot::~Slot() {
- free_string(fName);
- switch (this->type()) {
- case kObject:
- delete fValue.fObject;
- break;
- case kArray:
- delete fValue.fArray;
- break;
- case kString:
- free_string(fValue.fString);
- break;
- default:
- break;
- }
- LEAK_CODE(SkASSERT(gSlotCount > 0); SkDebugf("~slot[%d]\n", --gSlotCount);)
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-SkJSON::Object::Iter::Iter(const Object& obj) : fSlot(obj.fHead) {}
-
-bool SkJSON::Object::Iter::done() const {
- return NULL == fSlot;
-}
-
-void SkJSON::Object::Iter::next() {
- SkASSERT(fSlot);
- fSlot = fSlot->fNext;
-}
-
-SkJSON::Type SkJSON::Object::Iter::type() const {
- SkASSERT(fSlot);
- return fSlot->type();
-}
-
-const char* SkJSON::Object::Iter::name() const {
- SkASSERT(fSlot);
- return fSlot->name();
-}
-
-SkJSON::Object* SkJSON::Object::Iter::objectValue() const {
- SkASSERT(fSlot);
- SkASSERT(kObject == fSlot->type());
- return fSlot->fValue.fObject;
-}
-
-SkJSON::Array* SkJSON::Object::Iter::arrayValue() const {
- SkASSERT(fSlot);
- SkASSERT(kArray == fSlot->type());
- return fSlot->fValue.fArray;
-}
-
-const char* SkJSON::Object::Iter::stringValue() const {
- SkASSERT(fSlot);
- SkASSERT(kString == fSlot->type());
- return fSlot->fValue.fString;
-}
-
-int32_t SkJSON::Object::Iter::intValue() const {
- SkASSERT(fSlot);
- SkASSERT(kInt == fSlot->type());
- return fSlot->fValue.fInt;
-}
-
-float SkJSON::Object::Iter::floatValue() const {
- SkASSERT(fSlot);
- SkASSERT(kFloat == fSlot->type());
- return fSlot->fValue.fFloat;
-}
-
-bool SkJSON::Object::Iter::boolValue() const {
- SkASSERT(fSlot);
- SkASSERT(kBool == fSlot->type());
- return fSlot->fValue.fBool;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-SkJSON::Object::Object() : fHead(NULL), fTail(NULL) {
- LEAK_CODE(SkDebugf(" object[%d]\n", gObjectCount++);)
-}
-
-SkJSON::Object::Object(const Object& other) : fHead(NULL), fTail(NULL) {
- LEAK_CODE(SkDebugf(" object[%d]\n", gObjectCount++);)
-
- Iter iter(other);
- while (!iter.done()) {
- switch (iter.type()) {
- case kObject:
- this->addObject(iter.name(), new Object(*iter.objectValue()));
- break;
- case kArray:
- this->addArray(iter.name(), new Array(*iter.arrayValue()));
- break;
- case kString:
- this->addString(iter.name(), dup_string(iter.stringValue()));
- break;
- case kInt:
- this->addInt(iter.name(), iter.intValue());
- break;
- case kFloat:
- this->addFloat(iter.name(), iter.floatValue());
- break;
- case kBool:
- this->addBool(iter.name(), iter.boolValue());
- break;
- }
- iter.next();
- }
-}
-
-SkJSON::Object::~Object() {
- Slot* slot = fHead;
- while (slot) {
- Slot* next = slot->fNext;
- delete slot;
- slot = next;
- }
- LEAK_CODE(SkASSERT(gObjectCount > 0); SkDebugf("~object[%d]\n", --gObjectCount);)
-}
-
-int SkJSON::Object::count() const {
- int n = 0;
- for (const Slot* slot = fHead; slot; slot = slot->fNext) {
- n += 1;
- }
- return n;
-}
-
-SkJSON::Object::Slot* SkJSON::Object::addSlot(Slot* slot) {
- SkASSERT(NULL == slot->fNext);
- if (NULL == fHead) {
- SkASSERT(NULL == fTail);
- fHead = fTail = slot;
- } else {
- SkASSERT(fTail);
- SkASSERT(NULL == fTail->fNext);
- fTail->fNext = slot;
- fTail = slot;
- }
- return slot;
-}
-
-void SkJSON::Object::addObject(const char name[], SkJSON::Object* value) {
- this->addSlot(new Slot(name, kObject))->fValue.fObject = value;
-}
-
-void SkJSON::Object::addArray(const char name[], SkJSON::Array* value) {
- this->addSlot(new Slot(name, kArray))->fValue.fArray = value;
-}
-
-void SkJSON::Object::addString(const char name[], const char value[]) {
- this->addSlot(new Slot(name, kString))->fValue.fString = dup_string(value);
-}
-
-void SkJSON::Object::addInt(const char name[], int32_t value) {
- this->addSlot(new Slot(name, kInt))->fValue.fInt = value;
-}
-
-void SkJSON::Object::addFloat(const char name[], float value) {
- this->addSlot(new Slot(name, kFloat))->fValue.fFloat = value;
-}
-
-void SkJSON::Object::addBool(const char name[], bool value) {
- this->addSlot(new Slot(name, kBool))->fValue.fBool = value;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-const SkJSON::Object::Slot* SkJSON::Object::findSlot(const char name[],
- Type t) const {
- for (const Slot* slot = fHead; slot; slot = slot->fNext) {
- if (t == slot->type() && !strcmp(slot->name(), name)) {
- return slot;
- }
- }
- return NULL;
-}
-
-bool SkJSON::Object::find(const char name[], Type t) const {
- return this->findSlot(name, t) != NULL;
-}
-
-bool SkJSON::Object::findObject(const char name[], SkJSON::Object** value) const {
- const Slot* slot = this->findSlot(name, kObject);
- if (slot) {
- if (value) {
- *value = slot->fValue.fObject;
- }
- return true;
- }
- return false;
-}
-
-bool SkJSON::Object::findArray(const char name[], SkJSON::Array** value) const {
- const Slot* slot = this->findSlot(name, kArray);
- if (slot) {
- if (value) {
- *value = slot->fValue.fArray;
- }
- return true;
- }
- return false;
-}
-
-bool SkJSON::Object::findString(const char name[], SkString* value) const {
- const Slot* slot = this->findSlot(name, kString);
- if (slot) {
- if (value) {
- value->set(slot->fValue.fString);
- }
- return true;
- }
- return false;
-}
-
-bool SkJSON::Object::findInt(const char name[], int32_t* value) const {
- const Slot* slot = this->findSlot(name, kInt);
- if (slot) {
- if (value) {
- *value = slot->fValue.fInt;
- }
- return true;
- }
- return false;
-}
-
-bool SkJSON::Object::findFloat(const char name[], float* value) const {
- const Slot* slot = this->findSlot(name, kFloat);
- if (slot) {
- if (value) {
- *value = slot->fValue.fFloat;
- }
- return true;
- }
- return false;
-}
-
-bool SkJSON::Object::findBool(const char name[], bool* value) const {
- const Slot* slot = this->findSlot(name, kBool);
- if (slot) {
- if (value) {
- *value = slot->fValue.fBool;
- }
- return true;
- }
- return false;
-}
-
-bool SkJSON::Object::remove(const char name[], Type t) {
- SkDEBUGCODE(int count = this->count();)
- Slot* prev = NULL;
- Slot* slot = fHead;
- while (slot) {
- Slot* next = slot->fNext;
- if (t == slot->type() && !strcmp(slot->name(), name)) {
- if (prev) {
- SkASSERT(fHead != slot);
- prev->fNext = next;
- } else {
- SkASSERT(fHead == slot);
- fHead = next;
- }
- if (fTail == slot) {
- fTail = prev;
- }
- delete slot;
- SkASSERT(count - 1 == this->count());
- return true;
- }
- prev = slot;
- slot = next;
- }
- SkASSERT(count == this->count());
- return false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-static void tabForLevel(int level) {
- for (int i = 0; i < level; ++i) {
- SkDebugf(" ");
- }
-}
-
-void SkJSON::Object::toDebugf() const {
- SkDebugf("{\n");
- this->dumpLevel(0);
- SkDebugf("}\n");
-}
-
-void SkJSON::Object::dumpLevel(int level) const {
- for (Slot* slot = fHead; slot; slot = slot->fNext) {
- Type t = slot->type();
- tabForLevel(level + 1);
- SkDebugf("\"%s\" : ", slot->name());
- switch (slot->type()) {
- case kObject:
- if (slot->fValue.fObject) {
- SkDebugf("{\n");
- slot->fValue.fObject->dumpLevel(level + 1);
- tabForLevel(level + 1);
- SkDebugf("}");
- } else {
- SkDebugf("null");
- }
- break;
- case kArray:
- if (slot->fValue.fArray) {
- SkDebugf("[");
- slot->fValue.fArray->dumpLevel(level + 1);
- SkDebugf("]");
- } else {
- SkDebugf("null");
- }
- break;
- case kString:
- SkDebugf("\"%s\"", slot->fValue.fString);
- break;
- case kInt:
- SkDebugf("%d", slot->fValue.fInt);
- break;
- case kFloat:
- SkDebugf("%g", slot->fValue.fFloat);
- break;
- case kBool:
- SkDebugf("%s", slot->fValue.fBool ? "true" : "false");
- break;
- default:
- SkDEBUGFAIL("how did I get here");
- break;
- }
- if (slot->fNext) {
- SkDebugf(",");
- }
- SkDebugf("\n");
- }
-}
-
-void SkJSON::Array::dumpLevel(int level) const {
- if (0 == fCount) {
- return;
- }
- int last = fCount - 1;
-
- switch (this->type()) {
- case kObject: {
- SkDebugf("\n");
- for (int i = 0; i <= last; ++i) {
- Object* obj = fArray.fObjects[i];
- tabForLevel(level + 1);
- if (obj) {
- SkDebugf("{\n");
- obj->dumpLevel(level + 1);
- tabForLevel(level + 1);
- SkDebugf(i < last ? "}," : "}");
- } else {
- SkDebugf(i < last ? "null," : "null");
- }
- SkDebugf("\n");
- }
- } break;
- case kArray: {
- SkDebugf("\n");
- for (int i = 0; i <= last; ++i) {
- Array* array = fArray.fArrays[i];
- tabForLevel(level + 1);
- if (array) {
- SkDebugf("[");
- array->dumpLevel(level + 1);
- tabForLevel(level + 1);
- SkDebugf(i < last ? "]," : "]");
- } else {
- SkDebugf(i < last ? "null," : "null");
- }
- SkDebugf("\n");
- }
- } break;
- case kString: {
- for (int i = 0; i < last; ++i) {
- const char* str = fArray.fStrings[i];
- SkDebugf(str ? " \"%s\"," : " null,", str);
- }
- const char* str = fArray.fStrings[last];
- SkDebugf(str ? " \"%s\" " : " null ", str);
- } break;
- case kInt: {
- for (int i = 0; i < last; ++i) {
- SkDebugf(" %d,", fArray.fInts[i]);
- }
- SkDebugf(" %d ", fArray.fInts[last]);
- } break;
- case kFloat: {
- for (int i = 0; i < last; ++i) {
- SkDebugf(" %g,", fArray.fFloats[i]);
- }
- SkDebugf(" %g ", fArray.fFloats[last]);
- } break;
- case kBool: {
- for (int i = 0; i < last; ++i) {
- SkDebugf(" %s,", fArray.fBools[i] ? "true" : "false");
- }
- SkDebugf(" %s ", fArray.fInts[last] ? "true" : "false");
- } break;
- default:
- SkDEBUGFAIL("unsupported array type");
- break;
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-static const uint8_t gBytesPerType[] = {
- sizeof(SkJSON::Object*),
- sizeof(SkJSON::Array*),
- sizeof(char*),
- sizeof(int32_t),
- sizeof(float),
- sizeof(bool)
-};
-
-typedef void* (*DupProc)(const void*);
-
-static void* dup_object(const void* src) {
- return SkNEW_ARGS(SkJSON::Object, (*(SkJSON::Object*)src));
-}
-
-static void* dup_array(const void* src) {
- return SkNEW_ARGS(SkJSON::Array, (*(SkJSON::Array*)src));
-}
-
-static const DupProc gDupProcs[] = {
- dup_object, // Object
- dup_array, // Array
- (DupProc)dup_string, // String
- NULL, // int
- NULL, // float
- NULL, // bool
-};
-
-void SkJSON::Array::init(Type type, int count, const void* src) {
- LEAK_CODE(SkDebugf(" array[%d]\n", gArrayCount++);)
-
- SkASSERT((unsigned)type < SK_ARRAY_COUNT(gBytesPerType));
-
- if (count < 0) {
- count = 0;
- }
- size_t size = count * gBytesPerType[type];
-
- fCount = count;
- fType = type;
- fArray.fVoids = sk_malloc_throw(size);
- if (src) {
- DupProc proc = gDupProcs[fType];
- if (!proc) {
- memcpy(fArray.fVoids, src, size);
- } else {
- void** srcPtr = (void**)src;
- void** dstPtr = (void**)fArray.fVoids;
- for (int i = 0; i < fCount; ++i) {
- dstPtr[i] = proc(srcPtr[i]);
- }
- }
- } else {
- sk_bzero(fArray.fVoids, size);
- }
-}
-
-SkJSON::Array::Array(Type type, int count) {
- this->init(type, count, NULL);
-}
-
-SkJSON::Array::Array(const int32_t values[], int count) {
- this->init(kInt, count, values);
-}
-
-SkJSON::Array::Array(const float values[], int count) {
- this->init(kFloat, count, values);
-}
-
-SkJSON::Array::Array(const bool values[], int count) {
- this->init(kBool, count, values);
-}
-
-SkJSON::Array::Array(const Array& other) {
- this->init(other.type(), other.count(), other.fArray.fVoids);
-}
-
-typedef void (*FreeProc)(void*);
-
-static void free_object(void* obj) {
- delete (SkJSON::Object*)obj;
-}
-
-static void free_array(void* array) {
- delete (SkJSON::Array*)array;
-}
-
-static const FreeProc gFreeProcs[] = {
- free_object, // Object
- free_array, // Array
- (FreeProc)free_string, // String
- NULL, // int
- NULL, // float
- NULL, // bool
-};
-
-SkJSON::Array::~Array() {
- FreeProc proc = gFreeProcs[fType];
- if (proc) {
- void** ptr = (void**)fArray.fVoids;
- for (int i = 0; i < fCount; ++i) {
- proc(ptr[i]);
- }
- }
- sk_free(fArray.fVoids);
-
- LEAK_CODE(SkASSERT(gArrayCount > 0); SkDebugf("~array[%d]\n", --gArrayCount);)
-}
-
-void SkJSON::Array::setObject(int index, Object* object) {
- SkASSERT((unsigned)index < (unsigned)fCount);
- Object*& prev = fArray.fObjects[index];
- if (prev != object) {
- delete prev;
- prev = object;
- }
-}
-
-void SkJSON::Array::setArray(int index, Array* array) {
- SkASSERT((unsigned)index < (unsigned)fCount);
- Array*& prev = fArray.fArrays[index];
- if (prev != array) {
- delete prev;
- prev = array;
- }
-}
-
-void SkJSON::Array::setString(int index, const char str[]) {
- SkASSERT((unsigned)index < (unsigned)fCount);
- char*& prev = fArray.fStrings[index];
- if (prev != str) {
- free_string(prev);
- prev = dup_string(str);
- }
-}
diff --git a/chromium/third_party/skia/src/utils/SkLua.cpp b/chromium/third_party/skia/src/utils/SkLua.cpp
index 767e1772299..50478773240 100644
--- a/chromium/third_party/skia/src/utils/SkLua.cpp
+++ b/chromium/third_party/skia/src/utils/SkLua.cpp
@@ -6,6 +6,11 @@
*/
#include "SkLua.h"
+
+#if SK_SUPPORT_GPU
+#include "GrReducedClip.h"
+#endif
+
#include "SkCanvas.h"
#include "SkData.h"
#include "SkDocument.h"
@@ -38,6 +43,7 @@ DEF_MTNAME(SkMatrix)
DEF_MTNAME(SkRRect)
DEF_MTNAME(SkPath)
DEF_MTNAME(SkPaint)
+DEF_MTNAME(SkPathEffect)
DEF_MTNAME(SkShader)
DEF_MTNAME(SkTypeface)
@@ -56,7 +62,7 @@ template <typename T> void push_obj(lua_State* L, const T& obj) {
}
template <typename T> void push_ref(lua_State* L, T* ref) {
- *(T**)lua_newuserdata(L, sizeof(T*)) = SkRef(ref);
+ *(T**)lua_newuserdata(L, sizeof(T*)) = SkSafeRef(ref);
luaL_getmetatable(L, get_mtname<T>());
lua_setmetatable(L, -2);
}
@@ -150,6 +156,10 @@ static void setarray_number(lua_State* L, int index, double value) {
lua_rawseti(L, -2, index);
}
+static void setarray_scalar(lua_State* L, int index, SkScalar value) {
+ setarray_number(L, index, SkScalarToLua(value));
+}
+
void SkLua::pushBool(bool value, const char key[]) {
lua_pushboolean(fL, value);
CHECK_SETFIELD(key);
@@ -200,6 +210,27 @@ void SkLua::pushArrayU16(const uint16_t array[], int count, const char key[]) {
CHECK_SETFIELD(key);
}
+void SkLua::pushArrayPoint(const SkPoint array[], int count, const char key[]) {
+ lua_newtable(fL);
+ for (int i = 0; i < count; ++i) {
+ // make it base-1 to match lua convention
+ lua_newtable(fL);
+ this->pushScalar(array[i].fX, "x");
+ this->pushScalar(array[i].fY, "y");
+ lua_rawseti(fL, -2, i + 1);
+ }
+ CHECK_SETFIELD(key);
+}
+
+void SkLua::pushArrayScalar(const SkScalar array[], int count, const char key[]) {
+ lua_newtable(fL);
+ for (int i = 0; i < count; ++i) {
+ // make it base-1 to match lua convention
+ setarray_scalar(fL, i + 1, array[i]);
+ }
+ CHECK_SETFIELD(key);
+}
+
void SkLua::pushRect(const SkRect& r, const char key[]) {
lua_newtable(fL);
setfield_scalar(fL, "left", r.fLeft);
@@ -214,6 +245,14 @@ void SkLua::pushRRect(const SkRRect& rr, const char key[]) {
CHECK_SETFIELD(key);
}
+void SkLua::pushDash(const SkPathEffect::DashInfo& info, const char key[]) {
+ lua_newtable(fL);
+ setfield_scalar(fL, "phase", info.fPhase);
+ this->pushArrayScalar(info.fIntervals, info.fCount, "intervals");
+ CHECK_SETFIELD(key);
+}
+
+
void SkLua::pushMatrix(const SkMatrix& matrix, const char key[]) {
push_obj(fL, matrix);
CHECK_SETFIELD(key);
@@ -234,6 +273,73 @@ void SkLua::pushCanvas(SkCanvas* canvas, const char key[]) {
CHECK_SETFIELD(key);
}
+static const char* element_type(SkClipStack::Element::Type type) {
+ switch (type) {
+ case SkClipStack::Element::kEmpty_Type:
+ return "empty";
+ case SkClipStack::Element::kRect_Type:
+ return "rect";
+ case SkClipStack::Element::kRRect_Type:
+ return "rrect";
+ case SkClipStack::Element::kPath_Type:
+ return "path";
+ }
+ return "unknown";
+}
+
+static const char* region_op(SkRegion::Op op) {
+ switch (op) {
+ case SkRegion::kDifference_Op:
+ return "difference";
+ case SkRegion::kIntersect_Op:
+ return "intersect";
+ case SkRegion::kUnion_Op:
+ return "union";
+ case SkRegion::kXOR_Op:
+ return "xor";
+ case SkRegion::kReverseDifference_Op:
+ return "reverse-difference";
+ case SkRegion::kReplace_Op:
+ return "replace";
+ }
+ return "unknown";
+}
+
+void SkLua::pushClipStack(const SkClipStack& stack, const char* key) {
+ lua_newtable(fL);
+ SkClipStack::B2TIter iter(stack);
+ const SkClipStack::Element* element;
+ int i = 0;
+ while (NULL != (element = iter.next())) {
+ this->pushClipStackElement(*element);
+ lua_rawseti(fL, -2, ++i);
+ }
+ CHECK_SETFIELD(key);
+}
+
+void SkLua::pushClipStackElement(const SkClipStack::Element& element, const char* key) {
+ lua_newtable(fL);
+ SkClipStack::Element::Type type = element.getType();
+ this->pushString(element_type(type), "type");
+ switch (type) {
+ case SkClipStack::Element::kEmpty_Type:
+ break;
+ case SkClipStack::Element::kRect_Type:
+ this->pushRect(element.getRect(), "rect");
+ break;
+ case SkClipStack::Element::kRRect_Type:
+ this->pushRRect(element.getRRect(), "rrect");
+ break;
+ case SkClipStack::Element::kPath_Type:
+ this->pushPath(element.getPath(), "path");
+ break;
+ }
+ this->pushString(region_op(element.getOp()), "op");
+ this->pushBool(element.isAA(), "aa");
+ CHECK_SETFIELD(key);
+}
+
+
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
@@ -377,6 +483,50 @@ static int lcanvas_getTotalMatrix(lua_State* L) {
return 1;
}
+static int lcanvas_getClipStack(lua_State* L) {
+ SkLua(L).pushClipStack(*get_ref<SkCanvas>(L, 1)->getClipStack());
+ return 1;
+}
+
+int SkLua::lcanvas_getReducedClipStack(lua_State* L) {
+#if SK_SUPPORT_GPU
+ const SkCanvas* canvas = get_ref<SkCanvas>(L, 1);
+ SkISize layerSize = canvas->getTopLayerSize();
+ SkIPoint layerOrigin = canvas->getTopLayerOrigin();
+ SkIRect queryBounds = SkIRect::MakeXYWH(layerOrigin.fX, layerOrigin.fY,
+ layerSize.fWidth, layerSize.fHeight);
+
+ GrReducedClip::ElementList elements;
+ GrReducedClip::InitialState initialState;
+ int32_t genID;
+ SkIRect resultBounds;
+
+ const SkClipStack& stack = *canvas->getClipStack();
+
+ GrReducedClip::ReduceClipStack(stack,
+ queryBounds,
+ &elements,
+ &genID,
+ &initialState,
+ &resultBounds,
+ NULL);
+
+ GrReducedClip::ElementList::Iter iter(elements);
+ int i = 0;
+ lua_newtable(L);
+ while(NULL != iter.get()) {
+ SkLua(L).pushClipStackElement(*iter.get());
+ iter.next();
+ lua_rawseti(L, -2, ++i);
+ }
+ // Currently this only returns the element list to lua, not the initial state or result bounds.
+ // It could return these as additional items on the lua stack.
+ return 1;
+#else
+ return 0;
+#endif
+}
+
static int lcanvas_save(lua_State* L) {
lua_pushinteger(L, get_ref<SkCanvas>(L, 1)->save());
return 1;
@@ -412,7 +562,7 @@ static int lcanvas_gc(lua_State* L) {
return 0;
}
-static const struct luaL_Reg gSkCanvas_Methods[] = {
+const struct luaL_Reg gSkCanvas_Methods[] = {
{ "drawColor", lcanvas_drawColor },
{ "drawRect", lcanvas_drawRect },
{ "drawOval", lcanvas_drawOval },
@@ -422,6 +572,10 @@ static const struct luaL_Reg gSkCanvas_Methods[] = {
{ "drawText", lcanvas_drawText },
{ "getSaveCount", lcanvas_getSaveCount },
{ "getTotalMatrix", lcanvas_getTotalMatrix },
+ { "getClipStack", lcanvas_getClipStack },
+#if SK_SUPPORT_GPU
+ { "getReducedClipStack", SkLua::lcanvas_getReducedClipStack },
+#endif
{ "save", lcanvas_save },
{ "restore", lcanvas_restore },
{ "scale", lcanvas_scale },
@@ -476,6 +630,61 @@ static int lpaint_setAntiAlias(lua_State* L) {
return 0;
}
+static int lpaint_isDither(lua_State* L) {
+ lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDither());
+ return 1;
+}
+
+static int lpaint_isUnderlineText(lua_State* L) {
+ lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isUnderlineText());
+ return 1;
+}
+
+static int lpaint_isStrikeThruText(lua_State* L) {
+ lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isStrikeThruText());
+ return 1;
+}
+
+static int lpaint_isFakeBoldText(lua_State* L) {
+ lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isFakeBoldText());
+ return 1;
+}
+
+static int lpaint_isLinearText(lua_State* L) {
+ lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLinearText());
+ return 1;
+}
+
+static int lpaint_isSubpixelText(lua_State* L) {
+ lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isSubpixelText());
+ return 1;
+}
+
+static int lpaint_isDevKernText(lua_State* L) {
+ lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isDevKernText());
+ return 1;
+}
+
+static int lpaint_isLCDRenderText(lua_State* L) {
+ lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isLCDRenderText());
+ return 1;
+}
+
+static int lpaint_isEmbeddedBitmapText(lua_State* L) {
+ lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isEmbeddedBitmapText());
+ return 1;
+}
+
+static int lpaint_isAutohinted(lua_State* L) {
+ lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isAutohinted());
+ return 1;
+}
+
+static int lpaint_isVerticalText(lua_State* L) {
+ lua_pushboolean(L, get_obj<SkPaint>(L, 1)->isVerticalText());
+ return 1;
+}
+
static int lpaint_getColor(lua_State* L) {
SkLua(L).pushColor(get_obj<SkPaint>(L, 1)->getColor());
return 1;
@@ -491,6 +700,16 @@ static int lpaint_getTextSize(lua_State* L) {
return 1;
}
+static int lpaint_getTextScaleX(lua_State* L) {
+ SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextScaleX());
+ return 1;
+}
+
+static int lpaint_getTextSkewX(lua_State* L) {
+ SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getTextSkewX());
+ return 1;
+}
+
static int lpaint_setTextSize(lua_State* L) {
get_obj<SkPaint>(L, 1)->setTextSize(lua2scalar(L, 2));
return 0;
@@ -506,6 +725,11 @@ static int lpaint_setTypeface(lua_State* L) {
return 0;
}
+static int lpaint_getHinting(lua_State* L) {
+ SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getHinting());
+ return 1;
+}
+
static int lpaint_getFontID(lua_State* L) {
SkTypeface* face = get_obj<SkPaint>(L, 1)->getTypeface();
SkLua(L).pushU32(SkTypeface::UniqueID(face));
@@ -564,6 +788,21 @@ static int lpaint_setStroke(lua_State* L) {
return 0;
}
+static int lpaint_getStrokeCap(lua_State* L) {
+ SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeCap());
+ return 1;
+}
+
+static int lpaint_getStrokeJoin(lua_State* L) {
+ SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getStrokeJoin());
+ return 1;
+}
+
+static int lpaint_getTextEncoding(lua_State* L) {
+ SkLua(L).pushU32(get_obj<SkPaint>(L, 1)->getTextEncoding());
+ return 1;
+}
+
static int lpaint_getStrokeWidth(lua_State* L) {
SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeWidth());
return 1;
@@ -574,6 +813,11 @@ static int lpaint_setStrokeWidth(lua_State* L) {
return 0;
}
+static int lpaint_getStrokeMiter(lua_State* L) {
+ SkLua(L).pushScalar(get_obj<SkPaint>(L, 1)->getStrokeMiter());
+ return 1;
+}
+
static int lpaint_measureText(lua_State* L) {
if (lua_isstring(L, 2)) {
size_t len;
@@ -635,6 +879,16 @@ static int lpaint_getShader(lua_State* L) {
return 0;
}
+static int lpaint_getPathEffect(lua_State* L) {
+ const SkPaint* paint = get_obj<SkPaint>(L, 1);
+ SkPathEffect* pe = paint->getPathEffect();
+ if (pe) {
+ push_ref(L, pe);
+ return 1;
+ }
+ return 0;
+}
+
static int lpaint_gc(lua_State* L) {
get_obj<SkPaint>(L, 1)->~SkPaint();
return 0;
@@ -643,23 +897,42 @@ static int lpaint_gc(lua_State* L) {
static const struct luaL_Reg gSkPaint_Methods[] = {
{ "isAntiAlias", lpaint_isAntiAlias },
{ "setAntiAlias", lpaint_setAntiAlias },
+ { "isDither", lpaint_isDither },
+ { "isUnderlineText", lpaint_isUnderlineText },
+ { "isStrikeThruText", lpaint_isStrikeThruText },
+ { "isFakeBoldText", lpaint_isFakeBoldText },
+ { "isLinearText", lpaint_isLinearText },
+ { "isSubpixelText", lpaint_isSubpixelText },
+ { "isDevKernText", lpaint_isDevKernText },
+ { "isLCDRenderText", lpaint_isLCDRenderText },
+ { "isEmbeddedBitmapText", lpaint_isEmbeddedBitmapText },
+ { "isAutohinted", lpaint_isAutohinted },
+ { "isVerticalText", lpaint_isVerticalText },
{ "getColor", lpaint_getColor },
{ "setColor", lpaint_setColor },
{ "getTextSize", lpaint_getTextSize },
{ "setTextSize", lpaint_setTextSize },
+ { "getTextScaleX", lpaint_getTextScaleX },
+ { "getTextSkewX", lpaint_getTextSkewX },
{ "getTypeface", lpaint_getTypeface },
{ "setTypeface", lpaint_setTypeface },
+ { "getHinting", lpaint_getHinting },
{ "getFontID", lpaint_getFontID },
{ "getTextAlign", lpaint_getTextAlign },
{ "setTextAlign", lpaint_setTextAlign },
{ "getStroke", lpaint_getStroke },
{ "setStroke", lpaint_setStroke },
+ { "getStrokeCap", lpaint_getStrokeCap },
+ { "getStrokeJoin", lpaint_getStrokeJoin },
+ { "getTextEncoding", lpaint_getTextEncoding },
{ "getStrokeWidth", lpaint_getStrokeWidth },
{ "setStrokeWidth", lpaint_setStrokeWidth },
+ { "getStrokeMiter", lpaint_getStrokeMiter },
{ "measureText", lpaint_measureText },
{ "getFontMetrics", lpaint_getFontMetrics },
{ "getEffects", lpaint_getEffects },
{ "getShader", lpaint_getShader },
+ { "getPathEffect", lpaint_getPathEffect },
{ "__gc", lpaint_gc },
{ NULL, NULL }
};
@@ -753,6 +1026,35 @@ static const struct luaL_Reg gSkShader_Methods[] = {
///////////////////////////////////////////////////////////////////////////////
+static int lpatheffect_asADash(lua_State* L) {
+ SkPathEffect* pe = get_ref<SkPathEffect>(L, 1);
+ if (pe) {
+ SkPathEffect::DashInfo info;
+ SkPathEffect::DashType dashType = pe->asADash(&info);
+ if (SkPathEffect::kDash_DashType == dashType) {
+ SkAutoTArray<SkScalar> intervals(info.fCount);
+ info.fIntervals = intervals.get();
+ pe->asADash(&info);
+ SkLua(L).pushDash(info);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int lpatheffect_gc(lua_State* L) {
+ get_ref<SkPathEffect>(L, 1)->unref();
+ return 0;
+}
+
+static const struct luaL_Reg gSkPathEffect_Methods[] = {
+ { "asADash", lpatheffect_asADash },
+ { "__gc", lpatheffect_gc },
+ { NULL, NULL }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
static int lmatrix_getType(lua_State* L) {
SkMatrix::TypeMask mask = get_obj<SkMatrix>(L, 1)->getType();
@@ -800,6 +1102,73 @@ static int lpath_getBounds(lua_State* L) {
return 1;
}
+static const char* fill_type_to_str(SkPath::FillType fill) {
+ switch (fill) {
+ case SkPath::kEvenOdd_FillType:
+ return "even-odd";
+ case SkPath::kWinding_FillType:
+ return "winding";
+ case SkPath::kInverseEvenOdd_FillType:
+ return "inverse-even-odd";
+ case SkPath::kInverseWinding_FillType:
+ return "inverse-winding";
+ }
+ return "unknown";
+}
+
+static int lpath_getFillType(lua_State* L) {
+ SkPath::FillType fill = get_obj<SkPath>(L, 1)->getFillType();
+ SkLua(L).pushString(fill_type_to_str(fill));
+ return 1;
+}
+
+static SkString segment_masks_to_str(uint32_t segmentMasks) {
+ SkString result;
+ bool first = true;
+ if (SkPath::kLine_SegmentMask & segmentMasks) {
+ result.append("line");
+ first = false;
+ SkDEBUGCODE(segmentMasks &= ~SkPath::kLine_SegmentMask;)
+ }
+ if (SkPath::kQuad_SegmentMask & segmentMasks) {
+ if (!first) {
+ result.append(" ");
+ }
+ result.append("quad");
+ first = false;
+ SkDEBUGCODE(segmentMasks &= ~SkPath::kQuad_SegmentMask;)
+ }
+ if (SkPath::kConic_SegmentMask & segmentMasks) {
+ if (!first) {
+ result.append(" ");
+ }
+ result.append("conic");
+ first = false;
+ SkDEBUGCODE(segmentMasks &= ~SkPath::kConic_SegmentMask;)
+ }
+ if (SkPath::kCubic_SegmentMask & segmentMasks) {
+ if (!first) {
+ result.append(" ");
+ }
+ result.append("cubic");
+ SkDEBUGCODE(segmentMasks &= ~SkPath::kCubic_SegmentMask;)
+ }
+ SkASSERT(0 == segmentMasks);
+ return result;
+}
+
+static int lpath_getSegementTypes(lua_State* L) {
+ uint32_t segMasks = get_obj<SkPath>(L, 1)->getSegmentMasks();
+ SkLua(L).pushString(segment_masks_to_str(segMasks));
+ return 1;
+}
+
+static int lpath_isConvex(lua_State* L) {
+ bool isConvex = SkPath::kConvex_Convexity == get_obj<SkPath>(L, 1)->getConvexity();
+ SkLua(L).pushBool(isConvex);
+ return 1;
+}
+
static int lpath_isEmpty(lua_State* L) {
lua_pushboolean(L, get_obj<SkPath>(L, 1)->isEmpty());
return 1;
@@ -842,6 +1211,11 @@ static int lpath_isNestedRects(lua_State* L) {
return ret_count;
}
+static int lpath_countPoints(lua_State* L) {
+ lua_pushinteger(L, get_obj<SkPath>(L, 1)->countPoints());
+ return 1;
+}
+
static int lpath_reset(lua_State* L) {
get_obj<SkPath>(L, 1)->reset();
return 0;
@@ -882,9 +1256,13 @@ static int lpath_gc(lua_State* L) {
static const struct luaL_Reg gSkPath_Methods[] = {
{ "getBounds", lpath_getBounds },
+ { "getFillType", lpath_getFillType },
+ { "getSegmentTypes", lpath_getSegementTypes },
+ { "isConvex", lpath_isConvex },
{ "isEmpty", lpath_isEmpty },
{ "isRect", lpath_isRect },
{ "isNestedRects", lpath_isNestedRects },
+ { "countPoints", lpath_countPoints },
{ "reset", lpath_reset },
{ "moveTo", lpath_moveTo },
{ "lineTo", lpath_lineTo },
@@ -904,6 +1282,7 @@ static const char* rrect_type(const SkRRect& rr) {
case SkRRect::kRect_Type: return "rect";
case SkRRect::kOval_Type: return "oval";
case SkRRect::kSimple_Type: return "simple";
+ case SkRRect::kNinePatch_Type: return "nine-patch";
case SkRRect::kComplex_Type: return "complex";
}
SkDEBUGFAIL("never get here");
@@ -921,7 +1300,7 @@ static int lrrect_type(lua_State* L) {
}
static int lrrect_radii(lua_State* L) {
- int corner = lua_tointeger(L, 2);
+ int corner = SkToInt(lua_tointeger(L, 2));
SkVector v;
if (corner < 0 || corner > 3) {
SkDebugf("bad corner index %d", corner);
@@ -974,7 +1353,7 @@ static const struct luaL_Reg gSkImage_Methods[] = {
///////////////////////////////////////////////////////////////////////////////
static int ltypeface_gc(lua_State* L) {
- get_ref<SkTypeface>(L, 1)->unref();
+ SkSafeUnref(get_ref<SkTypeface>(L, 1));
return 0;
}
@@ -1114,8 +1493,9 @@ void SkLua::Load(lua_State* L) {
REG_CLASS(L, SkCanvas);
REG_CLASS(L, SkDocument);
REG_CLASS(L, SkImage);
- REG_CLASS(L, SkPath);
REG_CLASS(L, SkPaint);
+ REG_CLASS(L, SkPath);
+ REG_CLASS(L, SkPathEffect);
REG_CLASS(L, SkRRect);
REG_CLASS(L, SkShader);
REG_CLASS(L, SkTypeface);
diff --git a/chromium/third_party/skia/src/utils/SkLuaCanvas.cpp b/chromium/third_party/skia/src/utils/SkLuaCanvas.cpp
index c5ec0069135..d9c5dc1d762 100644
--- a/chromium/third_party/skia/src/utils/SkLuaCanvas.cpp
+++ b/chromium/third_party/skia/src/utils/SkLuaCanvas.cpp
@@ -57,7 +57,8 @@ void AutoCallLua::pushEncodedText(SkPaint::TextEncoding enc, const void* text,
this->pushString(str, "text");
} break;
case SkPaint::kGlyphID_TextEncoding:
- this->pushArrayU16((const uint16_t*)text, length >> 1, "glyphs");
+ this->pushArrayU16((const uint16_t*)text, SkToInt(length >> 1),
+ "glyphs");
break;
case SkPaint::kUTF32_TextEncoding:
break;
@@ -72,27 +73,21 @@ void SkLuaCanvas::pushThis() {
///////////////////////////////////////////////////////////////////////////////
-static SkBitmap make_bm(int width, int height) {
- SkBitmap bm;
- bm.setConfig(SkBitmap::kNo_Config, width, height);
- return bm;
-}
-
SkLuaCanvas::SkLuaCanvas(int width, int height, lua_State* L, const char func[])
- : INHERITED(make_bm(width, height))
+ : INHERITED(width, height)
, fL(L)
, fFunc(func) {
}
SkLuaCanvas::~SkLuaCanvas() {}
-int SkLuaCanvas::save(SaveFlags flags) {
+void SkLuaCanvas::willSave(SaveFlags flags) {
AUTO_LUA("save");
- return this->INHERITED::save(flags);
+ this->INHERITED::willSave(flags);
}
-int SkLuaCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
- SaveFlags flags) {
+SkCanvas::SaveLayerStrategy SkLuaCanvas::willSaveLayer(const SkRect* bounds, const SkPaint* paint,
+ SaveFlags flags) {
AUTO_LUA("saveLayer");
if (bounds) {
lua.pushRect(*bounds, "bounds");
@@ -100,74 +95,71 @@ int SkLuaCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
if (paint) {
lua.pushPaint(*paint, "paint");
}
- return this->INHERITED::save(flags);
-}
-
-void SkLuaCanvas::restore() {
- AUTO_LUA("restore");
- this->INHERITED::restore();
-}
-bool SkLuaCanvas::translate(SkScalar dx, SkScalar dy) {
- AUTO_LUA("translate");
- lua.pushScalar(dx, "dx");
- lua.pushScalar(dy, "dy");
- return this->INHERITED::translate(dx, dy);
+ this->INHERITED::willSaveLayer(bounds, paint, flags);
+ // No need for a layer.
+ return kNoLayer_SaveLayerStrategy;
}
-bool SkLuaCanvas::scale(SkScalar sx, SkScalar sy) {
- AUTO_LUA("scale");
- lua.pushScalar(sx, "sx");
- lua.pushScalar(sy, "sy");
- return this->INHERITED::scale(sx, sy);
-}
-
-bool SkLuaCanvas::rotate(SkScalar degrees) {
- AUTO_LUA("rotate");
- lua.pushScalar(degrees, "degrees");
- return this->INHERITED::rotate(degrees);
+void SkLuaCanvas::willRestore() {
+ AUTO_LUA("restore");
+ this->INHERITED::willRestore();
}
-bool SkLuaCanvas::skew(SkScalar kx, SkScalar ky) {
- AUTO_LUA("skew");
- lua.pushScalar(kx, "kx");
- lua.pushScalar(ky, "ky");
- return this->INHERITED::skew(kx, ky);
-}
+void SkLuaCanvas::didConcat(const SkMatrix& matrix) {
+ switch (matrix.getType()) {
+ case SkMatrix::kTranslate_Mask: {
+ AUTO_LUA("translate");
+ lua.pushScalar(matrix.getTranslateX(), "dx");
+ lua.pushScalar(matrix.getTranslateY(), "dy");
+ break;
+ }
+ case SkMatrix::kScale_Mask: {
+ AUTO_LUA("scale");
+ lua.pushScalar(matrix.getScaleX(), "sx");
+ lua.pushScalar(matrix.getScaleY(), "sy");
+ break;
+ }
+ default: {
+ AUTO_LUA("concat");
+ // pushMatrix added in https://codereview.chromium.org/203203004/
+ // Doesn't seem to have ever been working correctly since added
+ // lua.pushMatrix(matrix);
+ break;
+ }
+ }
-bool SkLuaCanvas::concat(const SkMatrix& matrix) {
- AUTO_LUA("concat");
- return this->INHERITED::concat(matrix);
+ this->INHERITED::didConcat(matrix);
}
-void SkLuaCanvas::setMatrix(const SkMatrix& matrix) {
- this->INHERITED::setMatrix(matrix);
+void SkLuaCanvas::didSetMatrix(const SkMatrix& matrix) {
+ this->INHERITED::didSetMatrix(matrix);
}
-bool SkLuaCanvas::clipRect(const SkRect& r, SkRegion::Op op, bool doAA) {
+void SkLuaCanvas::onClipRect(const SkRect& r, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
AUTO_LUA("clipRect");
lua.pushRect(r, "rect");
- lua.pushBool(doAA, "aa");
- return this->INHERITED::clipRect(r, op, doAA);
+ lua.pushBool(kSoft_ClipEdgeStyle == edgeStyle, "aa");
+ this->INHERITED::onClipRect(r, op, edgeStyle);
}
-bool SkLuaCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
+void SkLuaCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
AUTO_LUA("clipRRect");
lua.pushRRect(rrect, "rrect");
- lua.pushBool(doAA, "aa");
- return this->INHERITED::clipRRect(rrect, op, doAA);
+ lua.pushBool(kSoft_ClipEdgeStyle == edgeStyle, "aa");
+ this->INHERITED::onClipRRect(rrect, op, edgeStyle);
}
-bool SkLuaCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
+void SkLuaCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
AUTO_LUA("clipPath");
lua.pushPath(path, "path");
- lua.pushBool(doAA, "aa");
- return this->INHERITED::clipPath(path, op, doAA);
+ lua.pushBool(kSoft_ClipEdgeStyle == edgeStyle, "aa");
+ this->INHERITED::onClipPath(path, op, edgeStyle);
}
-bool SkLuaCanvas::clipRegion(const SkRegion& deviceRgn, SkRegion::Op op) {
+void SkLuaCanvas::onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op) {
AUTO_LUA("clipRegion");
- return this->INHERITED::clipRegion(deviceRgn, op);
+ this->INHERITED::onClipRegion(deviceRgn, op);
}
void SkLuaCanvas::drawPaint(const SkPaint& paint) {
@@ -178,6 +170,7 @@ void SkLuaCanvas::drawPaint(const SkPaint& paint) {
void SkLuaCanvas::drawPoints(PointMode mode, size_t count,
const SkPoint pts[], const SkPaint& paint) {
AUTO_LUA("drawPoints");
+ lua.pushArrayPoint(pts, SkToInt(count), "points");
lua.pushPaint(paint, "paint");
}
@@ -199,6 +192,14 @@ void SkLuaCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
lua.pushPaint(paint, "paint");
}
+void SkLuaCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
+ const SkPaint& paint) {
+ AUTO_LUA("drawDRRect");
+ lua.pushRRect(outer, "outer");
+ lua.pushRRect(inner, "inner");
+ lua.pushPaint(paint, "paint");
+}
+
void SkLuaCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
AUTO_LUA("drawPath");
lua.pushPath(path, "path");
@@ -238,41 +239,39 @@ void SkLuaCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
}
}
-void SkLuaCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
- SkScalar y, const SkPaint& paint) {
+void SkLuaCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
+ const SkPaint& paint) {
AUTO_LUA("drawText");
lua.pushEncodedText(paint.getTextEncoding(), text, byteLength);
lua.pushPaint(paint, "paint");
}
-void SkLuaCanvas::drawPosText(const void* text, size_t byteLength,
- const SkPoint pos[], const SkPaint& paint) {
+void SkLuaCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
+ const SkPaint& paint) {
AUTO_LUA("drawPosText");
lua.pushEncodedText(paint.getTextEncoding(), text, byteLength);
lua.pushPaint(paint, "paint");
}
-void SkLuaCanvas::drawPosTextH(const void* text, size_t byteLength,
- const SkScalar xpos[], SkScalar constY,
- const SkPaint& paint) {
+void SkLuaCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
+ SkScalar constY, const SkPaint& paint) {
AUTO_LUA("drawPosTextH");
lua.pushEncodedText(paint.getTextEncoding(), text, byteLength);
lua.pushPaint(paint, "paint");
}
-void SkLuaCanvas::drawTextOnPath(const void* text, size_t byteLength,
- const SkPath& path, const SkMatrix* matrix,
- const SkPaint& paint) {
+void SkLuaCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
+ const SkMatrix* matrix, const SkPaint& paint) {
AUTO_LUA("drawTextOnPath");
lua.pushPath(path, "path");
lua.pushEncodedText(paint.getTextEncoding(), text, byteLength);
lua.pushPaint(paint, "paint");
}
-void SkLuaCanvas::drawPicture(SkPicture& picture) {
+void SkLuaCanvas::onDrawPicture(const SkPicture* picture) {
AUTO_LUA("drawPicture");
// call through so we can see the nested picture ops
- this->INHERITED::drawPicture(picture);
+ this->INHERITED::onDrawPicture(picture);
}
void SkLuaCanvas::drawVertices(VertexMode vmode, int vertexCount,
diff --git a/chromium/third_party/skia/src/utils/SkMD5.h b/chromium/third_party/skia/src/utils/SkMD5.h
index 6b4fc53636d..4f504782b6b 100644
--- a/chromium/third_party/skia/src/utils/SkMD5.h
+++ b/chromium/third_party/skia/src/utils/SkMD5.h
@@ -25,10 +25,12 @@ public:
* Note that this treats the buffer as a series of uint8_t values.
*/
virtual bool write(const void* buffer, size_t size) SK_OVERRIDE {
- update(reinterpret_cast<const uint8_t*>(buffer), size);
+ this->update(reinterpret_cast<const uint8_t*>(buffer), size);
return true;
}
+ virtual size_t bytesWritten() const SK_OVERRIDE { return SkToSizeT(this->byteCount); }
+
/** Processes input, adding it to the digest. Calling this after finish is undefined. */
void update(const uint8_t* input, size_t length);
diff --git a/chromium/third_party/skia/src/utils/SkMatrix22.cpp b/chromium/third_party/skia/src/utils/SkMatrix22.cpp
new file mode 100644
index 00000000000..a13b72939f8
--- /dev/null
+++ b/chromium/third_party/skia/src/utils/SkMatrix22.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkMatrix.h"
+#include "SkMatrix22.h"
+#include "SkPoint.h"
+#include "SkScalar.h"
+
+void SkComputeGivensRotation(const SkVector& h, SkMatrix* G) {
+ const SkScalar& a = h.fX;
+ const SkScalar& b = h.fY;
+ SkScalar c, s;
+ if (0 == b) {
+ c = SkScalarCopySign(SK_Scalar1, a);
+ s = 0;
+ //r = SkScalarAbs(a);
+ } else if (0 == a) {
+ c = 0;
+ s = -SkScalarCopySign(SK_Scalar1, b);
+ //r = SkScalarAbs(b);
+ } else if (SkScalarAbs(b) > SkScalarAbs(a)) {
+ SkScalar t = a / b;
+ SkScalar u = SkScalarCopySign(SkScalarSqrt(SK_Scalar1 + t*t), b);
+ s = -SK_Scalar1 / u;
+ c = -s * t;
+ //r = b * u;
+ } else {
+ SkScalar t = b / a;
+ SkScalar u = SkScalarCopySign(SkScalarSqrt(SK_Scalar1 + t*t), a);
+ c = SK_Scalar1 / u;
+ s = -c * t;
+ //r = a * u;
+ }
+
+ G->setSinCos(s, c);
+}
diff --git a/chromium/third_party/skia/src/utils/SkMatrix22.h b/chromium/third_party/skia/src/utils/SkMatrix22.h
new file mode 100644
index 00000000000..bc567eab8e3
--- /dev/null
+++ b/chromium/third_party/skia/src/utils/SkMatrix22.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkMatrix22_DEFINED
+#define SkMatrix22_DEFINED
+
+#include "SkPoint.h"
+
+class SkMatrix;
+
+/** Find the Givens matrix G, which is the rotational matrix
+ * that rotates the vector h to the positive hoizontal axis.
+ * G * h = [hypot(h), 0]
+ *
+ * This is equivalent to
+ *
+ * SkScalar r = h.length();
+ * SkScalar r_inv = r ? SkScalarInvert(r) : 0;
+ * h.scale(r_inv);
+ * G->setSinCos(-h.fY, h.fX);
+ *
+ * but has better numerical stability by using (partial) hypot,
+ * and saves a multiply by not computing r.
+ */
+void SkComputeGivensRotation(const SkVector& h, SkMatrix* G);
+
+#endif
diff --git a/chromium/third_party/skia/src/utils/SkNWayCanvas.cpp b/chromium/third_party/skia/src/utils/SkNWayCanvas.cpp
index da8bdb6f41c..505c05cbf16 100644
--- a/chromium/third_party/skia/src/utils/SkNWayCanvas.cpp
+++ b/chromium/third_party/skia/src/utils/SkNWayCanvas.cpp
@@ -7,14 +7,8 @@
*/
#include "SkNWayCanvas.h"
-static SkBitmap make_noconfig_bm(int width, int height) {
- SkBitmap bm;
- bm.setConfig(SkBitmap::kNo_Config, width, height);
- return bm;
-}
-
SkNWayCanvas::SkNWayCanvas(int width, int height)
- : INHERITED(make_noconfig_bm(width, height)) {}
+ : INHERITED(width, height) {}
SkNWayCanvas::~SkNWayCanvas() {
this->removeAll();
@@ -63,109 +57,81 @@ private:
SkCanvas* fCanvas;
};
-int SkNWayCanvas::save(SaveFlags flags) {
+void SkNWayCanvas::willSave(SaveFlags flags) {
Iter iter(fList);
while (iter.next()) {
iter->save(flags);
}
- return this->INHERITED::save(flags);
-}
-
-int SkNWayCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
- SaveFlags flags) {
- Iter iter(fList);
- while (iter.next()) {
- iter->saveLayer(bounds, paint, flags);
- }
- return this->INHERITED::saveLayer(bounds, paint, flags);
-}
-
-void SkNWayCanvas::restore() {
- Iter iter(fList);
- while (iter.next()) {
- iter->restore();
- }
- this->INHERITED::restore();
-}
-bool SkNWayCanvas::translate(SkScalar dx, SkScalar dy) {
- Iter iter(fList);
- while (iter.next()) {
- iter->translate(dx, dy);
- }
- return this->INHERITED::translate(dx, dy);
+ this->INHERITED::willSave(flags);
}
-bool SkNWayCanvas::scale(SkScalar sx, SkScalar sy) {
+SkCanvas::SaveLayerStrategy SkNWayCanvas::willSaveLayer(const SkRect* bounds, const SkPaint* paint,
+ SaveFlags flags) {
Iter iter(fList);
while (iter.next()) {
- iter->scale(sx, sy);
+ iter->saveLayer(bounds, paint, flags);
}
- return this->INHERITED::scale(sx, sy);
-}
-bool SkNWayCanvas::rotate(SkScalar degrees) {
- Iter iter(fList);
- while (iter.next()) {
- iter->rotate(degrees);
- }
- return this->INHERITED::rotate(degrees);
+ this->INHERITED::willSaveLayer(bounds, paint, flags);
+ // No need for a layer.
+ return kNoLayer_SaveLayerStrategy;
}
-bool SkNWayCanvas::skew(SkScalar sx, SkScalar sy) {
+void SkNWayCanvas::willRestore() {
Iter iter(fList);
while (iter.next()) {
- iter->skew(sx, sy);
+ iter->restore();
}
- return this->INHERITED::skew(sx, sy);
+ this->INHERITED::willRestore();
}
-bool SkNWayCanvas::concat(const SkMatrix& matrix) {
+void SkNWayCanvas::didConcat(const SkMatrix& matrix) {
Iter iter(fList);
while (iter.next()) {
iter->concat(matrix);
}
- return this->INHERITED::concat(matrix);
+ this->INHERITED::didConcat(matrix);
}
-void SkNWayCanvas::setMatrix(const SkMatrix& matrix) {
+void SkNWayCanvas::didSetMatrix(const SkMatrix& matrix) {
Iter iter(fList);
while (iter.next()) {
iter->setMatrix(matrix);
}
- this->INHERITED::setMatrix(matrix);
+ this->INHERITED::didSetMatrix(matrix);
}
-bool SkNWayCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
+void SkNWayCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
Iter iter(fList);
while (iter.next()) {
- iter->clipRect(rect, op, doAA);
+ iter->clipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
}
- return this->INHERITED::clipRect(rect, op, doAA);
+ this->INHERITED::onClipRect(rect, op, edgeStyle);
}
-bool SkNWayCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
+void SkNWayCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
Iter iter(fList);
while (iter.next()) {
- iter->clipRRect(rrect, op, doAA);
+ iter->clipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
}
- return this->INHERITED::clipRRect(rrect, op, doAA);
+ this->INHERITED::onClipRRect(rrect, op, edgeStyle);
}
-bool SkNWayCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
+void SkNWayCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
Iter iter(fList);
while (iter.next()) {
- iter->clipPath(path, op, doAA);
+ iter->clipPath(path, op, kSoft_ClipEdgeStyle == edgeStyle);
}
- return this->INHERITED::clipPath(path, op, doAA);
+ this->INHERITED::onClipPath(path, op, edgeStyle);
}
-bool SkNWayCanvas::clipRegion(const SkRegion& deviceRgn, SkRegion::Op op) {
+void SkNWayCanvas::onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op) {
Iter iter(fList);
while (iter.next()) {
iter->clipRegion(deviceRgn, op);
}
- return this->INHERITED::clipRegion(deviceRgn, op);
+ this->INHERITED::onClipRegion(deviceRgn, op);
}
void SkNWayCanvas::clear(SkColor color) {
@@ -211,6 +177,14 @@ void SkNWayCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
}
}
+void SkNWayCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
+ const SkPaint& paint) {
+ Iter iter(fList);
+ while (iter.next()) {
+ iter->drawDRRect(outer, inner, paint);
+ }
+}
+
void SkNWayCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
Iter iter(fList);
while (iter.next()) {
@@ -259,41 +233,39 @@ void SkNWayCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
}
}
-void SkNWayCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
- SkScalar y, const SkPaint& paint) {
+void SkNWayCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
+ const SkPaint& paint) {
Iter iter(fList);
while (iter.next()) {
iter->drawText(text, byteLength, x, y, paint);
}
}
-void SkNWayCanvas::drawPosText(const void* text, size_t byteLength,
- const SkPoint pos[], const SkPaint& paint) {
+void SkNWayCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
+ const SkPaint& paint) {
Iter iter(fList);
while (iter.next()) {
iter->drawPosText(text, byteLength, pos, paint);
}
}
-void SkNWayCanvas::drawPosTextH(const void* text, size_t byteLength,
- const SkScalar xpos[], SkScalar constY,
- const SkPaint& paint) {
+void SkNWayCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
+ SkScalar constY, const SkPaint& paint) {
Iter iter(fList);
while (iter.next()) {
iter->drawPosTextH(text, byteLength, xpos, constY, paint);
}
}
-void SkNWayCanvas::drawTextOnPath(const void* text, size_t byteLength,
- const SkPath& path, const SkMatrix* matrix,
- const SkPaint& paint) {
+void SkNWayCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
+ const SkMatrix* matrix, const SkPaint& paint) {
Iter iter(fList);
while (iter.next()) {
iter->drawTextOnPath(text, byteLength, path, matrix, paint);
}
}
-void SkNWayCanvas::drawPicture(SkPicture& picture) {
+void SkNWayCanvas::onDrawPicture(const SkPicture* picture) {
Iter iter(fList);
while (iter.next()) {
iter->drawPicture(picture);
@@ -319,14 +291,6 @@ void SkNWayCanvas::drawData(const void* data, size_t length) {
}
}
-SkBounder* SkNWayCanvas::setBounder(SkBounder* bounder) {
- Iter iter(fList);
- while (iter.next()) {
- iter->setBounder(bounder);
- }
- return this->INHERITED::setBounder(bounder);
-}
-
SkDrawFilter* SkNWayCanvas::setDrawFilter(SkDrawFilter* filter) {
Iter iter(fList);
while (iter.next()) {
diff --git a/chromium/third_party/skia/src/utils/SkPDFRasterizer.cpp b/chromium/third_party/skia/src/utils/SkPDFRasterizer.cpp
index 89ac4015b8a..66634804bc6 100644
--- a/chromium/third_party/skia/src/utils/SkPDFRasterizer.cpp
+++ b/chromium/third_party/skia/src/utils/SkPDFRasterizer.cpp
@@ -11,17 +11,21 @@
#pragma warning(disable : 4530)
#endif
-#include <poppler-document.h>
-#include <poppler-image.h>
-#include <poppler-page.h>
-#include <poppler-page-renderer.h>
-
#include "SkPDFRasterizer.h"
#include "SkColorPriv.h"
+
#ifdef SK_BUILD_NATIVE_PDF_RENDERER
#include "SkPdfRenderer.h"
#endif // SK_BUILD_NATIVE_PDF_RENDERER
+#ifdef SK_BUILD_POPPLER
+#include <poppler-document.h>
+#include <poppler-image.h>
+#include <poppler-page.h>
+#include <poppler-page-renderer.h>
+#endif // SK_BUILD_POPPLER
+
+#ifdef SK_BUILD_POPPLER
bool SkPopplerRasterizePDF(SkStream* pdf, SkBitmap* output) {
size_t size = pdf->getLength();
SkAutoFree buffer(sk_malloc_throw(size));
@@ -46,8 +50,7 @@ bool SkPopplerRasterizePDF(SkStream* pdf, SkBitmap* output) {
char *imgData = image.data();
SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
- if (!bitmap.allocPixels()) {
+ if (!bitmap.allocPixels(SkImageInfo::MakeN32Premul(width, height))) {
return false;
}
bitmap.eraseColor(SK_ColorWHITE);
@@ -74,6 +77,7 @@ bool SkPopplerRasterizePDF(SkStream* pdf, SkBitmap* output) {
return true;
}
+#endif // SK_BUILD_POPPLER
#ifdef SK_BUILD_NATIVE_PDF_RENDERER
bool SkNativeRasterizePDF(SkStream* pdf, SkBitmap* output) {
diff --git a/chromium/third_party/skia/src/utils/SkPDFRasterizer.h b/chromium/third_party/skia/src/utils/SkPDFRasterizer.h
index ebc9fa610ca..82ec09233ff 100644
--- a/chromium/third_party/skia/src/utils/SkPDFRasterizer.h
+++ b/chromium/third_party/skia/src/utils/SkPDFRasterizer.h
@@ -10,7 +10,9 @@
#include "SkBitmap.h"
#include "SkStream.h"
+#ifdef SK_BUILD_POPPLER
bool SkPopplerRasterizePDF(SkStream* pdf, SkBitmap* output);
+#endif // SK_BUILD_POPPLER
#ifdef SK_BUILD_NATIVE_PDF_RENDERER
bool SkNativeRasterizePDF(SkStream* pdf, SkBitmap* output);
diff --git a/chromium/third_party/skia/src/utils/SkParse.cpp b/chromium/third_party/skia/src/utils/SkParse.cpp
index 9609ddc568d..f6e2a438e85 100644
--- a/chromium/third_party/skia/src/utils/SkParse.cpp
+++ b/chromium/third_party/skia/src/utils/SkParse.cpp
@@ -201,7 +201,7 @@ const char* SkParse::FindMSec(const char str[], SkMSec* value)
const char* SkParse::FindScalar(const char str[], SkScalar* value) {
SkASSERT(str);
str = skip_ws(str);
-#ifdef SK_SCALAR_IS_FLOAT
+
char* stop;
float v = (float)strtod(str, &stop);
if (str == stop) {
@@ -211,49 +211,6 @@ const char* SkParse::FindScalar(const char str[], SkScalar* value) {
*value = v;
}
return stop;
-#else
- int sign = 0;
- if (*str == '-')
- {
- sign = -1;
- str += 1;
- }
-
- if (!is_digit(*str) && *str != '.')
- return NULL;
-
- int n = 0;
- while (is_digit(*str))
- {
- n = 10*n + *str - '0';
- if (n > 0x7FFF)
- return NULL;
- str += 1;
- }
- n <<= 16;
-
- if (*str == '.')
- {
- static const int gFractions[] = { (1 << 24) / 10, (1 << 24) / 100, (1 << 24) / 1000,
- (1 << 24) / 10000, (1 << 24) / 100000 };
- str += 1;
- int d = 0;
- const int* fraction = gFractions;
- const int* end = &fraction[SK_ARRAY_COUNT(gFractions)];
- while (is_digit(*str) && fraction < end)
- d += (*str++ - '0') * *fraction++;
- d += 0x80; // round
- n += d >> 8;
- }
- while (is_digit(*str))
- str += 1;
- if (value)
- {
- n = (n ^ sign) - sign; // apply the sign
- *value = SkFixedToScalar(n);
- }
-#endif
- return str;
}
const char* SkParse::FindScalars(const char str[], SkScalar value[], int count)
diff --git a/chromium/third_party/skia/src/utils/SkParseColor.cpp b/chromium/third_party/skia/src/utils/SkParseColor.cpp
index 37f1308bb19..989a6091ef8 100644
--- a/chromium/third_party/skia/src/utils/SkParseColor.cpp
+++ b/chromium/third_party/skia/src/utils/SkParseColor.cpp
@@ -487,8 +487,8 @@ const char* SkParse::FindColor(const char* value, SkColor* colorPtr) {
// if (end == NULL)
// return NULL;
// !!! range check for errors?
-// *colorPtr = SkColorSetARGB(SkScalarRound(array[0]), SkScalarRound(array[1]),
-// SkScalarRound(array[2]), SkScalarRound(array[3]));
+// *colorPtr = SkColorSetARGB(SkScalarRoundToInt(array[0]), SkScalarRoundToInt(array[1]),
+// SkScalarRoundToInt(array[2]), SkScalarRoundToInt(array[3]));
// return end;
} else
return FindNamedColor(value, strlen(value), colorPtr);
@@ -513,9 +513,9 @@ void SkParse::TestColor() {
size_t len = strlen(nameRGB.name);
memcpy(bad, nameRGB.name, len);
bad[len - 1] -= 1;
- SkASSERT(FindColor(bad, &result) == false);
+ SkASSERT(FindColor(bad, &result) == NULL);
bad[len - 1] += 2;
- SkASSERT(FindColor(bad, &result) == false);
+ SkASSERT(FindColor(bad, &result) == NULL);
}
result = SK_ColorBLACK;
SkASSERT(FindColor("lightGrey", &result));
diff --git a/chromium/third_party/skia/src/utils/SkParsePath.cpp b/chromium/third_party/skia/src/utils/SkParsePath.cpp
index 4c9923f49fb..1a3c87f31d9 100644
--- a/chromium/third_party/skia/src/utils/SkParsePath.cpp
+++ b/chromium/third_party/skia/src/utils/SkParsePath.cpp
@@ -188,7 +188,6 @@ bool SkParsePath::FromSVGString(const char data[], SkPath* result) {
#include "SkStream.h"
static void write_scalar(SkWStream* stream, SkScalar value) {
-#ifdef SK_SCALAR_IS_FLOAT
char buffer[64];
#ifdef SK_BUILD_FOR_WIN32
int len = _snprintf(buffer, sizeof(buffer), "%g", value);
@@ -196,10 +195,6 @@ static void write_scalar(SkWStream* stream, SkScalar value) {
int len = snprintf(buffer, sizeof(buffer), "%g", value);
#endif
char* stop = buffer + len;
-#else
- char buffer[SkStrAppendScalar_MaxSize];
- char* stop = SkStrAppendScalar(buffer, value);
-#endif
stream->write(buffer, stop - buffer);
}
diff --git a/chromium/third_party/skia/src/utils/SkPictureUtils.cpp b/chromium/third_party/skia/src/utils/SkPictureUtils.cpp
index fa16af07f28..702a78dda20 100644
--- a/chromium/third_party/skia/src/utils/SkPictureUtils.cpp
+++ b/chromium/third_party/skia/src/utils/SkPictureUtils.cpp
@@ -8,6 +8,7 @@
#include "SkBitmapDevice.h"
#include "SkCanvas.h"
#include "SkData.h"
+#include "SkNoSaveLayerCanvas.h"
#include "SkPictureUtils.h"
#include "SkPixelRef.h"
#include "SkRRect.h"
@@ -49,22 +50,20 @@ static void nothing_to_do() {}
*/
class GatherPixelRefDevice : public SkBaseDevice {
public:
+ SK_DECLARE_INST_COUNT(GatherPixelRefDevice)
+
GatherPixelRefDevice(int width, int height, PixelRefSet* prset) {
fSize.set(width, height);
- fEmptyBitmap.setConfig(SkBitmap::kNo_Config, width, height);
+ fEmptyBitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
fPRSet = prset;
}
- virtual uint32_t getDeviceCapabilities() SK_OVERRIDE { return 0; }
- virtual int width() const SK_OVERRIDE { return fSize.width(); }
- virtual int height() const SK_OVERRIDE { return fSize.height(); }
- virtual bool isOpaque() const SK_OVERRIDE { return false; }
- virtual SkBitmap::Config config() const SK_OVERRIDE {
- return SkBitmap::kNo_Config;
+ virtual SkImageInfo imageInfo() const SK_OVERRIDE {
+ return SkImageInfo::MakeUnknown(fSize.width(), fSize.height());
}
virtual GrRenderTarget* accessRenderTarget() SK_OVERRIDE { return NULL; }
virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) SK_OVERRIDE {
- return true;
+ return false;
}
// TODO: allow this call to return failure, or move to SkBitmapDevice only.
virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE {
@@ -72,9 +71,9 @@ public:
}
virtual void lockPixels() SK_OVERRIDE { nothing_to_do(); }
virtual void unlockPixels() SK_OVERRIDE { nothing_to_do(); }
- virtual bool allowImageFilter(SkImageFilter*) SK_OVERRIDE { return false; }
- virtual bool canHandleImageFilter(SkImageFilter*) SK_OVERRIDE { return false; }
- virtual bool filterImage(SkImageFilter*, const SkBitmap&, const SkMatrix&,
+ virtual bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
+ virtual bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
+ virtual bool filterImage(const SkImageFilter*, const SkBitmap&, const SkImageFilter::Context&,
SkBitmap* result, SkIPoint* offset) SK_OVERRIDE {
return false;
}
@@ -82,10 +81,6 @@ public:
virtual void clear(SkColor color) SK_OVERRIDE {
nothing_to_do();
}
- virtual void writePixels(const SkBitmap& bitmap, int x, int y,
- SkCanvas::Config8888 config8888) SK_OVERRIDE {
- not_supported();
- }
virtual void drawPaint(const SkDraw&, const SkPaint& paint) SK_OVERRIDE {
this->addBitmapFromPaint(paint);
@@ -112,14 +107,20 @@ public:
this->addBitmapFromPaint(paint);
}
virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
- const SkMatrix&, const SkPaint&) SK_OVERRIDE {
+ const SkMatrix&, const SkPaint& paint) SK_OVERRIDE {
this->addBitmap(bitmap);
+ if (kAlpha_8_SkColorType == bitmap.colorType()) {
+ this->addBitmapFromPaint(paint);
+ }
}
virtual void drawBitmapRect(const SkDraw&, const SkBitmap& bitmap,
const SkRect* srcOrNull, const SkRect& dst,
- const SkPaint&,
+ const SkPaint& paint,
SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE {
this->addBitmap(bitmap);
+ if (kAlpha_8_SkColorType == bitmap.colorType()) {
+ this->addBitmapFromPaint(paint);
+ }
}
virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
int x, int y, const SkPaint& paint) SK_OVERRIDE {
@@ -153,23 +154,13 @@ public:
}
protected:
- virtual bool onReadPixels(const SkBitmap& bitmap,
- int x, int y,
- SkCanvas::Config8888 config8888) SK_OVERRIDE {
- not_supported();
- return false;
- }
-
virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE {
not_supported();
}
- virtual SkBaseDevice* onCreateCompatibleDevice(SkBitmap::Config config,
- int width, int height,
- bool isOpaque,
- Usage usage) SK_OVERRIDE {
+ virtual SkBaseDevice* onCreateDevice(const SkImageInfo& info, Usage usage) SK_OVERRIDE {
// we expect to only get called via savelayer, in which case it is fine.
SkASSERT(kSaveLayer_Usage == usage);
- return SkNEW_ARGS(GatherPixelRefDevice, (width, height, fPRSet));
+ return SkNEW_ARGS(GatherPixelRefDevice, (info.width(), info.height(), fPRSet));
}
virtual void flush() SK_OVERRIDE {}
@@ -199,45 +190,6 @@ private:
typedef SkBaseDevice INHERITED;
};
-class NoSaveLayerCanvas : public SkCanvas {
-public:
- NoSaveLayerCanvas(SkBaseDevice* device) : INHERITED(device) {}
-
- // turn saveLayer() into save() for speed, should not affect correctness.
- virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
- SaveFlags flags) SK_OVERRIDE {
-
- // Like SkPictureRecord, we don't want to create layers, but we do need
- // to respect the save and (possibly) its rect-clip.
-
- int count = this->INHERITED::save(flags);
- if (bounds) {
- this->INHERITED::clipRectBounds(bounds, flags, NULL);
- }
- return count;
- }
-
- // disable aa for speed
- virtual bool clipRect(const SkRect& rect, SkRegion::Op op,
- bool doAA) SK_OVERRIDE {
- return this->INHERITED::clipRect(rect, op, false);
- }
-
- // for speed, just respect the bounds, and disable AA. May give us a few
- // false positives and negatives.
- virtual bool clipPath(const SkPath& path, SkRegion::Op op,
- bool doAA) SK_OVERRIDE {
- return this->updateClipConservativelyUsingBounds(path.getBounds(), op, path.isInverseFillType());
- }
- virtual bool clipRRect(const SkRRect& rrect, SkRegion::Op op,
- bool doAA) SK_OVERRIDE {
- return this->updateClipConservativelyUsingBounds(rrect.getBounds(), op, false);
- }
-
-private:
- typedef SkCanvas INHERITED;
-};
-
SkData* SkPictureUtils::GatherPixelRefs(SkPicture* pict, const SkRect& area) {
if (NULL == pict) {
return NULL;
@@ -254,10 +206,10 @@ SkData* SkPictureUtils::GatherPixelRefs(SkPicture* pict, const SkRect& area) {
PixelRefSet prset(&array);
GatherPixelRefDevice device(pict->width(), pict->height(), &prset);
- NoSaveLayerCanvas canvas(&device);
+ SkNoSaveLayerCanvas canvas(&device);
canvas.clipRect(area, SkRegion::kIntersect_Op, false);
- canvas.drawPicture(*pict);
+ canvas.drawPicture(pict);
SkData* data = NULL;
int count = array.count();
diff --git a/chromium/third_party/skia/src/utils/SkProxyCanvas.cpp b/chromium/third_party/skia/src/utils/SkProxyCanvas.cpp
index f530313b162..5cb54698f63 100644
--- a/chromium/third_party/skia/src/utils/SkProxyCanvas.cpp
+++ b/chromium/third_party/skia/src/utils/SkProxyCanvas.cpp
@@ -21,57 +21,48 @@ void SkProxyCanvas::setProxy(SkCanvas* proxy) {
///////////////////////////////// Overrides ///////////
-int SkProxyCanvas::save(SaveFlags flags) {
- return fProxy->save(flags);
+void SkProxyCanvas::willSave(SaveFlags flags) {
+ fProxy->save(flags);
+ this->INHERITED::willSave(flags);
}
-int SkProxyCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
- SaveFlags flags) {
- return fProxy->saveLayer(bounds, paint, flags);
+SkCanvas::SaveLayerStrategy SkProxyCanvas::willSaveLayer(const SkRect* bounds, const SkPaint* paint,
+ SaveFlags flags) {
+ fProxy->saveLayer(bounds, paint, flags);
+ this->INHERITED::willSaveLayer(bounds, paint, flags);
+ // No need for a layer.
+ return kNoLayer_SaveLayerStrategy;
}
-void SkProxyCanvas::restore() {
+void SkProxyCanvas::willRestore() {
fProxy->restore();
+ this->INHERITED::willRestore();
}
-bool SkProxyCanvas::translate(SkScalar dx, SkScalar dy) {
- return fProxy->translate(dx, dy);
+void SkProxyCanvas::didConcat(const SkMatrix& matrix) {
+ fProxy->concat(matrix);
+ this->INHERITED::didConcat(matrix);
}
-bool SkProxyCanvas::scale(SkScalar sx, SkScalar sy) {
- return fProxy->scale(sx, sy);
-}
-
-bool SkProxyCanvas::rotate(SkScalar degrees) {
- return fProxy->rotate(degrees);
-}
-
-bool SkProxyCanvas::skew(SkScalar sx, SkScalar sy) {
- return fProxy->skew(sx, sy);
-}
-
-bool SkProxyCanvas::concat(const SkMatrix& matrix) {
- return fProxy->concat(matrix);
-}
-
-void SkProxyCanvas::setMatrix(const SkMatrix& matrix) {
+void SkProxyCanvas::didSetMatrix(const SkMatrix& matrix) {
fProxy->setMatrix(matrix);
+ this->INHERITED::didSetMatrix(matrix);
}
-bool SkProxyCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
- return fProxy->clipRect(rect, op, doAA);
+void SkProxyCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
+ fProxy->clipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
}
-bool SkProxyCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
- return fProxy->clipRRect(rrect, op, doAA);
+void SkProxyCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
+ fProxy->clipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
}
-bool SkProxyCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
- return fProxy->clipPath(path, op, doAA);
+void SkProxyCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
+ fProxy->clipPath(path, op, kSoft_ClipEdgeStyle == edgeStyle);
}
-bool SkProxyCanvas::clipRegion(const SkRegion& deviceRgn, SkRegion::Op op) {
- return fProxy->clipRegion(deviceRgn, op);
+void SkProxyCanvas::onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op) {
+ fProxy->clipRegion(deviceRgn, op);
}
void SkProxyCanvas::drawPaint(const SkPaint& paint) {
@@ -95,6 +86,11 @@ void SkProxyCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
fProxy->drawRRect(rrect, paint);
}
+void SkProxyCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
+ const SkPaint& paint) {
+ fProxy->drawDRRect(outer, inner, paint);
+}
+
void SkProxyCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
fProxy->drawPath(path, paint);
}
@@ -120,29 +116,27 @@ void SkProxyCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
fProxy->drawSprite(bitmap, x, y, paint);
}
-void SkProxyCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
- SkScalar y, const SkPaint& paint) {
+void SkProxyCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
+ const SkPaint& paint) {
fProxy->drawText(text, byteLength, x, y, paint);
}
-void SkProxyCanvas::drawPosText(const void* text, size_t byteLength,
- const SkPoint pos[], const SkPaint& paint) {
+void SkProxyCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
+ const SkPaint& paint) {
fProxy->drawPosText(text, byteLength, pos, paint);
}
-void SkProxyCanvas::drawPosTextH(const void* text, size_t byteLength,
- const SkScalar xpos[], SkScalar constY,
- const SkPaint& paint) {
+void SkProxyCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
+ SkScalar constY, const SkPaint& paint) {
fProxy->drawPosTextH(text, byteLength, xpos, constY, paint);
}
-void SkProxyCanvas::drawTextOnPath(const void* text, size_t byteLength,
- const SkPath& path, const SkMatrix* matrix,
- const SkPaint& paint) {
+void SkProxyCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
+ const SkMatrix* matrix, const SkPaint& paint) {
fProxy->drawTextOnPath(text, byteLength, path, matrix, paint);
}
-void SkProxyCanvas::drawPicture(SkPicture& picture) {
+void SkProxyCanvas::onDrawPicture(const SkPicture* picture) {
fProxy->drawPicture(picture);
}
@@ -171,10 +165,6 @@ void SkProxyCanvas::endCommentGroup() {
fProxy->endCommentGroup();
}
-SkBounder* SkProxyCanvas::setBounder(SkBounder* bounder) {
- return fProxy->setBounder(bounder);
-}
-
SkDrawFilter* SkProxyCanvas::setDrawFilter(SkDrawFilter* filter) {
return fProxy->setDrawFilter(filter);
}
diff --git a/chromium/third_party/skia/src/utils/SkRTConf.cpp b/chromium/third_party/skia/src/utils/SkRTConf.cpp
index 895cfa5e310..bb6cb23cb93 100644
--- a/chromium/third_party/skia/src/utils/SkRTConf.cpp
+++ b/chromium/third_party/skia/src/utils/SkRTConf.cpp
@@ -44,8 +44,8 @@ SkRTConfRegistry::SkRTConfRegistry(): fConfs(100) {
continue;
}
- SkString* key = new SkString(keyptr);
- SkString* val = new SkString(valptr);
+ SkString* key = SkNEW_ARGS(SkString,(keyptr));
+ SkString* val = SkNEW_ARGS(SkString,(valptr));
fConfigFileKeys.append(1, &key);
fConfigFileValues.append(1, &val);
@@ -53,6 +53,20 @@ SkRTConfRegistry::SkRTConfRegistry(): fConfs(100) {
sk_fclose(fp);
}
+SkRTConfRegistry::~SkRTConfRegistry() {
+ ConfMap::Iter iter(fConfs);
+ SkTDArray<SkRTConfBase *> *confArray;
+
+ while (iter.next(&confArray)) {
+ delete confArray;
+ }
+
+ for (int i = 0 ; i < fConfigFileKeys.count() ; i++) {
+ SkDELETE(fConfigFileKeys[i]);
+ SkDELETE(fConfigFileValues[i]);
+ }
+}
+
const char *SkRTConfRegistry::configFileLocation() const {
return "skia.conf"; // for now -- should probably do something fancier like home directories or whatever.
}
@@ -105,6 +119,17 @@ void SkRTConfRegistry::printAll(const char *fname) const {
delete o;
}
+bool SkRTConfRegistry::hasNonDefault() const {
+ ConfMap::Iter iter(fConfs);
+ SkTDArray<SkRTConfBase *> *confArray;
+ while (iter.next(&confArray)) {
+ if (!confArray->getAt(0)->isDefault()) {
+ return true;
+ }
+ }
+ return false;
+}
+
void SkRTConfRegistry::printNonDefault(const char *fname) const {
SkWStream *o;
diff --git a/chromium/third_party/skia/src/utils/SkSHA1.h b/chromium/third_party/skia/src/utils/SkSHA1.h
index cf2cb8c6796..df8b9bf1b68 100644
--- a/chromium/third_party/skia/src/utils/SkSHA1.h
+++ b/chromium/third_party/skia/src/utils/SkSHA1.h
@@ -29,6 +29,8 @@ public:
return true;
}
+ virtual size_t bytesWritten() const SK_OVERRIDE { return SkToSizeT(this->byteCount); }
+
/** Processes input, adding it to the digest. Calling this after finish is undefined. */
void update(const uint8_t* input, size_t length);
diff --git a/chromium/third_party/skia/src/utils/SkTLogic.h b/chromium/third_party/skia/src/utils/SkTLogic.h
index bf9ee1ab250..2b5df0b16fe 100644
--- a/chromium/third_party/skia/src/utils/SkTLogic.h
+++ b/chromium/third_party/skia/src/utils/SkTLogic.h
@@ -30,6 +30,14 @@ template <typename T, T v> struct SkTIntegralConstant {
/** Convenience specialization of SkTIntegralConstant. */
template <bool b> struct SkTBool : SkTIntegralConstant<bool, b> { };
+/** Pre-C++11 version of std::is_empty<T>. */
+template <typename T>
+class SkTIsEmpty {
+ struct Derived : public T { char unused; };
+public:
+ static const bool value = sizeof(Derived) == sizeof(char);
+};
+
/** Pre-C++11 version of std::true_type. */
typedef SkTBool<true> SkTrue;
@@ -58,4 +66,45 @@ struct SkTMux {
typename SkTIf<b, B, Neither>::type>::type type;
};
+/** SkTEnableIf_c::type = (condition) ? T : [does not exist]; */
+template <bool condition, class T = void> struct SkTEnableIf_c { };
+template <class T> struct SkTEnableIf_c<true, T> {
+ typedef T type;
+};
+
+/** SkTEnableIf::type = (Condition::value) ? T : [does not exist]; */
+template <class Condition, class T = void> struct SkTEnableIf
+ : public SkTEnableIf_c<static_cast<bool>(Condition::value), T> { };
+
+/** Use as a return type to enable a function only when cond_type::value is true,
+ * like C++14's std::enable_if_t. E.g. (N.B. this is a dumb example.)
+ * SK_WHEN(SkTrue, int) f(void* ptr) { return 1; }
+ * SK_WHEN(!SkTrue, int) f(void* ptr) { return 2; }
+ */
+#define SK_WHEN(cond_prefix, T) typename SkTEnableIf_c<cond_prefix::value, T>::type
+
+// See http://en.wikibooks.org/wiki/More_C++_Idioms/Member_Detector
+#define SK_CREATE_MEMBER_DETECTOR(member) \
+template <typename T> \
+class HasMember_##member { \
+ struct Fallback { int member; }; \
+ struct Derived : T, Fallback {}; \
+ template <typename U, U> struct Check; \
+ template <typename U> static uint8_t func(Check<int Fallback::*, &U::member>*); \
+ template <typename U> static uint16_t func(...); \
+public: \
+ typedef HasMember_##member type; \
+ static const bool value = sizeof(func<Derived>(NULL)) == sizeof(uint16_t); \
+}
+
+// Same sort of thing as SK_CREATE_MEMBER_DETECTOR, but checks for the existence of a nested type.
+#define SK_CREATE_TYPE_DETECTOR(type) \
+template <typename T> \
+class HasType_##type { \
+ template <typename U> static uint8_t func(typename U::type*); \
+ template <typename U> static uint16_t func(...); \
+public: \
+ static const bool value = sizeof(func<T>(NULL)) == sizeof(uint8_t); \
+}
+
#endif
diff --git a/chromium/third_party/skia/src/utils/SkTextureCompressor.cpp b/chromium/third_party/skia/src/utils/SkTextureCompressor.cpp
new file mode 100644
index 00000000000..fb41928269b
--- /dev/null
+++ b/chromium/third_party/skia/src/utils/SkTextureCompressor.cpp
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkTextureCompressor.h"
+
+#include "SkBitmap.h"
+#include "SkData.h"
+#include "SkEndian.h"
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Utility Functions
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// Absolute difference between two values. More correct than SkTAbs(a - b)
+// because it works on unsigned values.
+template <typename T> inline T abs_diff(const T &a, const T &b) {
+ return (a > b) ? (a - b) : (b - a);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// LATC compressor
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// Return the squared minimum error cost of approximating 'pixel' using the
+// provided palette. Return this in the middle 16 bits of the integer. Return
+// the best index in the palette for this pixel in the bottom 8 bits.
+static uint32_t compute_error(uint8_t pixel, uint8_t palette[8]) {
+ int minIndex = 0;
+ uint8_t error = abs_diff(palette[0], pixel);
+ for (int i = 1; i < 8; ++i) {
+ uint8_t diff = abs_diff(palette[i], pixel);
+ if (diff < error) {
+ minIndex = i;
+ error = diff;
+ }
+ }
+ uint16_t errSq = static_cast<uint16_t>(error) * static_cast<uint16_t>(error);
+ SkASSERT(minIndex >= 0 && minIndex < 8);
+ return (static_cast<uint32_t>(errSq) << 8) | static_cast<uint32_t>(minIndex);
+}
+
+// Compress LATC block. Each 4x4 block of pixels is decompressed by LATC from two
+// values LUM0 and LUM1, and an index into the generated palette. LATC constructs
+// a palette of eight colors from LUM0 and LUM1 using the algorithm:
+//
+// LUM0, if lum0 > lum1 and code(x,y) == 0
+// LUM1, if lum0 > lum1 and code(x,y) == 1
+// (6*LUM0+ LUM1)/7, if lum0 > lum1 and code(x,y) == 2
+// (5*LUM0+2*LUM1)/7, if lum0 > lum1 and code(x,y) == 3
+// (4*LUM0+3*LUM1)/7, if lum0 > lum1 and code(x,y) == 4
+// (3*LUM0+4*LUM1)/7, if lum0 > lum1 and code(x,y) == 5
+// (2*LUM0+5*LUM1)/7, if lum0 > lum1 and code(x,y) == 6
+// ( LUM0+6*LUM1)/7, if lum0 > lum1 and code(x,y) == 7
+//
+// LUM0, if lum0 <= lum1 and code(x,y) == 0
+// LUM1, if lum0 <= lum1 and code(x,y) == 1
+// (4*LUM0+ LUM1)/5, if lum0 <= lum1 and code(x,y) == 2
+// (3*LUM0+2*LUM1)/5, if lum0 <= lum1 and code(x,y) == 3
+// (2*LUM0+3*LUM1)/5, if lum0 <= lum1 and code(x,y) == 4
+// ( LUM0+4*LUM1)/5, if lum0 <= lum1 and code(x,y) == 5
+// 0, if lum0 <= lum1 and code(x,y) == 6
+// 255, if lum0 <= lum1 and code(x,y) == 7
+//
+// We compute the LATC palette using the following simple algorithm:
+// 1. Choose the minimum and maximum values in the block as LUM0 and LUM1
+// 2. Figure out which of the two possible palettes is better.
+
+static uint64_t compress_latc_block(uint8_t block[16]) {
+ // Just do a simple min/max but choose which of the
+ // two palettes is better
+ uint8_t maxVal = 0;
+ uint8_t minVal = 255;
+ for (int i = 0; i < 16; ++i) {
+ maxVal = SkMax32(maxVal, block[i]);
+ minVal = SkMin32(minVal, block[i]);
+ }
+
+ // Generate palettes
+ uint8_t palettes[2][8];
+
+ // Straight linear ramp
+ palettes[0][0] = maxVal;
+ palettes[0][1] = minVal;
+ for (int i = 1; i < 7; ++i) {
+ palettes[0][i+1] = ((7-i)*maxVal + i*minVal) / 7;
+ }
+
+ // Smaller linear ramp with min and max byte values at the end.
+ palettes[1][0] = minVal;
+ palettes[1][1] = maxVal;
+ for (int i = 1; i < 5; ++i) {
+ palettes[1][i+1] = ((5-i)*maxVal + i*minVal) / 5;
+ }
+ palettes[1][6] = 0;
+ palettes[1][7] = 255;
+
+ // Figure out which of the two is better:
+ // - accumError holds the accumulated error for each pixel from
+ // the associated palette
+ // - indices holds the best indices for each palette in the
+ // bottom 48 (16*3) bits.
+ uint32_t accumError[2] = { 0, 0 };
+ uint64_t indices[2] = { 0, 0 };
+ for (int i = 15; i >= 0; --i) {
+ // For each palette:
+ // 1. Retreive the result of this pixel
+ // 2. Store the error in accumError
+ // 3. Store the minimum palette index in indices.
+ for (int p = 0; p < 2; ++p) {
+ uint32_t result = compute_error(block[i], palettes[p]);
+ accumError[p] += (result >> 8);
+ indices[p] <<= 3;
+ indices[p] |= result & 7;
+ }
+ }
+
+ SkASSERT(indices[0] < (static_cast<uint64_t>(1) << 48));
+ SkASSERT(indices[1] < (static_cast<uint64_t>(1) << 48));
+
+ uint8_t paletteIdx = (accumError[0] > accumError[1]) ? 0 : 1;
+
+ // Assemble the compressed block.
+ uint64_t result = 0;
+
+ // Jam the first two palette entries into the bottom 16 bits of
+ // a 64 bit integer. Based on the palette that we chose, one will
+ // be larger than the other and it will select the proper palette.
+ result |= static_cast<uint64_t>(palettes[paletteIdx][0]);
+ result |= static_cast<uint64_t>(palettes[paletteIdx][1]) << 8;
+
+ // Jam the indices into the top 48 bits.
+ result |= indices[paletteIdx] << 16;
+
+ // We assume everything is little endian, if it's not then make it so.
+ return SkEndian_SwapLE64(result);
+}
+
+static SkData *compress_a8_to_latc(const SkBitmap &bm) {
+ // LATC compressed texels down into square 4x4 blocks
+ static const int kLATCBlockSize = 4;
+
+ // Make sure that our data is well-formed enough to be
+ // considered for LATC compression
+ if (bm.width() == 0 || bm.height() == 0 ||
+ (bm.width() % kLATCBlockSize) != 0 ||
+ (bm.height() % kLATCBlockSize) != 0 ||
+ (bm.colorType() != kAlpha_8_SkColorType)) {
+ return NULL;
+ }
+
+ // The LATC format is 64 bits per 4x4 block.
+ static const int kLATCEncodedBlockSize = 8;
+
+ int blocksX = bm.width() / kLATCBlockSize;
+ int blocksY = bm.height() / kLATCBlockSize;
+
+ int compressedDataSize = blocksX * blocksY * kLATCEncodedBlockSize;
+ uint64_t* dst = reinterpret_cast<uint64_t*>(sk_malloc_throw(compressedDataSize));
+
+ uint8_t block[16];
+ const uint8_t* row = reinterpret_cast<const uint8_t*>(bm.getPixels());
+ uint64_t* encPtr = dst;
+ for (int y = 0; y < blocksY; ++y) {
+ for (int x = 0; x < blocksX; ++x) {
+ memcpy(block, row + (kLATCBlockSize * x), 4);
+ memcpy(block + 4, row + bm.rowBytes() + (kLATCBlockSize * x), 4);
+ memcpy(block + 8, row + 2*bm.rowBytes() + (kLATCBlockSize * x), 4);
+ memcpy(block + 12, row + 3*bm.rowBytes() + (kLATCBlockSize * x), 4);
+
+ *encPtr = compress_latc_block(block);
+ ++encPtr;
+ }
+ row += kLATCBlockSize * bm.rowBytes();
+ }
+
+ return SkData::NewFromMalloc(dst, compressedDataSize);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+namespace SkTextureCompressor {
+
+typedef SkData *(*CompressBitmapProc)(const SkBitmap &bitmap);
+
+SkData *CompressBitmapToFormat(const SkBitmap &bitmap, Format format) {
+ SkAutoLockPixels alp(bitmap);
+
+ CompressBitmapProc kProcMap[kLastEnum_SkColorType + 1][kFormatCnt];
+ memset(kProcMap, 0, sizeof(kProcMap));
+
+ // Map available bitmap configs to compression functions
+ kProcMap[kAlpha_8_SkColorType][kLATC_Format] = compress_a8_to_latc;
+
+ CompressBitmapProc proc = kProcMap[bitmap.colorType()][format];
+ if (NULL != proc) {
+ return proc(bitmap);
+ }
+
+ return NULL;
+}
+
+} // namespace SkTextureCompressor
diff --git a/chromium/third_party/skia/src/utils/SkTextureCompressor.h b/chromium/third_party/skia/src/utils/SkTextureCompressor.h
new file mode 100644
index 00000000000..38fb5eade29
--- /dev/null
+++ b/chromium/third_party/skia/src/utils/SkTextureCompressor.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkTextureCompressor_DEFINED
+#define SkTextureCompressor_DEFINED
+
+class SkBitmap;
+class SkData;
+
+namespace SkTextureCompressor {
+ // Various texture compression formats that we support.
+ enum Format {
+ // Alpha only format.
+ kLATC_Format,
+
+ kLast_Format = kLATC_Format
+ };
+ static const int kFormatCnt = kLast_Format + 1;
+
+ // Returns an SkData holding a blob of compressed data that corresponds
+ // to the bitmap. If the bitmap colorType cannot be compressed using the
+ // associated format, then we return NULL. The caller is responsible for
+ // calling unref() on the returned data.
+ SkData* CompressBitmapToFormat(const SkBitmap& bitmap, Format format);
+}
+
+#endif
diff --git a/chromium/third_party/skia/src/utils/SkThreadPool.cpp b/chromium/third_party/skia/src/utils/SkThreadPool.cpp
deleted file mode 100644
index 125a5d9b6ad..00000000000
--- a/chromium/third_party/skia/src/utils/SkThreadPool.cpp
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkRunnable.h"
-#include "SkThreadPool.h"
-#include "SkThreadUtils.h"
-#include "SkTypes.h"
-
-#if defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_ANDROID)
-#include <unistd.h>
-#endif
-
-// Returns the number of cores on this machine.
-static int num_cores() {
-#if defined(SK_BUILD_FOR_WIN32)
- SYSTEM_INFO sysinfo;
- GetSystemInfo(&sysinfo);
- return sysinfo.dwNumberOfProcessors;
-#elif defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_ANDROID)
- return sysconf(_SC_NPROCESSORS_ONLN);
-#else
- return 1;
-#endif
-}
-
-SkThreadPool::SkThreadPool(int count)
-: fState(kRunning_State), fBusyThreads(0) {
- if (count < 0) count = num_cores();
- // Create count threads, all running SkThreadPool::Loop.
- for (int i = 0; i < count; i++) {
- SkThread* thread = SkNEW_ARGS(SkThread, (&SkThreadPool::Loop, this));
- *fThreads.append() = thread;
- thread->start();
- }
-}
-
-SkThreadPool::~SkThreadPool() {
- if (kRunning_State == fState) {
- this->wait();
- }
-}
-
-void SkThreadPool::wait() {
- fReady.lock();
- fState = kWaiting_State;
- fReady.broadcast();
- fReady.unlock();
-
- // Wait for all threads to stop.
- for (int i = 0; i < fThreads.count(); i++) {
- fThreads[i]->join();
- SkDELETE(fThreads[i]);
- }
- SkASSERT(fQueue.isEmpty());
-}
-
-/*static*/ void SkThreadPool::Loop(void* arg) {
- // The SkThreadPool passes itself as arg to each thread as they're created.
- SkThreadPool* pool = static_cast<SkThreadPool*>(arg);
-
- while (true) {
- // We have to be holding the lock to read the queue and to call wait.
- pool->fReady.lock();
- while(pool->fQueue.isEmpty()) {
- // Does the client want to stop and are all the threads ready to stop?
- // If so, we move into the halting state, and whack all the threads so they notice.
- if (kWaiting_State == pool->fState && pool->fBusyThreads == 0) {
- pool->fState = kHalting_State;
- pool->fReady.broadcast();
- }
- // Any time we find ourselves in the halting state, it's quitting time.
- if (kHalting_State == pool->fState) {
- pool->fReady.unlock();
- return;
- }
- // wait yields the lock while waiting, but will have it again when awoken.
- pool->fReady.wait();
- }
- // We've got the lock back here, no matter if we ran wait or not.
-
- // The queue is not empty, so we have something to run. Claim it.
- LinkedRunnable* r = pool->fQueue.tail();
-
- pool->fQueue.remove(r);
-
- // Having claimed our SkRunnable, we now give up the lock while we run it.
- // Otherwise, we'd only ever do work on one thread at a time, which rather
- // defeats the point of this code.
- pool->fBusyThreads++;
- pool->fReady.unlock();
-
- // OK, now really do the work.
- r->fRunnable->run();
- SkDELETE(r);
-
- // Let everyone know we're not busy.
- pool->fReady.lock();
- pool->fBusyThreads--;
- pool->fReady.unlock();
- }
-
- SkASSERT(false); // Unreachable. The only exit happens when pool->fState is kHalting_State.
-}
-
-void SkThreadPool::add(SkRunnable* r) {
- if (NULL == r) {
- return;
- }
-
- // If we don't have any threads, obligingly just run the thing now.
- if (fThreads.isEmpty()) {
- return r->run();
- }
-
- // We have some threads. Queue it up!
- fReady.lock();
- SkASSERT(fState != kHalting_State); // Shouldn't be able to add work when we're halting.
- LinkedRunnable* linkedRunnable = SkNEW(LinkedRunnable);
- linkedRunnable->fRunnable = r;
- fQueue.addToHead(linkedRunnable);
- fReady.signal();
- fReady.unlock();
-}
diff --git a/chromium/third_party/skia/src/utils/SkUnitMappers.cpp b/chromium/third_party/skia/src/utils/SkUnitMappers.cpp
deleted file mode 100644
index 5976e9de52e..00000000000
--- a/chromium/third_party/skia/src/utils/SkUnitMappers.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "SkUnitMappers.h"
-#include "SkFlattenableBuffers.h"
-
-SkDiscreteMapper::SkDiscreteMapper(int segments) {
- if (segments < 2) {
- fSegments = 0;
- fScale = 0;
- } else {
- if (segments > 0xFFFF) {
- segments = 0xFFFF;
- }
- fSegments = segments;
- fScale = SK_Fract1 / (segments - 1);
- }
-}
-
-uint16_t SkDiscreteMapper::mapUnit16(uint16_t input) {
- SkFixed x = input * fSegments >> 16;
- x = x * fScale >> 14;
- x += x << 15 >> 31; // map 0x10000 to 0xFFFF
- return SkToU16(x);
-}
-
-SkDiscreteMapper::SkDiscreteMapper(SkFlattenableReadBuffer& rb)
- : SkUnitMapper(rb) {
- fSegments = rb.readInt();
- fScale = rb.read32();
-}
-
-void SkDiscreteMapper::flatten(SkFlattenableWriteBuffer& wb) const {
- this->INHERITED::flatten(wb);
-
- wb.writeInt(fSegments);
- wb.write32(fScale);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-uint16_t SkCosineMapper::mapUnit16(uint16_t input)
-{
- /* we want to call cosine(input * pi/2) treating input as [0...1)
- however, the straight multitply would overflow 32bits since input is
- 16bits and pi/2 is 17bits, so we shift down our pi const before we mul
- */
- SkFixed rads = (unsigned)(input * (SK_FixedPI >> 2)) >> 15;
- SkFixed x = SkFixedCos(rads);
- x += x << 15 >> 31; // map 0x10000 to 0xFFFF
- return SkToU16(x);
-}
-
-SkCosineMapper::SkCosineMapper(SkFlattenableReadBuffer& rb)
- : SkUnitMapper(rb) {}
diff --git a/chromium/third_party/skia/src/utils/android/ashmem.cpp b/chromium/third_party/skia/src/utils/android/ashmem.cpp
deleted file mode 100644
index 461c0623901..00000000000
--- a/chromium/third_party/skia/src/utils/android/ashmem.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2008 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/*
- * Implementation of the user-space ashmem API for devices, which have our
- * ashmem-enabled kernel. See ashmem-sim.c for the "fake" tmp-based version,
- * used by the simulator.
- */
-
-#include <android/ashmem.h>
-
-#include <unistd.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-
-#include <linux/ashmem.h>
-
-#define ASHMEM_DEVICE "/dev/ashmem"
-
-/*
- * ashmem_create_region - creates a new ashmem region and returns the file
- * descriptor, or <0 on error
- *
- * `name' is an optional label to give the region (visible in /proc/pid/maps)
- * `size' is the size of the region, in page-aligned bytes
- */
-int ashmem_create_region(const char *name, size_t size)
-{
- int fd, ret;
-
- fd = open(ASHMEM_DEVICE, O_RDWR);
- if (fd < 0)
- return fd;
-
- if (name) {
- char buf[ASHMEM_NAME_LEN];
-
- strlcpy(buf, name, sizeof(buf));
- ret = ioctl(fd, ASHMEM_SET_NAME, buf);
- if (ret < 0)
- goto error;
- }
-
- ret = ioctl(fd, ASHMEM_SET_SIZE, size);
- if (ret < 0)
- goto error;
-
- return fd;
-
-error:
- close(fd);
- return ret;
-}
-
-int ashmem_set_prot_region(int fd, int prot)
-{
- return ioctl(fd, ASHMEM_SET_PROT_MASK, prot);
-}
-
-int ashmem_pin_region(int fd, size_t offset, size_t len)
-{
- struct ashmem_pin pin = { offset, len };
- return ioctl(fd, ASHMEM_PIN, &pin);
-}
-
-int ashmem_unpin_region(int fd, size_t offset, size_t len)
-{
- struct ashmem_pin pin = { offset, len };
- return ioctl(fd, ASHMEM_UNPIN, &pin);
-}
-
-int ashmem_get_size_region(int fd)
-{
- return ioctl(fd, ASHMEM_GET_SIZE, NULL);
-}
-
-int ashmem_purge_all_caches(int fd)
-{
- return ioctl(fd, ASHMEM_PURGE_ALL_CACHES, NULL);
-}
diff --git a/chromium/third_party/skia/src/utils/android/ashmem.h b/chromium/third_party/skia/src/utils/android/ashmem.h
deleted file mode 100644
index 94ffe1a33b6..00000000000
--- a/chromium/third_party/skia/src/utils/android/ashmem.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2008 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef _CUTILS_ASHMEM_H
-#define _CUTILS_ASHMEM_H
-
-#include <stddef.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int ashmem_create_region(const char *name, size_t size);
-int ashmem_set_prot_region(int fd, int prot);
-
-/**
- * @return ASHMEM_NOT_PURGED if the memory was not purged.
- * ASHMEM_WAS_PURGED if the memory was purged.
- * -1 on error.
- */
-int ashmem_pin_region(int fd, size_t offset, size_t len);
-int ashmem_unpin_region(int fd, size_t offset, size_t len);
-int ashmem_get_size_region(int fd);
-int ashmem_purge_all_caches(int fd);
-
-#ifdef __cplusplus
-}
-#endif
-
-#ifndef __ASHMEMIOC /* in case someone included <linux/ashmem.h> too */
-
-#define ASHMEM_NAME_LEN 256
-
-#define ASHMEM_NAME_DEF "dev/ashmem"
-
-/* Return values from ASHMEM_PIN: Was the mapping purged while unpinned? */
-#define ASHMEM_NOT_PURGED 0
-#define ASHMEM_WAS_PURGED 1
-
-/* Return values from ASHMEM_UNPIN: Is the mapping now pinned or unpinned? */
-#define ASHMEM_IS_UNPINNED 0
-#define ASHMEM_IS_PINNED 1
-
-#endif /* ! __ASHMEMIOC */
-
-#endif /* _CUTILS_ASHMEM_H */
diff --git a/chromium/third_party/skia/src/utils/debugger/SkDebugCanvas.cpp b/chromium/third_party/skia/src/utils/debugger/SkDebugCanvas.cpp
index e491f3b8a79..8f6dc1b7a27 100644
--- a/chromium/third_party/skia/src/utils/debugger/SkDebugCanvas.cpp
+++ b/chromium/third_party/skia/src/utils/debugger/SkDebugCanvas.cpp
@@ -14,17 +14,13 @@
#include "SkDevice.h"
#include "SkXfermode.h"
-static SkBitmap make_noconfig_bm(int width, int height) {
- SkBitmap bm;
- bm.setConfig(SkBitmap::kNo_Config, width, height);
- return bm;
-}
-
SkDebugCanvas::SkDebugCanvas(int width, int height)
- : INHERITED(make_noconfig_bm(width, height))
+ : INHERITED(width, height)
+ , fPicture(NULL)
, fWidth(width)
, fHeight(height)
, fFilter(false)
+ , fMegaVizMode(false)
, fIndex(0)
, fOverdrawViz(false)
, fOverdrawFilter(NULL)
@@ -49,7 +45,8 @@ SkDebugCanvas::SkDebugCanvas(int width, int height)
large.roundOut(&largeIRect);
SkASSERT(!largeIRect.isEmpty());
#endif
- INHERITED::clipRect(large, SkRegion::kReplace_Op, false);
+ // call the base class' version to avoid adding a draw command
+ this->INHERITED::onClipRect(large, SkRegion::kReplace_Op, kHard_ClipEdgeStyle);
}
SkDebugCanvas::~SkDebugCanvas() {
@@ -59,12 +56,13 @@ SkDebugCanvas::~SkDebugCanvas() {
}
void SkDebugCanvas::addDrawCommand(SkDrawCommand* command) {
+ command->setOffset(this->getOpID());
fCommandVector.push(command);
}
void SkDebugCanvas::draw(SkCanvas* canvas) {
if (!fCommandVector.isEmpty()) {
- drawTo(canvas, fCommandVector.count() - 1);
+ this->drawTo(canvas, fCommandVector.count() - 1);
}
}
@@ -74,8 +72,7 @@ void SkDebugCanvas::applyUserTransform(SkCanvas* canvas) {
int SkDebugCanvas::getCommandAtPoint(int x, int y, int index) {
SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
- bitmap.allocPixels();
+ bitmap.allocPixels(SkImageInfo::MakeN32Premul(1, 1));
SkCanvas canvas(bitmap);
canvas.translate(SkIntToScalar(-x), SkIntToScalar(-y));
@@ -95,37 +92,43 @@ int SkDebugCanvas::getCommandAtPoint(int x, int y, int index) {
return layer;
}
-static SkPMColor OverdrawXferModeProc(SkPMColor src, SkPMColor dst) {
- // This table encodes the color progression of the overdraw visualization
- static const SkPMColor gTable[] = {
- SkPackARGB32(0x00, 0x00, 0x00, 0x00),
- SkPackARGB32(0xFF, 128, 158, 255),
- SkPackARGB32(0xFF, 170, 185, 212),
- SkPackARGB32(0xFF, 213, 195, 170),
- SkPackARGB32(0xFF, 255, 192, 127),
- SkPackARGB32(0xFF, 255, 185, 85),
- SkPackARGB32(0xFF, 255, 165, 42),
- SkPackARGB32(0xFF, 255, 135, 0),
- SkPackARGB32(0xFF, 255, 95, 0),
- SkPackARGB32(0xFF, 255, 50, 0),
- SkPackARGB32(0xFF, 255, 0, 0)
- };
-
- for (size_t i = 0; i < SK_ARRAY_COUNT(gTable)-1; ++i) {
- if (gTable[i] == dst) {
- return gTable[i+1];
+class OverdrawXfermode : public SkXfermode {
+public:
+ virtual SkPMColor xferColor(SkPMColor src, SkPMColor dst) const SK_OVERRIDE {
+ // This table encodes the color progression of the overdraw visualization
+ static const SkPMColor gTable[] = {
+ SkPackARGB32(0x00, 0x00, 0x00, 0x00),
+ SkPackARGB32(0xFF, 128, 158, 255),
+ SkPackARGB32(0xFF, 170, 185, 212),
+ SkPackARGB32(0xFF, 213, 195, 170),
+ SkPackARGB32(0xFF, 255, 192, 127),
+ SkPackARGB32(0xFF, 255, 185, 85),
+ SkPackARGB32(0xFF, 255, 165, 42),
+ SkPackARGB32(0xFF, 255, 135, 0),
+ SkPackARGB32(0xFF, 255, 95, 0),
+ SkPackARGB32(0xFF, 255, 50, 0),
+ SkPackARGB32(0xFF, 255, 0, 0)
+ };
+
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gTable)-1; ++i) {
+ if (gTable[i] == dst) {
+ return gTable[i+1];
+ }
}
+
+ return gTable[SK_ARRAY_COUNT(gTable)-1];
}
- return gTable[SK_ARRAY_COUNT(gTable)-1];
-}
+ virtual Factory getFactory() const SK_OVERRIDE { return NULL; }
+#ifndef SK_IGNORE_TO_STRING
+ virtual void toString(SkString* str) const { str->set("OverdrawXfermode"); }
+#endif
+};
-// The OverdrawFilter modifies every paint to use an SkProcXfermode which
-// in turn invokes OverdrawXferModeProc
class SkOverdrawFilter : public SkDrawFilter {
public:
SkOverdrawFilter() {
- fXferMode = new SkProcXfermode(OverdrawXferModeProc);
+ fXferMode = SkNEW(OverdrawXfermode);
}
virtual ~SkOverdrawFilter() {
@@ -167,17 +170,84 @@ private:
typedef SkDrawFilter INHERITED;
};
+class SkDebugClipVisitor : public SkCanvas::ClipVisitor {
+public:
+ SkDebugClipVisitor(SkCanvas* canvas) : fCanvas(canvas) {}
+
+ virtual void clipRect(const SkRect& r, SkRegion::Op, bool doAA) SK_OVERRIDE {
+ SkPaint p;
+ p.setColor(SK_ColorRED);
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setAntiAlias(doAA);
+ fCanvas->drawRect(r, p);
+ }
+ virtual void clipRRect(const SkRRect& rr, SkRegion::Op, bool doAA) SK_OVERRIDE {
+ SkPaint p;
+ p.setColor(SK_ColorGREEN);
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setAntiAlias(doAA);
+ fCanvas->drawRRect(rr, p);
+ }
+ virtual void clipPath(const SkPath& path, SkRegion::Op, bool doAA) SK_OVERRIDE {
+ SkPaint p;
+ p.setColor(SK_ColorBLUE);
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setAntiAlias(doAA);
+ fCanvas->drawPath(path, p);
+ }
+
+protected:
+ SkCanvas* fCanvas;
+
+private:
+ typedef SkCanvas::ClipVisitor INHERITED;
+};
+
+// set up the saveLayer commands so that the active ones
+// return true in their 'active' method
+void SkDebugCanvas::markActiveCommands(int index) {
+ fActiveLayers.rewind();
+ fActiveCulls.rewind();
+
+ for (int i = 0; i < fCommandVector.count(); ++i) {
+ fCommandVector[i]->setActive(false);
+ }
+
+ for (int i = 0; i < index; ++i) {
+ SkDrawCommand::Action result = fCommandVector[i]->action();
+ if (SkDrawCommand::kPushLayer_Action == result) {
+ fActiveLayers.push(fCommandVector[i]);
+ } else if (SkDrawCommand::kPopLayer_Action == result) {
+ fActiveLayers.pop();
+ } else if (SkDrawCommand::kPushCull_Action == result) {
+ fActiveCulls.push(fCommandVector[i]);
+ } else if (SkDrawCommand::kPopCull_Action == result) {
+ fActiveCulls.pop();
+ }
+ }
+
+ for (int i = 0; i < fActiveLayers.count(); ++i) {
+ fActiveLayers[i]->setActive(true);
+ }
+
+ for (int i = 0; i < fActiveCulls.count(); ++i) {
+ fActiveCulls[i]->setActive(true);
+ }
+}
+
void SkDebugCanvas::drawTo(SkCanvas* canvas, int index) {
SkASSERT(!fCommandVector.isEmpty());
SkASSERT(index < fCommandVector.count());
int i = 0;
+ bool pathOpsMode = getAllowSimplifyClip();
+ canvas->setAllowSimplifyClip(pathOpsMode);
// This only works assuming the canvas and device are the same ones that
// were previously drawn into because they need to preserve all saves
// and restores.
// The visibility filter also requires a full re-draw - otherwise we can
// end up drawing the filter repeatedly.
- if (fIndex < index && !fFilter) {
+ if (fIndex < index && !fFilter && !fMegaVizMode && !pathOpsMode) {
i = fIndex + 1;
} else {
for (int j = 0; j < fOutstandingSaveCount; j++) {
@@ -216,6 +286,10 @@ void SkDebugCanvas::drawTo(SkCanvas* canvas, int index) {
canvas->setDrawFilter(NULL);
}
+ if (fMegaVizMode) {
+ this->markActiveCommands(index);
+ }
+
for (; i <= index; i++) {
if (i == index && fFilter) {
SkPaint p;
@@ -232,12 +306,63 @@ void SkDebugCanvas::drawTo(SkCanvas* canvas, int index) {
}
if (fCommandVector[i]->isVisible()) {
- fCommandVector[i]->execute(canvas);
+ if (fMegaVizMode && fCommandVector[i]->active()) {
+ // "active" commands execute their visualization behaviors:
+ // All active saveLayers get replaced with saves so all draws go to the
+ // visible canvas.
+ // All active culls draw their cull box
+ fCommandVector[i]->vizExecute(canvas);
+ } else {
+ fCommandVector[i]->execute(canvas);
+ }
+
fCommandVector[i]->trackSaveState(&fOutstandingSaveCount);
}
}
+
+ if (fMegaVizMode) {
+ SkRect r = SkRect::MakeWH(SkIntToScalar(fWidth), SkIntToScalar(fHeight));
+ r.outset(SK_Scalar1, SK_Scalar1);
+
+ canvas->save();
+ // nuke the CTM
+ canvas->setMatrix(SkMatrix::I());
+ // turn off clipping
+ canvas->clipRect(r, SkRegion::kReplace_Op);
+
+ // visualize existing clips
+ SkDebugClipVisitor visitor(canvas);
+
+ canvas->replayClips(&visitor);
+
+ canvas->restore();
+ }
+ if (pathOpsMode) {
+ this->resetClipStackData();
+ const SkClipStack* clipStack = canvas->getClipStack();
+ SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart);
+ const SkClipStack::Element* element;
+ SkPath devPath;
+ while ((element = iter.next())) {
+ SkClipStack::Element::Type type = element->getType();
+ SkPath operand;
+ if (type != SkClipStack::Element::kEmpty_Type) {
+ element->asPath(&operand);
+ }
+ SkRegion::Op elementOp = element->getOp();
+ this->addClipStackData(devPath, operand, elementOp);
+ if (elementOp == SkRegion::kReplace_Op) {
+ devPath = operand;
+ } else {
+ Op(devPath, operand, (SkPathOp) elementOp, &devPath);
+ }
+ }
+ this->lastClipStackData(devPath);
+ }
fMatrix = canvas->getTotalMatrix();
- fClip = canvas->getTotalClip().getBounds();
+ if (!canvas->getClipDeviceBounds(&fClip)) {
+ fClip.setEmpty();
+ }
fIndex = index;
}
@@ -287,8 +412,14 @@ SkTArray<SkString>* SkDebugCanvas::getDrawCommandsAsStrings() const {
return commandString;
}
-void SkDebugCanvas::toggleFilter(bool toggle) {
- fFilter = toggle;
+SkTDArray<size_t>* SkDebugCanvas::getDrawCommandOffsets() const {
+ SkTDArray<size_t>* commandOffsets = new SkTDArray<size_t>;
+ if (!fCommandVector.isEmpty()) {
+ for (int i = 0; i < fCommandVector.count(); i ++) {
+ *commandOffsets->push() = fCommandVector[i]->offset();
+ }
+ }
+ return commandOffsets;
}
void SkDebugCanvas::overrideTexFiltering(bool overrideTexFiltering, SkPaint::FilterLevel level) {
@@ -301,101 +432,110 @@ void SkDebugCanvas::overrideTexFiltering(bool overrideTexFiltering, SkPaint::Fil
}
void SkDebugCanvas::clear(SkColor color) {
- addDrawCommand(new SkClearCommand(color));
+ this->addDrawCommand(new SkClearCommand(color));
}
-bool SkDebugCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
- addDrawCommand(new SkClipPathCommand(path, op, doAA));
- return true;
+void SkDebugCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
+ this->addDrawCommand(new SkClipPathCommand(path, op, kSoft_ClipEdgeStyle == edgeStyle));
}
-bool SkDebugCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
- addDrawCommand(new SkClipRectCommand(rect, op, doAA));
- return true;
+void SkDebugCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
+ this->addDrawCommand(new SkClipRectCommand(rect, op, kSoft_ClipEdgeStyle == edgeStyle));
}
-bool SkDebugCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
- addDrawCommand(new SkClipRRectCommand(rrect, op, doAA));
- return true;
+void SkDebugCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
+ this->addDrawCommand(new SkClipRRectCommand(rrect, op, kSoft_ClipEdgeStyle == edgeStyle));
}
-bool SkDebugCanvas::clipRegion(const SkRegion& region, SkRegion::Op op) {
- addDrawCommand(new SkClipRegionCommand(region, op));
- return true;
+void SkDebugCanvas::onClipRegion(const SkRegion& region, SkRegion::Op op) {
+ this->addDrawCommand(new SkClipRegionCommand(region, op));
}
-bool SkDebugCanvas::concat(const SkMatrix& matrix) {
- addDrawCommand(new SkConcatCommand(matrix));
- return true;
+void SkDebugCanvas::didConcat(const SkMatrix& matrix) {
+ switch (matrix.getType()) {
+ case SkMatrix::kTranslate_Mask:
+ this->addDrawCommand(new SkTranslateCommand(matrix.getTranslateX(),
+ matrix.getTranslateY()));
+ break;
+ case SkMatrix::kScale_Mask:
+ this->addDrawCommand(new SkScaleCommand(matrix.getScaleX(),
+ matrix.getScaleY()));
+ break;
+ default:
+ this->addDrawCommand(new SkConcatCommand(matrix));
+ break;
+ }
+
+ this->INHERITED::didConcat(matrix);
}
void SkDebugCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar left,
SkScalar top, const SkPaint* paint = NULL) {
- addDrawCommand(new SkDrawBitmapCommand(bitmap, left, top, paint));
+ this->addDrawCommand(new SkDrawBitmapCommand(bitmap, left, top, paint));
}
void SkDebugCanvas::drawBitmapRectToRect(const SkBitmap& bitmap,
const SkRect* src, const SkRect& dst,
const SkPaint* paint,
SkCanvas::DrawBitmapRectFlags flags) {
- addDrawCommand(new SkDrawBitmapRectCommand(bitmap, src, dst, paint, flags));
+ this->addDrawCommand(new SkDrawBitmapRectCommand(bitmap, src, dst, paint, flags));
}
void SkDebugCanvas::drawBitmapMatrix(const SkBitmap& bitmap,
const SkMatrix& matrix, const SkPaint* paint) {
- addDrawCommand(new SkDrawBitmapMatrixCommand(bitmap, matrix, paint));
+ this->addDrawCommand(new SkDrawBitmapMatrixCommand(bitmap, matrix, paint));
}
void SkDebugCanvas::drawBitmapNine(const SkBitmap& bitmap,
const SkIRect& center, const SkRect& dst, const SkPaint* paint) {
- addDrawCommand(new SkDrawBitmapNineCommand(bitmap, center, dst, paint));
+ this->addDrawCommand(new SkDrawBitmapNineCommand(bitmap, center, dst, paint));
}
void SkDebugCanvas::drawData(const void* data, size_t length) {
- addDrawCommand(new SkDrawDataCommand(data, length));
+ this->addDrawCommand(new SkDrawDataCommand(data, length));
}
void SkDebugCanvas::beginCommentGroup(const char* description) {
- addDrawCommand(new SkBeginCommentGroupCommand(description));
+ this->addDrawCommand(new SkBeginCommentGroupCommand(description));
}
void SkDebugCanvas::addComment(const char* kywd, const char* value) {
- addDrawCommand(new SkCommentCommand(kywd, value));
+ this->addDrawCommand(new SkCommentCommand(kywd, value));
}
void SkDebugCanvas::endCommentGroup() {
- addDrawCommand(new SkEndCommentGroupCommand());
+ this->addDrawCommand(new SkEndCommentGroupCommand());
}
void SkDebugCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
- addDrawCommand(new SkDrawOvalCommand(oval, paint));
+ this->addDrawCommand(new SkDrawOvalCommand(oval, paint));
}
void SkDebugCanvas::drawPaint(const SkPaint& paint) {
- addDrawCommand(new SkDrawPaintCommand(paint));
+ this->addDrawCommand(new SkDrawPaintCommand(paint));
}
void SkDebugCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
- addDrawCommand(new SkDrawPathCommand(path, paint));
+ this->addDrawCommand(new SkDrawPathCommand(path, paint));
}
-void SkDebugCanvas::drawPicture(SkPicture& picture) {
- addDrawCommand(new SkDrawPictureCommand(picture));
+void SkDebugCanvas::onDrawPicture(const SkPicture* picture) {
+ this->addDrawCommand(new SkDrawPictureCommand(picture));
}
void SkDebugCanvas::drawPoints(PointMode mode, size_t count,
const SkPoint pts[], const SkPaint& paint) {
- addDrawCommand(new SkDrawPointsCommand(mode, count, pts, paint));
+ this->addDrawCommand(new SkDrawPointsCommand(mode, count, pts, paint));
}
-void SkDebugCanvas::drawPosText(const void* text, size_t byteLength,
- const SkPoint pos[], const SkPaint& paint) {
- addDrawCommand(new SkDrawPosTextCommand(text, byteLength, pos, paint));
+void SkDebugCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
+ const SkPaint& paint) {
+ this->addDrawCommand(new SkDrawPosTextCommand(text, byteLength, pos, paint));
}
-void SkDebugCanvas::drawPosTextH(const void* text, size_t byteLength,
- const SkScalar xpos[], SkScalar constY, const SkPaint& paint) {
- addDrawCommand(
+void SkDebugCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
+ SkScalar constY, const SkPaint& paint) {
+ this->addDrawCommand(
new SkDrawPosTextHCommand(text, byteLength, xpos, constY, paint));
}
@@ -405,22 +545,27 @@ void SkDebugCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
}
void SkDebugCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
- addDrawCommand(new SkDrawRRectCommand(rrect, paint));
+ this->addDrawCommand(new SkDrawRRectCommand(rrect, paint));
+}
+
+void SkDebugCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
+ const SkPaint& paint) {
+ this->addDrawCommand(new SkDrawDRRectCommand(outer, inner, paint));
}
void SkDebugCanvas::drawSprite(const SkBitmap& bitmap, int left, int top,
const SkPaint* paint = NULL) {
- addDrawCommand(new SkDrawSpriteCommand(bitmap, left, top, paint));
+ this->addDrawCommand(new SkDrawSpriteCommand(bitmap, left, top, paint));
}
-void SkDebugCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
- SkScalar y, const SkPaint& paint) {
- addDrawCommand(new SkDrawTextCommand(text, byteLength, x, y, paint));
+void SkDebugCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
+ const SkPaint& paint) {
+ this->addDrawCommand(new SkDrawTextCommand(text, byteLength, x, y, paint));
}
-void SkDebugCanvas::drawTextOnPath(const void* text, size_t byteLength,
- const SkPath& path, const SkMatrix* matrix, const SkPaint& paint) {
- addDrawCommand(
+void SkDebugCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
+ const SkMatrix* matrix, const SkPaint& paint) {
+ this->addDrawCommand(
new SkDrawTextOnPathCommand(text, byteLength, path, matrix, paint));
}
@@ -428,50 +573,167 @@ void SkDebugCanvas::drawVertices(VertexMode vmode, int vertexCount,
const SkPoint vertices[], const SkPoint texs[], const SkColor colors[],
SkXfermode*, const uint16_t indices[], int indexCount,
const SkPaint& paint) {
- addDrawCommand(new SkDrawVerticesCommand(vmode, vertexCount, vertices,
- texs, colors, NULL, indices, indexCount, paint));
+ this->addDrawCommand(new SkDrawVerticesCommand(vmode, vertexCount, vertices,
+ texs, colors, NULL, indices, indexCount, paint));
}
-void SkDebugCanvas::restore() {
- addDrawCommand(new SkRestoreCommand());
+void SkDebugCanvas::onPushCull(const SkRect& cullRect) {
+ this->addDrawCommand(new SkPushCullCommand(cullRect));
}
-bool SkDebugCanvas::rotate(SkScalar degrees) {
- addDrawCommand(new SkRotateCommand(degrees));
- return true;
+void SkDebugCanvas::onPopCull() {
+ this->addDrawCommand(new SkPopCullCommand());
}
-int SkDebugCanvas::save(SaveFlags flags) {
- addDrawCommand(new SkSaveCommand(flags));
- return true;
+void SkDebugCanvas::willRestore() {
+ this->addDrawCommand(new SkRestoreCommand());
+ this->INHERITED::willRestore();
}
-int SkDebugCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
- SaveFlags flags) {
- addDrawCommand(new SkSaveLayerCommand(bounds, paint, flags));
- return true;
+void SkDebugCanvas::willSave(SaveFlags flags) {
+ this->addDrawCommand(new SkSaveCommand(flags));
+ this->INHERITED::willSave(flags);
}
-bool SkDebugCanvas::scale(SkScalar sx, SkScalar sy) {
- addDrawCommand(new SkScaleCommand(sx, sy));
- return true;
+SkCanvas::SaveLayerStrategy SkDebugCanvas::willSaveLayer(const SkRect* bounds, const SkPaint* paint,
+ SaveFlags flags) {
+ this->addDrawCommand(new SkSaveLayerCommand(bounds, paint, flags));
+ this->INHERITED::willSaveLayer(bounds, paint, flags);
+ // No need for a full layer.
+ return kNoLayer_SaveLayerStrategy;
+}
+
+void SkDebugCanvas::didSetMatrix(const SkMatrix& matrix) {
+ this->addDrawCommand(new SkSetMatrixCommand(matrix));
+ this->INHERITED::didSetMatrix(matrix);
+}
+
+void SkDebugCanvas::toggleCommand(int index, bool toggle) {
+ SkASSERT(index < fCommandVector.count());
+ fCommandVector[index]->setVisible(toggle);
+}
+
+static const char* gFillTypeStrs[] = {
+ "kWinding_FillType",
+ "kEvenOdd_FillType",
+ "kInverseWinding_FillType",
+ "kInverseEvenOdd_FillType"
+};
+
+static const char* gOpStrs[] = {
+ "kDifference_PathOp",
+ "kIntersect_PathOp",
+ "kUnion_PathOp",
+ "kXor_PathOp",
+ "kReverseDifference_PathOp",
+};
+
+static const char kHTML4SpaceIndent[] = "&nbsp;&nbsp;&nbsp;&nbsp;";
+
+void SkDebugCanvas::outputScalar(SkScalar num) {
+ if (num == (int) num) {
+ fClipStackData.appendf("%d", (int) num);
+ } else {
+ SkString str;
+ str.printf("%1.9g", num);
+ int width = (int) str.size();
+ const char* cStr = str.c_str();
+ while (cStr[width - 1] == '0') {
+ --width;
+ }
+ str.resize(width);
+ fClipStackData.appendf("%sf", str.c_str());
+ }
}
-void SkDebugCanvas::setMatrix(const SkMatrix& matrix) {
- addDrawCommand(new SkSetMatrixCommand(matrix));
+void SkDebugCanvas::outputPointsCommon(const SkPoint* pts, int count) {
+ for (int index = 0; index < count; ++index) {
+ this->outputScalar(pts[index].fX);
+ fClipStackData.appendf(", ");
+ this->outputScalar(pts[index].fY);
+ if (index + 1 < count) {
+ fClipStackData.appendf(", ");
+ }
+ }
}
-bool SkDebugCanvas::skew(SkScalar sx, SkScalar sy) {
- addDrawCommand(new SkSkewCommand(sx, sy));
- return true;
+void SkDebugCanvas::outputPoints(const SkPoint* pts, int count) {
+ this->outputPointsCommon(pts, count);
+ fClipStackData.appendf(");<br>");
+}
+
+void SkDebugCanvas::outputConicPoints(const SkPoint* pts, SkScalar weight) {
+ this->outputPointsCommon(pts, 2);
+ fClipStackData.appendf(", ");
+ this->outputScalar(weight);
+ fClipStackData.appendf(");<br>");
+}
+
+void SkDebugCanvas::addPathData(const SkPath& path, const char* pathName) {
+ SkPath::RawIter iter(path);
+ SkPath::FillType fillType = path.getFillType();
+ fClipStackData.appendf("%sSkPath %s;<br>", kHTML4SpaceIndent, pathName);
+ fClipStackData.appendf("%s%s.setFillType(SkPath::%s);<br>", kHTML4SpaceIndent, pathName,
+ gFillTypeStrs[fillType]);
+ iter.setPath(path);
+ uint8_t verb;
+ SkPoint pts[4];
+ while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
+ switch (verb) {
+ case SkPath::kMove_Verb:
+ fClipStackData.appendf("%s%s.moveTo(", kHTML4SpaceIndent, pathName);
+ this->outputPoints(&pts[0], 1);
+ continue;
+ case SkPath::kLine_Verb:
+ fClipStackData.appendf("%s%s.lineTo(", kHTML4SpaceIndent, pathName);
+ this->outputPoints(&pts[1], 1);
+ break;
+ case SkPath::kQuad_Verb:
+ fClipStackData.appendf("%s%s.quadTo(", kHTML4SpaceIndent, pathName);
+ this->outputPoints(&pts[1], 2);
+ break;
+ case SkPath::kConic_Verb:
+ fClipStackData.appendf("%s%s.conicTo(", kHTML4SpaceIndent, pathName);
+ this->outputConicPoints(&pts[1], iter.conicWeight());
+ break;
+ case SkPath::kCubic_Verb:
+ fClipStackData.appendf("%s%s.cubicTo(", kHTML4SpaceIndent, pathName);
+ this->outputPoints(&pts[1], 3);
+ break;
+ case SkPath::kClose_Verb:
+ fClipStackData.appendf("%s%s.close();<br>", kHTML4SpaceIndent, pathName);
+ break;
+ default:
+ SkDEBUGFAIL("bad verb");
+ return;
+ }
+ }
}
-bool SkDebugCanvas::translate(SkScalar dx, SkScalar dy) {
- addDrawCommand(new SkTranslateCommand(dx, dy));
- return true;
+void SkDebugCanvas::addClipStackData(const SkPath& devPath, const SkPath& operand,
+ SkRegion::Op elementOp) {
+ if (elementOp == SkRegion::kReplace_Op) {
+ if (!lastClipStackData(devPath)) {
+ fSaveDevPath = operand;
+ }
+ fCalledAddStackData = false;
+ } else {
+ fClipStackData.appendf("<br>static void test(skiatest::Reporter* reporter,"
+ " const char* filename) {<br>");
+ addPathData(fCalledAddStackData ? devPath : fSaveDevPath, "path");
+ addPathData(operand, "pathB");
+ fClipStackData.appendf("%stestPathOp(reporter, path, pathB, %s, filename);<br>",
+ kHTML4SpaceIndent, gOpStrs[elementOp]);
+ fClipStackData.appendf("}<br>");
+ fCalledAddStackData = true;
+ }
}
-void SkDebugCanvas::toggleCommand(int index, bool toggle) {
- SkASSERT(index < fCommandVector.count());
- fCommandVector[index]->setVisible(toggle);
+bool SkDebugCanvas::lastClipStackData(const SkPath& devPath) {
+ if (fCalledAddStackData) {
+ fClipStackData.appendf("<br>");
+ addPathData(devPath, "pathOut");
+ return true;
+ }
+ return false;
}
diff --git a/chromium/third_party/skia/src/utils/debugger/SkDebugCanvas.h b/chromium/third_party/skia/src/utils/debugger/SkDebugCanvas.h
index 262619e7f19..f15b397251e 100644
--- a/chromium/third_party/skia/src/utils/debugger/SkDebugCanvas.h
+++ b/chromium/third_party/skia/src/utils/debugger/SkDebugCanvas.h
@@ -12,6 +12,7 @@
#include "SkCanvas.h"
#include "SkDrawCommand.h"
+#include "SkPathOps.h"
#include "SkPicture.h"
#include "SkTArray.h"
#include "SkString.h"
@@ -23,12 +24,23 @@ public:
SkDebugCanvas(int width, int height);
virtual ~SkDebugCanvas();
- void toggleFilter(bool toggle);
+ void toggleFilter(bool toggle) { fFilter = toggle; }
+
+ void setMegaVizMode(bool megaVizMode) { fMegaVizMode = megaVizMode; }
+ bool getMegaVizMode() const { return fMegaVizMode; }
/**
* Enable or disable overdraw visualization
*/
void setOverdrawViz(bool overdrawViz) { fOverdrawViz = overdrawViz; }
+ bool getOverdrawViz() const { return fOverdrawViz; }
+
+ void setOutstandingSaveCount(int saveCount) { fOutstandingSaveCount = saveCount; }
+ int getOutstandingSaveCount() const { return fOutstandingSaveCount; }
+
+ bool getAllowSimplifyClip() const { return fAllowSimplifyClip; }
+
+ void setPicture(SkPicture* picture) { fPicture = picture; }
/**
* Enable or disable texure filtering override
@@ -116,6 +128,11 @@ public:
SkTArray<SkString>* getDrawCommandsAsStrings() const;
/**
+ * Returns an array containing an offset (in the SkPicture) for each command
+ */
+ SkTDArray<size_t>* getDrawCommandOffsets() const;
+
+ /**
Returns length of draw command vector.
*/
int getSize() const {
@@ -137,24 +154,14 @@ public:
fUserMatrix = matrix;
}
+ SkString clipStackData() const { return fClipStackData; }
+
////////////////////////////////////////////////////////////////////////////////
// Inherited from SkCanvas
////////////////////////////////////////////////////////////////////////////////
virtual void clear(SkColor) SK_OVERRIDE;
- virtual bool clipPath(const SkPath&, SkRegion::Op, bool) SK_OVERRIDE;
-
- virtual bool clipRect(const SkRect&, SkRegion::Op, bool) SK_OVERRIDE;
-
- virtual bool clipRRect(const SkRRect& rrect,
- SkRegion::Op op = SkRegion::kIntersect_Op,
- bool doAntiAlias = false) SK_OVERRIDE;
-
- virtual bool clipRegion(const SkRegion& region, SkRegion::Op op) SK_OVERRIDE;
-
- virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE;
-
virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
const SkPaint*) SK_OVERRIDE;
@@ -182,18 +189,9 @@ public:
virtual void drawPath(const SkPath& path, const SkPaint&) SK_OVERRIDE;
- virtual void drawPicture(SkPicture& picture) SK_OVERRIDE;
-
virtual void drawPoints(PointMode, size_t count, const SkPoint pts[],
const SkPaint&) SK_OVERRIDE;
- virtual void drawPosText(const void* text, size_t byteLength,
- const SkPoint pos[], const SkPaint&) SK_OVERRIDE;
-
- virtual void drawPosTextH(const void* text, size_t byteLength,
- const SkScalar xpos[], SkScalar constY,
- const SkPaint&) SK_OVERRIDE;
-
virtual void drawRect(const SkRect& rect, const SkPaint&) SK_OVERRIDE;
virtual void drawRRect(const SkRRect& rrect, const SkPaint& paint) SK_OVERRIDE;
@@ -201,48 +199,82 @@ public:
virtual void drawSprite(const SkBitmap&, int left, int top,
const SkPaint*) SK_OVERRIDE;
- virtual void drawText(const void* text, size_t byteLength, SkScalar x,
- SkScalar y, const SkPaint&) SK_OVERRIDE;
-
- virtual void drawTextOnPath(const void* text, size_t byteLength,
- const SkPath& path, const SkMatrix* matrix,
- const SkPaint&) SK_OVERRIDE;
-
virtual void drawVertices(VertexMode, int vertexCount,
const SkPoint vertices[], const SkPoint texs[],
const SkColor colors[], SkXfermode*,
const uint16_t indices[], int indexCount,
const SkPaint&) SK_OVERRIDE;
- virtual void restore() SK_OVERRIDE;
-
- virtual bool rotate(SkScalar degrees) SK_OVERRIDE;
+ static const int kVizImageHeight = 256;
+ static const int kVizImageWidth = 256;
- virtual int save(SaveFlags) SK_OVERRIDE;
+ virtual bool isClipEmpty() const SK_OVERRIDE { return false; }
+ virtual bool isClipRect() const SK_OVERRIDE { return true; }
+#ifdef SK_SUPPORT_LEGACY_GETCLIPTYPE
+ virtual ClipType getClipType() const SK_OVERRIDE {
+ return kRect_ClipType;
+ }
+#endif
+ virtual bool getClipBounds(SkRect* bounds) const SK_OVERRIDE {
+ if (NULL != bounds) {
+ bounds->setXYWH(0, 0,
+ SkIntToScalar(this->imageInfo().fWidth),
+ SkIntToScalar(this->imageInfo().fHeight));
+ }
+ return true;
+ }
+ virtual bool getClipDeviceBounds(SkIRect* bounds) const SK_OVERRIDE {
+ if (NULL != bounds) {
+ bounds->setLargest();
+ }
+ return true;
+ }
- virtual int saveLayer(const SkRect* bounds, const SkPaint*, SaveFlags) SK_OVERRIDE;
+protected:
+ virtual void willSave(SaveFlags) SK_OVERRIDE;
+ virtual SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SaveFlags) SK_OVERRIDE;
+ virtual void willRestore() SK_OVERRIDE;
- virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE;
+ virtual void didConcat(const SkMatrix&) SK_OVERRIDE;
+ virtual void didSetMatrix(const SkMatrix&) SK_OVERRIDE;
- virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE;
+ virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) SK_OVERRIDE;
+ virtual void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
+ const SkPaint&) SK_OVERRIDE;
+ virtual void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
+ const SkPaint&) SK_OVERRIDE;
+ virtual void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
+ SkScalar constY, const SkPaint&) SK_OVERRIDE;
+ virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
+ const SkMatrix* matrix, const SkPaint&) SK_OVERRIDE;
+ virtual void onPushCull(const SkRect& cullRect) SK_OVERRIDE;
+ virtual void onPopCull() SK_OVERRIDE;
- virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE;
+ virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
+ virtual void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
+ virtual void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
+ virtual void onClipRegion(const SkRegion& region, SkRegion::Op) SK_OVERRIDE;
- virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE;
+ virtual void onDrawPicture(const SkPicture* picture) SK_OVERRIDE;
- static const int kVizImageHeight = 256;
- static const int kVizImageWidth = 256;
+ void markActiveCommands(int index);
private:
SkTDArray<SkDrawCommand*> fCommandVector;
+ SkPicture* fPicture;
int fWidth;
int fHeight;
bool fFilter;
+ bool fMegaVizMode;
int fIndex;
SkMatrix fUserMatrix;
SkMatrix fMatrix;
SkIRect fClip;
+ SkString fClipStackData;
+ bool fCalledAddStackData;
+ SkPath fSaveDevPath;
+
bool fOverdrawViz;
SkDrawFilter* fOverdrawFilter;
@@ -258,6 +290,18 @@ private:
int fOutstandingSaveCount;
/**
+ The active saveLayer commands at a given point in the renderering.
+ Only used when "mega" visualization is enabled.
+ */
+ SkTDArray<SkDrawCommand*> fActiveLayers;
+
+ /**
+ The active cull commands at a given point in the rendering.
+ Only used when "mega" visualization is enabled.
+ */
+ SkTDArray<SkDrawCommand*> fActiveCulls;
+
+ /**
Adds the command to the classes vector of commands.
@param command The draw command for execution
*/
@@ -269,6 +313,23 @@ private:
*/
void applyUserTransform(SkCanvas* canvas);
+ size_t getOpID() const {
+ if (NULL != fPicture) {
+ return fPicture->EXPERIMENTAL_curOpID();
+ }
+ return 0;
+ }
+
+ void resetClipStackData() { fClipStackData.reset(); fCalledAddStackData = false; }
+
+ void addClipStackData(const SkPath& devPath, const SkPath& operand, SkRegion::Op elementOp);
+ void addPathData(const SkPath& path, const char* pathName);
+ bool lastClipStackData(const SkPath& devPath);
+ void outputConicPoints(const SkPoint* pts, SkScalar weight);
+ void outputPoints(const SkPoint* pts, int count);
+ void outputPointsCommon(const SkPoint* pts, int count);
+ void outputScalar(SkScalar num);
+
typedef SkCanvas INHERITED;
};
diff --git a/chromium/third_party/skia/src/utils/debugger/SkDrawCommand.cpp b/chromium/third_party/skia/src/utils/debugger/SkDrawCommand.cpp
index db041cdce6c..7c73cec786c 100644
--- a/chromium/third_party/skia/src/utils/debugger/SkDrawCommand.cpp
+++ b/chromium/third_party/skia/src/utils/debugger/SkDrawCommand.cpp
@@ -14,10 +14,12 @@
SkDrawCommand::SkDrawCommand(DrawType type)
: fDrawType(type)
+ , fOffset(0)
, fVisible(true) {
}
SkDrawCommand::SkDrawCommand() {
+ fOffset = 0;
fVisible = true;
}
@@ -64,6 +66,9 @@ const char* SkDrawCommand::GetCommandString(DrawType type) {
case BEGIN_COMMENT_GROUP: return "BeginCommentGroup";
case COMMENT: return "Comment";
case END_COMMENT_GROUP: return "EndCommentGroup";
+ case DRAW_DRRECT: return "Draw DRRect";
+ case PUSH_CULL: return "PushCull";
+ case POP_CULL: return "PopCull";
default:
SkDebugf("DrawType error 0x%08x\n", type);
SkASSERT(0);
@@ -77,9 +82,8 @@ SkString SkDrawCommand::toString() {
return SkString(GetCommandString(fDrawType));
}
-SkClearCommand::SkClearCommand(SkColor color) {
+SkClearCommand::SkClearCommand(SkColor color) : INHERITED(DRAW_CLEAR) {
fColor = color;
- fDrawType = DRAW_CLEAR;
fInfo.push(SkObjectParser::CustomTextToString("No Parameters"));
}
@@ -170,14 +174,30 @@ void render_rrect(SkCanvas* canvas, const SkRRect& rrect) {
canvas->restore();
}
+void render_drrect(SkCanvas* canvas, const SkRRect& outer, const SkRRect& inner) {
+ canvas->clear(0xFFFFFFFF);
+ canvas->save();
+
+ const SkRect& bounds = outer.getBounds();
+
+ xlate_and_scale_to_bounds(canvas, bounds);
+
+ SkPaint p;
+ p.setColor(SK_ColorBLACK);
+ p.setStyle(SkPaint::kStroke_Style);
+
+ canvas->drawDRRect(outer, inner, p);
+ canvas->restore();
+}
+
};
-SkClipPathCommand::SkClipPathCommand(const SkPath& path, SkRegion::Op op, bool doAA) {
+SkClipPathCommand::SkClipPathCommand(const SkPath& path, SkRegion::Op op, bool doAA)
+ : INHERITED(CLIP_PATH) {
fPath = path;
fOp = op;
fDoAA = doAA;
- fDrawType = CLIP_PATH;
fInfo.push(SkObjectParser::PathToString(path));
fInfo.push(SkObjectParser::RegionOpToString(op));
@@ -193,10 +213,10 @@ bool SkClipPathCommand::render(SkCanvas* canvas) const {
return true;
}
-SkClipRegionCommand::SkClipRegionCommand(const SkRegion& region, SkRegion::Op op) {
+SkClipRegionCommand::SkClipRegionCommand(const SkRegion& region, SkRegion::Op op)
+ : INHERITED(CLIP_REGION) {
fRegion = region;
fOp = op;
- fDrawType = CLIP_REGION;
fInfo.push(SkObjectParser::RegionToString(region));
fInfo.push(SkObjectParser::RegionOpToString(op));
@@ -206,11 +226,11 @@ void SkClipRegionCommand::execute(SkCanvas* canvas) {
canvas->clipRegion(fRegion, fOp);
}
-SkClipRectCommand::SkClipRectCommand(const SkRect& rect, SkRegion::Op op, bool doAA) {
+SkClipRectCommand::SkClipRectCommand(const SkRect& rect, SkRegion::Op op, bool doAA)
+ : INHERITED(CLIP_RECT) {
fRect = rect;
fOp = op;
fDoAA = doAA;
- fDrawType = CLIP_RECT;
fInfo.push(SkObjectParser::RectToString(rect));
fInfo.push(SkObjectParser::RegionOpToString(op));
@@ -221,11 +241,11 @@ void SkClipRectCommand::execute(SkCanvas* canvas) {
canvas->clipRect(fRect, fOp, fDoAA);
}
-SkClipRRectCommand::SkClipRRectCommand(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
+SkClipRRectCommand::SkClipRRectCommand(const SkRRect& rrect, SkRegion::Op op, bool doAA)
+ : INHERITED(CLIP_RRECT) {
fRRect = rrect;
fOp = op;
fDoAA = doAA;
- fDrawType = CLIP_RRECT;
fInfo.push(SkObjectParser::RRectToString(rrect));
fInfo.push(SkObjectParser::RegionOpToString(op));
@@ -241,9 +261,9 @@ bool SkClipRRectCommand::render(SkCanvas* canvas) const {
return true;
}
-SkConcatCommand::SkConcatCommand(const SkMatrix& matrix) {
+SkConcatCommand::SkConcatCommand(const SkMatrix& matrix)
+ : INHERITED(CONCAT) {
fMatrix = matrix;
- fDrawType = CONCAT;
fInfo.push(SkObjectParser::MatrixToString(matrix));
}
@@ -253,7 +273,8 @@ void SkConcatCommand::execute(SkCanvas* canvas) {
}
SkDrawBitmapCommand::SkDrawBitmapCommand(const SkBitmap& bitmap, SkScalar left, SkScalar top,
- const SkPaint* paint) {
+ const SkPaint* paint)
+ : INHERITED(DRAW_BITMAP) {
fBitmap = bitmap;
fLeft = left;
fTop = top;
@@ -263,7 +284,6 @@ SkDrawBitmapCommand::SkDrawBitmapCommand(const SkBitmap& bitmap, SkScalar left,
} else {
fPaintPtr = NULL;
}
- fDrawType = DRAW_BITMAP;
fInfo.push(SkObjectParser::BitmapToString(bitmap));
fInfo.push(SkObjectParser::ScalarToString(left, "SkScalar left: "));
@@ -284,7 +304,8 @@ bool SkDrawBitmapCommand::render(SkCanvas* canvas) const {
SkDrawBitmapMatrixCommand::SkDrawBitmapMatrixCommand(const SkBitmap& bitmap,
const SkMatrix& matrix,
- const SkPaint* paint) {
+ const SkPaint* paint)
+ : INHERITED(DRAW_BITMAP_MATRIX) {
fBitmap = bitmap;
fMatrix = matrix;
if (NULL != paint) {
@@ -293,7 +314,6 @@ SkDrawBitmapMatrixCommand::SkDrawBitmapMatrixCommand(const SkBitmap& bitmap,
} else {
fPaintPtr = NULL;
}
- fDrawType = DRAW_BITMAP_MATRIX;
fInfo.push(SkObjectParser::BitmapToString(bitmap));
fInfo.push(SkObjectParser::MatrixToString(matrix));
@@ -312,7 +332,8 @@ bool SkDrawBitmapMatrixCommand::render(SkCanvas* canvas) const {
}
SkDrawBitmapNineCommand::SkDrawBitmapNineCommand(const SkBitmap& bitmap, const SkIRect& center,
- const SkRect& dst, const SkPaint* paint) {
+ const SkRect& dst, const SkPaint* paint)
+ : INHERITED(DRAW_BITMAP_NINE) {
fBitmap = bitmap;
fCenter = center;
fDst = dst;
@@ -322,7 +343,6 @@ SkDrawBitmapNineCommand::SkDrawBitmapNineCommand(const SkBitmap& bitmap, const S
} else {
fPaintPtr = NULL;
}
- fDrawType = DRAW_BITMAP_NINE;
fInfo.push(SkObjectParser::BitmapToString(bitmap));
fInfo.push(SkObjectParser::IRectToString(center));
@@ -343,7 +363,8 @@ bool SkDrawBitmapNineCommand::render(SkCanvas* canvas) const {
SkDrawBitmapRectCommand::SkDrawBitmapRectCommand(const SkBitmap& bitmap, const SkRect* src,
const SkRect& dst, const SkPaint* paint,
- SkCanvas::DrawBitmapRectFlags flags) {
+ SkCanvas::DrawBitmapRectFlags flags)
+ : INHERITED(DRAW_BITMAP_RECT_TO_RECT) {
fBitmap = bitmap;
if (NULL != src) {
fSrc = *src;
@@ -360,8 +381,6 @@ SkDrawBitmapRectCommand::SkDrawBitmapRectCommand(const SkBitmap& bitmap, const S
}
fFlags = flags;
- fDrawType = DRAW_BITMAP_RECT_TO_RECT;
-
fInfo.push(SkObjectParser::BitmapToString(bitmap));
if (NULL != src) {
fInfo.push(SkObjectParser::RectToString(*src, "Src: "));
@@ -382,11 +401,11 @@ bool SkDrawBitmapRectCommand::render(SkCanvas* canvas) const {
return true;
}
-SkDrawDataCommand::SkDrawDataCommand(const void* data, size_t length) {
+SkDrawDataCommand::SkDrawDataCommand(const void* data, size_t length)
+ : INHERITED(DRAW_DATA) {
fData = new char[length];
memcpy(fData, data, length);
fLength = length;
- fDrawType = DRAW_DATA;
// TODO: add display of actual data?
SkString* str = new SkString;
@@ -415,13 +434,14 @@ SkCommentCommand::SkCommentCommand(const char* kywd, const char* value)
fInfo.push(temp);
}
-SkEndCommentGroupCommand::SkEndCommentGroupCommand() : INHERITED(END_COMMENT_GROUP) {
+SkEndCommentGroupCommand::SkEndCommentGroupCommand()
+ : INHERITED(END_COMMENT_GROUP) {
}
-SkDrawOvalCommand::SkDrawOvalCommand(const SkRect& oval, const SkPaint& paint) {
+SkDrawOvalCommand::SkDrawOvalCommand(const SkRect& oval, const SkPaint& paint)
+ : INHERITED(DRAW_OVAL) {
fOval = oval;
fPaint = paint;
- fDrawType = DRAW_OVAL;
fInfo.push(SkObjectParser::RectToString(oval));
fInfo.push(SkObjectParser::PaintToString(paint));
@@ -447,9 +467,9 @@ bool SkDrawOvalCommand::render(SkCanvas* canvas) const {
return true;
}
-SkDrawPaintCommand::SkDrawPaintCommand(const SkPaint& paint) {
+SkDrawPaintCommand::SkDrawPaintCommand(const SkPaint& paint)
+ : INHERITED(DRAW_PAINT) {
fPaint = paint;
- fDrawType = DRAW_PAINT;
fInfo.push(SkObjectParser::PaintToString(paint));
}
@@ -464,10 +484,10 @@ bool SkDrawPaintCommand::render(SkCanvas* canvas) const {
return true;
}
-SkDrawPathCommand::SkDrawPathCommand(const SkPath& path, const SkPaint& paint) {
+SkDrawPathCommand::SkDrawPathCommand(const SkPath& path, const SkPaint& paint)
+ : INHERITED(DRAW_PATH) {
fPath = path;
fPaint = paint;
- fDrawType = DRAW_PATH;
fInfo.push(SkObjectParser::PathToString(path));
fInfo.push(SkObjectParser::PaintToString(paint));
@@ -482,11 +502,11 @@ bool SkDrawPathCommand::render(SkCanvas* canvas) const {
return true;
}
-SkDrawPictureCommand::SkDrawPictureCommand(SkPicture& picture) :
- fPicture(picture) {
- fDrawType = DRAW_PICTURE;
+SkDrawPictureCommand::SkDrawPictureCommand(const SkPicture* picture)
+ : INHERITED(DRAW_PICTURE)
+ , fPicture(SkRef(picture)) {
SkString* temp = new SkString;
- temp->appendf("SkPicture: W: %d H: %d", picture.width(), picture.height());
+ temp->appendf("SkPicture: W: %d H: %d", picture->width(), picture->height());
fInfo.push(temp);
}
@@ -498,11 +518,11 @@ bool SkDrawPictureCommand::render(SkCanvas* canvas) const {
canvas->clear(0xFFFFFFFF);
canvas->save();
- SkRect bounds = SkRect::MakeWH(SkIntToScalar(fPicture.width()),
- SkIntToScalar(fPicture.height()));
+ SkRect bounds = SkRect::MakeWH(SkIntToScalar(fPicture->width()),
+ SkIntToScalar(fPicture->height()));
xlate_and_scale_to_bounds(canvas, bounds);
- canvas->drawPicture(const_cast<SkPicture&>(fPicture));
+ canvas->drawPicture(fPicture.get());
canvas->restore();
@@ -510,13 +530,13 @@ bool SkDrawPictureCommand::render(SkCanvas* canvas) const {
}
SkDrawPointsCommand::SkDrawPointsCommand(SkCanvas::PointMode mode, size_t count,
- const SkPoint pts[], const SkPaint& paint) {
+ const SkPoint pts[], const SkPaint& paint)
+ : INHERITED(DRAW_POINTS) {
fMode = mode;
fCount = count;
fPts = new SkPoint[count];
memcpy(fPts, pts, count * sizeof(SkPoint));
fPaint = paint;
- fDrawType = DRAW_POINTS;
fInfo.push(SkObjectParser::PointsToString(pts, count));
fInfo.push(SkObjectParser::ScalarToString(SkIntToScalar((unsigned int)count),
@@ -553,7 +573,8 @@ bool SkDrawPointsCommand::render(SkCanvas* canvas) const {
}
SkDrawPosTextCommand::SkDrawPosTextCommand(const void* text, size_t byteLength,
- const SkPoint pos[], const SkPaint& paint) {
+ const SkPoint pos[], const SkPaint& paint)
+ : INHERITED(DRAW_POS_TEXT) {
size_t numPts = paint.countText(text, byteLength);
fText = new char[byteLength];
@@ -564,7 +585,6 @@ SkDrawPosTextCommand::SkDrawPosTextCommand(const void* text, size_t byteLength,
memcpy(fPos, pos, numPts * sizeof(SkPoint));
fPaint = paint;
- fDrawType = DRAW_POS_TEXT;
fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
// TODO(chudy): Test that this works.
@@ -579,7 +599,8 @@ void SkDrawPosTextCommand::execute(SkCanvas* canvas) {
SkDrawPosTextHCommand::SkDrawPosTextHCommand(const void* text, size_t byteLength,
const SkScalar xpos[], SkScalar constY,
- const SkPaint& paint) {
+ const SkPaint& paint)
+ : INHERITED(DRAW_POS_TEXT_H) {
size_t numPts = paint.countText(text, byteLength);
fText = new char[byteLength];
@@ -591,7 +612,6 @@ SkDrawPosTextHCommand::SkDrawPosTextHCommand(const void* text, size_t byteLength
fConstY = constY;
fPaint = paint;
- fDrawType = DRAW_POS_TEXT_H;
fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
fInfo.push(SkObjectParser::ScalarToString(xpos[0], "XPOS: "));
@@ -603,10 +623,10 @@ void SkDrawPosTextHCommand::execute(SkCanvas* canvas) {
canvas->drawPosTextH(fText, fByteLength, fXpos, fConstY, fPaint);
}
-SkDrawRectCommand::SkDrawRectCommand(const SkRect& rect, const SkPaint& paint) {
+SkDrawRectCommand::SkDrawRectCommand(const SkRect& rect, const SkPaint& paint)
+ : INHERITED(DRAW_RECT) {
fRect = rect;
fPaint = paint;
- fDrawType = DRAW_RECT;
fInfo.push(SkObjectParser::RectToString(rect));
fInfo.push(SkObjectParser::PaintToString(paint));
@@ -616,10 +636,10 @@ void SkDrawRectCommand::execute(SkCanvas* canvas) {
canvas->drawRect(fRect, fPaint);
}
-SkDrawRRectCommand::SkDrawRRectCommand(const SkRRect& rrect, const SkPaint& paint) {
+SkDrawRRectCommand::SkDrawRRectCommand(const SkRRect& rrect, const SkPaint& paint)
+ : INHERITED(DRAW_RRECT) {
fRRect = rrect;
fPaint = paint;
- fDrawType = DRAW_RRECT;
fInfo.push(SkObjectParser::RRectToString(rrect));
fInfo.push(SkObjectParser::PaintToString(paint));
@@ -634,8 +654,31 @@ bool SkDrawRRectCommand::render(SkCanvas* canvas) const {
return true;
}
+SkDrawDRRectCommand::SkDrawDRRectCommand(const SkRRect& outer,
+ const SkRRect& inner,
+ const SkPaint& paint)
+ : INHERITED(DRAW_DRRECT) {
+ fOuter = outer;
+ fInner = inner;
+ fPaint = paint;
+
+ fInfo.push(SkObjectParser::RRectToString(outer));
+ fInfo.push(SkObjectParser::RRectToString(inner));
+ fInfo.push(SkObjectParser::PaintToString(paint));
+}
+
+void SkDrawDRRectCommand::execute(SkCanvas* canvas) {
+ canvas->drawDRRect(fOuter, fInner, fPaint);
+}
+
+bool SkDrawDRRectCommand::render(SkCanvas* canvas) const {
+ render_drrect(canvas, fOuter, fInner);
+ return true;
+}
+
SkDrawSpriteCommand::SkDrawSpriteCommand(const SkBitmap& bitmap, int left, int top,
- const SkPaint* paint) {
+ const SkPaint* paint)
+ : INHERITED(DRAW_SPRITE) {
fBitmap = bitmap;
fLeft = left;
fTop = top;
@@ -645,7 +688,6 @@ SkDrawSpriteCommand::SkDrawSpriteCommand(const SkBitmap& bitmap, int left, int t
} else {
fPaintPtr = NULL;
}
- fDrawType = DRAW_SPRITE;
fInfo.push(SkObjectParser::BitmapToString(bitmap));
fInfo.push(SkObjectParser::IntToString(left, "Left: "));
@@ -665,14 +707,14 @@ bool SkDrawSpriteCommand::render(SkCanvas* canvas) const {
}
SkDrawTextCommand::SkDrawTextCommand(const void* text, size_t byteLength, SkScalar x, SkScalar y,
- const SkPaint& paint) {
+ const SkPaint& paint)
+ : INHERITED(DRAW_TEXT) {
fText = new char[byteLength];
memcpy(fText, text, byteLength);
fByteLength = byteLength;
fX = x;
fY = y;
fPaint = paint;
- fDrawType = DRAW_TEXT;
fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
fInfo.push(SkObjectParser::ScalarToString(x, "SkScalar x: "));
@@ -686,7 +728,8 @@ void SkDrawTextCommand::execute(SkCanvas* canvas) {
SkDrawTextOnPathCommand::SkDrawTextOnPathCommand(const void* text, size_t byteLength,
const SkPath& path, const SkMatrix* matrix,
- const SkPaint& paint) {
+ const SkPaint& paint)
+ : INHERITED(DRAW_TEXT_ON_PATH) {
fText = new char[byteLength];
memcpy(fText, text, byteLength);
fByteLength = byteLength;
@@ -697,7 +740,6 @@ SkDrawTextOnPathCommand::SkDrawTextOnPathCommand(const void* text, size_t byteLe
fMatrix.setIdentity();
}
fPaint = paint;
- fDrawType = DRAW_TEXT_ON_PATH;
fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
fInfo.push(SkObjectParser::PathToString(path));
@@ -717,7 +759,8 @@ SkDrawVerticesCommand::SkDrawVerticesCommand(SkCanvas::VertexMode vmode, int ver
const SkPoint vertices[], const SkPoint texs[],
const SkColor colors[], SkXfermode* xfermode,
const uint16_t indices[], int indexCount,
- const SkPaint& paint) {
+ const SkPaint& paint)
+ : INHERITED(DRAW_VERTICES) {
fVmode = vmode;
fVertexCount = vertexCount;
@@ -753,7 +796,6 @@ SkDrawVerticesCommand::SkDrawVerticesCommand(SkCanvas::VertexMode vmode, int ver
fIndexCount = indexCount;
fPaint = paint;
- fDrawType = DRAW_VERTICES;
// TODO(chudy)
fInfo.push(SkObjectParser::CustomTextToString("To be implemented."));
@@ -774,8 +816,8 @@ void SkDrawVerticesCommand::execute(SkCanvas* canvas) {
fIndexCount, fPaint);
}
-SkRestoreCommand::SkRestoreCommand() {
- fDrawType = RESTORE;
+SkRestoreCommand::SkRestoreCommand()
+ : INHERITED(RESTORE) {
fInfo.push(SkObjectParser::CustomTextToString("No Parameters"));
}
@@ -787,9 +829,9 @@ void SkRestoreCommand::trackSaveState(int* state) {
(*state)--;
}
-SkRotateCommand::SkRotateCommand(SkScalar degrees) {
+SkRotateCommand::SkRotateCommand(SkScalar degrees)
+ : INHERITED(ROTATE) {
fDegrees = degrees;
- fDrawType = ROTATE;
fInfo.push(SkObjectParser::ScalarToString(degrees, "SkScalar degrees: "));
}
@@ -798,9 +840,9 @@ void SkRotateCommand::execute(SkCanvas* canvas) {
canvas->rotate(fDegrees);
}
-SkSaveCommand::SkSaveCommand(SkCanvas::SaveFlags flags) {
+SkSaveCommand::SkSaveCommand(SkCanvas::SaveFlags flags)
+ : INHERITED(SAVE) {
fFlags = flags;
- fDrawType = SAVE;
fInfo.push(SkObjectParser::SaveFlagsToString(flags));
}
@@ -813,7 +855,8 @@ void SkSaveCommand::trackSaveState(int* state) {
}
SkSaveLayerCommand::SkSaveLayerCommand(const SkRect* bounds, const SkPaint* paint,
- SkCanvas::SaveFlags flags) {
+ SkCanvas::SaveFlags flags)
+ : INHERITED(SAVE_LAYER) {
if (NULL != bounds) {
fBounds = *bounds;
} else {
@@ -827,7 +870,6 @@ SkSaveLayerCommand::SkSaveLayerCommand(const SkRect* bounds, const SkPaint* pain
fPaintPtr = NULL;
}
fFlags = flags;
- fDrawType = SAVE_LAYER;
if (NULL != bounds) {
fInfo.push(SkObjectParser::RectToString(*bounds, "Bounds: "));
@@ -844,14 +886,18 @@ void SkSaveLayerCommand::execute(SkCanvas* canvas) {
fFlags);
}
+void SkSaveLayerCommand::vizExecute(SkCanvas* canvas) {
+ canvas->save();
+}
+
void SkSaveLayerCommand::trackSaveState(int* state) {
(*state)++;
}
-SkScaleCommand::SkScaleCommand(SkScalar sx, SkScalar sy) {
+SkScaleCommand::SkScaleCommand(SkScalar sx, SkScalar sy)
+ : INHERITED(SCALE) {
fSx = sx;
fSy = sy;
- fDrawType = SCALE;
fInfo.push(SkObjectParser::ScalarToString(sx, "SkScalar sx: "));
fInfo.push(SkObjectParser::ScalarToString(sy, "SkScalar sy: "));
@@ -861,9 +907,9 @@ void SkScaleCommand::execute(SkCanvas* canvas) {
canvas->scale(fSx, fSy);
}
-SkSetMatrixCommand::SkSetMatrixCommand(const SkMatrix& matrix) {
+SkSetMatrixCommand::SkSetMatrixCommand(const SkMatrix& matrix)
+ : INHERITED(SET_MATRIX) {
fMatrix = matrix;
- fDrawType = SET_MATRIX;
fInfo.push(SkObjectParser::MatrixToString(matrix));
}
@@ -872,10 +918,10 @@ void SkSetMatrixCommand::execute(SkCanvas* canvas) {
canvas->setMatrix(fMatrix);
}
-SkSkewCommand::SkSkewCommand(SkScalar sx, SkScalar sy) {
+SkSkewCommand::SkSkewCommand(SkScalar sx, SkScalar sy)
+ : INHERITED(SKEW) {
fSx = sx;
fSy = sy;
- fDrawType = SKEW;
fInfo.push(SkObjectParser::ScalarToString(sx, "SkScalar sx: "));
fInfo.push(SkObjectParser::ScalarToString(sy, "SkScalar sy: "));
@@ -885,10 +931,10 @@ void SkSkewCommand::execute(SkCanvas* canvas) {
canvas->skew(fSx, fSy);
}
-SkTranslateCommand::SkTranslateCommand(SkScalar dx, SkScalar dy) {
+SkTranslateCommand::SkTranslateCommand(SkScalar dx, SkScalar dy)
+ : INHERITED(TRANSLATE) {
fDx = dx;
fDy = dy;
- fDrawType = TRANSLATE;
fInfo.push(SkObjectParser::ScalarToString(dx, "SkScalar dx: "));
fInfo.push(SkObjectParser::ScalarToString(dy, "SkScalar dy: "));
@@ -897,3 +943,28 @@ SkTranslateCommand::SkTranslateCommand(SkScalar dx, SkScalar dy) {
void SkTranslateCommand::execute(SkCanvas* canvas) {
canvas->translate(fDx, fDy);
}
+
+SkPushCullCommand::SkPushCullCommand(const SkRect& cullRect)
+ : INHERITED(PUSH_CULL)
+ , fCullRect(cullRect) {
+ fInfo.push(SkObjectParser::RectToString(cullRect));
+}
+
+void SkPushCullCommand::execute(SkCanvas* canvas) {
+ canvas->pushCull(fCullRect);
+}
+
+void SkPushCullCommand::vizExecute(SkCanvas* canvas) {
+ canvas->pushCull(fCullRect);
+
+ SkPaint p;
+ p.setColor(SK_ColorCYAN);
+ p.setStyle(SkPaint::kStroke_Style);
+ canvas->drawRect(fCullRect, p);
+}
+
+SkPopCullCommand::SkPopCullCommand() : INHERITED(POP_CULL) { }
+
+void SkPopCullCommand::execute(SkCanvas* canvas) {
+ canvas->popCull();
+}
diff --git a/chromium/third_party/skia/src/utils/debugger/SkDrawCommand.h b/chromium/third_party/skia/src/utils/debugger/SkDrawCommand.h
index b78dc9c3c4d..a0bfb2ddca5 100644
--- a/chromium/third_party/skia/src/utils/debugger/SkDrawCommand.h
+++ b/chromium/third_party/skia/src/utils/debugger/SkDrawCommand.h
@@ -23,6 +23,9 @@ public:
virtual SkString toString();
+ void setOffset(size_t offset) { fOffset = offset; }
+ virtual size_t offset() { return fOffset; }
+
virtual const char* toCString() {
return GetCommandString(fDrawType);
}
@@ -36,10 +39,34 @@ public:
}
SkTDArray<SkString*>* Info() {return &fInfo; };
- virtual void execute(SkCanvas* canvas)=0;
+ virtual void execute(SkCanvas* canvas) = 0;
+ virtual void vizExecute(SkCanvas* canvas) { };
/** Does nothing by default, but used by save() and restore()-type
- subclassse to track unresolved save() calls. */
+ subclasses to track unresolved save() calls. */
virtual void trackSaveState(int* state) { };
+
+ // The next "active" system is only used by save, saveLayer, restore,
+ // pushCull and popCull. It is used in two ways:
+ // To determine which saveLayers are currently active (at a
+ // given point in the rendering).
+ // saves just return a kPushLayer action but don't track active state
+ // restores just return a kPopLayer action
+ // saveLayers return kPushLayer but also track the active state
+ // To determine which culls are currently active (at a given point)
+ // in the rendering).
+ // pushCulls return a kPushCull action
+ // popCulls return a kPopCull action
+ enum Action {
+ kNone_Action,
+ kPopLayer_Action,
+ kPushLayer_Action,
+ kPopCull_Action,
+ kPushCull_Action
+ };
+ virtual Action action() const { return kNone_Action; }
+ virtual void setActive(bool active) {}
+ virtual bool active() const { return false; }
+
DrawType getType() { return fDrawType; };
virtual bool render(SkCanvas* canvas) const { return false; }
@@ -47,11 +74,12 @@ public:
static const char* GetCommandString(DrawType type);
protected:
- DrawType fDrawType;
SkTDArray<SkString*> fInfo;
private:
- bool fVisible;
+ DrawType fDrawType;
+ size_t fOffset;
+ bool fVisible;
};
class SkRestoreCommand : public SkDrawCommand {
@@ -59,6 +87,7 @@ public:
SkRestoreCommand();
virtual void execute(SkCanvas* canvas) SK_OVERRIDE;
virtual void trackSaveState(int* state) SK_OVERRIDE;
+ virtual Action action() const SK_OVERRIDE { return kPopLayer_Action; }
private:
typedef SkDrawCommand INHERITED;
@@ -146,7 +175,7 @@ private:
class SkDrawBitmapCommand : public SkDrawCommand {
public:
SkDrawBitmapCommand(const SkBitmap& bitmap, SkScalar left, SkScalar top,
- const SkPaint* paint);
+ const SkPaint* paint);
virtual void execute(SkCanvas* canvas) SK_OVERRIDE;
virtual bool render(SkCanvas* canvas) const SK_OVERRIDE;
private:
@@ -162,7 +191,7 @@ private:
class SkDrawBitmapMatrixCommand : public SkDrawCommand {
public:
SkDrawBitmapMatrixCommand(const SkBitmap& bitmap, const SkMatrix& matrix,
- const SkPaint* paint);
+ const SkPaint* paint);
virtual void execute(SkCanvas* canvas) SK_OVERRIDE;
virtual bool render(SkCanvas* canvas) const SK_OVERRIDE;
private:
@@ -177,7 +206,7 @@ private:
class SkDrawBitmapNineCommand : public SkDrawCommand {
public:
SkDrawBitmapNineCommand(const SkBitmap& bitmap, const SkIRect& center,
- const SkRect& dst, const SkPaint* paint);
+ const SkRect& dst, const SkPaint* paint);
virtual void execute(SkCanvas* canvas) SK_OVERRIDE;
virtual bool render(SkCanvas* canvas) const SK_OVERRIDE;
private:
@@ -314,12 +343,12 @@ private:
class SkDrawPictureCommand : public SkDrawCommand {
public:
- SkDrawPictureCommand(SkPicture& picture);
+ SkDrawPictureCommand(const SkPicture* picture);
virtual void execute(SkCanvas* canvas) SK_OVERRIDE;
virtual bool render(SkCanvas* canvas) const SK_OVERRIDE;
private:
- SkPicture fPicture;
+ SkAutoTUnref<const SkPicture> fPicture;
typedef SkDrawCommand INHERITED;
};
@@ -327,7 +356,7 @@ private:
class SkDrawPointsCommand : public SkDrawCommand {
public:
SkDrawPointsCommand(SkCanvas::PointMode mode, size_t count, const SkPoint pts[],
- const SkPaint& paint);
+ const SkPaint& paint);
virtual ~SkDrawPointsCommand() { delete [] fPts; }
virtual void execute(SkCanvas* canvas) SK_OVERRIDE;
virtual bool render(SkCanvas* canvas) const SK_OVERRIDE;
@@ -343,7 +372,7 @@ private:
class SkDrawTextCommand : public SkDrawCommand {
public:
SkDrawTextCommand(const void* text, size_t byteLength, SkScalar x, SkScalar y,
- const SkPaint& paint);
+ const SkPaint& paint);
virtual ~SkDrawTextCommand() { delete [] fText; }
virtual void execute(SkCanvas* canvas) SK_OVERRIDE;
private:
@@ -429,6 +458,20 @@ private:
typedef SkDrawCommand INHERITED;
};
+class SkDrawDRRectCommand : public SkDrawCommand {
+public:
+ SkDrawDRRectCommand(const SkRRect& outer, const SkRRect& inner,
+ const SkPaint& paint);
+ virtual void execute(SkCanvas* canvas) SK_OVERRIDE;
+ virtual bool render(SkCanvas* canvas) const SK_OVERRIDE;
+private:
+ SkRRect fOuter;
+ SkRRect fInner;
+ SkPaint fPaint;
+
+ typedef SkDrawCommand INHERITED;
+};
+
class SkDrawSpriteCommand : public SkDrawCommand {
public:
SkDrawSpriteCommand(const SkBitmap& bitmap, int left, int top, const SkPaint* paint);
@@ -482,6 +525,7 @@ public:
SkSaveCommand(SkCanvas::SaveFlags flags);
virtual void execute(SkCanvas* canvas) SK_OVERRIDE;
virtual void trackSaveState(int* state) SK_OVERRIDE;
+ virtual Action action() const SK_OVERRIDE { return kPushLayer_Action; }
private:
SkCanvas::SaveFlags fFlags;
@@ -493,7 +537,11 @@ public:
SkSaveLayerCommand(const SkRect* bounds, const SkPaint* paint,
SkCanvas::SaveFlags flags);
virtual void execute(SkCanvas* canvas) SK_OVERRIDE;
+ virtual void vizExecute(SkCanvas* canvas) SK_OVERRIDE;
virtual void trackSaveState(int* state) SK_OVERRIDE;
+ virtual Action action() const SK_OVERRIDE{ return kPushLayer_Action; }
+ virtual void setActive(bool active) SK_OVERRIDE { fActive = active; }
+ virtual bool active() const SK_OVERRIDE { return fActive; }
const SkPaint* paint() const { return fPaintPtr; }
@@ -503,6 +551,8 @@ private:
SkPaint* fPaintPtr;
SkCanvas::SaveFlags fFlags;
+ bool fActive;
+
typedef SkDrawCommand INHERITED;
};
@@ -557,4 +607,28 @@ private:
typedef SkDrawCommand INHERITED;
};
+class SkPushCullCommand : public SkDrawCommand {
+public:
+ SkPushCullCommand(const SkRect&);
+ virtual void execute(SkCanvas*) SK_OVERRIDE;
+ virtual void vizExecute(SkCanvas* canvas) SK_OVERRIDE;
+ virtual Action action() const { return kPushCull_Action; }
+ virtual void setActive(bool active) { fActive = active; }
+ virtual bool active() const { return fActive; }
+private:
+ SkRect fCullRect;
+ bool fActive;
+
+ typedef SkDrawCommand INHERITED;
+};
+
+class SkPopCullCommand : public SkDrawCommand {
+public:
+ SkPopCullCommand();
+ virtual void execute(SkCanvas* canvas) SK_OVERRIDE;
+ virtual Action action() const { return kPopCull_Action; }
+private:
+ typedef SkDrawCommand INHERITED;
+};
+
#endif
diff --git a/chromium/third_party/skia/src/utils/debugger/SkObjectParser.cpp b/chromium/third_party/skia/src/utils/debugger/SkObjectParser.cpp
index ebbd40018e7..b932036a894 100644
--- a/chromium/third_party/skia/src/utils/debugger/SkObjectParser.cpp
+++ b/chromium/third_party/skia/src/utils/debugger/SkObjectParser.cpp
@@ -25,13 +25,13 @@ SkString* SkObjectParser::BitmapToString(const SkBitmap& bitmap) {
mBitmap->append(" H: ");
mBitmap->appendS32(bitmap.height());
- const char* gConfigStrings[] = {
- "None", "A8", "Index8", "RGB565", "ARGB4444", "ARGB8888"
+ const char* gColorTypeStrings[] = {
+ "None", "A8", "565", "4444", "RGBA", "BGRA", "Index8"
};
- SkASSERT(SkBitmap::kConfigCount == SK_ARRAY_COUNT(gConfigStrings));
+ SkASSERT(kLastEnum_SkColorType + 1 == SK_ARRAY_COUNT(gColorTypeStrings));
- mBitmap->append(" Config: ");
- mBitmap->append(gConfigStrings[bitmap.config()]);
+ mBitmap->append(" ColorType: ");
+ mBitmap->append(gColorTypeStrings[bitmap.colorType()]);
if (bitmap.isOpaque()) {
mBitmap->append(" opaque");
@@ -94,7 +94,7 @@ SkString* SkObjectParser::IRectToString(const SkIRect& rect) {
SkString* SkObjectParser::MatrixToString(const SkMatrix& matrix) {
SkString* str = new SkString("SkMatrix: ");
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
matrix.toString(str);
#endif
return str;
@@ -102,7 +102,7 @@ SkString* SkObjectParser::MatrixToString(const SkMatrix& matrix) {
SkString* SkObjectParser::PaintToString(const SkPaint& paint) {
SkString* str = new SkString;
-#ifdef SK_DEVELOPER
+#ifndef SK_IGNORE_TO_STRING
paint.toString(str);
#endif
return str;
@@ -241,6 +241,8 @@ SkString* SkObjectParser::RRectToString(const SkRRect& rrect, const char* title)
mRRect->append("oval");
} else if (rrect.isSimple()) {
mRRect->append("simple");
+ } else if (rrect.isNinePatch()) {
+ mRRect->append("nine-patch");
} else {
SkASSERT(rrect.isComplex());
mRRect->append("complex");
diff --git a/chromium/third_party/skia/src/utils/debugger/SkObjectParser.h b/chromium/third_party/skia/src/utils/debugger/SkObjectParser.h
index 911b7789215..da842653ffc 100644
--- a/chromium/third_party/skia/src/utils/debugger/SkObjectParser.h
+++ b/chromium/third_party/skia/src/utils/debugger/SkObjectParser.h
@@ -20,7 +20,7 @@ class SkObjectParser {
public:
/**
- Returns a string about a bitmaps bounds and config.
+ Returns a string about a bitmaps bounds and colortype.
@param bitmap SkBitmap
*/
static SkString* BitmapToString(const SkBitmap& bitmap);
diff --git a/chromium/third_party/skia/src/utils/ios/SkImageDecoder_iOS.mm b/chromium/third_party/skia/src/utils/ios/SkImageDecoder_iOS.mm
index f347e060c88..5e4261ff1db 100755
--- a/chromium/third_party/skia/src/utils/ios/SkImageDecoder_iOS.mm
+++ b/chromium/third_party/skia/src/utils/ios/SkImageDecoder_iOS.mm
@@ -29,7 +29,8 @@ bool SkImageDecoder_iOS::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
const int width = uimage.size.width;
const int height = uimage.size.height;
- bm->setConfig(SkBitmap::kARGB_8888_Config, width, height);
+ SkColorType ct = SkBitmapConfigToColorType(SkBitmap::kARGB_8888_Config);
+ bm->setInfo(SkImageInfo::Make(width, height, ct, kPremul_SkAlphaType), 0);
if (SkImageDecoder::kDecodeBounds_Mode == mode) {
return true;
}
diff --git a/chromium/third_party/skia/src/utils/mac/SkCreateCGImageRef.cpp b/chromium/third_party/skia/src/utils/mac/SkCreateCGImageRef.cpp
index 0677b7bc304..01b774df09f 100644
--- a/chromium/third_party/skia/src/utils/mac/SkCreateCGImageRef.cpp
+++ b/chromium/third_party/skia/src/utils/mac/SkCreateCGImageRef.cpp
@@ -9,6 +9,40 @@
#include "SkBitmap.h"
#include "SkColorPriv.h"
+static CGBitmapInfo ComputeCGAlphaInfo_RGBA(SkAlphaType at) {
+ CGBitmapInfo info = kCGBitmapByteOrder32Big;
+ switch (at) {
+ case kOpaque_SkAlphaType:
+ case kIgnore_SkAlphaType:
+ info |= kCGImageAlphaNoneSkipLast;
+ break;
+ case kPremul_SkAlphaType:
+ info |= kCGImageAlphaPremultipliedLast;
+ break;
+ case kUnpremul_SkAlphaType:
+ info |= kCGImageAlphaLast;
+ break;
+ }
+ return info;
+}
+
+static CGBitmapInfo ComputeCGAlphaInfo_BGRA(SkAlphaType at) {
+ CGBitmapInfo info = kCGBitmapByteOrder32Little;
+ switch (at) {
+ case kOpaque_SkAlphaType:
+ case kIgnore_SkAlphaType:
+ info |= kCGImageAlphaNoneSkipFirst;
+ break;
+ case kPremul_SkAlphaType:
+ info |= kCGImageAlphaPremultipliedFirst;
+ break;
+ case kUnpremul_SkAlphaType:
+ info |= kCGImageAlphaFirst;
+ break;
+ }
+ return info;
+}
+
static void SkBitmap_ReleaseInfo(void* info, const void* pixelData, size_t size) {
SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(info);
delete bitmap;
@@ -22,52 +56,30 @@ static bool getBitmapInfo(const SkBitmap& bm,
*upscaleTo32 = false;
}
- switch (bm.config()) {
- case SkBitmap::kRGB_565_Config:
+ switch (bm.colorType()) {
+ case kRGB_565_SkColorType:
+#if 0
+ // doesn't see quite right. Are they thinking 1555?
+ *bitsPerComponent = 5;
+ *info = kCGBitmapByteOrder16Little | kCGImageAlphaNone;
+#else
if (upscaleTo32) {
*upscaleTo32 = true;
}
- // fall through
- case SkBitmap::kARGB_8888_Config:
+ // now treat like RGBA
*bitsPerComponent = 8;
-#if SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
- *info = kCGBitmapByteOrder32Big;
- if (bm.isOpaque()) {
- *info |= kCGImageAlphaNoneSkipLast;
- } else {
- *info |= kCGImageAlphaPremultipliedLast;
- }
-#elif SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
- // Matches the CGBitmapInfo that Apple recommends for best
- // performance, used by google chrome.
- *info = kCGBitmapByteOrder32Little;
- if (bm.isOpaque()) {
- *info |= kCGImageAlphaNoneSkipFirst;
- } else {
- *info |= kCGImageAlphaPremultipliedFirst;
- }
-#else
- // ...add more formats as required...
-#warning Cannot convert SkBitmap to CGImageRef with these shiftmasks. \
-This will probably not work.
- // Legacy behavior. Perhaps turn this into an error at some
- // point.
- *info = kCGBitmapByteOrder32Big;
- if (bm.isOpaque()) {
- *info |= kCGImageAlphaNoneSkipLast;
- } else {
- *info |= kCGImageAlphaPremultipliedLast;
- }
+ *info = ComputeCGAlphaInfo_RGBA(kOpaque_SkAlphaType);
#endif
break;
-#if 0
- case SkBitmap::kRGB_565_Config:
- // doesn't see quite right. Are they thinking 1555?
- *bitsPerComponent = 5;
- *info = kCGBitmapByteOrder16Little | kCGImageAlphaNone;
+ case kRGBA_8888_SkColorType:
+ *bitsPerComponent = 8;
+ *info = ComputeCGAlphaInfo_RGBA(bm.alphaType());
break;
-#endif
- case SkBitmap::kARGB_4444_Config:
+ case kBGRA_8888_SkColorType:
+ *bitsPerComponent = 8;
+ *info = ComputeCGAlphaInfo_BGRA(bm.alphaType());
+ break;
+ case kARGB_4444_SkColorType:
*bitsPerComponent = 4;
*info = kCGBitmapByteOrder16Little;
if (bm.isOpaque()) {
@@ -95,7 +107,7 @@ static SkBitmap* prepareForImageRef(const SkBitmap& bm,
copy = new SkBitmap;
// here we make a ceep copy of the pixels, since CG won't take our
// 565 directly
- bm.copyTo(copy, SkBitmap::kARGB_8888_Config);
+ bm.copyTo(copy, kN32_SkColorType);
} else {
copy = new SkBitmap(bm);
}
@@ -209,8 +221,9 @@ bool SkPDFDocumentToBitmap(SkStream* stream, SkBitmap* output) {
int h = (int)CGRectGetHeight(bounds);
SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, w, h);
- bitmap.allocPixels();
+ if (!bitmap.allocPixels(SkImageInfo::MakeN32Premul(w, h))) {
+ return false;
+ }
bitmap.eraseColor(SK_ColorWHITE);
size_t bitsPerComponent;
@@ -231,3 +244,72 @@ bool SkPDFDocumentToBitmap(SkStream* stream, SkBitmap* output) {
output->swap(bitmap);
return true;
}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+SK_API bool SkCopyPixelsFromCGImage(const SkImageInfo& info, size_t rowBytes, void* pixels,
+ CGImageRef image) {
+ CGBitmapInfo cg_bitmap_info = 0;
+ size_t bitsPerComponent = 0;
+ switch (info.colorType()) {
+ case kRGBA_8888_SkColorType:
+ bitsPerComponent = 8;
+ cg_bitmap_info = ComputeCGAlphaInfo_RGBA(info.alphaType());
+ break;
+ case kBGRA_8888_SkColorType:
+ bitsPerComponent = 8;
+ cg_bitmap_info = ComputeCGAlphaInfo_BGRA(info.alphaType());
+ break;
+ default:
+ return false; // no other colortypes are supported (for now)
+ }
+
+ CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
+ CGContextRef cg = CGBitmapContextCreate(pixels, info.width(), info.height(), bitsPerComponent,
+ rowBytes, cs, cg_bitmap_info);
+ CFRelease(cs);
+ if (NULL == cg) {
+ return false;
+ }
+
+ // use this blend mode, to avoid having to erase the pixels first, and to avoid CG performing
+ // any blending (which could introduce errors and be slower).
+ CGContextSetBlendMode(cg, kCGBlendModeCopy);
+
+ CGContextDrawImage(cg, CGRectMake(0, 0, info.width(), info.height()), image);
+ CGContextRelease(cg);
+ return true;
+}
+
+bool SkCreateBitmapFromCGImage(SkBitmap* dst, CGImageRef image, SkISize* scaleToFit) {
+ const int width = scaleToFit ? scaleToFit->width() : SkToInt(CGImageGetWidth(image));
+ const int height = scaleToFit ? scaleToFit->height() : SkToInt(CGImageGetHeight(image));
+ SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
+
+ SkBitmap tmp;
+ if (!tmp.allocPixels(info)) {
+ return false;
+ }
+
+ if (!SkCopyPixelsFromCGImage(tmp.info(), tmp.rowBytes(), tmp.getPixels(), image)) {
+ return false;
+ }
+
+ CGImageAlphaInfo cgInfo = CGImageGetAlphaInfo(image);
+ switch (cgInfo) {
+ case kCGImageAlphaNone:
+ case kCGImageAlphaNoneSkipLast:
+ case kCGImageAlphaNoneSkipFirst:
+ SkASSERT(SkBitmap::ComputeIsOpaque(tmp));
+ tmp.setAlphaType(kOpaque_SkAlphaType);
+ break;
+ default:
+ // we don't know if we're opaque or not, so compute it.
+ if (SkBitmap::ComputeIsOpaque(tmp)) {
+ tmp.setAlphaType(kOpaque_SkAlphaType);
+ }
+ }
+
+ *dst = tmp;
+ return true;
+}
diff --git a/chromium/third_party/skia/src/utils/win/SkDWrite.cpp b/chromium/third_party/skia/src/utils/win/SkDWrite.cpp
new file mode 100644
index 00000000000..87826b5194e
--- /dev/null
+++ b/chromium/third_party/skia/src/utils/win/SkDWrite.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkDWrite.h"
+#include "SkHRESULT.h"
+#include "SkOnce.h"
+#include "SkString.h"
+
+#include <dwrite.h>
+
+static IDWriteFactory* gDWriteFactory = NULL;
+
+static void release_dwrite_factory() {
+ if (gDWriteFactory) {
+ gDWriteFactory->Release();
+ }
+}
+
+static void create_dwrite_factory(IDWriteFactory** factory) {
+ typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc;
+ DWriteCreateFactoryProc dWriteCreateFactoryProc = reinterpret_cast<DWriteCreateFactoryProc>(
+ GetProcAddress(LoadLibraryW(L"dwrite.dll"), "DWriteCreateFactory"));
+
+ if (!dWriteCreateFactoryProc) {
+ HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
+ if (!IS_ERROR(hr)) {
+ hr = ERROR_PROC_NOT_FOUND;
+ }
+ HRVM(hr, "Could not get DWriteCreateFactory proc.");
+ }
+
+ HRVM(dWriteCreateFactoryProc(DWRITE_FACTORY_TYPE_SHARED,
+ __uuidof(IDWriteFactory),
+ reinterpret_cast<IUnknown**>(factory)),
+ "Could not create DirectWrite factory.");
+ atexit(release_dwrite_factory);
+}
+
+
+IDWriteFactory* sk_get_dwrite_factory() {
+ SK_DECLARE_STATIC_ONCE(once);
+ SkOnce(&once, create_dwrite_factory, &gDWriteFactory);
+
+ return gDWriteFactory;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// String conversion
+
+/** Converts a utf8 string to a WCHAR string. */
+HRESULT sk_cstring_to_wchar(const char* skname, SkSMallocWCHAR* name) {
+ int wlen = MultiByteToWideChar(CP_UTF8, 0, skname, -1, NULL, 0);
+ if (0 == wlen) {
+ HRM(HRESULT_FROM_WIN32(GetLastError()),
+ "Could not get length for wchar to utf-8 conversion.");
+ }
+ name->reset(wlen);
+ wlen = MultiByteToWideChar(CP_UTF8, 0, skname, -1, name->get(), wlen);
+ if (0 == wlen) {
+ HRM(HRESULT_FROM_WIN32(GetLastError()), "Could not convert wchar to utf-8.");
+ }
+ return S_OK;
+}
+
+/** Converts a WCHAR string to a utf8 string. */
+HRESULT sk_wchar_to_skstring(WCHAR* name, SkString* skname) {
+ int len = WideCharToMultiByte(CP_UTF8, 0, name, -1, NULL, 0, NULL, NULL);
+ if (0 == len) {
+ HRM(HRESULT_FROM_WIN32(GetLastError()),
+ "Could not get length for utf-8 to wchar conversion.");
+ }
+ skname->resize(len - 1);
+
+ // TODO: remove after https://code.google.com/p/skia/issues/detail?id=1989 is fixed.
+ // If we resize to 0 then the skname points to gEmptyRec (the unique empty SkString::Rec).
+ // gEmptyRec is static const and on Windows this means the value is in a read only page.
+ // Writing to it in the following call to WideCharToMultiByte will cause an access violation.
+ if (1 == len) {
+ return S_OK;
+ }
+
+ len = WideCharToMultiByte(CP_UTF8, 0, name, -1, skname->writable_str(), len, NULL, NULL);
+ if (0 == len) {
+ HRM(HRESULT_FROM_WIN32(GetLastError()), "Could not convert utf-8 to wchar.");
+ }
+ return S_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Locale
+
+void sk_get_locale_string(IDWriteLocalizedStrings* names, const WCHAR* preferedLocale,
+ SkString* skname) {
+ UINT32 nameIndex = 0;
+ if (preferedLocale) {
+ // Ignore any errors and continue with index 0 if there is a problem.
+ BOOL nameExists;
+ names->FindLocaleName(preferedLocale, &nameIndex, &nameExists);
+ if (!nameExists) {
+ nameIndex = 0;
+ }
+ }
+
+ UINT32 nameLength;
+ HRVM(names->GetStringLength(nameIndex, &nameLength), "Could not get name length.");
+ nameLength += 1;
+
+ SkSMallocWCHAR name(nameLength);
+ HRVM(names->GetString(nameIndex, name.get(), nameLength), "Could not get string.");
+
+ HRV(sk_wchar_to_skstring(name.get(), skname));
+}
+
+HRESULT SkGetGetUserDefaultLocaleNameProc(SkGetUserDefaultLocaleNameProc* proc) {
+ *proc = reinterpret_cast<SkGetUserDefaultLocaleNameProc>(
+ GetProcAddress(LoadLibraryW(L"Kernel32.dll"), "GetUserDefaultLocaleName")
+ );
+ if (!*proc) {
+ HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
+ if (!IS_ERROR(hr)) {
+ hr = ERROR_PROC_NOT_FOUND;
+ }
+ return hr;
+ }
+ return S_OK;
+}
diff --git a/chromium/third_party/skia/src/utils/win/SkDWrite.h b/chromium/third_party/skia/src/utils/win/SkDWrite.h
new file mode 100644
index 00000000000..679447dfc61
--- /dev/null
+++ b/chromium/third_party/skia/src/utils/win/SkDWrite.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkDWrite_DEFINED
+#define SkDWrite_DEFINED
+
+#include "SkTemplates.h"
+
+#include <dwrite.h>
+
+class SkString;
+
+////////////////////////////////////////////////////////////////////////////////
+// Factory
+
+IDWriteFactory* sk_get_dwrite_factory();
+
+////////////////////////////////////////////////////////////////////////////////
+// String conversion
+
+/** Prefer to use this type to prevent template proliferation. */
+typedef SkAutoSTMalloc<16, WCHAR> SkSMallocWCHAR;
+
+/** Converts a utf8 string to a WCHAR string. */
+HRESULT sk_cstring_to_wchar(const char* skname, SkSMallocWCHAR* name);
+
+/** Converts a WCHAR string to a utf8 string. */
+HRESULT sk_wchar_to_skstring(WCHAR* name, SkString* skname);
+
+////////////////////////////////////////////////////////////////////////////////
+// Locale
+
+void sk_get_locale_string(IDWriteLocalizedStrings* names, const WCHAR* preferedLocale,
+ SkString* skname);
+
+typedef decltype(GetUserDefaultLocaleName)* SkGetUserDefaultLocaleNameProc;
+HRESULT SkGetGetUserDefaultLocaleNameProc(SkGetUserDefaultLocaleNameProc* proc);
+
+////////////////////////////////////////////////////////////////////////////////
+// Table handling
+
+class AutoDWriteTable {
+public:
+ AutoDWriteTable(IDWriteFontFace* fontFace, UINT32 beTag) : fFontFace(fontFace), fExists(FALSE) {
+ // Any errors are ignored, user must check fExists anyway.
+ fontFace->TryGetFontTable(beTag,
+ reinterpret_cast<const void **>(&fData), &fSize, &fLock, &fExists);
+ }
+ ~AutoDWriteTable() {
+ if (fExists) {
+ fFontFace->ReleaseFontTable(fLock);
+ }
+ }
+
+ const uint8_t* fData;
+ UINT32 fSize;
+ BOOL fExists;
+private:
+ // Borrowed reference, the user must ensure the fontFace stays alive.
+ IDWriteFontFace* fFontFace;
+ void* fLock;
+};
+template<typename T> class AutoTDWriteTable : public AutoDWriteTable {
+public:
+ static const UINT32 tag = DWRITE_MAKE_OPENTYPE_TAG(T::TAG0, T::TAG1, T::TAG2, T::TAG3);
+ AutoTDWriteTable(IDWriteFontFace* fontFace) : AutoDWriteTable(fontFace, tag) { }
+
+ const T* get() const { return reinterpret_cast<const T*>(fData); }
+ const T* operator->() const { return reinterpret_cast<const T*>(fData); }
+};
+
+#endif
diff --git a/chromium/third_party/skia/src/utils/win/SkDWriteFontFileStream.h b/chromium/third_party/skia/src/utils/win/SkDWriteFontFileStream.h
index 5a56290c14c..ac98be6142a 100644
--- a/chromium/third_party/skia/src/utils/win/SkDWriteFontFileStream.h
+++ b/chromium/third_party/skia/src/utils/win/SkDWriteFontFileStream.h
@@ -68,6 +68,7 @@ public:
private:
explicit SkDWriteFontFileStreamWrapper(SkStream* stream);
+ virtual ~SkDWriteFontFileStreamWrapper() { }
ULONG fRefCount;
SkAutoTUnref<SkStream> fStream;
diff --git a/chromium/third_party/skia/src/utils/win/SkHRESULT.cpp b/chromium/third_party/skia/src/utils/win/SkHRESULT.cpp
index 32d9d4c35c3..495f074eb25 100644
--- a/chromium/third_party/skia/src/utils/win/SkHRESULT.cpp
+++ b/chromium/third_party/skia/src/utils/win/SkHRESULT.cpp
@@ -7,12 +7,13 @@
#include "SkTypes.h"
-#include "SKHRESULT.h"
+#include "SkHRESULT.h"
-void SkTraceHR(const char* file, unsigned long line,
- HRESULT hr, const char* msg) {
- SkDEBUGCODE(if (NULL != msg) SkDEBUGF(("%s\n", msg)));
- SkDEBUGF(("%s(%lu) : error 0x%x: ", file, line, hr));
+void SkTraceHR(const char* file, unsigned long line, HRESULT hr, const char* msg) {
+ if (NULL != msg) {
+ SkDebugf("%s\n", msg);
+ }
+ SkDebugf("%s(%lu) : error 0x%x: ", file, line, hr);
LPSTR errorText = NULL;
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
@@ -27,9 +28,9 @@ void SkTraceHR(const char* file, unsigned long line,
);
if (NULL == errorText) {
- SkDEBUGF(("<unknown>\n"));
+ SkDebugf("<unknown>\n");
} else {
- SkDEBUGF(("%s", errorText));
+ SkDebugf("%s", errorText);
LocalFree(errorText);
errorText = NULL;
}
diff --git a/chromium/third_party/skia/src/views/SkParsePaint.cpp b/chromium/third_party/skia/src/views/SkParsePaint.cpp
index 344da0b5720..5b4476423e8 100644
--- a/chromium/third_party/skia/src/views/SkParsePaint.cpp
+++ b/chromium/third_party/skia/src/views/SkParsePaint.cpp
@@ -96,7 +96,7 @@ void SkPaint_Inflate(SkPaint* paint, const SkDOM& dom, const SkDOM::Node* node)
if (dom.findScalar(node, "opacity", &x))
{
x = SkMaxScalar(0, SkMinScalar(x, SK_Scalar1));
- paint->setAlpha(SkScalarRound(x * 255));
+ paint->setAlpha(SkScalarRoundToInt(x * 255));
}
int index = dom.findList(node, "text-anchor", "left,center,right");
diff --git a/chromium/third_party/skia/src/views/SkStackViewLayout.cpp b/chromium/third_party/skia/src/views/SkStackViewLayout.cpp
index 9a3a3528533..aba6f2e93a2 100644
--- a/chromium/third_party/skia/src/views/SkStackViewLayout.cpp
+++ b/chromium/third_party/skia/src/views/SkStackViewLayout.cpp
@@ -167,11 +167,11 @@ void SkStackViewLayout::onLayoutChildren(SkView* parent)
while ((child = iter.next()) != NULL)
{
if (fRound)
- pos = SkIntToScalar(SkScalarRound(pos));
+ pos = SkScalarRoundToScalar(pos);
(child->*mainLocP)(pos);
SkScalar crossLoc = crossStartM + gAlignProcs[fAlign]((child->*crossGetSizeP)(), crossLimit);
if (fRound)
- crossLoc = SkIntToScalar(SkScalarRound(crossLoc));
+ crossLoc = SkScalarRoundToScalar(crossLoc);
(child->*crossLocP)(crossLoc);
if (crossSetSizeP)
diff --git a/chromium/third_party/skia/src/views/SkWidgets.cpp b/chromium/third_party/skia/src/views/SkWidgets.cpp
index e4547ec0e60..cde2b427389 100644
--- a/chromium/third_party/skia/src/views/SkWidgets.cpp
+++ b/chromium/third_party/skia/src/views/SkWidgets.cpp
@@ -234,6 +234,7 @@ static const char* computeAnimatorState(int enabled, int focused, SkButtonWidget
return "enabled";
}
+#include "SkBlurMask.h"
#include "SkBlurMaskFilter.h"
#include "SkEmbossMaskFilter.h"
@@ -255,7 +256,8 @@ static void create_emboss(SkPaint* paint, SkScalar radius, bool focus, bool pres
if (focus)
light.fDirection[2] += SK_Scalar1/4;
- paint->setMaskFilter(new SkEmbossMaskFilter(light, radius))->unref();
+ SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(radius);
+ paint->setMaskFilter(new SkEmbossMaskFilter(sigma, light))->unref();
}
void SkPushButtonWidget::onDraw(SkCanvas* canvas)
@@ -507,7 +509,7 @@ bool SkBitmapView::getBitmap(SkBitmap* bitmap) const
{
if (bitmap)
*bitmap = fBitmap;
- return fBitmap.getConfig() != SkBitmap::kNo_Config;
+ return fBitmap.colorType() != kUnknown_SkColorType;
}
void SkBitmapView::setBitmap(const SkBitmap* bitmap, bool viewOwnsPixels)
@@ -534,7 +536,7 @@ bool SkBitmapView::loadBitmapFromFile(const char path[])
void SkBitmapView::onDraw(SkCanvas* canvas)
{
- if (fBitmap.getConfig() != SkBitmap::kNo_Config &&
+ if (fBitmap.colorType() != kUnknown_SkColorType &&
fBitmap.width() && fBitmap.height())
{
SkAutoCanvasRestore restore(canvas, true);
diff --git a/chromium/third_party/skia/src/views/SkWindow.cpp b/chromium/third_party/skia/src/views/SkWindow.cpp
index 32914502d9c..99c2d30e8a6 100644
--- a/chromium/third_party/skia/src/views/SkWindow.cpp
+++ b/chromium/third_party/skia/src/views/SkWindow.cpp
@@ -14,54 +14,20 @@
#define SK_EventDelayInval "\xd" "n" "\xa" "l"
-#define TEST_BOUNDERx
-
-#include "SkBounder.h"
-class test_bounder : public SkBounder {
-public:
- test_bounder(const SkBitmap& bm) : fCanvas(bm) {}
-protected:
- virtual bool onIRect(const SkIRect& r)
- {
- SkRect rr;
-
- rr.set(SkIntToScalar(r.fLeft), SkIntToScalar(r.fTop),
- SkIntToScalar(r.fRight), SkIntToScalar(r.fBottom));
-
- SkPaint p;
-
- p.setStyle(SkPaint::kStroke_Style);
- p.setColor(SK_ColorYELLOW);
-
-#if 0
- rr.inset(SK_ScalarHalf, SK_ScalarHalf);
-#else
- rr.inset(-SK_ScalarHalf, -SK_ScalarHalf);
-#endif
-
- fCanvas.drawRect(rr, p);
- return true;
- }
-private:
- SkCanvas fCanvas;
-};
-
-SkWindow::SkWindow() : fFocusView(NULL)
-{
+SkWindow::SkWindow() : fFocusView(NULL) {
fClicks.reset();
fWaitingOnInval = false;
#ifdef SK_BUILD_FOR_WINCE
- fConfig = SkBitmap::kRGB_565_Config;
+ fColorType = kRGB_565_SkColorType;
#else
- fConfig = SkBitmap::kARGB_8888_Config;
+ fColorType = kN32_SkColorType;
#endif
fMatrix.reset();
}
-SkWindow::~SkWindow()
-{
+SkWindow::~SkWindow() {
fClicks.deleteAll();
fMenus.deleteAll();
}
@@ -89,40 +55,26 @@ void SkWindow::postConcat(const SkMatrix& matrix) {
this->setMatrix(m);
}
-void SkWindow::setConfig(SkBitmap::Config config)
-{
- this->resize(fBitmap.width(), fBitmap.height(), config);
+void SkWindow::setColorType(SkColorType ct) {
+ this->resize(fBitmap.width(), fBitmap.height(), ct);
}
-void SkWindow::resize(int width, int height, SkBitmap::Config config)
-{
- if (config == SkBitmap::kNo_Config)
- config = fConfig;
+void SkWindow::resize(int width, int height, SkColorType ct) {
+ if (ct == kUnknown_SkColorType)
+ ct = fColorType;
- if (width != fBitmap.width() || height != fBitmap.height() || config != fConfig)
- {
- fConfig = config;
- fBitmap.setConfig(config, width, height, 0, kOpaque_SkAlphaType);
- fBitmap.allocPixels();
+ if (width != fBitmap.width() || height != fBitmap.height() || ct != fColorType) {
+ fColorType = ct;
+ fBitmap.allocPixels(SkImageInfo::Make(width, height,
+ ct, kPremul_SkAlphaType));
this->setSize(SkIntToScalar(width), SkIntToScalar(height));
this->inval(NULL);
}
}
-void SkWindow::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
-{
- fBitmap.eraseARGB(a, r, g, b);
-}
-
-void SkWindow::eraseRGB(U8CPU r, U8CPU g, U8CPU b)
-{
- fBitmap.eraseARGB(0xFF, r, g, b);
-}
-
-bool SkWindow::handleInval(const SkRect* localR)
-{
- SkIRect ir;
+bool SkWindow::handleInval(const SkRect* localR) {
+ SkIRect ir;
if (localR) {
SkRect devR;
@@ -134,8 +86,8 @@ bool SkWindow::handleInval(const SkRect* localR)
devR.round(&ir);
} else {
ir.set(0, 0,
- SkScalarRound(this->width()),
- SkScalarRound(this->height()));
+ SkScalarRoundToInt(this->width()),
+ SkScalarRoundToInt(this->height()));
}
fDirtyRgn.op(ir, SkRegion::kUnion_Op);
@@ -145,8 +97,8 @@ bool SkWindow::handleInval(const SkRect* localR)
void SkWindow::forceInvalAll() {
fDirtyRgn.setRect(0, 0,
- SkScalarCeil(this->width()),
- SkScalarCeil(this->height()));
+ SkScalarCeilToInt(this->width()),
+ SkScalarCeilToInt(this->height()));
}
#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
@@ -159,10 +111,8 @@ void SkWindow::forceInvalAll() {
extern bool gEnableControlledThrow;
#endif
-bool SkWindow::update(SkIRect* updateArea)
-{
- if (!fDirtyRgn.isEmpty())
- {
+bool SkWindow::update(SkIRect* updateArea) {
+ if (!fDirtyRgn.isEmpty()) {
SkBitmap bm = this->getBitmap();
#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
@@ -189,10 +139,6 @@ bool SkWindow::update(SkIRect* updateArea)
// might be made during the draw call.
fDirtyRgn.setEmpty();
-#ifdef TEST_BOUNDER
- test_bounder b(bm);
- canvas->setBounder(&b);
-#endif
#ifdef SK_SIMULATE_FAILED_MALLOC
gEnableControlledThrow = true;
#endif
@@ -208,9 +154,6 @@ bool SkWindow::update(SkIRect* updateArea)
#ifdef SK_SIMULATE_FAILED_MALLOC
gEnableControlledThrow = false;
#endif
-#ifdef TEST_BOUNDER
- canvas->setBounder(NULL);
-#endif
#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
GXEndDraw();
@@ -221,8 +164,7 @@ bool SkWindow::update(SkIRect* updateArea)
return false;
}
-bool SkWindow::handleChar(SkUnichar uni)
-{
+bool SkWindow::handleChar(SkUnichar uni) {
if (this->onHandleChar(uni))
return true;
@@ -235,8 +177,7 @@ bool SkWindow::handleChar(SkUnichar uni)
return focus->doEvent(evt);
}
-bool SkWindow::handleKey(SkKey key)
-{
+bool SkWindow::handleKey(SkKey key) {
if (key == kNONE_SkKey)
return false;
@@ -255,8 +196,7 @@ bool SkWindow::handleKey(SkKey key)
return true;
}
- if (key == kUp_SkKey || key == kDown_SkKey)
- {
+ if (key == kUp_SkKey || key == kDown_SkKey) {
if (this->moveFocus(key == kUp_SkKey ? kPrev_FocusDirection : kNext_FocusDirection) == NULL)
this->onSetFocusView(NULL);
return true;
@@ -264,8 +204,7 @@ bool SkWindow::handleKey(SkKey key)
return false;
}
-bool SkWindow::handleKeyUp(SkKey key)
-{
+bool SkWindow::handleKeyUp(SkKey key) {
if (key == kNONE_SkKey)
return false;
@@ -300,15 +239,9 @@ void SkWindow::setTitle(const char title[]) {
this->onSetTitle(title);
}
-//////////////////////////////////////////////////////////////////////
-
-bool SkWindow::onEvent(const SkEvent& evt)
-{
- if (evt.isType(SK_EventDelayInval))
- {
- SkRegion::Iterator iter(fDirtyRgn);
-
- for (; !iter.done(); iter.next())
+bool SkWindow::onEvent(const SkEvent& evt) {
+ if (evt.isType(SK_EventDelayInval)) {
+ for (SkRegion::Iterator iter(fDirtyRgn); !iter.done(); iter.next())
this->onHandleInval(iter.rect());
fWaitingOnInval = false;
return true;
@@ -316,17 +249,14 @@ bool SkWindow::onEvent(const SkEvent& evt)
return this->INHERITED::onEvent(evt);
}
-bool SkWindow::onGetFocusView(SkView** focus) const
-{
+bool SkWindow::onGetFocusView(SkView** focus) const {
if (focus)
*focus = fFocusView;
return true;
}
-bool SkWindow::onSetFocusView(SkView* focus)
-{
- if (fFocusView != focus)
- {
+bool SkWindow::onSetFocusView(SkView* focus) {
+ if (fFocusView != focus) {
if (fFocusView)
fFocusView->onFocusChange(false);
fFocusView = focus;
@@ -336,24 +266,18 @@ bool SkWindow::onSetFocusView(SkView* focus)
return true;
}
-//////////////////////////////////////////////////////////////////////
-
-void SkWindow::onHandleInval(const SkIRect&)
-{
+void SkWindow::onHandleInval(const SkIRect&) {
}
-bool SkWindow::onHandleChar(SkUnichar)
-{
+bool SkWindow::onHandleChar(SkUnichar) {
return false;
}
-bool SkWindow::onHandleKey(SkKey)
-{
+bool SkWindow::onHandleKey(SkKey) {
return false;
}
-bool SkWindow::onHandleKeyUp(SkKey)
-{
+bool SkWindow::onHandleKeyUp(SkKey) {
return false;
}
diff --git a/chromium/third_party/skia/src/views/mac/SkNSView.mm b/chromium/third_party/skia/src/views/mac/SkNSView.mm
index 475b08f67dc..80bfd670ef4 100644
--- a/chromium/third_party/skia/src/views/mac/SkNSView.mm
+++ b/chromium/third_party/skia/src/views/mac/SkNSView.mm
@@ -11,6 +11,7 @@
#include "SkCGUtils.h"
#include "SkEvent.h"
SK_COMPILE_ASSERT(SK_SUPPORT_GPU, not_implemented_for_non_gpu_build);
+#include <OpenGL/gl.h>
//#define FORCE_REDRAW
// Can be dropped when we no longer support 10.6.
@@ -56,7 +57,7 @@ SK_COMPILE_ASSERT(SK_SUPPORT_GPU, not_implemented_for_non_gpu_build);
size = [self convertSizeToBacking:self.frame.size];
#endif
fWind->resize((int) size.width, (int) size.height,
- SkBitmap::kARGB_8888_Config);
+ kN32_SkColorType);
}
}
diff --git a/chromium/third_party/skia/src/views/mac/SkOptionsTableView.mm b/chromium/third_party/skia/src/views/mac/SkOptionsTableView.mm
index 7a6afe42b34..b4cdbf4119b 100644
--- a/chromium/third_party/skia/src/views/mac/SkOptionsTableView.mm
+++ b/chromium/third_party/skia/src/views/mac/SkOptionsTableView.mm
@@ -66,7 +66,7 @@
int menuIndex = fMenus->find(const_cast<SkOSMenu *>(menu));
if (menuIndex >= 0 && menuIndex < fMenus->count()) {
NSUInteger first = 0;
- for (NSInteger i = 0; i < menuIndex; ++i) {
+ for (int i = 0; i < menuIndex; ++i) {
first += (*fMenus)[i]->getCount();
}
[fItems removeObjectsInRange:NSMakeRange(first, [fItems count] - first)];
@@ -148,7 +148,7 @@
}
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
- int columnIndex = [tableView columnWithIdentifier:[tableColumn identifier]];
+ NSInteger columnIndex = [tableView columnWithIdentifier:[tableColumn identifier]];
if (columnIndex == 0) {
const SkOSMenu::Item* item = ((SkOptionItem*)[fItems objectAtIndex:row]).fItem;
NSString* label = [NSString stringWithUTF8String:item->getLabel()];
@@ -163,7 +163,7 @@
- (NSCell *)tableView:(NSTableView *)tableView dataCellForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
if (tableColumn) {
- int columnIndex = [tableView columnWithIdentifier:[tableColumn identifier]];
+ NSInteger columnIndex = [tableView columnWithIdentifier:[tableColumn identifier]];
if (columnIndex == 1)
return [((SkOptionItem*)[fItems objectAtIndex:row]).fCell copy];
else
@@ -173,7 +173,7 @@
}
- (void)tableView:(NSTableView *)tableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
- int columnIndex = [tableView columnWithIdentifier:[tableColumn identifier]];
+ NSInteger columnIndex = [tableView columnWithIdentifier:[tableColumn identifier]];
if (columnIndex == 1) {
SkOptionItem* option = (SkOptionItem*)[self.fItems objectAtIndex:row];
NSCell* storedCell = option.fCell;
@@ -207,7 +207,7 @@
}
- (void)tableView:(NSTableView *)tableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
- int columnIndex = [tableView columnWithIdentifier:[tableColumn identifier]];
+ NSInteger columnIndex = [tableView columnWithIdentifier:[tableColumn identifier]];
if (columnIndex == 1) {
SkOptionItem* option = (SkOptionItem*)[self.fItems objectAtIndex:row];
NSCell* cell = option.fCell;
diff --git a/chromium/third_party/skia/src/views/sdl/SkOSWindow_SDL.cpp b/chromium/third_party/skia/src/views/sdl/SkOSWindow_SDL.cpp
index 2a1fae28a6e..27783d41fc7 100644
--- a/chromium/third_party/skia/src/views/sdl/SkOSWindow_SDL.cpp
+++ b/chromium/third_party/skia/src/views/sdl/SkOSWindow_SDL.cpp
@@ -23,22 +23,23 @@ static void post_SkEvent_event() {
}
static bool skia_setBitmapFromSurface(SkBitmap* dst, SDL_Surface* src) {
- SkBitmap::Config config;
+ SkColorType ct;
+ SkAlphaType at;
switch (src->format->BytesPerPixel) {
case 2:
- config = SkBitmap::kRGB_565_Config;
+ ct = kRGB_565_SkColorType;
+ at = kOpaque_SkAlphaType;
break;
case 4:
- config = SkBitmap::kARGB_8888_Config;
+ ct = kN32_SkColorType;
+ at = kPremul_SkAlphaType;
break;
default:
return false;
}
- dst->setConfig(config, src->w, src->h, src->pitch);
- dst->setPixels(src->pixels);
- return true;
+ return dst->installPixels(SkImageInfo::Make(src->w, src->h, ct, at), src->pixels, src->pitch);
}
SkOSWindow::SkOSWindow(void* screen) {
diff --git a/chromium/third_party/skia/src/views/unix/SkOSWindow_Unix.cpp b/chromium/third_party/skia/src/views/unix/SkOSWindow_Unix.cpp
index 9fa2b304b9f..078a9f9d56c 100644
--- a/chromium/third_party/skia/src/views/unix/SkOSWindow_Unix.cpp
+++ b/chromium/third_party/skia/src/views/unix/SkOSWindow_Unix.cpp
@@ -172,6 +172,13 @@ static unsigned getModi(const XEvent& evt) {
static SkMSec gTimerDelay;
static bool MyXNextEventWithDelay(Display* dsp, XEvent* evt) {
+ // Check for pending events before entering the select loop. There might
+ // be events in the in-memory queue but not processed yet.
+ if (XPending(dsp)) {
+ XNextEvent(dsp, evt);
+ return true;
+ }
+
SkMSec ms = gTimerDelay;
if (ms > 0) {
int x11_fd = ConnectionNumber(dsp);
@@ -330,7 +337,8 @@ bool SkOSWindow::attach(SkBackEndTypes, int msaaSampleCount, AttachmentInfo* inf
fUnixWindow.fWin,
fUnixWindow.fGLContext);
glViewport(0, 0,
- SkScalarRound(this->width()), SkScalarRound(this->height()));
+ SkScalarRoundToInt(this->width()),
+ SkScalarRoundToInt(this->height()));
glClearColor(0, 0, 0, 0);
glClearStencil(0);
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
diff --git a/chromium/third_party/skia/src/views/unix/skia_unix.cpp b/chromium/third_party/skia/src/views/unix/skia_unix.cpp
index 7dcbeccae61..03a2915adb3 100644
--- a/chromium/third_party/skia/src/views/unix/skia_unix.cpp
+++ b/chromium/third_party/skia/src/views/unix/skia_unix.cpp
@@ -1,37 +1,26 @@
-
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
-#include "X11/Xlib.h"
-#include "X11/keysym.h"
#include "SkApplication.h"
#include "SkEvent.h"
#include "SkWindow.h"
-#include "SkTypes.h"
-
-#include <signal.h>
-#include <sys/time.h>
-
-SkOSWindow* gWindow;
int main(int argc, char** argv){
- gWindow = create_sk_window(NULL, argc, argv);
+ SkOSWindow* window = create_sk_window(NULL, argc, argv);
- // drain any events that occurred before gWindow was assigned.
+ // drain any events that occurred before |window| was assigned.
while (SkEvent::ProcessEvent());
// Start normal Skia sequence
application_init();
- gWindow->loop();
+ window->loop();
- delete gWindow;
+ delete window;
application_term();
return 0;
}
-
-// SkEvent handlers
diff --git a/chromium/third_party/skia/src/views/win/SkOSWindow_win.cpp b/chromium/third_party/skia/src/views/win/SkOSWindow_win.cpp
index 7549ea21da1..027bc667577 100644
--- a/chromium/third_party/skia/src/views/win/SkOSWindow_win.cpp
+++ b/chromium/third_party/skia/src/views/win/SkOSWindow_win.cpp
@@ -27,7 +27,7 @@
#define ANGLE_GL_CALL(IFACE, X) \
do { \
- (IFACE)->f##X; \
+ (IFACE)->fFunctions.f##X; \
} while (false)
#endif
@@ -361,7 +361,9 @@ bool SkOSWindow::attachGL(int msaaSampleCount, AttachmentInfo* info) {
info->fSampleCount = 0;
}
- glViewport(0, 0, SkScalarRound(this->width()), SkScalarRound(this->height()));
+ glViewport(0, 0,
+ SkScalarRoundToInt(this->width()),
+ SkScalarRoundToInt(this->height()));
return true;
}
return false;
@@ -500,8 +502,9 @@ bool SkOSWindow::attachANGLE(int msaaSampleCount, AttachmentInfo* info) {
SkAutoTUnref<const GrGLInterface> intf(GrGLCreateANGLEInterface());
if (intf ) {
- ANGLE_GL_CALL(intf, Viewport(0, 0, SkScalarRound(this->width()),
- SkScalarRound(this->height())));
+ ANGLE_GL_CALL(intf, Viewport(0, 0,
+ SkScalarRoundToInt(this->width()),
+ SkScalarRoundToInt(this->height())));
}
return true;
}
diff --git a/chromium/third_party/skia/src/xml/SkJSDisplayable.cpp b/chromium/third_party/skia/src/xml/SkJSDisplayable.cpp
index 502779743fc..02a05016727 100644
--- a/chromium/third_party/skia/src/xml/SkJSDisplayable.cpp
+++ b/chromium/third_party/skia/src/xml/SkJSDisplayable.cpp
@@ -277,11 +277,7 @@ JSBool SkJSDisplayable::GetProperty(JSContext *cx, JSObject *obj, jsval id,
if (SkScalarFraction(scalar) == 0)
*vp = INT_TO_JSVAL(SkScalarFloor(scalar));
else
-#ifdef SK_SCALAR_IS_FLOAT
*vp = DOUBLE_TO_JSVAL(scalar);
-#else
- *vp = DOUBLE_TO_JSVAL(scalar / 65536.0f );
-#endif
break;
case SkType_String:
str = JS_NewStringCopyN(cx, string->c_str(), string->size());
@@ -323,11 +319,7 @@ JSBool SkJSDisplayable::SetProperty(JSContext *cx, JSObject *obj, jsval id, jsva
scalar = SkIntToScalar(JSVAL_TO_INT(value));
else {
SkASSERT(JSVAL_IS_DOUBLE(value));
-#ifdef SK_SCALAR_IS_FLOAT
scalar = (float) *(double*) JSVAL_TO_DOUBLE(value);
-#else
- scalar = (SkFixed) (*(double*)JSVAL_TO_DOUBLE(value) * 65536.0);
-#endif
}
break;
case SkType_String:
diff --git a/chromium/third_party/skia/src/xml/SkXMLWriter.cpp b/chromium/third_party/skia/src/xml/SkXMLWriter.cpp
index 2ff47eae66c..ec351b728b8 100644
--- a/chromium/third_party/skia/src/xml/SkXMLWriter.cpp
+++ b/chromium/third_party/skia/src/xml/SkXMLWriter.cpp
@@ -309,9 +309,7 @@ void SkXMLStreamWriter::UnitTest()
w.addAttribute("hello", "world");
w.addS32Attribute("dec", 42);
w.addHexAttribute("hex", 0x42, 3);
-#ifdef SK_SCALAR_IS_FLOAT
w.addScalarAttribute("scalar", -4.2f);
-#endif
w.startElement("elem1");
w.endElement();
w.startElement("elem1");